RegisterConverter: - accept raw byte arrays which are to small for the required data type - padding
This commit is contained in:
parent
bae922b8f1
commit
0852b0559b
Binary file not shown.
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -51,7 +52,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
String strRawResult;
|
||||
if (registerName.Contains("EncryptionKey") || registerName.Contains("Password"))
|
||||
{
|
||||
strRawResult = GetRegisterRawText(registerDefinition, regRawByteArray, encryptData:true);
|
||||
strRawResult = GetRegisterRawText(registerDefinition, regRawByteArray, encryptData: true);
|
||||
msg = $"{registerName}: ({strRawResult})h";
|
||||
}
|
||||
else
|
||||
@ -64,7 +65,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
{
|
||||
throw new ApplicationException($"Cannot convert register {registerName}");
|
||||
}
|
||||
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
@ -86,7 +87,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
/// <remarks date="2024-Mar-20" author="Thomas Wiedebusch">
|
||||
/// - Hash password and encryption key with SHA256.
|
||||
/// </remarks>
|
||||
public static String GetRegisterRawText(RegisterDefinition registerDefinition, Byte[] regRawByteArray,
|
||||
public static String GetRegisterRawText(RegisterDefinition registerDefinition, Byte[] regRawByteArray,
|
||||
Boolean encryptData = false)
|
||||
{
|
||||
String msg;
|
||||
@ -146,8 +147,8 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
regRawByteArray = ValueToByteArray(registerDefinition.Default);
|
||||
return true;
|
||||
}
|
||||
|
||||
regRawByteArray = new Byte[] {0};
|
||||
|
||||
regRawByteArray = new Byte[] { 0 };
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -291,7 +292,7 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
}
|
||||
|
||||
else if (registerDefinition.DataType == typeof(UInt48))
|
||||
{
|
||||
{
|
||||
// 48 Bits / 8 Bits/Byte
|
||||
size = 6;
|
||||
}
|
||||
@ -436,6 +437,9 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
/// <remarks date="2025-Mar-31" author="Thomas Wiedebusch/Roland Drabesch">
|
||||
/// - Return default (T) on input == null;
|
||||
/// </remarks>
|
||||
/// <remarks date="2025-Jun-16" author="Thomas Wiedebusch/Roland Drabesch">
|
||||
/// - Padding bytes if input doesn't fit the required size;
|
||||
/// </remarks>
|
||||
public static T ByteArrayToValue<T>(Byte[] rawByteArray)
|
||||
{
|
||||
if (rawByteArray == null)
|
||||
@ -443,61 +447,39 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
|
||||
try
|
||||
{
|
||||
Object convertedObj;
|
||||
Object convertedObj = null;
|
||||
var type = typeof(T);
|
||||
|
||||
if (type == typeof(Boolean))
|
||||
{
|
||||
convertedObj = BitConverter.ToBoolean(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(UInt16))
|
||||
{
|
||||
convertedObj = BitConverter.ToUInt16(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(UInt32))
|
||||
{
|
||||
convertedObj = BitConverter.ToUInt32(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(UInt64))
|
||||
{
|
||||
convertedObj = BitConverter.ToUInt64(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(UInt48))
|
||||
// For non-numerical or single byte values use the standard implementation
|
||||
if (type == typeof(UInt48))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
else if (type == typeof(UInt72))
|
||||
if (type == typeof(UInt72))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
else if (type == typeof(UInt88))
|
||||
if (type == typeof(UInt88))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
else if (type == typeof(UInt96))
|
||||
if (type == typeof(UInt96))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
else if (type == typeof(UInt128))
|
||||
if (type == typeof(UInt128))
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
else if (type == typeof(Int16))
|
||||
{
|
||||
convertedObj = BitConverter.ToInt16(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(Int32))
|
||||
{
|
||||
convertedObj = BitConverter.ToInt32(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(Int64))
|
||||
{
|
||||
convertedObj = BitConverter.ToInt64(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(Byte) || type == typeof(Enum8))
|
||||
|
||||
if (type == typeof(Byte) || type == typeof(Enum8))
|
||||
{
|
||||
convertedObj = rawByteArray[0];
|
||||
}
|
||||
else if (type == typeof(Boolean))
|
||||
{
|
||||
convertedObj = BitConverter.ToBoolean(rawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(SByte))
|
||||
{
|
||||
// set all others to 0 as only the LSB is of interest
|
||||
@ -545,6 +527,54 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
// the value contains always the seconds since 01.Jan 2000
|
||||
convertedObj = new TimeT { SecondsSince2000 = ByteArrayToValue<Int32>(rawByteArray) };
|
||||
}
|
||||
|
||||
if (convertedObj != null)
|
||||
{
|
||||
return (T)Convert.ChangeType(convertedObj, type);
|
||||
}
|
||||
|
||||
// Padding byte array to required byte size will be used for numerical values
|
||||
var requiredSize = Marshal.SizeOf(typeof(T));
|
||||
var paddedRawByteArray = new Byte[requiredSize];
|
||||
var inputArraySize = rawByteArray.Length;
|
||||
for (var ctr = 0; ctr < requiredSize; ctr++)
|
||||
{
|
||||
if (inputArraySize > 0)
|
||||
{
|
||||
paddedRawByteArray[ctr] = rawByteArray[ctr];
|
||||
inputArraySize--;
|
||||
}
|
||||
else
|
||||
{
|
||||
paddedRawByteArray[ctr] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
// For all numerical values the padded raw byte array will be used
|
||||
if (type == typeof(UInt16))
|
||||
{
|
||||
convertedObj = BitConverter.ToUInt16(paddedRawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(UInt32))
|
||||
{
|
||||
convertedObj = BitConverter.ToUInt32(paddedRawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(UInt64))
|
||||
{
|
||||
convertedObj = BitConverter.ToUInt64(paddedRawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(Int16))
|
||||
{
|
||||
convertedObj = BitConverter.ToInt16(paddedRawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(Int32))
|
||||
{
|
||||
convertedObj = BitConverter.ToInt32(paddedRawByteArray, 0);
|
||||
}
|
||||
else if (type == typeof(Int64))
|
||||
{
|
||||
convertedObj = BitConverter.ToInt64(paddedRawByteArray, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ApplicationException($"Data type {type} not implemented");
|
||||
@ -552,9 +582,10 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.Registers
|
||||
|
||||
return (T)Convert.ChangeType(convertedObj, type);
|
||||
}
|
||||
catch (Exception)
|
||||
catch (Exception ex)
|
||||
{
|
||||
return default(T);
|
||||
throw new ApplicationException($"Data type {typeof(T)} not implemented. Message: {ex.Message}");
|
||||
//return default(T);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user