using System; using System.Collections.Generic; using System.Linq; using System.Text; using XYLEM.Communication; using System.Xml; using System.Xml.Linq; using XYLEM.Base; using XYLEM.Base.Files; using XYLEM.Device.Value; using System.Numerics; using XYLEM.Communication.ValueEncoders; using XYLEM.Base.XML; namespace XYLEM.Communication.ValueEncoders { /// /// Return used character set used for email or empty if not Loaded from setup /// /// ex. "iso-8859-1" public delegate string GetEmailCharacterSetToUse(); public static class DeviceValueEncoder { public static object Default(this ValueDataType dataType) { try { switch (dataType) { case ValueDataType.U8: case ValueDataType.B8: return (byte)0; case ValueDataType.S8: return (sbyte)0; case ValueDataType.B16: case ValueDataType.U16: case ValueDataType.U16MJK_SN: return (UInt16)0; case ValueDataType.U32TIME_Y1970: case ValueDataType.U32TIME_Y1970_UTC: return ((UInt32)0).Convert1970SecToTime(TimeType.UTC); case ValueDataType.U32TIME_Y2000: return ((UInt32)0).Convert2000SecToTime(); case ValueDataType.U32MJK_SN: return ((UInt32)0); //case DeviceValueDataType.U24DateHH_MM_SS: //case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: return ((UInt32)0); //case DeviceValueDataType.U24: //case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: case ValueDataType.B32: case ValueDataType.U32: return (UInt32)0; case ValueDataType.B64: case ValueDataType.U64: return (UInt64)0; case ValueDataType.F64: return (double)0; case ValueDataType.U128: return (BigInteger)0; case ValueDataType.S16: return (Int16)0; case ValueDataType.F32: return (Single)0; //case DeviceValueDataType.U32IPV4: return "0.0.0.0"; // handled as a string default: if (dataType.IsText()) { // Do this as the last check to save CPU power return ""; } throw new Exception(dataType.ToString() + "has no default value)"); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Default()", "dataType = " + dataType.ToString())); } } public static string EncodeXML(this object value, ValueDataType type) { try { string valueAsTxt = value.ToString(); switch (type) { case ValueDataType.U32TIME_Y1970: case ValueDataType.U32TIME_Y1970_UTC: if (value is DateTime) { var value32bit = ((DateTime)value).ConvertTimeTo1970Sec(TimeType.Local); return XmlConvert.ToString(value32bit); } return XmlConvert.ToString((Double)value); case ValueDataType.U32TIME_Y2000: if (value is DateTime) { var value32bit = ((DateTime)value).ConvertTimeTo2000Sec(TimeType.Local); return XmlConvert.ToString(value32bit); } return XmlConvert.ToString((Double)value); case ValueDataType.U8: case ValueDataType.B8: case ValueDataType.S8: //case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: case ValueDataType.B16: case ValueDataType.U16: case ValueDataType.U16MJK_SN: //case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: //case DeviceValueDataType.U24DateHH_MM_SS: //case DeviceValueDataType.U24: case ValueDataType.B32: case ValueDataType.U32: case ValueDataType.B64: case ValueDataType.U64: case ValueDataType.S16: case ValueDataType.S32: case ValueDataType.S64: case ValueDataType.F32: case ValueDataType.F64: case ValueDataType.U32MJK_SN: { if (typeof(Double) == value.GetType()) { valueAsTxt = XmlConvert.ToString((Double)value); } else if (typeof(Single) == value.GetType()) { valueAsTxt = XmlConvert.ToString((Single)value); } return valueAsTxt; } case ValueDataType.U128: if (typeof(BigInteger) == value.GetType()) { valueAsTxt = ((BigInteger)value).ToString("X"); // enclode as hex } else { throw new Exception($"{value.GetType()} is not supported for U128 xml convert"); } return valueAsTxt; //case DeviceValueDataType.U32IPV4: return valueAsTxt.Trim( ).StripIllegalXMLChars( );// handled as a string default: if (type.IsText()) { // Do this as the last check to save CPU power return valueAsTxt.Trim().StripIllegalXMLChars(); } throw new NotImplementedException("DataType '" + type + "' not recognized."); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "EncodeXML()", "dataType = " + type.ToString() + " Value is = " + value.ToString())); } } public static Object DecodeXML(this string valueInXml, ValueDataType type) { try { switch (type) { case ValueDataType.U32TIME_Y1970: case ValueDataType.U32TIME_Y1970_UTC: return XmlConvert.ToUInt32(valueInXml).Convert1970SecToTime(TimeType.Local); case ValueDataType.U32TIME_Y2000: return XmlConvert.ToUInt32(valueInXml).Convert2000SecToTime(); //case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: return XmlConvert.ToUInt32( valueInXml ); case ValueDataType.B8: case ValueDataType.U8: return XmlConvert.ToByte(valueInXml); case ValueDataType.S8: return XmlConvert.ToSByte(valueInXml); case ValueDataType.B16: case ValueDataType.U16: case ValueDataType.U16MJK_SN: return XmlConvert.ToUInt16(valueInXml); //case DeviceValueDataType.U24DateHH_MM_SS: //case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: //case DeviceValueDataType.U24: case ValueDataType.B32: case ValueDataType.U32: case ValueDataType.U32MJK_SN: return XmlConvert.ToUInt32(valueInXml); case ValueDataType.B64: case ValueDataType.U64: return XmlConvert.ToUInt64(valueInXml); case ValueDataType.S16: return XmlConvert.ToInt16(valueInXml); case ValueDataType.S32: return XmlConvert.ToInt32(valueInXml); case ValueDataType.S64: return XmlConvert.ToInt64(valueInXml); case ValueDataType.F32: return XmlConvert.ToSingle(valueInXml); case ValueDataType.F64: return XmlConvert.ToDouble(valueInXml); case ValueDataType.U128: return BigInteger.Parse(valueInXml, System.Globalization.NumberStyles.HexNumber); //case DeviceValueDataType.U32IPV4: return valueInXml.ReinsetIllegalXMLChars( );// handled as a string default: if (type.IsText()) { // Do this as the last check to save CPU power return valueInXml.ReinsetIllegalXMLChars(); } throw new NotImplementedException("DataType '" + type + "' not recognized."); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "DecodeXML()", "dataType = " + type.ToString() + " Value is = " + valueInXml)); } } /// /// do layout changes on byte stream /// /// /// /// static byte[] DoLayout(this byte[] bytes, LayoutType layout = LayoutType.Normal) { try { switch (layout) { case LayoutType.Normal: return bytes; ; // Do nothing case LayoutType.SwapAll: return bytes.Reverse(); default: throw new NotSupportedException(layout + " is not supported"); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "DoLayout", "layout = " + layout)); } } /// /// Encode data with normal data layout /// /// /// /// Null if not used /// public static byte[] Encode(this object value, ValueDataType dataType, GetEmailCharacterSetToUse emailCharacterSet = null) { try { if (value == null) { throw new Exception("Value is null"); } switch (dataType) { case ValueDataType.B8: case ValueDataType.U8: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(byte));// Try set type if not the correct one return BitConverter.GetBytes((byte)value); } case ValueDataType.S8: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(sbyte));// Try set type if not the correct one return BitConverter.GetBytes((sbyte)value); } case ValueDataType.B16: case ValueDataType.U16: case ValueDataType.U16MJK_SN: return BitConverter.GetBytes((UInt16)value); case ValueDataType.U32TIME_Y1970: if (value is DateTime) { return BitConverter.GetBytes(((DateTime)value).ConvertTimeTo1970Sec(TimeType.Local)); } return BitConverter.GetBytes((UInt32)value); // Work around on olde types case ValueDataType.U32TIME_Y1970_UTC: if (value is DateTime) { return BitConverter.GetBytes(((DateTime)value).ConvertTimeTo1970Sec(TimeType.UTC)); } return BitConverter.GetBytes((UInt32)value); // Work around on olde types case ValueDataType.U32TIME_Y2000: if (value is DateTime) { return BitConverter.GetBytes(((DateTime)value).ConvertTimeTo2000Sec(TimeType.Local)); } return BitConverter.GetBytes((UInt32)value); // Work around on olde types //case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: // return BitConverter.GetBytes( TimeConvertClass.ToMidnightSecOffsetUTC( (UInt32)value ) ); //case DeviceValueDataType.U24DateHH_MM_SS: { // var timeSpan = TimeConvertClass.ConvertTimeSpan( (UInt32)value ); // return new byte[] { (byte)timeSpan.Seconds, (byte)timeSpan.Minutes, (byte)timeSpan.Hours }; // } //case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: { // var date = ((UInt32)value).Convert1970SecToTime( TimeType.Local ); // return new byte[] { // (byte)date.Second, // (byte)date.Minute, // (byte)date.Hour, // (byte)date.Day, // (byte)date.Month, // (byte)(date.Year - 2000) // }; // } //case DeviceValueDataType.U24: { // value = CorrectTypeIfNotTheSame( value, dataType, typeof( UInt32 ) );// Try set type if not the correct one // return BitConverter.GetBytes( (UInt32)value ).Remove( 3 ); // } case ValueDataType.B32: case ValueDataType.U32: case ValueDataType.U32MJK_SN: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(UInt32));// Try set type if not the correct one return BitConverter.GetBytes((UInt32)value); } case ValueDataType.B64: case ValueDataType.U64: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(UInt64));// Try set type if not the correct one return BitConverter.GetBytes((UInt64)value); } case ValueDataType.S16: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(Int16));// Try set type if not the correct one return BitConverter.GetBytes((Int16)value); } case ValueDataType.S32: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(Int32));// Try set type if not the correct one return BitConverter.GetBytes((Int32)value); } case ValueDataType.F32: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(Single));// Try set type if not the correct one return BitConverter.GetBytes((Single)value); } case ValueDataType.F64: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(double));// Try set type if not the correct one return BitConverter.GetBytes((double)value); } case ValueDataType.U128: { value = CorrectTypeIfNotTheSame(value, dataType, typeof(BigInteger));// Try set type if not the correct one return ((BigInteger)value).ToByteArray(); // TODO: Is this okay or need always to be the 16 byte in size? } //case DeviceValueDataType.U32IPV4: return U32_IP_Encoder.Encode( value.ToString( ) ); default: if (dataType.IsText()) { // Do this as the last check to save CPU power var typeAsText = dataType.ToString(); // is Email if (dataType.IsEmailText()) { return StringEncoderEmail.Encode(value.ToString(), Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet())); } // is SMS if (dataType.IsSMSText()) { return StringEncoderUnicode.Encode(value.ToString(), Length(dataType)); } // is Windows 1252 if (dataType.IsWindows1252Text()) { return StringEncoder_W1252.Encode(value.ToString(), Length(dataType)); } // is Windows 1252, but needs to have "<>" in frond and end // Ex. end result is "," or "" if (dataType.IsWindows1252TextRecipient()) { var valueAsText = value.ToString().Trim(); if (!String.IsNullOrEmpty(valueAsText)) { // Remove manual added brackets or " if user has done it in the past if (valueAsText.Contains("\"")) { valueAsText = valueAsText.Replace("\"", ""); } //// work arround if user has already used "," as separation //if (valueAsText.Contains( "," )) { // valueAsText = valueAsText.Replace( ",", ">,<" ); //old modem firmware V1.003 and TDC NO //} // Replace ";" with correct "," as separation and add bracked ">" "<" to support RCF821 if (valueAsText.Contains(";")) { //valueAsText = valueAsText.Replace( ";", ">,<" ); old modem firmware V1.003 and TDC NO valueAsText = valueAsText.Replace(";", ",");//new modem firmware V1.3 using mail.mjk-link.dk } // Trim valueAsText = valueAsText.Trim(); // Add brackets "<>" around address / addresses and end with " to tell modem where it starts and end in MC55I at command //Ex. end result is "," or "" if (!String.IsNullOrEmpty(valueAsText)) { //valueAsText = "\"<" + valueAsText + "\">"; old modem firmware V1.003 and TDC NO valueAsText = "\"" + valueAsText + "\""; //new modem firmware V1.3 using mail.mjk-link.dk } } return StringEncoder_W1252.Encode(valueAsText, Length(dataType)); } // is Quoted Printable Text if (dataType.IsEmailQuotedPrintableText()) { return StringEncoderEmail_Q_Types.Encode(value.ToString(), Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet())); } // Is is normal utf8 return StringEncoder.Encode(value.ToString(), Length(dataType)); } throw new NotImplementedException("DataType '" + dataType + "' not recognized."); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Encode", "dataType = " + dataType.ToString())); } } private static object CorrectTypeIfNotTheSame(object value, ValueDataType correctTypeTag, Type typeUsedForCast) { try { if (value.GetType() == typeUsedForCast) { return value; // Nothing to change } { AppConst.Logger.AddFuncLog( #if DEBUG // true // log as error #else false // Log silent in log #endif //#if DEBUG , typeof(DeviceValueEncoder).ToString(), "CorrectTypeIfNotTheSame()", "Warning! correction was needed. Is this a older setting else not okay? " + MakeCorrectTypeValueInfoText(value, correctTypeTag, typeUsedForCast) ); } return ToValue(value.ToString(), correctTypeTag); } catch (Exception ex) { var valueInfo = MakeCorrectTypeValueInfoText(value, correctTypeTag, typeUsedForCast); throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "CorrectTypeIfNotTheSame", valueInfo)); } } /// /// Generate the value info possible to get for a value to convert /// /// Value to correct /// correct value type tag /// type used for cast /// Text to show in log private static string MakeCorrectTypeValueInfoText(object value, ValueDataType correctTypeTag, Type typeUsedForCast) { var ValueInfo = ""; try { if (ValueInfo == null) { ValueInfo += " Value= IS NULL and not possible to correct!"; } else { ValueInfo += " Value=\"" + value.ToString() + "\""; ValueInfo += " From Type=\"" + value.GetType() + "\""; } ValueInfo += " To Type=\"" + correctTypeTag.ToString() + "\""; } catch { ValueInfo += " [Fail to get info ?] "; } return ValueInfo; } /// /// Encode data with data layout setting /// /// /// /// /// Null if not used /// public static byte[] Encode(this object value, ValueDataType dataType, LayoutType layout, GetEmailCharacterSetToUse emailCharacterSet = null) { try { var bytes = Encode(value, dataType, emailCharacterSet); if (bytes == null) { return bytes; } return bytes.DoLayout(layout); } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Encode", "dataType = " + dataType.ToString())); } } /// /// Decode data with normal data layout /// /// /// /// Null if not used /// public static object Decode(this byte[] value, ValueDataType dataType, GetEmailCharacterSetToUse emailCharacterSet = null) { try { if (value == null) { throw new Exception("Value is null"); } if (value.Count() == 0) { throw new Exception("Value Has no values in array"); } switch (dataType) { case ValueDataType.B8: case ValueDataType.U8: return (byte)value.First(); case ValueDataType.S8: return (sbyte)value.First(); case ValueDataType.B16: case ValueDataType.U16: case ValueDataType.U16MJK_SN: return BitConverter.ToUInt16(value, 0); case ValueDataType.U32TIME_Y1970: return BitConverter.ToUInt32(value, 0).Convert1970SecToTime(TimeType.Local); case ValueDataType.U32TIME_Y1970_UTC: return BitConverter.ToUInt32(value, 0).Convert1970SecToTime(TimeType.UTC).ToLocalTime(); case ValueDataType.U32TIME_Y2000: return BitConverter.ToUInt32(value, 0).Convert2000SecToTime(); //case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: // return TimeConvertClass.FromMidnightSecOffsetUTC( BitConverter.ToUInt32( value, 0 ) ); //case DeviceValueDataType.U24DateHH_MM_SS: { // return (UInt32)((UInt32)value[ 2 ] * 3600) + ((UInt32)value[ 1 ] * 60 + (UInt32)value[ 0 ]); // } //case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: { // var date = new DateTime( (int)value[ 5 ] + 2000, value[ 4 ], value[ 3 ], value[ 2 ], value[ 1 ], value[ 0 ] ); // return date.ConvertTimeTo1970Sec( TimeType.Local ); // } //case DeviceValueDataType.U24: { // var as32bitValue = new byte[] { value[ 0 ], value[ 1 ], value[ 2 ], 0 }; // return BitConverter.ToUInt32( as32bitValue, 0 ); // } case ValueDataType.B32: case ValueDataType.U32: case ValueDataType.U32MJK_SN: return BitConverter.ToUInt32(value, 0); case ValueDataType.B64: case ValueDataType.U64: return BitConverter.ToUInt64(value, 0); case ValueDataType.S16: return BitConverter.ToInt16(value, 0); case ValueDataType.S32: return BitConverter.ToInt32(value, 0); case ValueDataType.F32: return BitConverter.ToSingle(value, 0); case ValueDataType.F64: return BitConverter.ToDouble(value, 0); case ValueDataType.U128: { // Need a zero in msb to avoid value is handled as signed var valueConverted = new BigInteger((value).Concat(new byte[1]).ToArray()); return valueConverted; } case ValueDataType.Array6B: case ValueDataType.Array10B: case ValueDataType.Array12B: case ValueDataType.Array64B: case ValueDataType.Array128B: case ValueDataType.Array136B: case ValueDataType.Array250B: return value; //case DeviceValueDataType.U32IPV4: return U32_IP_Encoder.Decode( value ); default: if (dataType.IsText()) { // Do this as the last check to save CPU power var typeAsText = dataType.ToString(); if (dataType.IsEmailText()) { // is Email return StringEncoderEmail.Decode(value, Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet())); } if (dataType.IsSMSText()) { // is SMS return StringEncoderUnicode.Decode(value, Length(dataType)); } if (dataType.IsWindows1252Text()) { // is Windows 1252 return StringEncoder_W1252.Decode(value, Length(dataType)); } if (dataType.IsWindows1252TextRecipient()) { // is Windows 1252, but needs to have "<>" in frond and end var valueAsText = StringEncoder_W1252.Decode(value, Length(dataType)); if (!String.IsNullOrEmpty(valueAsText)) { // Remove added brackets or " nessesarry that is only to be // Ex. end result is "," or "" if (valueAsText.Contains("\"")) { valueAsText = valueAsText.Replace("\"", ""); } if (valueAsText.Contains("<")) { valueAsText = valueAsText.Replace("<", ""); } if (valueAsText.Contains(">")) { valueAsText = valueAsText.Replace(">", ""); } // Replace email seperation and replace it with correct the standard ";" if (valueAsText.Contains(",")) { valueAsText = valueAsText.Replace(",", ";"); } } return valueAsText; } if (dataType.IsEmailQuotedPrintableText()) { return StringEncoderEmail_Q_Types.Decode(value, Length(dataType), ((emailCharacterSet == null) ? "" : emailCharacterSet())); } // Is allowed to have a variable length on a string / text var maxLng = dataType.Length(); if (value.Length > maxLng) { throw new Exception(String.Format("Size of text is {0} and more than max {1}", value.Length, maxLng)); } // Is is normal utf8 return StringEncoder.Decode(value, value.Length); } throw new NotImplementedException("DataType '" + dataType + "' not recognized."); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Decode", "dataType = " + dataType.ToString())); } } /// /// Decode data with data layout setting /// /// /// /// Null if not used /// /// public static object Decode(this byte[] value, ValueDataType dataType, LayoutType layout, GetEmailCharacterSetToUse emailCharacterSet = null) { try { var bytes = value.DoLayout(layout); return Decode(value, dataType, emailCharacterSet); } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Encode", "dataType = " + dataType.ToString())); } } /// /// Convert a local defined string value to the correct value object according to dataType ("DeviceValueType") /// /// Value as string (floating point must use local setting for "," or ".") and DateTime as local time /// /// public static object ToValue(this string value, ValueDataType dataType) { try { if (value == null) { throw new Exception("Value is null"); } switch (dataType) { case ValueDataType.B8: case ValueDataType.U8: return (byte)Convert.ToUInt16(value); case ValueDataType.S8: return (sbyte)Convert.ToInt16(value); case ValueDataType.B16: case ValueDataType.U16: case ValueDataType.U16MJK_SN: return Convert.ToUInt16(value); case ValueDataType.U32TIME_Y1970: case ValueDataType.U32TIME_Y1970_UTC: case ValueDataType.U32TIME_Y2000: // Always expect this as local time return new DateTime(Convert.ToDateTime(value).Ticks, DateTimeKind.Local); //case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: //case DeviceValueDataType.U24DateHH_MM_SS: //case DeviceValueDataType.U24: case ValueDataType.B32: case ValueDataType.U32: case ValueDataType.U32MJK_SN: return Convert.ToUInt32(value); case ValueDataType.B64: case ValueDataType.U64: return Convert.ToUInt64(value); case ValueDataType.S16: return Convert.ToInt16(value); case ValueDataType.S32: return Convert.ToInt32(value); case ValueDataType.F32: return Convert.ToSingle(value); case ValueDataType.F64: return Convert.ToDouble(value); case ValueDataType.U128: // Need a zero in msb to avoid value is handled as signed return BigInteger.Parse("0"+value, System.Globalization.NumberStyles.HexNumber); //case DeviceValueDataType.U32IPV4: { // if (dataType.IsText( )) { // return value.ToString( ); // } // throw new NotImplementedException( "DataType '" + dataType + "' not recognized." ); // } default: if (dataType.IsText()) { // Do this as the last check to save CPU power var typeAsText = dataType.ToString(); if (dataType.IsEmailText()) { // is Email return value; } if (dataType.IsSMSText()) { // is SMS return value; } if (dataType.IsWindows1252Text()) { // is Windows 1252 return value; } if (dataType.IsWindows1252TextRecipient()) { // is Windows 1252, but needs to have "<>" in frond and end return value; } if (dataType.IsEmailQuotedPrintableText()) { // is Special Email Quoted Printable return value; } // Is is normal utf8 return value; //TODO: No converting is done. may have to be converted to utf8? } throw new NotImplementedException("DataType '" + dataType + "' not recognized."); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "ToValue()", "dataType = " + dataType.ToString())); } } /// /// Return data Byte Length (1x8bit) /// /// public static int Length(this ValueDataType DataType) { try { switch (DataType) { case ValueDataType._Empty: return 0; #region ---- 8 Bit ---- case ValueDataType.Bool: case ValueDataType.B8: case ValueDataType.S8: case ValueDataType.U8: return 1; #endregion // #region ---- 8 Bit ---- //case DeviceValueDataType.U24DateHH_MM_SS: //case DeviceValueDataType.U24: return 3; //case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: return 6; default: return WLength(DataType) << 1; } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "Length")); } } /// /// Return data Word Length (2x8bit) /// /// public static int WLength(this ValueDataType DataType) { try { switch (DataType) { case ValueDataType._Empty: return 0; #region ---- 8 / 16 Bit ---- case ValueDataType.Bool: case ValueDataType.B8: case ValueDataType.S8: case ValueDataType.U8: case ValueDataType.U16: case ValueDataType.U16MJK_SN: case ValueDataType.B16: case ValueDataType.S16: case ValueDataType.U16TEXTID: case ValueDataType.U16UNIT: case ValueDataType.U16UNITGROUP: return 1; #endregion //case DeviceValueDataType.U48DateYY_MM_DD_HH_MM_SS: return 3; //case DeviceValueDataType.U24DateHH_MM_SS: //case DeviceValueDataType.U24: return 2; #region ---- 32 Bit ---- case ValueDataType.B32: case ValueDataType.U32: case ValueDataType.U32MJK_SN: case ValueDataType.S32: case ValueDataType.F32: //case DeviceValueDataType.U32TIMESPAN_MIDNIGHT_UTC: case ValueDataType.U32TIME_Y2000: case ValueDataType.U32TIME_Y1970: case ValueDataType.U32TIME_Y1970_UTC: //case DeviceValueDataType.U32IPV4: return 2; #endregion #region ---- 12 x 8 Bit Time Types ---- case ValueDataType.TIME_ASCII_12B: case ValueDataType.TIME_ymdhms: return 6; #endregion #region ---- 64 Bit ---- case ValueDataType.B64: case ValueDataType.U64: case ValueDataType.S64: case ValueDataType.F64: return 4; #endregion #region ---- 128 Bit ---- case ValueDataType.U128: return 8; #endregion #region ---- Bit Arrays ---- case ValueDataType.Array6B: return (6 / 2); case ValueDataType.Array10B: return (10 / 2); case ValueDataType.Array12B: return (12 / 2); case ValueDataType.Array64B: return (64 / 2); case ValueDataType.Array128B: return (128 / 2); case ValueDataType.Array136B: return (136 / 2); case ValueDataType.Array250B: return (250 / 2); #endregion #region ---- Strings / Text ---- //6bytes case ValueDataType.STR6E: case ValueDataType.STR6S: //case DeviceValueDataType.STR6Q: //case DeviceValueDataType.STR6W1252: case ValueDataType.STR6: return 3; //8bytes case ValueDataType.STR8E: case ValueDataType.STR8S: //case DeviceValueDataType.STR8Q: //case DeviceValueDataType.STR8W1252: case ValueDataType.STR8: return 4; //10bytes case ValueDataType.STR10E: case ValueDataType.STR10S: //case DeviceValueDataType.STR10Q: //case DeviceValueDataType.STR10W1252: case ValueDataType.STR10: return 5; //16bytes case ValueDataType.STR16E: case ValueDataType.STR16S: //case DeviceValueDataType.STR16Q: //case DeviceValueDataType.STR16W1252: case ValueDataType.STR16: return 8; //18bytes case ValueDataType.STR18E: case ValueDataType.STR18S: //case DeviceValueDataType.STR18Q: //case DeviceValueDataType.STR18W1252: case ValueDataType.STR18: return 9; //20bytes case ValueDataType.STR20E: case ValueDataType.STR20S: //case DeviceValueDataType.STR20Q: //case DeviceValueDataType.STR20W1252: case ValueDataType.STR20: return 10; //22bytes case ValueDataType.STR22E: case ValueDataType.STR22S: //case DeviceValueDataType.STR22Q: //case DeviceValueDataType.STR22W1252: case ValueDataType.STR22: return 11; //30bytes case ValueDataType.STR30E: case ValueDataType.STR30S: //case DeviceValueDataType.STR30Q: //case DeviceValueDataType.STR30W1252: case ValueDataType.STR30: return 15; //32bytes case ValueDataType.STR32E: case ValueDataType.STR32S: //case DeviceValueDataType.STR32Q: //case DeviceValueDataType.STR32W1252: case ValueDataType.STR32: return 16; //64bytes case ValueDataType.STR64E: case ValueDataType.STR64S: //case DeviceValueDataType.STR64Q: //case DeviceValueDataType.STR64W1252: case ValueDataType.STR64: return 32; //100bytes case ValueDataType.STR100E: case ValueDataType.STR100S: //case DeviceValueDataType.STR100Q: //case DeviceValueDataType.STR100W1252: case ValueDataType.STR100: return 50; //128bytes case ValueDataType.STR128E: case ValueDataType.STR128S: //case DeviceValueDataType.STR128Q: //case DeviceValueDataType.STR128W1252: //case DeviceValueDataType.STR128W1252rec: case ValueDataType.STR128: return 64; //160bytes //case DeviceValueDataType.STR160E: //case DeviceValueDataType.STR160S: //case DeviceValueDataType.STR160Q: //case DeviceValueDataType.STR160W1252: //case DeviceValueDataType.STR160: return 80; //240bytes case ValueDataType.STR240E: case ValueDataType.STR240S: //case DeviceValueDataType.STR240Q: //case DeviceValueDataType.STR240W1252: case ValueDataType.STR240: return 240; #endregion default: throw (new Exception("No known length for tag = " + DataType.ToString())); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "WLength")); } } /// /// Return the text length for value type if it is a text /// /// public static int StringLength(this ValueDataType DataType) { try { switch (DataType) { //case DeviceValueDataType.U32IPV4: return (4 * 3 + 3); default: if (DataType.IsSMSText()) { // is SMS return DataType.Length() / 2; // is always 16bit } return Length(DataType); } } catch (Exception ex) { throw new Exception(ex.ToFuncErrorText(typeof(DeviceValueEncoder).ToString(), "StringLength")); } } } }