啊鑫
2025-07-22 b03b881275a164c635521c319f3f645c77675b29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
using GSModbus.Config;
 
namespace GSModbus.Config
{
    /// <summary>
    /// 动态Modbus数据容器 - 基于配置动态存储和访问数据
    /// </summary>
    public class DynamicModbusData
    {
        #region 私有字段
 
        /// <summary>
        /// 数据存储字典 - 键为字段名,值为解析后的数据
        /// </summary>
        private readonly Dictionary<string, object?> _data = new();
 
        /// <summary>
        /// 原始寄存器数据 - 键为字段名,值为原始寄存器数组
        /// </summary>
        private readonly Dictionary<string, int[]> _rawData = new();
 
        #endregion
 
        #region 公共属性
 
        /// <summary>
        /// 数据读取时间
        /// </summary>
        public DateTime ReadTime { get; set; } = DateTime.Now;
 
        /// <summary>
        /// 数据源配置
        /// </summary>
        public ModbusConfiguration? SourceConfiguration { get; set; }
 
        /// <summary>
        /// 获取所有数据字段名
        /// </summary>
        public IEnumerable<string> FieldNames => _data.Keys;
 
        /// <summary>
        /// 获取所有原始寄存器数据
        /// </summary>
        public Dictionary<string, int[]>? RawRegisters => _rawData?.Count > 0 ? _rawData : null;
 
        #endregion
 
        #region 数据访问方法
 
        /// <summary>
        /// 设置字段数据
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <param name="value">解析后的值</param>
        /// <param name="rawRegisters">原始寄存器数据</param>
        public void SetFieldData(string fieldName, object? value, int[] rawRegisters)
        {
            _data[fieldName] = value;
            _rawData[fieldName] = rawRegisters;
        }
 
        /// <summary>
        /// 获取字段数据
        /// </summary>
        /// <typeparam name="T">期望的数据类型</typeparam>
        /// <param name="fieldName">字段名</param>
        /// <returns>字段值,如果不存在或类型不匹配则返回默认值</returns>
        public T? GetFieldData<T>(string fieldName)
        {
            if (!_data.TryGetValue(fieldName, out var value))
            {
                return default(T);
            }
 
            try
            {
                if (value is T typedValue)
                {
                    return typedValue;
                }
 
                // 尝试类型转换
                if (value != null)
                {
                    return (T)Convert.ChangeType(value, typeof(T));
                }
            }
            catch
            {
                // 转换失败,返回默认值
            }
 
            return default(T);
        }
 
        /// <summary>
        /// 获取字段的原始数据(未经类型转换)
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <returns>字段值对象</returns>
        public object? GetFieldValue(string fieldName)
        {
            _data.TryGetValue(fieldName, out var value);
            return value;
        }
 
        /// <summary>
        /// 获取字段的原始寄存器数据
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <returns>原始寄存器数组,如果不存在则返回空数组</returns>
        public int[] GetRawData(string fieldName)
        {
            return _rawData.TryGetValue(fieldName, out var rawData) ? rawData : Array.Empty<int>();
        }
 
        /// <summary>
        /// 检查字段是否存在
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <returns>字段是否存在</returns>
        public bool HasField(string fieldName)
        {
            return _data.ContainsKey(fieldName);
        }
 
        /// <summary>
        /// 获取所有字段数据的字典
        /// </summary>
        /// <returns>字段名到值的映射</returns>
        public Dictionary<string, object?> GetAllFieldData()
        {
            return new Dictionary<string, object?>(_data);
        }
 
        #endregion
 
        #region 便捷访问方法
 
        /// <summary>
        /// 获取字符串字段
        /// </summary>
        public string GetString(string fieldName, string defaultValue = "")
        {
            return GetFieldData<string>(fieldName) ?? defaultValue;
        }
 
        /// <summary>
        /// 获取整数字段
        /// </summary>
        public int GetInt(string fieldName, int defaultValue = 0)
        {
            return GetFieldData<int>(fieldName);
        }
 
        /// <summary>
        /// 获取字节字段
        /// </summary>
        public byte GetByte(string fieldName, byte defaultValue = 0)
        {
            return GetFieldData<byte>(fieldName);
        }
 
        /// <summary>
        /// 获取双精度浮点字段
        /// </summary>
        public double GetDouble(string fieldName, double defaultValue = 0.0)
        {
            return GetFieldData<double>(fieldName);
        }
 
        /// <summary>
        /// 获取布尔字段
        /// </summary>
        public bool GetBool(string fieldName, bool defaultValue = false)
        {
            return GetFieldData<bool>(fieldName);
        }
 
        /// <summary>
        /// 获取日期时间字段
        /// </summary>
        public DateTime GetDateTime(string fieldName, DateTime? defaultValue = null)
        {
            return GetFieldData<DateTime>(fieldName) != default ? GetFieldData<DateTime>(fieldName) : (defaultValue ?? DateTime.MinValue);
        }
 
        #endregion
 
        #region 调试和诊断方法
 
        /// <summary>
        /// 获取数据摘要(用于调试和日志)
        /// </summary>
        /// <returns>数据摘要字符串</returns>
        public string GetDataSummary()
        {
            var summary = new List<string>();
            
            foreach (var kvp in _data)
            {
                var valueStr = kvp.Value switch
                {
                    string s => $"\"{s}\"",
                    DateTime dt => dt.ToString("yyyy-MM-dd HH:mm:ss"),
                    double d => d.ToString("F2"),
                    null => "null",
                    _ => kvp.Value.ToString()
                };
                
                summary.Add($"{kvp.Key}: {valueStr}");
            }
 
            return string.Join(", ", summary);
        }
 
        /// <summary>
        /// 获取字段详细信息(包含配置信息)
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <returns>字段详细信息</returns>
        public string GetFieldDetails(string fieldName)
        {
            if (!HasField(fieldName))
            {
                return $"字段 '{fieldName}' 不存在";
            }
 
            var value = GetFieldValue(fieldName);
            var rawData = GetRawData(fieldName);
            var config = GetFieldConfiguration(fieldName);
 
            var details = new List<string>
            {
                $"字段名: {fieldName}",
                $"显示名: {config?.DisplayName ?? "未知"}",
                $"数据类型: {config?.DataType ?? "未知"}",
                $"地址: {config?.Address ?? 0}",
                $"长度: {config?.Length ?? 0}",
                $"解析值: {value ?? "null"}",
                $"原始数据: [{string.Join(", ", rawData)}]"
            };
 
            return string.Join("\n", details);
        }
 
        /// <summary>
        /// 获取字段配置信息
        /// </summary>
        /// <param name="fieldName">字段名</param>
        /// <returns>字段配置,如果不存在则返回null</returns>
        public DataField? GetFieldConfiguration(string fieldName)
        {
            if (SourceConfiguration?.InputAddresses == null)
                return null;
 
            // 在各个数据组中查找字段配置
            var allFields = new List<Dictionary<string, DataField>>
            {
                SourceConfiguration.InputAddresses.ControlSignals,
                SourceConfiguration.InputAddresses.ProductData,
                SourceConfiguration.InputAddresses.MeasurementData
            };
 
            foreach (var fieldGroup in allFields)
            {
                if (fieldGroup.TryGetValue(fieldName, out var fieldConfig))
                {
                    return fieldConfig;
                }
            }
 
            return null;
        }
 
        #endregion
    }
}