Commit c3e2dbc5807c7c61697ec9dfc69670258961a3f7
1 parent
4c1029e1
优化S7批量读取功能
Showing
4 changed files
with
45 additions
and
143 deletions
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