/// /// Copyright (c) 2015 Sensus Metering Systems /// Author: Milan Hanajík /// using System; namespace TBF.BenchControl.WaterMeters.iPerl { public class StatusStruct { public static readonly int Length = 48; public Byte Version; public FlowState FlowState; public UInt32 BillingVolume; public UInt32 ForwardVolume; public UInt32 ReverseVolume; public UInt32 SecondsActive; public UInt32 SecondsIdle; public UInt32 SecondsUsed; public UInt32 UTC; public Int32 ScaledAvgFlowRate; public UInt16 PeakFlowRate; public UInt16 AlarmState; public byte RebootCount; public byte[] AlarmCount; public UInt16 FlipTime; public StatusStruct() { AlarmCount = new byte[7]; } public byte[] ToByteArray() { byte[] result = new byte[Length]; result[0] = Version; result[1] = (byte)FlowState; result[2] = (byte)(BillingVolume & 0x000000FF); result[3] = (byte)((BillingVolume >> 8) & 0x000000FF); result[4] = (byte)((BillingVolume >> 16) & 0x000000FF); result[5] = (byte)((BillingVolume >> 24) & 0x000000FF); result[6] = (byte)(ForwardVolume & 0x000000FF); result[7] = (byte)((ForwardVolume >> 8) & 0x000000FF); result[8] = (byte)((ForwardVolume >> 16) & 0x000000FF); result[9] = (byte)((ForwardVolume >> 24) & 0x000000FF); result[10] = (byte)(ReverseVolume & 0x000000FF); result[11] = (byte)((ReverseVolume >> 8) & 0x000000FF); result[12] = (byte)((ReverseVolume >> 16) & 0x000000FF); result[13] = (byte)((ReverseVolume >> 24) & 0x000000FF); result[14] = (byte)(SecondsActive & 0x000000FF); result[15] = (byte)((SecondsActive >> 8) & 0x000000FF); result[16] = (byte)((SecondsActive >> 16) & 0x000000FF); result[17] = (byte)((SecondsActive >> 24) & 0x000000FF); result[18] = (byte)(SecondsIdle & 0x000000FF); result[19] = (byte)((SecondsIdle >> 8) & 0x000000FF); result[20] = (byte)((SecondsIdle >> 16) & 0x000000FF); result[21] = (byte)((SecondsIdle >> 24) & 0x000000FF); result[22] = (byte)(SecondsUsed & 0x000000FF); result[23] = (byte)((SecondsUsed >> 8) & 0x000000FF); result[24] = (byte)((SecondsUsed >> 16) & 0x000000FF); result[25] = (byte)((SecondsUsed >> 24) & 0x000000FF); result[26] = (byte)(UTC & 0x000000FF); result[27] = (byte)((UTC >> 8) & 0x000000FF); result[28] = (byte)((UTC >> 16) & 0x000000FF); result[29] = (byte)((UTC >> 24) & 0x000000FF); result[30] = (byte)(ScaledAvgFlowRate & 0x000000FF); result[31] = (byte)((ScaledAvgFlowRate >> 8) & 0x000000FF); result[32] = (byte)((ScaledAvgFlowRate >> 16) & 0x000000FF); result[33] = (byte)((ScaledAvgFlowRate >> 24) & 0x000000FF); /// TODO: test with negative value result[34] = (byte)(PeakFlowRate & 0x00FF); result[35] = (byte)((PeakFlowRate >> 8) & 0x00FF); result[36] = (byte)(AlarmState & 0x00FF); result[37] = (byte)((AlarmState >> 8) & 0x00FF); result[38] = RebootCount; result[39] = AlarmCount[0]; result[40] = AlarmCount[1]; result[41] = AlarmCount[2]; result[42] = AlarmCount[3]; result[43] = AlarmCount[4]; result[44] = AlarmCount[5]; result[45] = AlarmCount[6]; result[46] = (byte)(FlipTime & 0x00FF); result[47] = (byte)((FlipTime >> 8) & 0x00FF); return result; } public static StatusStruct FromByteArray(byte[] data) { if (data.Length != Length) return null; StatusStruct result = new StatusStruct(); result.Version = data[0]; result.FlowState = (FlowState)data[1]; result.BillingVolume = (((UInt32)data[5] * 256 + data[4]) * 256 + data[3]) * 256 + data[2]; result.ForwardVolume = (((UInt32)data[9] * 256 + data[8]) * 256 + data[7]) * 256 + data[6]; result.ReverseVolume = (((UInt32)data[13] * 256 + data[12]) * 256 + data[11]) * 256 + data[10]; result.SecondsActive = (((UInt32)data[17] * 256 + data[16]) * 256 + data[15]) * 256 + data[14]; result.SecondsIdle = (((UInt32)data[21] * 256 + data[20]) * 256 + data[19]) * 256 + data[18]; result.SecondsUsed = (((UInt32)data[25] * 256 + data[24]) * 256 + data[23]) * 256 + data[22]; result.UTC = (((UInt32)data[29] * 256 + data[28]) * 256 + data[27]) * 256 + data[26]; result.ScaledAvgFlowRate = (((Int32)data[33] * 256 + data[32]) * 256 + data[31]) * 256 + data[30]; /// TODO: test with negative value result.PeakFlowRate = (UInt16)(data[34] + 256 * data[35]); result.AlarmState = (UInt16)(data[36] + 256 * data[37]); result.RebootCount = data[38]; result.AlarmCount[0] = data[39]; result.AlarmCount[1] = data[40]; result.AlarmCount[2] = data[41]; result.AlarmCount[3] = data[42]; result.AlarmCount[4] = data[43]; result.AlarmCount[5] = data[44]; result.AlarmCount[6] = data[45]; result.FlipTime = (UInt16)(data[46] * 256 + data[47]); return result; } public override string ToString() { return string.Format("Status: V{0} Flow={1} BillVol={2} ForwVol={3} RevVol={4} SecActive={5}s SecIdle={6}s SecUsed={7}s UTC={8} AvgFlowRate={9} PeekFlowRate={10} AlarmState={11} RebootCount={12} A0={13} A1={14} A2={15} A3={16} A4={17} A5={18} A6={19} FlipTime={20}", Version, FlowState, BillingVolume, ForwardVolume, ReverseVolume, SecondsActive, SecondsIdle, SecondsUsed, UTC, ScaledAvgFlowRate, PeakFlowRate, AlarmState, RebootCount, AlarmCount[0], AlarmCount[1], AlarmCount[2], AlarmCount[3], AlarmCount[4], AlarmCount[5], AlarmCount[6], FlipTime); } } }