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 valueConverters = new Dictionary(); 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(); } } */ } }