using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Opc.Ua; using ZB.MOM.WW.LmxOpcUa.Client.Shared; using ZB.MOM.WW.LmxOpcUa.Client.UI.Services; namespace ZB.MOM.WW.LmxOpcUa.Client.UI.ViewModels; /// /// ViewModel for the read/write panel. /// public partial class ReadWriteViewModel : ObservableObject { private readonly IUiDispatcher _dispatcher; private readonly IOpcUaClientService _service; [ObservableProperty] private string? _currentStatus; [ObservableProperty] private string? _currentValue; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(ReadCommand))] [NotifyCanExecuteChangedFor(nameof(WriteCommand))] private bool _isConnected; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(ReadCommand))] [NotifyCanExecuteChangedFor(nameof(WriteCommand))] private string? _selectedNodeId; [ObservableProperty] private string? _serverTimestamp; [ObservableProperty] private string? _sourceTimestamp; [ObservableProperty] private string? _writeStatus; [ObservableProperty] private string? _writeValue; public ReadWriteViewModel(IOpcUaClientService service, IUiDispatcher dispatcher) { _service = service; _dispatcher = dispatcher; } public bool IsNodeSelected => !string.IsNullOrEmpty(SelectedNodeId); partial void OnSelectedNodeIdChanged(string? value) { OnPropertyChanged(nameof(IsNodeSelected)); if (!string.IsNullOrEmpty(value) && IsConnected) _ = ExecuteReadAsync(); } private bool CanReadOrWrite() { return IsConnected && !string.IsNullOrEmpty(SelectedNodeId); } [RelayCommand(CanExecute = nameof(CanReadOrWrite))] private async Task ReadAsync() { await ExecuteReadAsync(); } private async Task ExecuteReadAsync() { if (string.IsNullOrEmpty(SelectedNodeId)) return; try { var nodeId = NodeId.Parse(SelectedNodeId); var dataValue = await _service.ReadValueAsync(nodeId); _dispatcher.Post(() => { CurrentValue = dataValue.Value?.ToString() ?? "(null)"; CurrentStatus = dataValue.StatusCode.ToString(); SourceTimestamp = dataValue.SourceTimestamp.ToString("O"); ServerTimestamp = dataValue.ServerTimestamp.ToString("O"); }); } catch (Exception ex) { _dispatcher.Post(() => { CurrentValue = null; CurrentStatus = $"Error: {ex.Message}"; SourceTimestamp = null; ServerTimestamp = null; }); } } [RelayCommand(CanExecute = nameof(CanReadOrWrite))] private async Task WriteAsync() { if (string.IsNullOrEmpty(SelectedNodeId) || WriteValue == null) return; try { var nodeId = NodeId.Parse(SelectedNodeId); var statusCode = await _service.WriteValueAsync(nodeId, WriteValue); _dispatcher.Post(() => { WriteStatus = statusCode.ToString(); }); } catch (Exception ex) { _dispatcher.Post(() => { WriteStatus = $"Error: {ex.Message}"; }); } } /// /// Clears all displayed values. /// public void Clear() { SelectedNodeId = null; CurrentValue = null; CurrentStatus = null; SourceTimestamp = null; ServerTimestamp = null; WriteValue = null; WriteStatus = null; } }