using BPASmart.Model; using BPA.Helper; using BPA.Communication; using Microsoft.EntityFrameworkCore.Metadata.Conventions; using Communication; using System.Collections.Concurrent; using Newtonsoft.Json; namespace BPASmart.Server { internal class CommunicationServer : IServer { ConcurrentDictionary CommunicationDevices = new ConcurrentDictionary(); public void Init() { var tt = sizeof(bool); BPASmartClient.Message.MessageLog.GetInstance.ShowDebugLog("通讯模块初始化"); RedisHelper.GetInstance.ConnectAsync(); MqttInit(); Json.Data.CommunicationDevices.ToList()?.ForEach(item => { ThreadManage.GetInstance().Start(new Action(() => { switch (item.CommDevice) { case BPASmart.Model.ModbusRtu _modbusRtu: break; case BPASmart.Model.ModbusTcp _modbusTcp: BPA.Communication.ModbusTcp modbusTcpMaster = new BPA.Communication.ModbusTcp(); modbusTcpMaster.ConnectOk = new Action(() => { if (!CommunicationDevices.ContainsKey(item.DeviceName)) CommunicationDevices.TryAdd(item.DeviceName, modbusTcpMaster); ThreadManage.GetInstance().StartLong(new Action(() => { GetReadDataModels(item).ToList()?.ForEach(temp => { switch (temp.Key) { case EDataType.Bool: temp.Value?.ForEach(value => { var res = modbusTcpMaster.ReadBool(value.StartAddress.ToString(), value.Length); SetValue(res.Content, item.DeviceName, value, 1); }); break; case EDataType.Byte: break; case EDataType.Int: break; case EDataType.Word: temp.Value?.ForEach(value => { var res = modbusTcpMaster.ReadUshort(value.StartAddress.ToString(), value.Length); SetValue(res.Content, item.DeviceName, value, 1); }); break; case EDataType.Dint: break; case EDataType.Dword: temp.Value?.ForEach(value => { var res = modbusTcpMaster.ReadUint(value.StartAddress.ToString(), value.Length); SetValue(res.Content, item.DeviceName, value, 2); }); break; case EDataType.Float: temp.Value?.ForEach(value => { var res = modbusTcpMaster.ReadFloat(value.StartAddress.ToString(), value.Length); SetValue(res.Content, item.DeviceName, value, 2); }); break; default: break; } }); Thread.Sleep(100); }), $"{item.DeviceName} 设备数据采集"); var DeviceModel = item; }); modbusTcpMaster.IsReconnect = true; modbusTcpMaster.ModbusTcpConnect(_modbusTcp.IP, _modbusTcp.PortNum); break; case BPASmart.Model.Siemens _siemens: break; default: break; } }), $"{item.DeviceName} 初始化连接"); }); } ConcurrentQueue msg = new ConcurrentQueue(); private void MqttInit() { MqttHelper mqttHelper = new MqttHelper(); mqttHelper.Connect("admin", "fengyoufu067101!@#", "124.222.238.75", 61613, $"分布式上位机:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); mqttHelper.ConnectOk = new Action(() => { mqttHelper.Subscrib("DistributedHostComputer/Control"); ThreadManage.GetInstance().StartLong(new Action(() => { while (msg.Count > 0) { DeviceControl(); } Thread.Sleep(100); }), "MQTT 消息监听"); }); mqttHelper.MessageRecive = new Action((s) => { msg.Enqueue(s); }); } private void DeviceControl() { if (msg.TryDequeue(out string s)) { var res = JsonConvert.DeserializeObject(s); if (res != null) { res.PublishModels.ForEach(item => { if (CommunicationDevices.ContainsKey(item.DeviceName)) { switch (item.DataType) { case EDataType.Bool: CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToBoolean(item.Value)); break; case EDataType.Byte: CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToByte(item.Value)); break; case EDataType.Int: CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToInt16(item.Value)); break; case EDataType.Word: CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToUInt16(item.Value)); break; case EDataType.Dint: CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToInt32(item.Value)); break; case EDataType.Dword: CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToUInt32(item.Value)); break; case EDataType.Float: CommunicationDevices[item.DeviceName].Write(item.RealAddress, Convert.ToSingle(item.Value)); break; default: break; } } }); } } } private void SetValue(TArray[] arrays, string DeviceName, ReadDataModel readDataModel, ushort by) { if (arrays != null) { int index = Array.FindIndex(Json.Data.CommunicationDevices.ToArray(), p => p.DeviceName == DeviceName);//获取设备所在集合位置 if (index >= 0 && index < Json.Data.CommunicationDevices.Count) { var tempArray = Json.Data.CommunicationDevices.ElementAt(index).VarTableModels.ToArray(); for (int i = 0; i < arrays.Length; i++) { int varIndex = Array.FindIndex(tempArray, p => p.RealAddress == (readDataModel.StartAddress + (i * by)).ToString()); if (varIndex >= 0 && varIndex < tempArray.Length) { Json.Data.CommunicationDevices.ElementAt(index).VarTableModels.ElementAt(varIndex).CurrentValue = arrays[i].ToString(); } } var Devicename = Json.Data.CommunicationDevices[index].DeviceName; List reeisDataModels = new List(); Json.Data.CommunicationDevices[index].VarTableModels.ToList().ForEach(tempVar => { if (tempVar.VarName.Length > 0) { reeisDataModels.Add(new ReeisDataModel() { VarName = tempVar.VarName, VarVaule = tempVar.CurrentValue, DataType = (EDataType)Enum.Parse(typeof(EDataType), tempVar.DataType) }); } }); RedisHelper.GetInstance.SetValue($"{Devicename}", reeisDataModels); } } } private Dictionary> GetReadDataModels(CommunicationModel communicationModel) { Dictionary> readDataModels = new Dictionary>(); communicationModel.VarTableModels.GroupBy(p => p.DataType)?.ToList()?.ForEach(tempVar => { if (tempVar.Key != null && tempVar.Key.Length > 0) { //int address = tempVar.Min(p => p.RealAddress); EDataType dataType = (EDataType)Enum.Parse(typeof(EDataType), tempVar.Key); switch (dataType) { case EDataType.Bool: case EDataType.Byte: case EDataType.Int: case EDataType.Word: if (!readDataModels.ContainsKey(dataType)) readDataModels.TryAdd(dataType, GetDataGroup(tempVar)); break; case EDataType.Dint: case EDataType.Dword: case EDataType.Float: if (!readDataModels.ContainsKey(dataType)) readDataModels.TryAdd(dataType, GetDataGroup(tempVar, 2)); break; default: break; } } }); return readDataModels; } private List GetDataGroup(IGrouping variableInfos, int by = 1) { List ReturnValue = new List(); var res = variableInfos?.OrderBy(p => p.RealAddress).ToList(); List RealAddresss = new List(); variableInfos.ToList()?.ForEach(item => { if (int.TryParse(item.RealAddress, out int add)) RealAddresss.Add(add); }); int count = 0; if (res != null) { //int address = variableInfos.Min(p => p.RealAddress); int address = RealAddresss.Min(); int startAddress = address; for (int i = 0; i < res.Count; i++) { if (int.TryParse(res.ElementAt(i).RealAddress, out int TempAddress)) { if (TempAddress == address) { count++; address += by; } else { ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count }); count = 1; address = TempAddress + by; startAddress = TempAddress; } } } ReturnValue.Add(new ReadDataModel() { StartAddress = (ushort)startAddress, Length = (ushort)count }); } return ReturnValue; } } }