ln.ethercat/ln.ethercat/ECDataTypeConverter.cs

235 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using ln.logging;
using ln.type;
namespace ln.ethercat
{
public delegate bool ToEthercatDelegate(object value, out byte[] ethercatBytes);
public delegate bool FromEthercatDelegate(byte[] ethercatBytes, out object value);
public interface IECValueConverter {
Type NativeType { get; }
bool ToEthercat(object value, out byte[] ethercatBytes);
bool FromEthercat(byte[] ethercatBytes, out object value);
}
public class ECValueConverterAdapter : IECValueConverter
{
public ToEthercatDelegate ToEthercatDelegate { get; }
public FromEthercatDelegate FromEthercatDelegate { get; }
public Type NativeType { get; set; }
public ECValueConverterAdapter(Type nativeType, ToEthercatDelegate toEthercatDelegate,FromEthercatDelegate fromEthercatDelegate)
{
NativeType = nativeType;
ToEthercatDelegate = toEthercatDelegate;
FromEthercatDelegate = fromEthercatDelegate;
}
public bool ToEthercat(object value, out byte[] ethercatBytes) => ToEthercatDelegate(value, out ethercatBytes);
public bool FromEthercat(byte[] ethercatBytes, out object value) => FromEthercatDelegate(ethercatBytes, out value);
}
public static class ECDataTypeConverter
{
static Dictionary<ECDataTypes, IECValueConverter> valueConverters = new Dictionary<ECDataTypes, IECValueConverter>();
public static void AddConverter(ECDataTypes dataType, IECValueConverter valueConverter) => valueConverters.Add(dataType, valueConverter);
public static bool FromEthercat(ECDataTypes dataType, byte[] ethercatBytes, out object value)
{
try
{
if (valueConverters.TryGetValue(dataType, out IECValueConverter converter))
return converter.FromEthercat(ethercatBytes, out value);
} catch (Exception e)
{
Logging.Log(LogLevel.ERROR, "Exception caught while converting {0} = {1} from ethercat to native value", dataType, ethercatBytes.ToHexString());
Logging.Log(e);
}
value = null;
return false;
}
public static bool ToEthercat(ECDataTypes dataType, object value, out byte[] ethercatBytes)
{
try
{
if (valueConverters.TryGetValue(dataType, out IECValueConverter converter))
return converter.ToEthercat(Cast.To(value, converter.NativeType), out ethercatBytes);
} catch (Exception e)
{
Logging.Log(LogLevel.ERROR, "Exception caught while converting {0} = {1} to ethercat from native value", dataType, value);
Logging.Log(e);
}
ethercatBytes = null;
return false;
}
public static object FromEthercat(ECDataTypes dataType, byte[] ethercatBytes)
{
try{
if (FromEthercat(dataType, ethercatBytes, out object value))
return value;
} catch (Exception e)
{
Logging.Log(LogLevel.ERROR, "Exception caught while converting {0} = {1} from ethercat to native value", dataType, ethercatBytes.ToHexString());
Logging.Log(e);
}
throw new NotSupportedException(String.Format("converting {0} is currently not supported", dataType ));
}
public static byte[] ToEthercat(ECDataTypes dataType, object value)
{
try
{
if (ToEthercat(dataType, value, out byte[] ethercatBytes))
return ethercatBytes;
} catch (Exception e)
{
Logging.Log(LogLevel.ERROR, "Exception caught while converting {0} = {1} to ethercat from native value", dataType, value);
Logging.Log(e);
}
throw new NotSupportedException(String.Format("converting {0} to {1} is currently not supported", value.GetType().Name, dataType));
}
static ECDataTypeConverter(){
AddConverter(ECDataTypes.SINT, new ECValueConverterAdapter(
typeof(sbyte),
(object value, out byte[] ethercatBytes) => { ethercatBytes = new byte[]{ (byte)(sbyte)value }; return true; },
(byte[] ethercatBytes, out object value) => { value = (sbyte)ethercatBytes[0]; return true; }
));
AddConverter(ECDataTypes.INT, new ECValueConverterAdapter(
typeof(short),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((short)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToInt16(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.DINT, new ECValueConverterAdapter(
typeof(int),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((int)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToInt32(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.LINT, new ECValueConverterAdapter(
typeof(long),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((long)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToInt64(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.USINT, new ECValueConverterAdapter(
typeof(byte),
(object value, out byte[] ethercatBytes) => { ethercatBytes = new byte[]{ (byte)value }; return true; },
(byte[] ethercatBytes, out object value) => { value = ethercatBytes[0]; return true; }
));
AddConverter(ECDataTypes.UINT, new ECValueConverterAdapter(
typeof(ushort),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((ushort)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToUInt16(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.UDINT, new ECValueConverterAdapter(
typeof(UInt32),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((UInt32)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToUInt32(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.ULINT, new ECValueConverterAdapter(
typeof(UInt64),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((UInt64)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToUInt64(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.REAL, new ECValueConverterAdapter(
typeof(float),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((float)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToSingle(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.LREAL, new ECValueConverterAdapter(
typeof(double),
(object value, out byte[] ethercatBytes) => { ethercatBytes = BitConverter.GetBytes((double)value); return true; },
(byte[] ethercatBytes, out object value) => { value = BitConverter.ToDouble(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.STRING, new ECValueConverterAdapter(
typeof(string),
(object value, out byte[] ethercatBytes) => { ethercatBytes = Encoding.ASCII.GetBytes(value.ToString()); return true; },
(byte[] ethercatBytes, out object value) => { value = Encoding.ASCII.GetString(ethercatBytes); return true; }
));
AddConverter(ECDataTypes.NONE, new ECValueConverterAdapter(
typeof(string),
(object value, out byte[] ethercatBytes) => { ethercatBytes = Extensions.BytesFromHexString(value as string); return true; },
(byte[] ethercatBytes, out object value) => { value = ethercatBytes.ToHexString(); return true; }
));
}
/*
if (rawData == null)
return null;
int offset = 0;
switch (dataType)
{
case ECDataTypes.NONE:
return null;
case ECDataTypes.REAL:
return rawData.GetSingle(ref offset, Endianess.LITTLE);
case ECDataTypes.LREAL:
return rawData.GetDouble(ref offset, Endianess.LITTLE);
case ECDataTypes.STRING:
return Encoding.ASCII.GetString(rawData);
case ECDataTypes.INT:
return rawData.GetShort(ref offset, Endianess.LITTLE);
case ECDataTypes.DINT:
return rawData.GetInt(ref offset, Endianess.LITTLE);
case ECDataTypes.UINT:
return rawData.GetUShort(ref offset, Endianess.LITTLE);
case ECDataTypes.UDINT:
return rawData.GetUInt(ref offset, Endianess.LITTLE);
case ECDataTypes.USINT:
return rawData[offset];
default:
return rawData;
}
}
{
if (value is byte[] bytes)
return bytes;
switch (dataType)
{
case ECDataTypes.NONE:
return new byte[0];
case ECDataTypes.REAL:
return BitConverter.GetBytes((float)(double)value);
case ECDataTypes.LREAL:
return BitConverter.GetBytes((double)value);
case ECDataTypes.STRING:
return Encoding.ASCII.GetBytes(value.ToString());
case ECDataTypes.INT:
return BitConverter.GetBytes((short)value);
case ECDataTypes.DINT:
return BitConverter.GetBytes((int)value);
case ECDataTypes.UINT:
return BitConverter.GetBytes((ushort)value);
case ECDataTypes.UDINT:
return BitConverter.GetBytes((uint)value);
case ECDataTypes.SINT:
return BitConverter.GetBytes((byte)value);
case ECDataTypes.USINT:
return BitConverter.GetBytes((byte)value);
default:
throw new NotImplementedException();
}
}
*/
}
}