Files
Sharp7Reactive/Sharp7.Rx/S7ValueConverter.cs
Peter Butzhammer baef1afac1 Use BinaryPrimitives
2024-02-06 17:47:00 +01:00

88 lines
3.0 KiB
C#

using System;
using System.Buffers.Binary;
using System.Runtime.InteropServices;
using System.Text;
using Sharp7.Rx.Enums;
namespace Sharp7.Rx
{
internal static class S7ValueConverter
{
public static TValue ConvertToType<TValue>(byte[] buffer, S7VariableAddress address)
{
if (typeof(TValue) == typeof(bool))
return (TValue) (object) (((buffer[0] >> address.Bit) & 1) > 0);
if (typeof(TValue) == typeof(int))
{
if (address.Length == 2)
return (TValue) (object) BinaryPrimitives.ReadInt16BigEndian(buffer);
if (address.Length == 4)
{
return (TValue) (object) BinaryPrimitives.ReadInt32BigEndian(buffer);
}
throw new InvalidOperationException($"length must be 2 or 4 but is {address.Length}");
}
if (typeof(TValue) == typeof(long))
{
return (TValue) (object) BinaryPrimitives.ReadInt64BigEndian(buffer);
}
if (typeof(TValue) == typeof(ulong))
{
return (TValue) (object) BinaryPrimitives.ReadUInt64BigEndian(buffer);
}
if (typeof(TValue) == typeof(short))
{
return (TValue) (object) BinaryPrimitives.ReadInt16BigEndian(buffer);
}
if (typeof(TValue) == typeof(byte) || typeof(TValue) == typeof(char))
{
return (TValue) (object) buffer[0];
}
if (typeof(TValue) == typeof(byte[]))
{
return (TValue) (object) buffer;
}
if (typeof(TValue) == typeof(double) || typeof(TValue) == typeof(float))
{
var d = new UInt32SingleMap
{
UInt32 = BinaryPrimitives.ReadUInt32BigEndian(buffer)
};
return (TValue) (object) d.Single;
}
if (typeof(TValue) == typeof(string))
if (address.Type == DbType.String)
{
// First byte is maximal length
// Second byte is actual length
// https://cache.industry.siemens.com/dl/files/480/22506480/att_105176/v1/s7_scl_string_parameterzuweisung_e.pdf
var length = Math.Min(address.Length, buffer[1]);
return (TValue) (object) Encoding.ASCII.GetString(buffer, 2, length);
}
else
{
return (TValue) (object) Encoding.ASCII.GetString(buffer).Trim();
}
throw new InvalidOperationException(string.Format("type '{0}' not supported.", typeof(TValue)));
}
[StructLayout(LayoutKind.Explicit)]
private struct UInt32SingleMap
{
[FieldOffset(0)] public uint UInt32;
[FieldOffset(0)] public float Single;
}
}
}