diff --git a/PetWashControl/ViewModels/MainViewModel.cs b/PetWashControl/ViewModels/MainViewModel.cs index 7460070..7b2fa56 100644 --- a/PetWashControl/ViewModels/MainViewModel.cs +++ b/PetWashControl/ViewModels/MainViewModel.cs @@ -136,6 +136,7 @@ public partial class MainViewModel : ObservableObject private readonly System.Timers.Timer _carouselTimer; private readonly System.Timers.Timer _clockTimer; + private readonly System.Timers.Timer _liquidLevelTimer; private readonly string[] _carouselImages = { "/Images/dog.png", "/Images/dog1.png", "/Images/dog2.png" }; private int _currentImageIndex = 0; @@ -189,6 +190,24 @@ public partial class MainViewModel : ObservableObject }); }; _clockTimer.Start(); + + // 初始化液位监测定时器(每30秒更新一次) + _liquidLevelTimer = new System.Timers.Timer(30000); + _liquidLevelTimer.Elapsed += async (s, e) => + { + if (IsModbusConnected) + { + try + { + await LoadLiquidLevelsAsync(); + } + catch (Exception ex) + { + _logger.LogError("定时更新液位失败", ex); + } + } + }; + _liquidLevelTimer.Start(); } private void InitializeWashSteps() @@ -219,10 +238,14 @@ public partial class MainViewModel : ObservableObject if (modbusConnected) { _logger.LogInfo("Modbus TCP 设备连接成功"); + + // 从设备读取初始配置参数 + await LoadDeviceParametersAsync(); } else { - _logger.LogWarning("Modbus TCP 设备连接失败,系统将继续运行但设备控制功能可能不可用"); + _logger.LogWarning("Modbus TCP 设备连接失败,使用默认配置"); + LoadDefaultParameters(); } // 连接 MQTT @@ -252,6 +275,94 @@ public partial class MainViewModel : ObservableObject } } + /// + /// 从 Modbus 设备读取系统参数 + /// + private async Task LoadDeviceParametersAsync() + { + try + { + _logger.LogInfo("正在从设备读取系统参数..."); + + // 读取时间参数(D404-D424,共11个寄存器) + var timeParams = await _modbusService.ReadHoldingRegistersAsync(404, 11); + + FirstSprayWaterTime = timeParams[0]; // D404 首次喷水时间 + AfterShampoo1SprayTime = timeParams[1]; // D406 沐浴1后喷水时间 + AfterShampoo2SprayTime = timeParams[2]; // D408 沐浴2后喷水时间 + AfterShampoo3SprayTime = timeParams[3]; // D410 沐浴3后喷水时间 + // D412 清洗笼子喷水(暂不使用) + SprayShampoo1Time = timeParams[5]; // D414 喷沐浴露1时间 + SprayShampoo2Time = timeParams[6]; // D416 喷沐浴露2时间 + SprayShampoo3Time = timeParams[7]; // D418 喷沐浴露3时间 + HotAirTime = timeParams[8]; // D420 吹热风时间 + ColdAirTime = timeParams[9]; // D422 吹冷风时间 + UvSterilizationTime = timeParams[10]; // D424 紫外线杀菌时间 + + _logger.LogInfo($"时间参数读取成功 - 首次喷水:{FirstSprayWaterTime}min, 沐浴1后:{AfterShampoo1SprayTime}min, " + + $"沐浴2后:{AfterShampoo2SprayTime}min, 沐浴3后:{AfterShampoo3SprayTime}min, " + + $"喷沐浴露1:{SprayShampoo1Time}min, 喷沐浴露2:{SprayShampoo2Time}min, 喷沐浴露3:{SprayShampoo3Time}min, " + + $"热风:{HotAirTime}min, 冷风:{ColdAirTime}min, 紫外线:{UvSterilizationTime}min"); + + // 读取液位参数 + await LoadLiquidLevelsAsync(); + + StatusMessage = "设备参数加载成功"; + } + catch (Exception ex) + { + _logger.LogError("读取设备参数失败,使用默认配置", ex); + LoadDefaultParameters(); + StatusMessage = "设备参数读取失败,使用默认配置"; + } + } + + /// + /// 读取液位传感器数据 + /// + private async Task LoadLiquidLevelsAsync() + { + try + { + // 读取1号液位 (D1280) + var level1 = await _modbusService.ReadHoldingRegistersAsync(1280, 1); + Shampoo1Level = level1[0]; + + // 读取2号液位 (D1330) + var level2 = await _modbusService.ReadHoldingRegistersAsync(1330, 1); + Shampoo2Level = level2[0]; + + // 读取3号液位 (D1380) + var level3 = await _modbusService.ReadHoldingRegistersAsync(1380, 1); + Shampoo3Level = level3[0]; + + _logger.LogInfo($"液位读取成功 - 1号:{Shampoo1Level}%, 2号:{Shampoo2Level}%, 3号:{Shampoo3Level}%"); + } + catch (Exception ex) + { + _logger.LogError("读取液位失败", ex); + } + } + + /// + /// 加载默认参数 + /// + private void LoadDefaultParameters() + { + FirstSprayWaterTime = _config.FirstSprayWaterTime; + AfterShampoo1SprayTime = _config.AfterShampoo1SprayTime; + AfterShampoo2SprayTime = _config.AfterShampoo2SprayTime; + AfterShampoo3SprayTime = _config.AfterShampoo3SprayTime; + SprayShampoo1Time = _config.SprayShampoo1Time; + SprayShampoo2Time = _config.SprayShampoo2Time; + SprayShampoo3Time = _config.SprayShampoo3Time; + ColdAirTime = _config.ColdAirTime; + HotAirTime = _config.HotAirTime; + UvSterilizationTime = _config.UvSterilizationTime; + + _logger.LogInfo("已加载默认参数配置"); + } + [RelayCommand] private async Task LoadPackagesAsync() { @@ -323,11 +434,13 @@ public partial class MainViewModel : ObservableObject } [RelayCommand] - private void SaveSettings() + private async Task SaveSettingsAsync() { try { - // 更新配置 + StatusMessage = "正在保存参数..."; + + // 更新本地配置 _config.FirstSprayWaterTime = FirstSprayWaterTime; _config.AfterShampoo1SprayTime = AfterShampoo1SprayTime; _config.AfterShampoo2SprayTime = AfterShampoo2SprayTime; @@ -339,17 +452,68 @@ public partial class MainViewModel : ObservableObject _config.HotAirTime = HotAirTime; _config.UvSterilizationTime = UvSterilizationTime; - _logger.LogInfo($"系统参数已保存 - 首次喷水:{FirstSprayWaterTime}min, 沐浴1后喷水:{AfterShampoo1SprayTime}min, 沐浴2后喷水:{AfterShampoo2SprayTime}min, 沐浴3后喷水:{AfterShampoo3SprayTime}min, 喷沐浴露1:{SprayShampoo1Time}min, 喷沐浴露2:{SprayShampoo2Time}min, 喷沐浴露3:{SprayShampoo3Time}min, 冷风:{ColdAirTime}min, 热风:{HotAirTime}min, 紫外线杀菌:{UvSterilizationTime}min"); + _logger.LogInfo($"本地参数已更新 - 首次喷水:{FirstSprayWaterTime}min, 沐浴1后:{AfterShampoo1SprayTime}min, " + + $"沐浴2后:{AfterShampoo2SprayTime}min, 沐浴3后:{AfterShampoo3SprayTime}min, " + + $"喷沐浴露1:{SprayShampoo1Time}min, 喷沐浴露2:{SprayShampoo2Time}min, 喷沐浴露3:{SprayShampoo3Time}min, " + + $"冷风:{ColdAirTime}min, 热风:{HotAirTime}min, 紫外线:{UvSterilizationTime}min"); - MessageBox.Show("系统参数保存成功!", "成功", MessageBoxButton.OK, MessageBoxImage.Information); + // 如果 Modbus 已连接,写入设备 + if (IsModbusConnected) + { + await SaveParametersToDeviceAsync(); + MessageBox.Show("系统参数已保存到设备!", "成功", MessageBoxButton.OK, MessageBoxImage.Information); + StatusMessage = "参数保存成功"; + } + else + { + MessageBox.Show("系统参数已保存到本地配置!\n\n注意:设备未连接,参数未写入设备。", + "保存成功", MessageBoxButton.OK, MessageBoxImage.Warning); + StatusMessage = "参数已保存(仅本地)"; + } } catch (Exception ex) { _logger.LogError("保存系统参数失败", ex); + StatusMessage = "参数保存失败"; MessageBox.Show($"保存失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } + /// + /// 将参数保存到 Modbus 设备 + /// + private async Task SaveParametersToDeviceAsync() + { + try + { + _logger.LogInfo("正在将参数写入设备..."); + + // 准备时间参数数据(D404-D424,共11个寄存器) + ushort[] timeParams = new ushort[11]; + timeParams[0] = (ushort)FirstSprayWaterTime; // D404 首次喷水时间 + timeParams[1] = (ushort)AfterShampoo1SprayTime; // D406 沐浴1后喷水时间 + timeParams[2] = (ushort)AfterShampoo2SprayTime; // D408 沐浴2后喷水时间 + timeParams[3] = (ushort)AfterShampoo3SprayTime; // D410 沐浴3后喷水时间 + timeParams[4] = 0; // D412 清洗笼子喷水(保留) + timeParams[5] = (ushort)SprayShampoo1Time; // D414 喷沐浴露1时间 + timeParams[6] = (ushort)SprayShampoo2Time; // D416 喷沐浴露2时间 + timeParams[7] = (ushort)SprayShampoo3Time; // D418 喷沐浴露3时间 + timeParams[8] = (ushort)HotAirTime; // D420 吹热风时间 + timeParams[9] = (ushort)ColdAirTime; // D422 吹冷风时间 + timeParams[10] = (ushort)UvSterilizationTime; // D424 紫外线杀菌时间 + + // 写入设备 + await _modbusService.WriteMultipleRegistersAsync(404, timeParams); + + _logger.LogInfo("参数已成功写入设备"); + } + catch (Exception ex) + { + _logger.LogError("写入设备参数失败", ex); + throw new Exception($"写入设备失败: {ex.Message}", ex); + } + } + // 参数调整命令 [RelayCommand] private void IncreaseFirstSprayWater() => FirstSprayWaterTime = Math.Min(FirstSprayWaterTime + 1, 60);