tbf/Workplace/CheckItems/S640/DatastreamFrame.cs

102 lines
3.7 KiB
C#

///
/// 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() { }
/// <summary>
/// Parses optical telegram and returns OptoTelegramRaw object
/// </summary>
/// <description>
/// 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
/// ...
/// </description>
/// <param name="data">A complete byte array data</param>
/// <returns>true = telegram OK, false = telegram NOK</returns>
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());
}
}
}