using GSModbus.Config;
namespace GSModbus.Config
{
///
/// 动态Modbus数据容器 - 基于配置动态存储和访问数据
///
public class DynamicModbusData
{
#region 私有字段
///
/// 数据存储字典 - 键为字段名,值为解析后的数据
///
private readonly Dictionary _data = new();
///
/// 原始寄存器数据 - 键为字段名,值为原始寄存器数组
///
private readonly Dictionary _rawData = new();
#endregion
#region 公共属性
///
/// 数据读取时间
///
public DateTime ReadTime { get; set; } = DateTime.Now;
///
/// 数据源配置
///
public ModbusConfiguration? SourceConfiguration { get; set; }
///
/// 获取所有数据字段名
///
public IEnumerable FieldNames => _data.Keys;
///
/// 获取所有原始寄存器数据
///
public Dictionary? RawRegisters => _rawData?.Count > 0 ? _rawData : null;
#endregion
#region 数据访问方法
///
/// 设置字段数据
///
/// 字段名
/// 解析后的值
/// 原始寄存器数据
public void SetFieldData(string fieldName, object? value, int[] rawRegisters)
{
_data[fieldName] = value;
// 复制原始寄存器数据以避免引用问题
if (rawRegisters != null)
{
_rawData[fieldName] = (int[])rawRegisters.Clone();
Console.WriteLine($"[DATA-STORE] 字段 '{fieldName}' 存储: 解析值={value}, 原始=[{string.Join(", ", rawRegisters)}]");
}
else
{
_rawData[fieldName] = Array.Empty();
Console.WriteLine($"[DATA-STORE] 字段 '{fieldName}' 存储: 解析值={value}, 原始数据为null");
}
}
///
/// 获取字段数据
///
/// 期望的数据类型
/// 字段名
/// 字段值,如果不存在或类型不匹配则返回默认值
public T? GetFieldData(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);
}
///
/// 获取字段的原始数据(未经类型转换)
///
/// 字段名
/// 字段值对象
public object? GetFieldValue(string fieldName)
{
_data.TryGetValue(fieldName, out var value);
return value;
}
///
/// 获取字段的原始寄存器数据
///
/// 字段名
/// 原始寄存器数组,如果不存在则返回空数组
public int[] GetRawData(string fieldName)
{
return _rawData.TryGetValue(fieldName, out var rawData) ? rawData : Array.Empty();
}
///
/// 检查字段是否存在
///
/// 字段名
/// 字段是否存在
public bool HasField(string fieldName)
{
return _data.ContainsKey(fieldName);
}
///
/// 获取所有字段数据的字典
///
/// 字段名到值的映射
public Dictionary GetAllFieldData()
{
return new Dictionary(_data);
}
#endregion
#region 便捷访问方法
///
/// 获取字符串字段
///
public string GetString(string fieldName, string defaultValue = "")
{
return GetFieldData(fieldName) ?? defaultValue;
}
///
/// 获取整数字段
///
public int GetInt(string fieldName, int defaultValue = 0)
{
return GetFieldData(fieldName);
}
///
/// 获取字节字段
///
public byte GetByte(string fieldName, byte defaultValue = 0)
{
return GetFieldData(fieldName);
}
///
/// 获取双精度浮点字段
///
public double GetDouble(string fieldName, double defaultValue = 0.0)
{
return GetFieldData(fieldName);
}
///
/// 获取布尔字段
///
public bool GetBool(string fieldName, bool defaultValue = false)
{
return GetFieldData(fieldName);
}
///
/// 获取日期时间字段
///
public DateTime GetDateTime(string fieldName, DateTime? defaultValue = null)
{
return GetFieldData(fieldName) != default ? GetFieldData(fieldName) : (defaultValue ?? DateTime.MinValue);
}
#endregion
#region 调试和诊断方法
///
/// 获取数据摘要(用于调试和日志)
///
/// 数据摘要字符串
public string GetDataSummary()
{
var summary = new List();
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);
}
///
/// 获取字段详细信息(包含配置信息)
///
/// 字段名
/// 字段详细信息
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
{
$"字段名: {fieldName}",
$"显示名: {config?.DisplayName ?? "未知"}",
$"数据类型: {config?.DataType ?? "未知"}",
$"地址: {config?.Address ?? 0}",
$"长度: {config?.Length ?? 0}",
$"解析值: {value ?? "null"}",
$"原始数据: [{string.Join(", ", rawData)}]"
};
return string.Join("\n", details);
}
///
/// 获取字段配置信息
///
/// 字段名
/// 字段配置,如果不存在则返回null
public DataField? GetFieldConfiguration(string fieldName)
{
if (SourceConfiguration?.InputAddresses == null)
return null;
// 在各个数据组中查找字段配置
var allFields = new List>
{
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
}
}