using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using TeamAAS.Communication.Interfaces; namespace TeamAAS.Communication.LightSources { /// /// 光源控制器 - 整合串口通信与光源协议,提供 KCS/TSD 光源的统一控制接口 /// public class LightSourceController : IDisposable { private ICommunication _comm; private readonly LightModel _model; private readonly int _channelCount; public string Name { get; set; } = "光源"; public bool IsConnected => _comm?.IsConnected ?? false; public LightModel Model => _model; public int ChannelCount => _channelCount; /// /// 当前各通道亮度值 (0-255) /// public Dictionary ChannelBrightness { get; } = new Dictionary(); public event Action LogMessage; public LightSourceController(LightModel model, int channelCount) { _model = model; _channelCount = channelCount; for (int i = 0; i < channelCount; i++) ChannelBrightness[i] = 0; } public void AttachCommunication(ICommunication comm) { _comm = comm; } public async Task ConnectAsync() { if (_comm == null) { Log("未绑定通讯设备"); return false; } try { if (!_comm.IsConnected) await _comm.ConnectAsync(); Log($"已连接 ({_comm.Name})"); return true; } catch (Exception ex) { Log($"连接失败: {ex.Message}"); return false; } } public void Disconnect() { try { _comm?.Disconnect(); } catch { } Log("已断开"); } public async Task SetBrightnessAsync(int channel, int brightness, int timeoutMs = 1000) { if (channel < 1 || channel > _channelCount) { Log($"CH口超出范围: {channel}"); return false; } if (brightness < 0) brightness = 0; if (brightness > 255) brightness = 255; int idx = channel - 1; bool ok; switch (_model) { case LightModel.TSD_DPA12024V_4T_3_0: { string tsCmd = TSDLightProtocol.BuildSetBrightnessCommand(idx, brightness); var resp1 = await SendAndWaitAsync(tsCmd, timeoutMs); ok = TSDLightProtocol.VerifyResponse(resp1); } break; default: { string kcsCmd = KCSLightProtocol.BuildSetBrightnessCommand(idx, brightness); var resp2 = await SendAndWaitAsync(kcsCmd, timeoutMs); ok = KCSLightProtocol.VerifySetResponse(resp2, idx); } break; } if (ok) { ChannelBrightness[idx] = brightness; Log($"CH{channel} → {brightness} ✓"); } else { Log($"CH{channel} → {brightness} ✗ (超时或无响应)"); } return ok; } public async Task TurnOnAllAsync(int timeoutMs = 1000) { bool allOk = true; switch (_model) { case LightModel.TSD_DPA12024V_4T_3_0: foreach (string tsCmd in TSDLightProtocol.BuildTurnOnAllCommands(_channelCount)) { var resp = await SendAndWaitAsync(tsCmd, timeoutMs); if (!TSDLightProtocol.VerifyResponse(resp)) allOk = false; } break; default: int br = ChannelBrightness.Values.FirstOrDefault(v => v > 0); if (br == 0) br = 120; string kcsCmd = KCSLightProtocol.BuildTurnOnAllCommand(_channelCount, br); var resp2 = await SendAndWaitAsync(kcsCmd, timeoutMs); allOk = KCSLightProtocol.VerifyAllResponse(resp2); break; } Log(allOk ? "全开 ✓" : "全开 ✗"); return allOk; } public async Task TurnOffAllAsync(int timeoutMs = 1000) { bool allOk = true; switch (_model) { case LightModel.TSD_DPA12024V_4T_3_0: foreach (string tsCmd in TSDLightProtocol.BuildTurnOffAllCommands(_channelCount)) { var resp = await SendAndWaitAsync(tsCmd, timeoutMs); if (!TSDLightProtocol.VerifyResponse(resp)) allOk = false; } break; default: string kcsCmd = KCSLightProtocol.BuildTurnOffAllCommand(_channelCount); var resp2 = await SendAndWaitAsync(kcsCmd, timeoutMs); allOk = KCSLightProtocol.VerifyAllResponse(resp2); break; } if (allOk) { for (int i = 0; i < _channelCount; i++) ChannelBrightness[i] = 0; } Log(allOk ? "全关 ✓" : "全关 ✗"); return allOk; } public async Task ReadBrightnessAsync(int channel, int timeoutMs = 1000) { if (channel < 1 || channel > _channelCount) return 0; int idx = channel - 1; int brightness; switch (_model) { case LightModel.TSD_DPA12024V_4T_3_0: { string tsCmd = TSDLightProtocol.BuildReadCommand(idx); var resp1 = await SendAndWaitAsync(tsCmd, timeoutMs); brightness = TSDLightProtocol.ParseReadResponse(resp1); } break; default: { bool useSR = _model == LightModel.KCS_KDC3_24V300W_8T; string kcsCmd = KCSLightProtocol.BuildReadCommand(idx, useSR); var resp2 = await SendAndWaitAsync(kcsCmd, timeoutMs); brightness = KCSLightProtocol.ParseReadResponse(resp2); } break; } ChannelBrightness[idx] = brightness; Log($"读CH{channel}: {brightness}"); return brightness; } private async Task SendAndWaitAsync(string command, int timeoutMs) { if (_comm == null || !_comm.IsConnected) return null; string response = null; var mre = new ManualResetEventSlim(false); Action handler = (s, msg) => { response = msg; mre.Set(); }; _comm.DataReceivedEvent += handler; try { _comm.WriteValue("", command); if (await Task.Run(() => mre.Wait(timeoutMs))) return response; } finally { _comm.DataReceivedEvent -= handler; } return null; } private void Log(string msg) { LogMessage?.Invoke($"[{_model}] {msg}"); } public void Dispose() { try { _comm?.Disconnect(); } catch { } } } }