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
|
}
|
}
|