using System; using System.Globalization; namespace TBF.BenchControl.WaterMeters.iPerl { public class OptoTelegram { public static readonly int Length = 42; public double EMF; public Int16 MagneticField; public double Flow; public double Volume; public Int16 Impedance; public UInt32 Timestamp; public byte GG; string sourceStr; public OptoTelegram() { } public override string ToString() { return sourceStr; } /// /// Create a configuration structure from a complete byte array /// /// Telegram description: /// /// AAAAAA[tab]BBBB[tab]CCCC[tab]DDDDDD[tab]EEEE[tab]FFFFFFFF[tab]GG[cr][lf] (42 bytes) /// /// Data Comment Type Calculate to decimal /// ---------------------------------------------------------------- /// AAAAAA EMF Int24 Value * 0.000000333 /// BBBB Magnetic field Int16 Value /// CCCC Flow Int16 Value * 0.225 * Scalig factor /// DDDDDD Volume Int24 Value / 16000 * Scaling factor /// EEEE Impedance Int16 Value /// FFFFFFFF Timestamp Uint32 Value / 8192 /// GG /// ---------------------------------------------------------------- /// /// Example: /// FFFFFE 51EA 0000 65324E 0087 F6319DFF 86 /// FFDD3A 51F9 0000 65324E 0088 F631A60B 45 /// ... /// /// A complete byte array data /// ConfigStruct or null when byte array was not complete public static OptoTelegram FromString(string telegram, MeterType meterType) { if ((telegram == null) || (telegram.Length < Length) || (telegram[6] != '\t') || (telegram[11] != '\t') || (telegram[16] != '\t') || (telegram[23] != '\t') || (telegram[28] != '\t') || (telegram[37] != '\t') || (telegram[40] != '\r') || (telegram[41] != '\n')) { return null; } OptoTelegram opto = new OptoTelegram(); Int32 value; if (Int32.TryParse(telegram.Substring(0, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value)) { Int32 svalue = (value >= 0x00800000) ? (value - 0x01000000) : value; opto.EMF = 0.000000333 * (double)svalue; } else return null; if (Int32.TryParse(telegram.Substring(7, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value)) { Int32 svalue = (value >= 0x00008000) ? (value - 0x00010000) : value; opto.MagneticField = (Int16)svalue; } else return null; double factor = ScalingFactor(meterType); if (Int32.TryParse(telegram.Substring(12, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value)) { Int32 svalue = (value >= 0x00008000) ? (value - 0x00010000) : value; opto.Flow = 0.225 * (double)svalue * factor; } else return null; if (Int32.TryParse(telegram.Substring(17, 6), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value)) { Int32 svalue = (value >= 0x00800000) ? (value - 0x01000000) : value; opto.Volume = (double)svalue / 16000.0 * factor; } else return null; if (Int32.TryParse(telegram.Substring(24, 4), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out value)) { Int32 svalue = (value >= 0x00008000) ? (value - 0x00010000) : value; opto.Impedance = (Int16)svalue; } else return null; UInt32 uvalue; if (UInt32.TryParse(telegram.Substring(29, 8), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uvalue)) { opto.Timestamp = uvalue; } else return null; if (UInt32.TryParse(telegram.Substring(38, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out uvalue)) { opto.GG = (byte)uvalue; } else return null; opto.sourceStr = telegram.Substring(0, Length - 2); return opto; } /// /// Scaling factor: /// 0, 1 (DN15, Coax) . . . . 1 /// 2 (DN20) . . . . . . . . 2 /// 3 (DN25) . . . . . . . . 4 /// 4, 5 (DN26, DN32) . . . . 8 /// 6 (DN40) . . . . . . . . 16 /// /// MeterType (0..6) /// Scaling factor public static double ScalingFactor(MeterType meterType) { switch (meterType) { default: case MeterType.DN15: case MeterType.CoaxManifold: return 1.0; case MeterType.DN20: return 2.0; case MeterType.DN25: return 4.0; case MeterType.DN26: case MeterType.DN32: return 8.0; case MeterType.DN40: return 16.0; } } } }