diff --git a/PetWash.Api/petwash.db b/PetWash.Api/petwash.db index 99322d5..78b26c0 100644 Binary files a/PetWash.Api/petwash.db and b/PetWash.Api/petwash.db differ diff --git a/PetWashControl/Services/ModbusService.cs b/PetWashControl/Services/ModbusService.cs index 5572a42..ab32329 100644 --- a/PetWashControl/Services/ModbusService.cs +++ b/PetWashControl/Services/ModbusService.cs @@ -551,4 +551,90 @@ public class ModbusService : IDisposable } #endregion + + #region 复归型按钮控制方法 + + /// + /// 触发关闭门并开始洗护按钮 M80(复归型) + /// M80 是复归型按钮,需要写入脉冲信号:true → 延迟 → false + /// + public async Task TriggerStartWashAsync() + { + try + { + if (_modbusMaster != null && _isConnected) + { + const ushort START_WASH_BUTTON_ADDRESS = 80; // M80 复归型按钮 + _logger.LogInfo($"[Modbus] 触发关闭门并开始洗护按钮 M{START_WASH_BUTTON_ADDRESS}"); + + // 写入 true(触发) + await WriteSingleCoilAsync(START_WASH_BUTTON_ADDRESS, true); + _logger.LogInfo($"[Modbus] M{START_WASH_BUTTON_ADDRESS} = true"); + + // 延迟 100ms + await Task.Delay(100); + + // 写入 false(复位) + await WriteSingleCoilAsync(START_WASH_BUTTON_ADDRESS, false); + _logger.LogInfo($"[Modbus] M{START_WASH_BUTTON_ADDRESS} = false"); + + // 延迟 100ms 确保 PLC 处理完成 + await Task.Delay(100); + + _logger.LogInfo($"[Modbus] M{START_WASH_BUTTON_ADDRESS} 脉冲信号发送完成"); + } + else + { + throw new InvalidOperationException("Modbus 未连接"); + } + } + catch (Exception ex) + { + _logger.LogError($"触发关闭门并开始洗护失败: {ex.Message}", ex); + throw; + } + } + + /// + /// 触发紧急停止按钮 M83(复归型) + /// M83 是复归型按钮,需要写入脉冲信号:true → 延迟 → false + /// + public async Task TriggerEmergencyStopAsync() + { + try + { + if (_modbusMaster != null && _isConnected) + { + const ushort EMERGENCY_STOP_BUTTON_ADDRESS = 83; // M83 复归型按钮 + _logger.LogInfo($"[Modbus] 触发紧急停止按钮 M{EMERGENCY_STOP_BUTTON_ADDRESS}"); + + // 写入 true(触发) + await WriteSingleCoilAsync(EMERGENCY_STOP_BUTTON_ADDRESS, true); + _logger.LogInfo($"[Modbus] M{EMERGENCY_STOP_BUTTON_ADDRESS} = true"); + + // 延迟 100ms + await Task.Delay(100); + + // 写入 false(复位) + await WriteSingleCoilAsync(EMERGENCY_STOP_BUTTON_ADDRESS, false); + _logger.LogInfo($"[Modbus] M{EMERGENCY_STOP_BUTTON_ADDRESS} = false"); + + // 延迟 100ms 确保 PLC 处理完成 + await Task.Delay(100); + + _logger.LogInfo($"[Modbus] M{EMERGENCY_STOP_BUTTON_ADDRESS} 脉冲信号发送完成"); + } + else + { + throw new InvalidOperationException("Modbus 未连接"); + } + } + catch (Exception ex) + { + _logger.LogError($"触发紧急停止失败: {ex.Message}", ex); + throw; + } + } + + #endregion } diff --git a/PetWashControl/ViewModels/MainViewModel.cs b/PetWashControl/ViewModels/MainViewModel.cs index 8d9ff38..de96ed3 100644 --- a/PetWashControl/ViewModels/MainViewModel.cs +++ b/PetWashControl/ViewModels/MainViewModel.cs @@ -758,7 +758,10 @@ public partial class MainViewModel : ObservableObject try { - _logger.LogInfo($"关门,订单ID: {CurrentOrder.Id}"); + _logger.LogInfo($"关门并开始洗护,订单ID: {CurrentOrder.Id}"); + + // 触发 Modbus M80 复归型按钮 + await _modbusService.TriggerStartWashAsync(); // 通过MQTT发送关门状态 await _mqttService.PublishAsync("device/status", new @@ -794,6 +797,42 @@ public partial class MainViewModel : ObservableObject } } + [RelayCommand] + private async Task EmergencyStopAsync() + { + try + { + _logger.LogInfo("触发紧急停止"); + + // 触发 Modbus M83 复归型按钮 + await _modbusService.TriggerEmergencyStopAsync(); + + // 停止洗护流程 + IsWashing = false; + + // 通过MQTT发送紧急停止状态 + await _mqttService.PublishAsync("device/status", new + { + status = "emergency_stop", + orderId = CurrentOrder?.Id, + timestamp = DateTime.Now + }); + + StatusMessage = "紧急停止已触发"; + _logger.LogInfo("紧急停止执行成功"); + + MessageBox.Show("紧急停止已触发!\n\n设备已停止运行", + "紧急停止", MessageBoxButton.OK, MessageBoxImage.Warning); + } + catch (Exception ex) + { + _logger.LogError("紧急停止失败", ex); + StatusMessage = $"紧急停止失败: {ex.Message}"; + MessageBox.Show($"紧急停止失败\n\n{ex.Message}", "错误", + MessageBoxButton.OK, MessageBoxImage.Error); + } + } + private async Task SimulateWashingProcessAsync() { try diff --git a/PetWashControl/Views/MainWindow.xaml b/PetWashControl/Views/MainWindow.xaml index 0e968ed..7a17411 100644 --- a/PetWashControl/Views/MainWindow.xaml +++ b/PetWashControl/Views/MainWindow.xaml @@ -1337,7 +1337,8 @@ Foreground="White" BorderThickness="0" Margin="0,20,0,0" - Cursor="Hand"> + Cursor="Hand" + Command="{Binding EmergencyStopCommand}">