完善modbus协议连读

This commit is contained in:
iioter 2023-11-09 13:35:20 +08:00
parent 78c1314627
commit caf348a38b

View File

@ -226,6 +226,8 @@ namespace PLC.ModBusMaster
/// 批量读后缓存 /// 批量读后缓存
/// </summary> /// </summary>
private Dictionary<string, object> _cache = new(); private Dictionary<string, object> _cache = new();
private Dictionary<string, string> _cacheType = new();
private Dictionary<string, ushort> _cacheStart = new();
[Method("多地址读取", description: "多地址读取缓存")] [Method("多地址读取", description: "多地址读取缓存")]
public DriverReturnValueModel ReadMultiple(DriverAddressIoArgModel ioArg) public DriverReturnValueModel ReadMultiple(DriverAddressIoArgModel ioArg)
{ {
@ -240,6 +242,7 @@ namespace PLC.ModBusMaster
var startAddress = ushort.Parse(args[1]);//开始地址 var startAddress = ushort.Parse(args[1]);//开始地址
var length = ushort.Parse(args[2]);//读取字数 var length = ushort.Parse(args[2]);//读取字数
var cacheKey = args[3];//缓存字典名 var cacheKey = args[3];//缓存字典名
_cacheStart[cacheKey] = startAddress;
try try
{ {
@ -248,31 +251,36 @@ namespace PLC.ModBusMaster
case "1": case "1":
var coils = _master.ReadCoils(slaveId, startAddress, length); var coils = _master.ReadCoils(slaveId, startAddress, length);
_cache[cacheKey] = coils; _cache[cacheKey] = coils;
_cacheType[cacheKey] = "bool";
break; break;
case "2": case "2":
var inputs = _master.ReadInputs(slaveId, startAddress, length); var inputs = _master.ReadInputs(slaveId, startAddress, length);
_cache[cacheKey] = inputs; _cache[cacheKey] = inputs;
_cacheType[cacheKey] = "bool";
break; break;
case "3": case "3":
var holdingRs = _master.ReadHoldingRegisters(slaveId, startAddress, length); var holdingRs = _master.ReadHoldingRegisters(slaveId, startAddress, length);
_cache[cacheKey] = holdingRs; _cache[cacheKey] = holdingRs;
_cacheType[cacheKey] = "ushort";
break; break;
case "4": case "4":
var inputRs = _master.ReadInputRegisters(slaveId, startAddress, length); var inputRs = _master.ReadInputRegisters(slaveId, startAddress, length);
_cache[cacheKey] = inputRs; _cache[cacheKey] = inputRs;
_cacheType[cacheKey] = "ushort";
break; break;
} }
return new DriverReturnValueModel() return new DriverReturnValueModel()
{ {
StatusType = VaribaleStatusTypeEnum.Good, StatusType = VaribaleStatusTypeEnum.Good,
Value = Newtonsoft.Json.JsonConvert.SerializeObject(_cache[cacheKey]) Value = _cache[cacheKey]
}; };
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, $"Device:[{_device}],ReadMultiple(),Error"); _logger.LogError(ex, $"Device:[{_device}],ReadMultiple(),Error");
_cache[cacheKey] = null; _cache[cacheKey] = null;
_cacheStart[cacheKey] = 0;
return new DriverReturnValueModel() return new DriverReturnValueModel()
{ {
StatusType = VaribaleStatusTypeEnum.Bad StatusType = VaribaleStatusTypeEnum.Bad
@ -298,57 +306,115 @@ namespace PLC.ModBusMaster
{ {
var args = ioArg.Address.Split(','); var args = ioArg.Address.Split(',');
cacheName = args[0]; cacheName = args[0];
startIndex = int.Parse(args[1]); startIndex = ushort.Parse(args[1]) - _cacheStart[cacheName];
} }
else else
{ {
startIndex = int.Parse(ioArg.Address); startIndex = ushort.Parse(ioArg.Address) - _cacheStart[cacheName];
} }
if (_cache.ContainsKey(cacheName) && _cache[cacheName] != null) if (_cache.ContainsKey(cacheName) && _cache[cacheName] != null)
{ {
var cacheBuffers = (ushort[])_cache[cacheName]; if (_cacheType[cacheName] == "ushort")
var rawBuffers = cacheBuffers.Skip(startIndex).Take(cacheBuffers.Length - startIndex).ToArray();
var retBuffers = ChangeBuffersOrder(rawBuffers, ioArg.EndianType);
if (ioArg.ValueType == DataTypeEnum.AsciiString)
retBuffers = rawBuffers;
if (ioArg.ValueType.ToString().Contains("Uint16"))
ret.Value = retBuffers[0];
else if (ioArg.ValueType.ToString().Contains("Int16"))
ret.Value = (short)retBuffers[0];
else if (ioArg.ValueType.ToString().Contains("Bcd16"))
ret.Value = ModBusDataConvert.GetBCD(GetBytes(retBuffers));
else if (ioArg.ValueType.ToString().Contains("Uint32"))
ret.Value = (uint)(retBuffers[0] << 16) + retBuffers[1];
else if (ioArg.ValueType.ToString().Contains("Int32"))
ret.Value = (retBuffers[0] << 16) + retBuffers[1];
else if (ioArg.ValueType.ToString().Contains("Bcd32"))
{ {
var newBuffers = new ushort[2] { retBuffers[1], retBuffers[0] }; var cacheBuffers = (ushort[])_cache[cacheName];
ret.Value = ModBusDataConvert.GetBCD(GetBytes(newBuffers)); var wordLen = GetModbusReadCount(0, ioArg.ValueType);
} var rawBuffers = cacheBuffers.Skip(startIndex).Take(wordLen).ToArray();
else if (ioArg.ValueType.ToString().Contains("Float"))
{
var bytes = new[] var retBuffers = ChangeBuffersOrder(rawBuffers, ioArg.EndianType);
if (ioArg.ValueType == DataTypeEnum.AsciiString)
retBuffers = rawBuffers;
ret.StatusType = VaribaleStatusTypeEnum.Good;
if (ioArg.ValueType == DataTypeEnum.Uint16)
ret.Value = retBuffers[0];
else if (ioArg.ValueType == DataTypeEnum.Int16)
ret.Value = (short)retBuffers[0];
else if (ioArg.ValueType == DataTypeEnum.Bcd16)
ret.Value = ModBusDataConvert.GetBCD(GetBytes(retBuffers));
else if (ioArg.ValueType == DataTypeEnum.Uint32)
ret.Value = (uint)(retBuffers[0] << 16) + retBuffers[1];
else if (ioArg.ValueType == DataTypeEnum.Int32)
ret.Value = (retBuffers[0] << 16) + retBuffers[1];
else if (ioArg.ValueType == DataTypeEnum.Bcd32)
{ {
var newBuffers = new ushort[2] { retBuffers[1], retBuffers[0] };
ret.Value = ModBusDataConvert.GetBCD(GetBytes(newBuffers));
}
else if (ioArg.ValueType == DataTypeEnum.Float)
{
var bytes = new[]
{
(byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff), (byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff) (byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff)
}; };
ret.Value = BitConverter.ToSingle(bytes, 0); ret.Value = BitConverter.ToSingle(bytes, 0);
}
else if (ioArg.ValueType == DataTypeEnum.Uint64)
{
var bytes = new[]
{
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff),
(byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[2] & 0xff), (byte)((retBuffers[2] >> 8) & 0xff),
(byte)(retBuffers[3] & 0xff), (byte)((retBuffers[3] >> 8) & 0xff)
};
ret.Value = BitConverter.ToUInt64(bytes, 0);
}
else if (ioArg.ValueType == DataTypeEnum.Int64)
{
var bytes = new[]
{
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff),
(byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[2] & 0xff), (byte)((retBuffers[2] >> 8) & 0xff),
(byte)(retBuffers[3] & 0xff), (byte)((retBuffers[3] >> 8) & 0xff)
};
ret.Value = BitConverter.ToInt64(bytes, 0);
}
else if (ioArg.ValueType == DataTypeEnum.Double)
{
var bytes = new[]
{
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff),
(byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[2] & 0xff), (byte)((retBuffers[2] >> 8) & 0xff),
(byte)(retBuffers[3] & 0xff), (byte)((retBuffers[3] >> 8) & 0xff)
};
ret.Value = BitConverter.ToDouble(bytes, 0);
}
else if (ioArg.ValueType == DataTypeEnum.AsciiString)
{
var str = Encoding.ASCII.GetString(GetBytes(retBuffers).Where(x => x is >= 32 and <= 126).ToArray());
if (str.Contains('\0'))
str = str.Split('\0')[0];
ret.Value = str;
}
else
{
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
ret.Message = "类型未定义";
_logger.LogError($"Device:[{_device}],[{ioArg.ValueType}]类型未定义");
}
} }
else if (ioArg.ValueType.ToString().Contains("AsciiString")) else if (_cacheType[cacheName] == "bool")
{ {
var str = Encoding.ASCII.GetString(GetBytes(retBuffers).ToArray()); ret.StatusType = VaribaleStatusTypeEnum.Good;
if (str.Contains('\0'))
str = str.Split('\0')[0]; var cacheBuffers = (bool[])_cache[cacheName];
ret.Value = str; var boolValue = cacheBuffers.Skip(startIndex).ToArray()[0];
if (ioArg.ValueType == DataTypeEnum.Bool)
ret.Value = boolValue;
else
{
ret.Value = boolValue ? 1 : 0;
}
} }
ret.StatusType = VaribaleStatusTypeEnum.Good;
} }
else else
{ {
@ -628,22 +694,22 @@ namespace PLC.ModBusMaster
if (ioArg.ValueType == DataTypeEnum.AsciiString) if (ioArg.ValueType == DataTypeEnum.AsciiString)
retBuffers = rawBuffers; retBuffers = rawBuffers;
if (ioArg.ValueType.ToString().Contains("Uint16")) if (ioArg.ValueType == DataTypeEnum.Uint16)
ret.Value = retBuffers[0]; ret.Value = retBuffers[0];
else if (ioArg.ValueType.ToString().Contains("Int16")) else if (ioArg.ValueType == DataTypeEnum.Int16)
ret.Value = (short)retBuffers[0]; ret.Value = (short)retBuffers[0];
else if (ioArg.ValueType.ToString().Contains("Bcd16")) else if (ioArg.ValueType == DataTypeEnum.Bcd16)
ret.Value = ModBusDataConvert.GetBCD(GetBytes(retBuffers)); ret.Value = ModBusDataConvert.GetBCD(GetBytes(retBuffers));
else if (ioArg.ValueType.ToString().Contains("Uint32")) else if (ioArg.ValueType == DataTypeEnum.Uint32)
ret.Value = (uint)(retBuffers[0] << 16) + retBuffers[1]; ret.Value = (uint)(retBuffers[0] << 16) + retBuffers[1];
else if (ioArg.ValueType.ToString().Contains("Int32")) else if (ioArg.ValueType == DataTypeEnum.Int32)
ret.Value = (retBuffers[0] << 16) + retBuffers[1]; ret.Value = (retBuffers[0] << 16) + retBuffers[1];
else if (ioArg.ValueType.ToString().Contains("Bcd32")) else if (ioArg.ValueType == DataTypeEnum.Bcd32)
{ {
var newBuffers = new ushort[2] { retBuffers[1], retBuffers[0] }; var newBuffers = new ushort[2] { retBuffers[1], retBuffers[0] };
ret.Value = ModBusDataConvert.GetBCD(GetBytes(newBuffers)); ret.Value = ModBusDataConvert.GetBCD(GetBytes(newBuffers));
} }
else if (ioArg.ValueType.ToString().Contains("Float")) else if (ioArg.ValueType == DataTypeEnum.Float)
{ {
var bytes = new[] var bytes = new[]
{ {
@ -652,24 +718,52 @@ namespace PLC.ModBusMaster
}; };
ret.Value = BitConverter.ToSingle(bytes, 0); ret.Value = BitConverter.ToSingle(bytes, 0);
} }
else if (ioArg.ValueType.ToString().Contains("Double")) else if (ioArg.ValueType == DataTypeEnum.Uint64)
{ {
var bytes = new[] var bytes = new[]
{ {
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff), (byte)(retBuffers[3] & 0xff), (byte)((retBuffers[3] >> 8) & 0xff),
(byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[2] & 0xff), (byte)((retBuffers[2] >> 8) & 0xff), (byte)(retBuffers[2] & 0xff), (byte)((retBuffers[2] >> 8) & 0xff),
(byte)(retBuffers[3] & 0xff), (byte)((retBuffers[3] >> 8) & 0xff) (byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff)
};
ret.Value = BitConverter.ToUInt64(bytes, 0);
}
else if (ioArg.ValueType == DataTypeEnum.Int64)
{
var bytes = new[]
{
(byte)(retBuffers[3] & 0xff), (byte)((retBuffers[3] >> 8) & 0xff),
(byte)(retBuffers[2] & 0xff), (byte)((retBuffers[2] >> 8) & 0xff),
(byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff)
};
ret.Value = BitConverter.ToInt64(bytes, 0);
}
else if (ioArg.ValueType == DataTypeEnum.Double)
{
var bytes = new[]
{
(byte)(retBuffers[3] & 0xff), (byte)((retBuffers[3] >> 8) & 0xff),
(byte)(retBuffers[2] & 0xff), (byte)((retBuffers[2] >> 8) & 0xff),
(byte)(retBuffers[1] & 0xff), (byte)((retBuffers[1] >> 8) & 0xff),
(byte)(retBuffers[0] & 0xff), (byte)((retBuffers[0] >> 8) & 0xff)
}; };
ret.Value = BitConverter.ToDouble(bytes, 0); ret.Value = BitConverter.ToDouble(bytes, 0);
} }
else if (ioArg.ValueType.ToString().Contains("AsciiString")) else if (ioArg.ValueType == DataTypeEnum.AsciiString)
{ {
var str = Encoding.ASCII.GetString(GetBytes(retBuffers).ToArray()); var str = Encoding.ASCII.GetString(GetBytes(retBuffers).Where(x => x is >= 32 and <= 126).ToArray());
if (str.Contains('\0')) if (str.Contains('\0'))
str = str.Split('\0')[0]; str = str.Split('\0')[0];
ret.Value = str; ret.Value = str;
} }
else
{
ret.StatusType = VaribaleStatusTypeEnum.UnKnow;
ret.Message = "类型未定义";
_logger.LogError($"Device:[{_device}],[{ioArg.ValueType}]类型未定义");
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -679,6 +773,7 @@ namespace PLC.ModBusMaster
} }
} }
return ret; return ret;
} }