using Aitex.Core.Common.DeviceData; using Aitex.Core.RT.Device; using Aitex.Core.RT.Log; using Aitex.Core.RT.SCCore; using Aitex.Core.RT.Tolerance; using Aitex.Core.Util; using MECF.Framework.Common.Communications; using MECF.Framework.Common.Equipment; using MECF.Framework.Common.Utilities; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using static Mono.Security.X509.X520; using Venus_Core; using System.Diagnostics; namespace Venus_RT.Devices { /// /// 描述:该类用于对单Chiller Controller下多设备共享 的驱动 只单一的用于串口的连接 /// 需要存储的变量及说明 /// Statusflag:与chiller的开关有关 /// Alarmflag: 报警 /// chillerIsOn:正在进行 /// ControlTcFeedback:返回值 /// public class SMCChillerDrive { public SMCChillerState StatusSMC { get; set; } private readonly string _PortNum = "COM92"; private readonly AsyncSerialPort _serial; BlockingCollection blockingCollection = new BlockingCollection(); public string PortName => _PortNum; private Dictionary _address2Module;//不正确 应该以字典的形式 以头去打印 private Dictionary _addressQuery; private ModuleName Module;//不正确 应该以字典的形式 以头去打印 // --------------------------Constructor----------------------- // public SMCChillerDrive(string Port) { _PortNum = Port; StatusSMC = SMCChillerState.Unknown; _serial = new AsyncSerialPort(_PortNum, 9600, 7, System.IO.Ports.Parity.Even, System.IO.Ports.StopBits.One, "\r\n", true); if (!_serial.Open()) { StatusSMC = SMCChillerState.Disconnected; LOG.Write(eEvent.ERR_DEVICE_CHILLER, ModuleName.System, $"SMC Chiller串口:{_PortNum}无法打开"); } StatusSMC = SMCChillerState.Connected; _serial.OnDataChanged += OnPortDataChanged; _serial.OnErrorHappened += OnErrorOccurred; _address2Module = new Dictionary(); _addressQuery = new Dictionary(); Task.Run(() => { foreach (var data in blockingCollection.GetConsumingEnumerable()) { _serial?.Write(data); System.Threading.Thread.Sleep(500); } }); } private void OnPortDataChanged(string obj) { try { if (SC.GetValue("System.IsSimulatorMode")) { //Statusflag[0] = true; //if (_controlTcSetPoint <= SetPointLimitMax / 2 && _controlTcSetPoint >= SetPointLimitMin) // _controlTcFeedback = _controlTcSetPoint; return; } if (string.IsNullOrEmpty(obj)) { LOG.Write(eEvent.ERR_DEVICE_CHILLER, ModuleName.System, $"[{_PortNum}] smc chiller message IsNullOrEmpty"); return; } string cmd = obj.Split(new char[] { '\r', '\n' })[0]; //注意 数据开头有":" //地址位 决定了是哪个chamber的哪个type ChillerData chillerData = null; ModuleName module = ModuleName.System; if (_address2Module.ContainsKey(cmd.Substring(1, 2)) && _addressQuery.ContainsKey(cmd.Substring(1, 2))) { _addressQuery[cmd.Substring(1, 2)] = chillerData; module = ModuleHelper.Converter(_address2Module[cmd.Substring(1, 2)].Split('.')[0]); } else { LOG.Write(eEvent.ERR_DEVICE_CHILLER, ModuleName.System, $"[{_PortNum}]:address => {cmd.Substring(1, 2)} not in Dictionary"); return; } //若为system或null 说明dic中无value或value无效 Debug.Assert(chillerData != null && module != ModuleName.System); if (ModbusUtility.CalculateLrc(ModbusUtility.HexToBytes(cmd.Substring(1, cmd.Length - 3))).ToString("X2") != cmd.Substring(cmd.Length - 2)) //LRC check { LOG.Write(eEvent.ERR_DEVICE_CHILLER, Module, $"[{_PortNum}] smc chiller message LRC check error"); return; } switch (cmd.Substring(3, 2)) //function code { case "03": //返回的寄存器内容 if (cmd.Substring(5, 2) == "16") //返回了全部11个寄存器、22个Byte数据 { for (int iRegisterNo = 0; iRegisterNo < 11; iRegisterNo++) { string sBuf = cmd.Substring(4 * iRegisterNo + 7, 4); int iBuf = 0; for (int i = 3; i > -1; i--) { iBuf += Convert.ToInt32(sBuf.Substring(i, 1), 16) * (int)Math.Pow(16, 3 - i); } switch (iRegisterNo) { case 0: //Circulating fluid discharge temperature chillerData.ControlTcFeedback = (float)iBuf / 10; break; case 4: //Status flag 1 for (int i = 0; i < 16; i++) { chillerData.Statusflag[i] = Convert.ToBoolean((int)Math.Pow(2, i) & iBuf); } break; case 5: //Alarm flag 1 for (int i = 0; i < 16; i++) { chillerData.Alarmflag[i] = Convert.ToBoolean((int)Math.Pow(2, i) & iBuf); } break; case 6: //Alarm flag 2 for (int i = 0; i < 16; i++) { chillerData.Alarmflag[i + 16] = Convert.ToBoolean((int)Math.Pow(2, i) & iBuf); } break; case 7: //Alarm flag 3 for (int i = 0; i < 16; i++) { chillerData.Alarmflag[i + 32] = Convert.ToBoolean((int)Math.Pow(2, i) & iBuf); } break; case 9: //Status flag 2 for (int i = 0; i < 16; i++) { chillerData.Statusflag[i + 16] = Convert.ToBoolean((int)Math.Pow(2, i) & iBuf); } break; } } } _addressQuery[cmd.Substring(1, 2)] = chillerData; break; case "06": //寄存器的写成功消息 break; } } catch (Exception ex) { LOG.Write(eEvent.ERR_DEVICE_CHILLER, ModuleName.System, $"[{_PortNum}] smc chiller error: [{ex.Message}]"); } } private void OnErrorOccurred(string obj) { StatusSMC = SMCChillerState.ERROR; LOG.Write(eEvent.ERR_DEVICE_CHILLER, ModuleName.System, $"[{_PortNum}] smc chiller error: [{obj}]"); } public void SendCmd(string str) { //if (Module == "PMB" && SC.GetValue($"PMB.Chiller.ChillerSameWithPMA") && SC.GetValue($"PMB.Chiller.EnableChiller")) return; //消息通用格式:开头 + 内容 + LRC + 结尾 //_serial?.Write(":" + str + ModbusUtility.CalculateLrc(ModbusUtility.HexToBytes(str)).ToString("X2") + "\r\n"); blockingCollection.Add(":" + str + ModbusUtility.CalculateLrc(ModbusUtility.HexToBytes(str)).ToString("X2") + "\r\n"); } public void AddAddress(string address, string chillertype) { //address => "02" chillertype => PMA.OutChiller _address2Module.Add(address,chillertype); _addressQuery.Add(address, new ChillerData()); } public ChillerData QueryData(string address) { if (_addressQuery.ContainsKey(address)) { return _addressQuery[address]; } else { LOG.Write(eEvent.ERR_DEVICE_CHILLER, ModuleName.System, $"[{_PortNum}] => address:{address} not exist"); return new ChillerData(); } } public void Terminate() { _serial?.Close(); } } public class ChillerData { public bool[] Statusflag {get; set;} public bool[] Alarmflag { get; set; } public float ControlTcFeedback { get; set; } public ChillerData() { Statusflag = new bool[32]; Alarmflag = new bool[48]; ControlTcFeedback = 0.0f; } } }