From e23581192976d1b1dd0af67809e0ba89fe629f03 Mon Sep 17 00:00:00 2001 From: ccongli <1441652193@qq.com> Date: Mon, 4 Sep 2023 18:33:57 +0800 Subject: [PATCH] =?UTF-8?q?Data=E6=A8=A1=E5=9D=97=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=87=87=E9=9B=86=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E5=BC=80?= =?UTF-8?q?=E5=8F=91v3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vol-net6/VOL.Core/Utils/CommonUtil.cs | 41 +++ vol-net6/VOL.Core/Utils/DataConvertUtil.cs | 304 ++++++++++++++++++ .../IServices/modbus/IModbusService.cs | 21 ++ .../Services/modbus/ModbusTcpService.cs | 76 +++++ .../Controllers/Data/DataCaptureController.cs | 2 +- .../Controllers/Data/DataTestController.cs | 169 +++++++++- vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs | 9 +- 7 files changed, 601 insertions(+), 21 deletions(-) create mode 100644 vol-net6/VOL.Core/Utils/CommonUtil.cs create mode 100644 vol-net6/VOL.Core/Utils/DataConvertUtil.cs diff --git a/vol-net6/VOL.Core/Utils/CommonUtil.cs b/vol-net6/VOL.Core/Utils/CommonUtil.cs new file mode 100644 index 0000000..202771c --- /dev/null +++ b/vol-net6/VOL.Core/Utils/CommonUtil.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; + +namespace VOL.Core.Utils +{ + public class CommonUtil + { + // 实体对象转Dictionary + + public static Dictionary ConvertToDictionary(T entity) + { + var dictionary = new Dictionary(); + var properties = typeof(T).GetProperties(); + + foreach (var property in properties) + { + var key = property.Name; + var value = property.GetValue(entity); + dictionary.Add(key, value); + } + + return dictionary; + } + + // Dictionary转实体对象 + public static T ConvertToObject(Dictionary dictionary) where T : new() + { + var obj = new T(); + var properties = typeof(T).GetProperties(); + + foreach (var property in properties) + { + if (dictionary.TryGetValue(property.Name, out var value)) + { + property.SetValue(obj, value); + } + } + + return obj; + } + } +} diff --git a/vol-net6/VOL.Core/Utils/DataConvertUtil.cs b/vol-net6/VOL.Core/Utils/DataConvertUtil.cs new file mode 100644 index 0000000..1b8723c --- /dev/null +++ b/vol-net6/VOL.Core/Utils/DataConvertUtil.cs @@ -0,0 +1,304 @@ +using System.Text; +using System; + +namespace VOL.Core.Utils +{ + public class DataConvertUtil + { + /// + /// 赋值string string => ushort[] + /// + /// + /// + /// + /// + public static void SetString(ushort[] src, int start, string value) + { + byte[] bytesTemp = Encoding.UTF8.GetBytes(value); + ushort[] dest = Bytes2Ushorts(bytesTemp); + dest.CopyTo(src, start); + } + + /// + /// 获取string ushort[] => string + /// + /// + /// + /// + /// string + public static string GetString(ushort[] src, int start, int len) + { + ushort[] temp = new ushort[len]; + for (int i = 0; i < len; i++) + { + temp[i] = src[i + start]; + } + byte[] bytesTemp = Ushorts2Bytes(temp); + //string res = Encoding.UTF8.GetString(bytesTemp).Trim(new char[] { '\0' }); // 去除字符串左右端的指定内容 + string res = Encoding.UTF8.GetString(bytesTemp).Trim(); + return res; + } + + /// + /// 赋值Real float => ushort[] + /// + /// + /// + /// + public static void SetReal(ushort[] src, int start, float value) + { + byte[] bytes = BitConverter.GetBytes(value); + + ushort[] dest = Bytes2Ushorts(bytes); + + dest.CopyTo(src, start); + } + + /// + /// 获取float ushort[] => float + /// + /// + /// + /// float + public static float GetReal(ushort[] src, int start) + { + try + { + ushort[] temp = new ushort[2]; + for (int i = 0; i < 2; i++) + { + temp[i] = src[i + start]; + } + byte[] bytesTemp = Ushorts2Bytes(temp,false); + //Array.Reverse(bytesTemp); + // !!!BitConverter默认是小端转换,如果是大端字节顺序存放,需要先反序字节顺序 + float res = BitConverter.ToSingle(bytesTemp, 0); + return res; + } catch (Exception e) + { + return 0; + } + + } + + /// + /// 赋值Short short => ushort[] + /// + /// + /// + /// + public static void SetShort(ushort[] src, int start, short value) + { + byte[] bytes = BitConverter.GetBytes(value); + + ushort[] dest = Bytes2Ushorts(bytes); + + dest.CopyTo(src, start); + } + + /// + /// 获取short ushort[] => short + /// + /// + /// + /// short + public static short GetShort(ushort[] src, int start) + { + try + { + ushort[] temp = new ushort[1]; + temp[0] = src[start]; + byte[] bytesTemp = Ushorts2Bytes(temp); + short res = BitConverter.ToInt16(bytesTemp, 0); + return res; + } + catch (Exception e) + { + return 0; + } + + } + + /// + /// 赋值Short short => ushort[] + /// + /// + /// + /// + public static void SetInt(ushort[] src, int start, int value) + { + byte[] bytes = BitConverter.GetBytes(value); + + ushort[] dest = Bytes2Ushorts(bytes); + + dest.CopyTo(src, start); + } + + + /// + /// 获取short ushort[] => int + /// + /// + /// + /// short + public static int GetInt(ushort[] src, int start) + { + try { + ushort[] temp = new ushort[2]; + temp[0] = src[start]; + temp[1] = src[start + 1]; // 0 100 + byte[] bytesTemp = Ushorts2Bytes(temp); + int res = BitConverter.ToInt32(bytesTemp, 0); + return res; + } catch (Exception e) + { + return 0; + } + + } + + + /// + /// 获取short ushort[] => long + /// + /// + /// + /// short + public static long GetLong(ushort[] src, int start) + { + try { + ushort[] temp = new ushort[4]; + temp[0] = src[start]; + temp[1] = src[start + 1]; + temp[2] = src[start + 2]; + temp[3] = src[start + 3]; + byte[] bytesTemp = Ushorts2Bytes(temp); + long res = BitConverter.ToInt64(bytesTemp, 0); + return res; + } catch (Exception e) + { + return 0; + } + + } + + + + /// + /// 获取bool数组 ushort[] => bool[] + /// + /// + /// + /// short + + public static bool[] GetBools(ushort[] src, int start, int num) + { + ushort[] temp = new ushort[num]; + for (int i = start; i < start + num; i++) + { + temp[i] = src[i + start]; + } // 0 1 0 1 0 0 0 0 默认小端模式 + //Array.Reverse(temp); // 0 0 0 0 1 0 1 0 + byte[] bytes = Ushorts2Bytes(temp); + bool[] res = Bytes2Bools(bytes); + return res; + } + + + // byte[] => bool[] + private static bool[] Bytes2Bools(byte[] b) + { + bool[] array = new bool[8 * b.Length]; + + for (int i = 0; i < b.Length; i++) + { + for (int j = 0; j < 8; j++) + { + array[i * 8 + j] = (b[i] & 1) == 1;//判定byte的最后一位是否为1,若为1,则是true;否则是false + b[i] = (byte)(b[i] >> 1);//将byte右移一位 + } + } + return array; + } + + // bool[] => byte + private static byte Bools2Byte(bool[] array) + { + if (array != null && array.Length > 0) + { + byte b = 0; + for (int i = 0; i < 8; i++) + { + if (array[i]) + { + byte nn = (byte)(1 << i);//左移一位,相当于×2 + b += nn; + } + } + return b; + } + return 0; + } + + + // byte[] => ushort[] + private static ushort[] Bytes2Ushorts(byte[] src, bool reverse = false) + { + int len = src.Length; + + byte[] srcPlus = new byte[len + 1]; + src.CopyTo(srcPlus, 0); + int count = len >> 1; + + if (len % 2 != 0) + { + count += 1; + } + + ushort[] dest = new ushort[count]; + if (reverse) + { + for (int i = 0; i < count; i++) + { + dest[i] = (ushort)(srcPlus[i * 2] << 8 | srcPlus[2 * i + 1] & 0xff); + } + } + else + { + for (int i = 0; i < count; i++) + { + dest[i] = (ushort)(srcPlus[i * 2] & 0xff | srcPlus[2 * i + 1] << 8); + } + } + + return dest; + } + + + // ushort[] => byte[] + private static byte[] Ushorts2Bytes(ushort[] src, bool reverse = false) + { + + int count = src.Length; + byte[] dest = new byte[count << 1]; + if (reverse) // 大端 + { + for (int i = 0; i < count; i++) + { + dest[i * 2] = (byte)(src[i] >> 8); + dest[i * 2 + 1] = (byte)(src[i] >> 0); + } + } + else // 小端 + { + for (int i = 0; i < count; i++) + { + dest[i * 2] = (byte)(src[i] >> 0); + dest[i * 2 + 1] = (byte)(src[i] >> 8); + } + } + return dest; + } + } + +} diff --git a/vol-net6/VOL.Data/IServices/modbus/IModbusService.cs b/vol-net6/VOL.Data/IServices/modbus/IModbusService.cs index c032f89..ce3f407 100644 --- a/vol-net6/VOL.Data/IServices/modbus/IModbusService.cs +++ b/vol-net6/VOL.Data/IServices/modbus/IModbusService.cs @@ -21,5 +21,26 @@ namespace VOL.Data.IServices.modbus /// /// void disConnent(); + + /// + /// 从站地址 + /// 起始地址 + /// 数据 + /// 写数据 + /// + /// + + void writeData(byte slaveAddress, ushort startAddress, object data); + + + /// + /// 从站地址 + /// 起始地址 + /// 寄存器单元地址数 + /// 读数据 + /// + /// dynamic + + dynamic readData(byte slaveAddress, ushort startAddress, string type, int units = 1); } } diff --git a/vol-net6/VOL.Data/Services/modbus/ModbusTcpService.cs b/vol-net6/VOL.Data/Services/modbus/ModbusTcpService.cs index 1509b3d..5d1d7ef 100644 --- a/vol-net6/VOL.Data/Services/modbus/ModbusTcpService.cs +++ b/vol-net6/VOL.Data/Services/modbus/ModbusTcpService.cs @@ -1,6 +1,10 @@ using NModbus; using System.Net.Sockets; using VOL.Data.IServices.modbus; +using VOL.Core.Utils; +using VOL.Core.Extensions; +using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; namespace VOL.Data.Services.modbus { @@ -43,6 +47,78 @@ namespace VOL.Data.Services.modbus get => client.Connected; } + + // 写寄存器数据 + public void writeData(byte slaveAddress, ushort startAddress, object data) + { + var type = data.GetType().Name.ToLower(); + dynamic val ; + ushort[]? units; // 单元数 + switch (type) { + case "int16": + val = data.ToShort(); + units = new ushort[1]; + DataConvertUtil.SetShort(units, 0, val); + break; + case "int32": + val = data.ToInt(); + units = new ushort[2]; + DataConvertUtil.SetInt(units, 0, val); + break; + case "single": + val = data.ToFloat(); + units = new ushort[2]; + DataConvertUtil.SetReal(units, 0, val); + break; + case "string": + val = data.ToString(); + int length = (int) Math.Ceiling((double) val.Length / 2); + units = new ushort[length]; // 先不考虑中文字符,一个寄存器地址存放两个字符 + DataConvertUtil.SetString(units, 0, val); // units 25690 25690 + break; + default: + throw new ArgumentException("暂未实现写入此类型:"+ type); + } + if (units != null) { + this.WriteMultipleRegisters(slaveAddress, startAddress, units); + } + } + + + + // 读寄存器数据 + public dynamic readData(byte slaveAddress, ushort startAddress, string type, int units = 1) + { + type = type.ToLower(); + ushort[]? source; + dynamic? data = null; + switch (type) + { + case "int16": + source = this.ReadHoldingRegisters(slaveAddress, startAddress, 1); + data = DataConvertUtil.GetShort(source, 0); + break; + case "int32": + source = this.ReadHoldingRegisters(slaveAddress, startAddress, 2); + data = DataConvertUtil.GetInt(source, 0); + break; + case "single": + source = this.ReadHoldingRegisters(slaveAddress, startAddress, 2); + data = DataConvertUtil.GetReal(source, 0); + break; + case "string": + //units = val.Length * 2; // 先不考虑中文字符 + source = this.ReadHoldingRegisters(slaveAddress, startAddress, (ushort) units); // 25690 25690 0 0 + data = DataConvertUtil.GetString(source, 0, units); + break; + default: + throw new ArgumentException("暂未实现读取此类型:" + type); + } + return data; + } + + + // 读线圈 0x01 0x public bool[] ReadCoils(byte slaveAddress, ushort startAddress, ushort num) { diff --git a/vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs b/vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs index 15baa9d..788242b 100644 --- a/vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs +++ b/vol-net6/VOL.WebApi/Controllers/Data/DataCaptureController.cs @@ -40,7 +40,7 @@ namespace VOL.WebApi.Controllers.Data /// 采集西门子设备 /// /// IActionResult - //[ApiTask] + [ApiTask] [HttpGet, HttpPost, Route("gatherSiemens")] public IActionResult Collection() { diff --git a/vol-net6/VOL.WebApi/Controllers/Data/DataTestController.cs b/vol-net6/VOL.WebApi/Controllers/Data/DataTestController.cs index 4e627dc..f414979 100644 --- a/vol-net6/VOL.WebApi/Controllers/Data/DataTestController.cs +++ b/vol-net6/VOL.WebApi/Controllers/Data/DataTestController.cs @@ -8,6 +8,7 @@ using VOL.Data.Services.modbus; using Microsoft.Extensions.DependencyInjection; using VOL.WebApi.Utils; using VOL.Entity.DomainModels; +using OfficeOpenXml.FormulaParsing.Excel.Functions.Math; namespace VOL.WebApi.Controllers.Data { @@ -42,7 +43,8 @@ namespace VOL.WebApi.Controllers.Data { try { - _service = new ModbusTcpService("127.0.0.1", 502); + //_service = new ModbusTcpService("127.0.0.1", 502); + _service = new ModbusTcpService("192.168.0.99", 502); Console.WriteLine("master modbus tcp created..."); } catch (Exception) @@ -62,12 +64,18 @@ namespace VOL.WebApi.Controllers.Data { //Logger.Info("log info test..."); //Logger.Error("log info error..."); - Data_Device data_Device = new Data_Device(); - bool result = _dataService.saveDeviceData(data_Device, out string message); - Console.WriteLine(message); - Data_Produce data_Produce = new Data_Produce(); - bool result2 = _dataService.saveProduceData(data_Produce, out string message1); - Console.WriteLine(message1); + //Data_Device data_Device = new Data_Device(); + //bool result = _dataService.saveDeviceData(data_Device, out string message); + //Console.WriteLine(message); + //Data_Produce data_Produce = new Data_Produce(); + //bool result2 = _dataService.saveProduceData(data_Produce, out string message1); + //Console.WriteLine(message1); + _service = new ModbusTcpService("192.168.0.99", 502); + _service.writeData(1,0,(short)1); + _service.writeData(1,0,1); + _service.writeData(1,0,1F); + _service.writeData(1,0,"1234"); + return Content(DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss")); } @@ -139,6 +147,7 @@ namespace VOL.WebApi.Controllers.Data [HttpGet, HttpPost, Route("readTest")] public IActionResult Test01() { + _service = new ModbusTcpService("192.168.0.99", 502); if (_service.isConnected) { //Console.WriteLine("=========read0x========="); @@ -151,20 +160,54 @@ namespace VOL.WebApi.Controllers.Data //bool[] data1x = _service.ReadInputs(1, 0, 5); //Array.ForEach(data1x, Console.WriteLine); //Console.WriteLine("=========read1x========="); - + // 读取从0开始,文档上地址从1开始的,地址需要减1 Console.WriteLine("=========read4x========="); - ushort[] data4xs_int16 = _service.ReadHoldingRegisters(1, 8, 2); - short val = DataConvertUtil.GetShort(data4xs_int16, 1); + // int16 + ushort[] src0 = new ushort[1]; + DataConvertUtil.SetShort(src0, 0, 2); + _service.WriteMultipleRegisters(1, 6429, src0); + + ushort[] data4xs_int16 = _service.ReadHoldingRegisters(1, 6429, 1); // 运行状态 + short val = DataConvertUtil.GetShort(data4xs_int16, 0); Console.WriteLine(val); - ushort[] data4xs_int32 = _service.ReadHoldingRegisters(1, 1, 2); - int vval = DataConvertUtil.GetInt(data4xs_int32, 0); - Console.WriteLine(vval); + // 写 float + ushort[] src1 = new ushort[2]; + DataConvertUtil.SetReal(src1, 0, 3.14F); + _service.WriteMultipleRegisters(1, 1215, src1); + + // 读 float + ushort[] data4xs_float = _service.ReadHoldingRegisters(1, 1215, 2); // 加工数 + float fval = DataConvertUtil.GetReal(data4xs_float, 0); + Console.WriteLine(fval); + + //// string + //ushort[] data_strlen = _service.ReadHoldingRegisters(1, 6689, 1); + //short strlen = DataConvertUtil.GetShort(data_strlen, 0); + //Console.WriteLine(strlen); + + //// 6690程序号不可写, 为双引号 asill码为34 + //ushort[] src2 = new ushort[6]; + //DataConvertUtil.SetString(src1, 0, "123456"); + //_service.WriteMultipleRegisters(1, 6691, src2); + + //ushort[] data4xs_str = _service.ReadHoldingRegisters(1, 6690, 52); // 程序号 + //string str = DataConvertUtil.GetString(data4xs_str, 0, 52); + //Console.WriteLine(str); - ushort[] data4xs_int64 = _service.ReadHoldingRegisters(1, 4, 4); - long vvval = DataConvertUtil.GetLong(data4xs_int64, 0); - Console.WriteLine(vvval); Console.WriteLine("=========read4x========="); + //ushort[] data4xs_float = _service.ReadHoldingRegisters(1, 1200, 2); // 刀具长度补偿编号 + //float fval = DataConvertUtil.GetReal(data4xs_float, 0); + //Console.WriteLine(fval); + + //ushort[] data4xs_int32 = _service.ReadHoldingRegisters(1, 1, 2); // 电机温度 + //int vval = DataConvertUtil.GetInt(data4xs_int32, 0); + //Console.WriteLine(vval); + + //ushort[] data4xs_int64 = _service.ReadHoldingRegisters(1, 4, 4); // 运行模式 + //long vvval = DataConvertUtil.GetLong(data4xs_int64, 0); + //Console.WriteLine(vvval); + //Console.WriteLine("=========read4x========="); //Console.WriteLine("=========read3x========="); //ushort[] data3xs = _service.ReadInputRegisters(1, 4, 2); @@ -186,5 +229,99 @@ namespace VOL.WebApi.Controllers.Data } } + + + [HttpGet, HttpPost, Route("unitTestSem")] + public IActionResult Test02() + { + Console.Write(5 / 2); + _service = new ModbusTcpService("192.168.0.99", 502); + if (_service.isConnected) + { + // 读取从0开始,文档上地址从1开始的,地址需要减1 + Console.WriteLine("=========read4x========="); + + // 写数据 + _service.writeData(1, 6429, 1); + + _service.writeData(1, 1173, 256); + + _service.writeData(1, 1215, 6.28F); + + _service.writeData(1, 6691, "Hello World!!"); + + + // 读数据 + short s = _service.readData(1, 6429, "int16"); + + int i = _service.readData(1, 1173, "int32"); + + float f = _service.readData(1, 1215, "single"); + + string str = _service.readData(1, 6690, "string", 52); + + Console.WriteLine(s); + Console.WriteLine(i); + Console.WriteLine(f); + Console.WriteLine(str); + + Console.WriteLine("=========read4x========="); + + _service.disConnent(); + + return Content("read ok"); + } + else + { + return Content("Modbus 从站连接失败!"); + } + } + + + [HttpGet, HttpPost, Route("unitTestCnc")] + public IActionResult Test03() + { + _service = new ModbusTcpService("192.168.0.100", 502); + if (_service.isConnected) + { + // 读取从0开始,文档上地址从1开始的,地址需要减1 + Console.WriteLine("=========read4x========="); + + // 写数据 + _service.writeData(1, 6424, 2); + + _service.writeData(1, 1309, 65537); + + _service.writeData(1, 1307, 5.68F); + + _service.writeData(1, 6640, "hehe"); + + + // 读数据 + short s = _service.readData(1, 6424, "int16"); + + int i = _service.readData(1, 1309, "int32"); + + float f = _service.readData(1, 1307, "single"); + + string str = _service.readData(1, 6640, "string", 2); // 一个寄存器地址存放两个字符 + + Console.WriteLine(s); + Console.WriteLine(i); + Console.WriteLine(f); + Console.WriteLine(str); + + Console.WriteLine("=========read4x========="); + + _service.disConnent(); + + return Content("read ok"); + } + else + { + return Content("Modbus 从站连接失败!"); + } + } + } } diff --git a/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs b/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs index db9e1d8..06464b4 100644 --- a/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs +++ b/vol-net6/VOL.WebApi/Utils/DataConvertUtil.cs @@ -34,7 +34,8 @@ namespace VOL.WebApi.Utils temp[i] = src[i + start]; } byte[] bytesTemp = Ushorts2Bytes(temp); - string res = Encoding.UTF8.GetString(bytesTemp).Trim(new char[] { '\0' }); + //string res = Encoding.UTF8.GetString(bytesTemp).Trim(new char[] { '\0' }); // 去除字符串左右端的指定内容 + string res = Encoding.UTF8.GetString(bytesTemp).Trim(); return res; } @@ -68,8 +69,8 @@ namespace VOL.WebApi.Utils { temp[i] = src[i + start]; } - byte[] bytesTemp = Ushorts2Bytes(temp,true); - Array.Reverse(bytesTemp); + byte[] bytesTemp = Ushorts2Bytes(temp,false); + //Array.Reverse(bytesTemp); // !!!BitConverter默认是小端转换,如果是大端字节顺序存放,需要先反序字节顺序 float res = BitConverter.ToSingle(bytesTemp, 0); return res; @@ -172,7 +173,7 @@ namespace VOL.WebApi.Utils temp[1] = src[start + 1]; temp[2] = src[start + 2]; temp[3] = src[start + 3]; // 0 0 0 100 - Array.Reverse(temp); // 100 0 0 0 + //Array.Reverse(temp); // 100 0 0 0 byte[] bytesTemp = Ushorts2Bytes(temp); long res = BitConverter.ToInt64(bytesTemp, 0); return res;