using System; using System.Collections; using HslCommunication; using HslCommunication.Core; using HslCommunication.ModBus; using HybirdFrameworkCore.Utils; using log4net; namespace HybirdFrameworkDriver.ModbusTcpMaster; public class ModbusTcpMaster { private static readonly ILog Log = LogManager.GetLogger(typeof(ModbusTcpMaster)); public string connectId { get; set; } // public string Ip { get; set; } = "127.0.0.1"; public string Ip { get; set; } = "192.168.1.5"; public int Port { get; set; } = 502; public static DataFormat DataFormat { get; set; } = DataFormat.ABCD; public int Duration { get; set; } = 1000; public bool Connected { get; set; } = false; public delegate void MyReadAction(ModbusTcpMaster str); public MyReadAction? ReadAction { get; set; } private bool StopFlag { get; set; } = false; public ModbusTcpNet ModbusTcpNet; ILog GetLog() { return Log; } public bool Connect() { GetLog().Info($"begin to connect {Ip}:{Port}"); try { if (ModbusTcpNet == null) { ModbusTcpNet = new ModbusTcpNet(Ip, Port); ModbusTcpNet.DataFormat = DataFormat; OperateResult result = ModbusTcpNet.ConnectServer(); if (result.IsSuccess) { Connected = true; GetLog().Info($"connect {Ip}:{Port} success"); StartListen(); } else { GetLog().Info($"connect {Ip}:{Port} failed {result.Message}"); } } } catch (Exception e) { GetLog().Error($"connect {Ip}:{Port} exception {e.Message}"); } return Connected; } public void StartListen() { StopListen(); StopFlag = false; Thread readThread = new Thread(ReadFunc) { IsBackground = true, Name = $"{Ip}:{Port}-reader-thread" }; readThread.Start(); } public void StopListen() { StopFlag = true; Thread.Sleep(500); } private void ReadFunc() { if (ReadAction != null) { while (!StopFlag) { try { ReadAction(this); Thread.Sleep(Duration); } catch (Exception e) { Log.Error(e); } } } GetLog().Info("stop listen"); } public byte[]? ReadRegister(int registerNo, int start, int length) { start = start % 16 == 0 ? start / 16 : start / 16 + 1; length = length % 8 == 0 ? length / 8 : length / 8 + 1; OperateResult result = ModbusTcpNet.Read("x=3;" + (registerNo + start), (ushort)length); if (result.IsSuccess) { return result.Content; } return null; } public byte[]? BatchRead(int registerNo, int length) { OperateResult result = ModbusTcpNet.Read("x=3;" + registerNo, (ushort)length); if (result.IsSuccess) { return result.Content; } return null; } public bool WriteValue(ModbusProperty property) { T value = property.Value; if (value == null) { GetLog().Warn($"write property{property.RegisterNo} null value"); return false; } bool result = false; ModbusDataType dataType = property.Type; int start = property.Start; int length = property.Length; int registerNo = property.RegisterNo - 40000; byte[] setValue = BitUtls.Value2Bytes(value, property.Scale, property.Offset); OperateResult operateResult; switch (dataType) { case ModbusDataType.Register: if (setValue.Length < length * 2) { //byte 需要读取寄存器中的内容 if (typeof(T) == typeof(byte)) { OperateResult readResultRegister = ModbusTcpNet.Read("x=3;" + (registerNo), 1); if (readResultRegister.IsSuccess) { switch (DataFormat) { case DataFormat.ABCD: readResultRegister.Content[1] = setValue[0]; break; case DataFormat.BADC: readResultRegister.Content[0] = setValue[0]; break; } operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), readResultRegister.Content); result = operateResult.IsSuccess; } } //其他类型 String 占用几个寄存器 直接补0 else { byte[] preWriteCont = new byte[length * 2]; switch (DataFormat) { case DataFormat.ABCD: for (int i = 0; i < setValue.Length; i++) { if (i % 2 == 0) preWriteCont[i + 1] = setValue[i]; else preWriteCont[i - 1] = setValue[i]; } break; case DataFormat.BADC: Array.Copy(setValue, preWriteCont, setValue.Length); break; } operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), preWriteCont); result = operateResult.IsSuccess; } } else if (setValue.Length == length * 2) { byte[] preWriteCont = new byte[setValue.Length]; switch (DataFormat) { case DataFormat.ABCD: for (int i = 0; i < setValue.Length; i++) { if (i % 2 == 0) preWriteCont[i + 1] = setValue[i]; else preWriteCont[i - 1] = setValue[i]; } break; case DataFormat.BADC: //Array.Copy(setValue, preWriteCont, setValue.Length); break; } operateResult = ModbusTcpNet.Write("x=16;" + (registerNo), preWriteCont); result = operateResult.IsSuccess; } break; case ModbusDataType.Bit: result = WriteRegisterOneBit(registerNo, start, Convert.ToBoolean(value)); break; } return result; } /// /// 写寄存器中的一个bit /// /// /// /// /// public bool WriteRegisterOneBit(int addr, int location, bool boolResult) { if (!Connected) return false; bool result = false; ushort registerValue1 = 0x1234; ushort mask = 0x1234; OperateResult readResult = ModbusTcpNet.Read("x=3;" + addr.ToString(), 1); if (readResult.IsSuccess) { if (location >= 0 && location <= 15) { registerValue1 = ModbusTcpNet.ByteTransform.TransUInt16(readResult.Content, 0); if (boolResult) { mask = (ushort)(1 << location); registerValue1 |= mask; } else { mask = (ushort)(~(1 << location)); registerValue1 &= mask; } OperateResult writeResult = ModbusTcpNet.Write("x=6;" + addr, registerValue1); if (writeResult.IsSuccess) { result = true; } } } return result; } }