Initial commit
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
using RobotNet10.RobotApp.Client.Shared.Devices;
|
||||
|
||||
namespace RobotNet10.RobotApp.Client.Services;
|
||||
|
||||
/// <summary>
|
||||
/// SignalR client để kết nối với DeviceHub
|
||||
/// </summary>
|
||||
public class DeviceHubClient : IAsyncDisposable
|
||||
{
|
||||
private readonly HubConnection _hubConnection;
|
||||
private bool _disposed;
|
||||
|
||||
public event Action<DeviceUpdateDto>? DeviceUpdated;
|
||||
public event Action<string, DeviceStatus>? DeviceStatusChanged;
|
||||
public event Action<HubConnectionState>? ConnectionStateChanged;
|
||||
|
||||
public bool IsConnected => _hubConnection.State == HubConnectionState.Connected;
|
||||
public HubConnectionState ConnectionState => _hubConnection.State;
|
||||
|
||||
public DeviceHubClient(NavigationManager navigationManager)
|
||||
{
|
||||
var hubUrl = navigationManager.ToAbsoluteUri("/hubs/devices");
|
||||
_hubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(hubUrl)
|
||||
.WithAutomaticReconnect()
|
||||
.Build();
|
||||
|
||||
_hubConnection.On<DeviceUpdateDto>("DeviceUpdated", update => DeviceUpdated?.Invoke(update));
|
||||
_hubConnection.On<string, DeviceStatus>("DeviceStatusChanged", (deviceId, status) =>
|
||||
DeviceStatusChanged?.Invoke(deviceId, status));
|
||||
|
||||
_hubConnection.Reconnecting += error =>
|
||||
{
|
||||
ConnectionStateChanged?.Invoke(_hubConnection.State);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
_hubConnection.Reconnected += connectionId =>
|
||||
{
|
||||
ConnectionStateChanged?.Invoke(_hubConnection.State);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
|
||||
_hubConnection.Closed += error =>
|
||||
{
|
||||
ConnectionStateChanged?.Invoke(_hubConnection.State);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public async Task StartAsync()
|
||||
{
|
||||
if (_hubConnection.State == HubConnectionState.Disconnected)
|
||||
{
|
||||
await _hubConnection.StartAsync();
|
||||
ConnectionStateChanged?.Invoke(_hubConnection.State);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
if (_hubConnection.State != HubConnectionState.Disconnected)
|
||||
{
|
||||
await _hubConnection.StopAsync();
|
||||
ConnectionStateChanged?.Invoke(_hubConnection.State);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DeviceDto[]> GetAllDevicesAsync()
|
||||
{
|
||||
return await _hubConnection.InvokeAsync<DeviceDto[]>("GetAllDevices");
|
||||
}
|
||||
|
||||
public async Task<DeviceDto?> GetDeviceAsync(string deviceId)
|
||||
{
|
||||
return await _hubConnection.InvokeAsync<DeviceDto?>("GetDevice", deviceId);
|
||||
}
|
||||
|
||||
public async Task<DeviceDto[]> GetDevicesByTypeAsync(DeviceType deviceType)
|
||||
{
|
||||
return await _hubConnection.InvokeAsync<DeviceDto[]>("GetDevicesByType", deviceType);
|
||||
}
|
||||
|
||||
public async Task<int> GetDeviceCountAsync()
|
||||
{
|
||||
return await _hubConnection.InvokeAsync<int>("GetDeviceCount");
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
_disposed = true;
|
||||
await StopAsync();
|
||||
await _hubConnection.DisposeAsync();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Net.Http.Json;
|
||||
using RobotNet10.RobotApp.Shared.DockStation;
|
||||
|
||||
namespace RobotNet10.RobotApp.Client.Services;
|
||||
|
||||
public class DockStationApiService(HttpClient httpClient)
|
||||
{
|
||||
private const string BaseUrl = "api/dock-station-config";
|
||||
|
||||
public async Task<List<DockStationConfigSummaryDto>> GetAllAsync()
|
||||
=> await httpClient.GetFromJsonAsync<List<DockStationConfigSummaryDto>>(BaseUrl) ?? [];
|
||||
|
||||
public async Task<DockStationConfigDto?> GetByIdAsync(Guid id)
|
||||
=> await httpClient.GetFromJsonAsync<DockStationConfigDto>($"{BaseUrl}/{id}");
|
||||
|
||||
public async Task<DockStationConfigDto> CreateAsync(CreateDockStationConfigRequest request)
|
||||
{
|
||||
var response = await httpClient.PostAsJsonAsync(BaseUrl, request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<DockStationConfigDto>()
|
||||
?? throw new InvalidOperationException("Failed to deserialize created dock station config.");
|
||||
}
|
||||
|
||||
public async Task<DockStationConfigDto> UpdateAsync(Guid id, UpdateDockStationConfigRequest request)
|
||||
{
|
||||
var response = await httpClient.PutAsJsonAsync($"{BaseUrl}/{id}", request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadFromJsonAsync<DockStationConfigDto>()
|
||||
?? throw new InvalidOperationException("Failed to deserialize updated dock station config.");
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(Guid id)
|
||||
{
|
||||
var response = await httpClient.DeleteAsync($"{BaseUrl}/{id}");
|
||||
response.EnsureSuccessStatusCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
using RobotNet10.RobotApp.Shared.DockStation;
|
||||
|
||||
namespace RobotNet10.RobotApp.Client.Services;
|
||||
|
||||
public class DockStationConfigState(DockStationApiService apiService)
|
||||
{
|
||||
public List<DockStationConfigSummaryDto> Configs { get; private set; } = [];
|
||||
public DockStationConfigDto? SelectedConfig { get; private set; }
|
||||
public bool IsLoading { get; private set; }
|
||||
public bool IsSaving { get; private set; }
|
||||
public string? ErrorMessage { get; private set; }
|
||||
|
||||
public event Action? OnStateChanged;
|
||||
|
||||
public async Task LoadConfigsAsync()
|
||||
{
|
||||
IsLoading = true;
|
||||
ErrorMessage = null;
|
||||
NotifyStateChanged();
|
||||
try
|
||||
{
|
||||
Configs = await apiService.GetAllAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = ex.Message;
|
||||
Configs = [];
|
||||
}
|
||||
IsLoading = false;
|
||||
NotifyStateChanged();
|
||||
}
|
||||
|
||||
public async Task SelectConfigAsync(Guid id)
|
||||
{
|
||||
IsLoading = true;
|
||||
ErrorMessage = null;
|
||||
NotifyStateChanged();
|
||||
try
|
||||
{
|
||||
SelectedConfig = await apiService.GetByIdAsync(id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = ex.Message;
|
||||
SelectedConfig = null;
|
||||
}
|
||||
IsLoading = false;
|
||||
NotifyStateChanged();
|
||||
}
|
||||
|
||||
public void ClearSelection()
|
||||
{
|
||||
SelectedConfig = null;
|
||||
NotifyStateChanged();
|
||||
}
|
||||
|
||||
public async Task<DockStationConfigDto> CreateConfigAsync(CreateDockStationConfigRequest request)
|
||||
{
|
||||
IsSaving = true;
|
||||
ErrorMessage = null;
|
||||
NotifyStateChanged();
|
||||
try
|
||||
{
|
||||
var result = await apiService.CreateAsync(request);
|
||||
await LoadConfigsAsync();
|
||||
SelectedConfig = result;
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = ex.Message;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsSaving = false;
|
||||
NotifyStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateConfigAsync(Guid id, UpdateDockStationConfigRequest request)
|
||||
{
|
||||
IsSaving = true;
|
||||
ErrorMessage = null;
|
||||
NotifyStateChanged();
|
||||
try
|
||||
{
|
||||
SelectedConfig = await apiService.UpdateAsync(id, request);
|
||||
await LoadConfigsAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = ex.Message;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsSaving = false;
|
||||
NotifyStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteConfigAsync(Guid id)
|
||||
{
|
||||
IsSaving = true;
|
||||
ErrorMessage = null;
|
||||
NotifyStateChanged();
|
||||
try
|
||||
{
|
||||
await apiService.DeleteAsync(id);
|
||||
if (SelectedConfig?.Id == id) ClearSelection();
|
||||
await LoadConfigsAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ErrorMessage = ex.Message;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsSaving = false;
|
||||
NotifyStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void NotifyStateChanged() => OnStateChanged?.Invoke();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using RobotNet10.RobotApp.Script.Shared;
|
||||
using RobotNet10.ScriptEngine.Shared;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace RobotNet10.RobotApp.Client.Services;
|
||||
|
||||
public class ScriptEngineResource : IScriptEngineResource
|
||||
{
|
||||
public Type AppGlobalType => RobotAppScriptEngineResource.GlobalType;
|
||||
|
||||
public ImmutableArray<string> UsingNamespaces => RobotAppScriptEngineResource.UsingNamespaces;
|
||||
|
||||
public ImmutableArray<string> Modules => RobotAppScriptEngineResource.Modules;
|
||||
|
||||
public ImmutableArray<string> DocModules => RobotAppScriptEngineResource.DocModules;
|
||||
|
||||
public IDictionary<string, object?> GetMissionGlobals(Guid id, CancellationToken cancellationToken)
|
||||
=> new Dictionary<string, object?>();
|
||||
|
||||
public IDictionary<string, object?> GetTaskGlobals()
|
||||
=> new Dictionary<string, object?>();
|
||||
}
|
||||
Reference in New Issue
Block a user