Commit c3e2dbc5807c7c61697ec9dfc69670258961a3f7

Authored by 唐召明
1 parent 4c1029e1

优化S7批量读取功能

HHECS.DAQClient/Communications/DataItem.cs
... ... @@ -25,11 +25,11 @@ namespace HHECS.DAQClient.Communications
25 25 /// 数据长度
26 26 /// </summary>
27 27 /// <remarks>仅<see cref="char"/>类型有效</remarks>
28   - public int Length
  28 + public ushort Length
29 29 {
30 30 get
31 31 {
32   - _ = int.TryParse(DataAddress.Split(',').LastOrDefault() ?? "1", out var val);
  32 + _ = ushort.TryParse(DataAddress.Split(',').LastOrDefault() ?? "1", out var val);
33 33 return val;
34 34 }
35 35 }
... ...
HHECS.DAQClient/Communications/SiemensS7Communication.cs
1 1 using HHECS.BllModel;
2 2 using HHECS.EquipmentModel;
3 3 using HslCommunication;
4   -using HslCommunication.Core;
  4 +using HslCommunication.Core.Address;
5 5 using HslCommunication.Profinet.Siemens;
6 6 using System.Text;
7   -using System.Text.RegularExpressions;
8 7  
9 8 namespace HHECS.DAQClient.Communications
10 9 {
... ... @@ -14,7 +13,6 @@ namespace HHECS.DAQClient.Communications
14 13 public class SiemensS7Communication : ICommunication
15 14 {
16 15 public readonly SiemensS7Net Siemens = null!;
17   - private readonly ReverseBytesTransform reverseBytesTransform = new();
18 16  
19 17 public string IpAddress => Siemens.IpAddress;
20 18  
... ... @@ -49,151 +47,42 @@ namespace HHECS.DAQClient.Communications
49 47 {
50 48 try
51 49 {
52   - //DB地址批量读取
53   - if (dataItems.All(x => x.DataAddress.StartsWith("DB", StringComparison.OrdinalIgnoreCase)))
  50 + var addressDatas = new List<S7AddressData>();
  51 + foreach (var item in dataItems)
54 52 {
55   - var regex = new Regex("[0-9]+");
56   - var separatingChars = new char[] { '.', ',' };
57   - foreach (var item in dataItems.GroupBy(x => x.DataAddress.Split(separatingChars).First()))
  53 + ushort byteLength = GetByteLength(item);
  54 + var i = item.DataAddress.IndexOf(',');
  55 + var address = i > 0 ? item.DataAddress[..i] : item.DataAddress;
  56 + var parseResult = S7AddressData.ParseFrom(address, byteLength);
  57 + if (!parseResult.IsSuccess)
58 58 {
59   - var amountItems = item.Select(x => Convert.ToInt32(regex.Match(x.DataAddress.Split(separatingChars)[1]).Value));
60   - var amountStart = amountItems.Min();
61   - var amountEnd = amountItems.Max();
62   -
63   - var lastItem = item.MaxBy(x => Convert.ToInt32(regex.Match(x.DataAddress.Split(separatingChars)[1]).Value));
64   - //最后一个地址占用的Byte数量,Word类型需要加2,Real需要加4
65   - var lastByteAmount = lastItem.DataType switch
66   - {
67   - EquipmentDataType.BOOL => 1,
68   - EquipmentDataType.WORD => 2,//UInt16
69   - EquipmentDataType.DWORD => 4,//UInt32
70   - EquipmentDataType.INT => 2,//Int16
71   - EquipmentDataType.DINT => 4,//Int32
72   - EquipmentDataType.CHAR => lastItem.Length,
73   - EquipmentDataType.REAL => 4,//Float
74   - _ => 1
75   - };
76   -
77   - var amount = (ushort)(amountEnd - amountStart + lastByteAmount);
78   - var multiReadResult = Siemens.Read($"{item.Key}.{amountStart}", amount);
79   - if (!multiReadResult.IsSuccess)
80   - {
81   - return BllResultFactory.Error($"读取[{IpAddress}]{item.Key},起始位:{amountStart},长度:{amount},出现异常:{multiReadResult.Message}");
82   - }
83   -
84   - //根据数据类型按byte转换,不同数据类型字节数不同
85   - foreach (var prop in item)
86   - {
87   - _ = int.TryParse(regex.Match(prop.DataAddress.Split(separatingChars)[1]).Value, out int currentAmountEnd);
88   - _ = int.TryParse(regex.Match(prop.DataAddress.Split(separatingChars).Skip(2).FirstOrDefault() ?? "0").Value, out int bitIndex);
89   - var index = currentAmountEnd - amountStart;
90   - prop.Value = prop.DataType switch
91   - {
92   - EquipmentDataType.BYTE => reverseBytesTransform.TransByte(multiReadResult.Content, index).ToString(),
93   - EquipmentDataType.BOOL => Convert.ToBoolean(multiReadResult.Content[index] & 1 << bitIndex).ToString(),
94   - EquipmentDataType.DINT => reverseBytesTransform.TransInt32(multiReadResult.Content, index).ToString(),
95   - EquipmentDataType.DWORD => reverseBytesTransform.TransUInt32(multiReadResult.Content, index).ToString(),
96   - EquipmentDataType.WORD => reverseBytesTransform.TransUInt16(multiReadResult.Content, index).ToString(),
97   - EquipmentDataType.INT => reverseBytesTransform.TransInt16(multiReadResult.Content, index).ToString(),
98   - EquipmentDataType.CHAR => reverseBytesTransform.TransString(multiReadResult.Content, index, prop.Length, Encoding.ASCII).Replace("\u0003", "").Trim(),
99   - EquipmentDataType.REAL => reverseBytesTransform.TransSingle(multiReadResult.Content, index).ToString(),
100   - _ => string.Empty
101   - };
102   - }
  59 + return BllResultFactory.Error(parseResult.Message);
103 60 }
104   - return BllResultFactory.Success();
  61 + addressDatas.Add(parseResult.Content);
105 62 }
106   -
107   - //单个地址读取
  63 + var result = Siemens.Read(addressDatas.ToArray());
  64 + if (!result.IsSuccess)
  65 + {
  66 + return BllResultFactory.Error(result.Message);
  67 + }
  68 + var buffer = result.Content;
  69 + var byteIndex = 0;
108 70 foreach (var item in dataItems)
109 71 {
110   - switch (item.DataType)
  72 + _ = ushort.TryParse(item.DataAddress.Split('.').LastOrDefault(), out var bitIndex);
  73 + item.Value = item.DataType switch
111 74 {
112   - case EquipmentDataType.BOOL:
113   - var boolDataResult = Siemens.ReadBool(item.DataAddress);
114   - if (!boolDataResult.IsSuccess)
115   - {
116   - item.Value = string.Empty;
117   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{boolDataResult.Message}");
118   - }
119   - item.Value = boolDataResult.Content.ToString();
120   - break;
121   - case EquipmentDataType.BYTE:
122   - var byteDataResult = Siemens.ReadByte(item.DataAddress);
123   - if (!byteDataResult.IsSuccess)
124   - {
125   - item.Value = string.Empty;
126   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{byteDataResult.Message}");
127   - }
128   - item.Value = byteDataResult.Content.ToString();
129   - break;
130   - case EquipmentDataType.WORD:
131   - var shortDataResult = Siemens.ReadInt16(item.DataAddress);
132   - if (!shortDataResult.IsSuccess)
133   - {
134   - item.Value = string.Empty;
135   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{shortDataResult.Message}");
136   - }
137   - item.Value = shortDataResult.Content.ToString();
138   - break;
139   - case EquipmentDataType.DWORD:
140   - var ushortDataResult = Siemens.ReadUInt16(item.DataAddress);
141   - if (!ushortDataResult.IsSuccess)
142   - {
143   - item.Value = string.Empty;
144   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{ushortDataResult.Message}");
145   - }
146   - item.Value = ushortDataResult.Content.ToString();
147   - break;
148   - case EquipmentDataType.INT:
149   - var intDataResult = Siemens.ReadInt32(item.DataAddress);
150   - if (!intDataResult.IsSuccess)
151   - {
152   - item.Value = string.Empty;
153   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{intDataResult.Message}");
154   - }
155   - item.Value = intDataResult.Content.ToString();
156   - break;
157   - case EquipmentDataType.DINT:
158   - var uintDataResult = Siemens.ReadUInt32(item.DataAddress);
159   - if (!uintDataResult.IsSuccess)
160   - {
161   - item.Value = string.Empty;
162   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{uintDataResult.Message}");
163   - }
164   - item.Value = uintDataResult.Content.ToString();
165   - break;
166   - case EquipmentDataType.REAL:
167   - var floatDataResult = Siemens.ReadFloat(item.DataAddress);
168   - if (!floatDataResult.IsSuccess)
169   - {
170   - item.Value = string.Empty;
171   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{floatDataResult.Message}");
172   - }
173   - item.Value = floatDataResult.Content.ToString();
174   - break;
175   - //case "double":
176   - // var doubleDataResult = Siemens.ReadDouble(item.DataAddress);
177   - // if (!doubleDataResult.IsSuccess)
178   - // {
179   - // item.Value = string.Empty;
180   - // systemLog.LogError($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{doubleDataResult.Message}");
181   - // return;
182   - // }
183   - // item.Value = doubleDataResult.Content.ToString();
184   - // break;
185   - case EquipmentDataType.CHAR:
186   - var stringDataResult = Siemens.ReadString(item.DataAddress);
187   - if (!stringDataResult.IsSuccess)
188   - {
189   - item.Value = string.Empty;
190   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}出现异常:{stringDataResult.Message}");
191   - }
192   - item.Value = stringDataResult.Content.ToString();
193   - break;
194   - default:
195   - return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]地址{item.DataAddress}失败:不支持“{item.DataType}”数据类型");
196   - }
  75 + EquipmentDataType.BYTE => Siemens.ByteTransform.TransByte(buffer, byteIndex).ToString(),
  76 + EquipmentDataType.BOOL => Convert.ToBoolean(buffer[byteIndex] & 1 << bitIndex).ToString(),
  77 + EquipmentDataType.DINT => Siemens.ByteTransform.TransInt32(buffer, byteIndex).ToString(),
  78 + EquipmentDataType.DWORD => Siemens.ByteTransform.TransUInt32(buffer, byteIndex).ToString(),
  79 + EquipmentDataType.WORD => Siemens.ByteTransform.TransUInt16(buffer, byteIndex).ToString(),
  80 + EquipmentDataType.INT => Siemens.ByteTransform.TransInt16(buffer, byteIndex).ToString(),
  81 + EquipmentDataType.CHAR => Siemens.ByteTransform.TransString(buffer, byteIndex, item.Length, Encoding.ASCII).Replace("\u0003", "").Trim(),
  82 + EquipmentDataType.REAL => Siemens.ByteTransform.TransSingle(buffer, byteIndex).ToString(),
  83 + _ => string.Empty,
  84 + };
  85 + byteIndex += GetByteLength(item);
197 86 }
198 87 return BllResultFactory.Success();
199 88 }
... ... @@ -252,5 +141,18 @@ namespace HHECS.DAQClient.Communications
252 141 {
253 142 return Write([dataItem]);
254 143 }
  144 +
  145 + private static ushort GetByteLength(DataItem data) => data.DataType switch
  146 + {
  147 + EquipmentDataType.BOOL => 1,
  148 + EquipmentDataType.WORD => 2,//UInt16
  149 + EquipmentDataType.DWORD => 4,//UInt32
  150 + EquipmentDataType.INT => 2,//Int16
  151 + EquipmentDataType.DINT => 4,//Int32
  152 + EquipmentDataType.CHAR or
  153 + EquipmentDataType.BYTE => data.Length,
  154 + EquipmentDataType.REAL => 4,//Float
  155 + _ => data.Length
  156 + };
255 157 }
256 158 }
... ...
HHECS.DAQClient/DB/hhecs.fuleixi.db
No preview for this file type
HHECS.DAQClient/DB/hhecs.kangshu.db
No preview for this file type