using MainShell.EventArgsFolder; using MainShell.Hardware; using MainShell.Manual.Model; using MainShell.DeviceMaintance.ViewModel.State; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace MainShell.DeviceMaintance.ViewModel { public class DeviceIoViewModel : OperateViewModelBase { private readonly IDeviceIoMonitorService _ioMonitorService; private readonly Dictionary _pointStateMap = new Dictionary(StringComparer.OrdinalIgnoreCase); private DeviceIoPageState _pageState; public DeviceIoPageState PageState { get { return _pageState; } set { SetAndNotify(ref _pageState, value); } } public DeviceIoViewModel(IDeviceIoMonitorService ioMonitorService) { _ioMonitorService = ioMonitorService; PageState = BuildState(); _ioMonitorService.IoChanged += OnIoChanged; _ioMonitorService.Start(); } protected override void OnViewLoaded() { base.OnViewLoaded(); RefreshFromCurrentPoints(); InitializeLatestPointsAsync(); } protected override void OnDeactivate() { _ioMonitorService.IoChanged -= OnIoChanged; base.OnDeactivate(); } private DeviceIoPageState BuildState() { var state = new DeviceIoPageState(); _pointStateMap.Clear(); foreach (var moduleGroup in _ioMonitorService.Definitions.GroupBy(x => string.IsNullOrWhiteSpace(x.Module) ? "Default" : x.Module)) { var moduleState = new DeviceIoModuleState { Name = moduleGroup.Key }; foreach (var definition in moduleGroup.OrderBy(x => x.StationNo).ThenBy(x => x.Id).ThenBy(x => x.LineNo)) { var item = new DeviceIoPointItemState { Id = definition.Id, PointKey = definition.PointKey, Module = definition.Module, Name = definition.Name, StationNo = definition.StationNo, LineNo = definition.LineNo, Description = definition.Description, IsOutput = definition.Type == IoPointType.Output, IsOn = definition.DefaultValue, IsInverse = definition.IsInverse, CanWrite = definition.Type == IoPointType.Output && definition.Enabled, }; if (item.IsOutput) { var command = new ActionCommand(() => ToggleOutput(item), () => item.CanWrite); item.ToggleCommand = command; } _pointStateMap[item.PointKey] = item; if (item.IsOutput) { moduleState.OutputPoints.Add(item); } else { moduleState.InputPoints.Add(item); } } state.Modules.Add(moduleState); } state.IsOnline = _ioMonitorService.IsOnline; return state; } private async void InitializeLatestPointsAsync() { _ioMonitorService.RequestRefresh(); await Task.Delay(150); RefreshFromCurrentPoints(); } private void RefreshFromCurrentPoints() { var points = _ioMonitorService.LatestPoints.Values.ToList(); ApplyPoints(points); } private void OnIoChanged(object sender, EventArgs e) { var args = e as DeviceIoChangedEventArgs; if (args == null) { return; } ApplyPoints(args.ChangedPoints); PageState.LastRefreshTime = DateTime.Now; } private void ApplyPoints(IEnumerable points) { if (points == null) { return; } var hasPoint = false; foreach (var point in points) { if (point == null) { continue; } hasPoint = true; DeviceIoPointItemState item; if (!_pointStateMap.TryGetValue(point.PointKey, out item)) { continue; } item.IsOn = point.Value; var outputPoint = point as DeviceOutputPointState; item.CanWrite = outputPoint != null && outputPoint.CanWrite; var command = item.ToggleCommand as ActionCommand; if (command != null) { command.RaiseCanExecuteChanged(); } } if (hasPoint) { PageState.LastRefreshTime = DateTime.Now; } PageState.IsOnline = hasPoint && _ioMonitorService.IsOnline; } private void ToggleOutput(DeviceIoPointItemState item) { DeviceIoPointState point; if (!_ioMonitorService.TryGetPoint(item.PointKey, out point)) { UpdateWriteResult(item.Name + " 写入失败:未找到输出点。", false); return; } var outputPoint = point as DeviceOutputPointState; if (outputPoint == null || !outputPoint.CanWrite) { UpdateWriteResult(item.Name + " 写入失败:输出点不可写。", false); return; } var targetState = !item.IsOn; var result = outputPoint.TrySetOutput(targetState); UpdateWriteResult(item.Name + (result ? (targetState ? " 已切换为 ON。" : " 已切换为 OFF。") : " 写入失败。"), result); } private void UpdateWriteResult(string message, bool success) { PageState.LastWriteMessage = message; PageState.IsWriteSuccess = success; PageState.LastWriteTime = DateTime.Now; } } }