/// /// Copyright (c) 2021 Sensus Slovensko a.s. /// using System; using System.Globalization; using System.Text; namespace Workplace.CheckItems.S640 { public class DatastreamFrame { public const int FrameLength = 49; /// Including CR,LF public const double VolumeScaleFactor = 1000.0; /// Raw volume is in ml public const double TimeScaleFactor = 1000.0; /// Raw time is in ms /// Stored values public DateTime DateTime; /// From PC public char[] Data = new char[FrameLength - 2]; public Int32 VolumeRaw; public Int64 VolumeRawExt; public Int64 Timestamp; public Int64 TimestampExt; /// Calculated values public double Volume() { return (double)VolumeRawExt / VolumeScaleFactor; } public double TimestampDbl() { return (double)TimestampExt / TimeScaleFactor; } public DatastreamFrame() { } /// /// Parses optical telegram and returns OptoTelegramRaw object /// /// /// Create a configuration structure from a complete byte array /// /// Telegram description: /// /// AAAAAAAAAAAA[tab]BBBBBBBBBB[tab]CCCCCCCCC[tab]DDDDDDDDDD[tab]EE[cr][lf] (49 bytes) /// /// Data Comment Type Calculate to decimal /// ---------------------------------------------------------------- /// AAAAAAAAAAAA PCB number Decimal /// BBBBBBBBBB Radio address Decimal /// CCCCCCCCC Meter reading Decimal Volume in ml /// DDDDDDDDDD Timestamp Decimal Time in ms /// EE Checksum Hexadecimal /// ---------------------------------------------------------------- /// /// Example: /// 540210730770 4291524429 000250215 0433411626 4F /// 540210730770 4291524429 000250215 0433411876 56 /// ... /// /// A complete byte array data /// true = telegram OK, false = telegram NOK public bool UpdateFromString(string frame, ref Int64 volumeRawExtLast, ref Int64 timestampExtLast) { DateTime = DateTime.Now; if (frame == null || frame.Length < FrameLength || frame[FrameLength - 2] != '\r' || frame[FrameLength - 1] != '\n' || frame[12] != '\t' || frame[23] != '\t' || frame[33] != '\t' || frame[44] != '\t') { return false; } /// Copy data into the fixed size buffer int sum = 0; for (int i = 0; i < FrameLength - 4; i++) { Data[i] = frame[i]; sum += (int)frame[i]; } Data[FrameLength - 4] = frame[FrameLength - 4]; Data[FrameLength - 3] = frame[FrameLength - 3]; byte checkSum; bool chksumOk = byte.TryParse(frame.Substring(FrameLength - 4, 2), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out checkSum) && checkSum == (sum & 0xFF); bool volumeOk = Int32.TryParse(frame.Substring(24, 9), out VolumeRaw); volumeRawExtLast = VolumeRawExt = VolumeRaw; bool timeOk = Int64.TryParse(frame.Substring(34, 10), out Timestamp); timestampExtLast = TimestampExt = Timestamp; bool allOk = volumeOk && timeOk && chksumOk; return allOk; } public override string ToString() { StringBuilder sb = new StringBuilder(FrameLength - 2); for (int i = 0; i < FrameLength - 2; i++) sb.Append(Data[i]); return string.Format("{0:HH:mm:ss.fff} {1} T={2} V={3}", DateTime, sb.ToString().Replace("\t","~"), TimestampDbl(), Volume()); } } }