using Edge.Core.Parser.BinaryParser.Util;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace VeederRoot_ATG_Console.MessageEntity.Incoming
{
///
/// i|I201
///
public class QueryInTankInventoryReportResponse : IncomingMessageBase
{
public DateTime? CurrentDateAndTime
{
get
{
if (base.FunctionCode.Item1 == MessageFormat.Display)
return null;
return DateTime.ParseExact(
Encoding.ASCII.GetString(base.DataFieldAndOptionalCheckSumAndETX.Take(10).ToArray()),
"yyMMddHHmm", CultureInfo.InvariantCulture);
}
}
public int? TankNumberInFunctionCode
{
get
{
if (base.FunctionCode.Item1 == MessageFormat.Display)
return null;
var r = int.Parse(base.FunctionCode.Item3);
return r;
}
}
public List InventoryDatas
{
get
{
// skip 10 bytes of current date and time
var rawDataBody = base.DataFieldAndOptionalCheckSumAndETX.Skip(10)
//and exclude tail of -> && + 4 bytes check sum + ETX <- which is total 7 bytes.
.Take(base.DataFieldAndOptionalCheckSumAndETX.Count - 10 - 7);
/*
* TT - Tank Number (Decimal, 00=all) - 2 bytes
* p - Product Code (one ASCII character [20h-7Eh]) - 1 bytes
* ssss - Tank Status Bits - 4 bytes
* NN - Number of eight character Data Fields to follow (Hex) - 2 bytes
*
* ABOVE TOTAL LEN IS 9
*/
var datas = new List();
int previousTotalDataCount = 0;
while (true)
{
var buffer = rawDataBody.Skip(previousTotalDataCount);
if (buffer.Count() < 7)
throw new ArgumentException("Min bytes count for describe an i201 tank report is 7, but now is " + buffer.Count());
var numberOfEightCharDataFieldsValue
= int.Parse(Encoding.ASCII.GetString(buffer.Skip(7).Take(2).ToArray()));
if (numberOfEightCharDataFieldsValue < 1 || numberOfEightCharDataFieldsValue > 99)
throw new ArgumentException("number Of Eight Char DataFields to follow must range from 1 to 99, but now is: " + numberOfEightCharDataFieldsValue);
datas.Add(new InventoryData(
buffer.Take(7 + 2 + 8 * numberOfEightCharDataFieldsValue).ToArray()));
previousTotalDataCount += 7 + 2 + 8 * numberOfEightCharDataFieldsValue;
if (previousTotalDataCount == rawDataBody.Count()) break;
}
return datas;
}
}
public override string ToLogString()
{
if (base.FunctionCode.Item1 == MessageFormat.Display)
return Encoding.ASCII.GetString(base.DataFieldAndOptionalCheckSumAndETX.ToArray());
return this.GetType().Name + " Current DateTime: " + this.CurrentDateAndTime.Value.ToString("yyyy-MM-dd HH:mm")
+ ", TankNumber_InFunctionCode: " + this.TankNumberInFunctionCode
+ ", data: " + this.InventoryDatas.Select(d => d.ToFullLogString())
.Aggregate((acc, n) => acc + " || " + n);
}
public class InventoryData
{
private byte[] bytes;
public enum TankState
{
DeliveryInProgress_LSB,
LeakTestInProgress,
InvalidFuelHeighAlarm_MagProbesOnly,
Unknown,
}
public enum TankReadingDataName
{
Volume = 1,
TC_Volume = 2,
Ullage = 3,
Height = 4,
Water = 5,
Temperature = 6,
WaterVolume = 7,
}
public InventoryData(byte[] bytes)
{
this.bytes = bytes;
}
public int? TankNumber
{
get
{
var r = int.Parse(Encoding.ASCII.GetString(this.bytes.Take(2).ToArray()));
return r;
}
}
public char? ProductCode
{
get
{
return
Encoding.ASCII.GetString(
this.bytes.Skip(2).Take(1).ToArray())[0];
}
}
public List States
{
get
{
/* 4 ascii encoded bytes,
* check 16 bits to get the states
* say now the raw data here is: 0x30,0x30,0x30,0x39
* then target byte here is the last byte of value 9 which binary format is 0000 1001.
* so is bit 0 is 1, indicates the TankState.DeliveryInProgress_LSB
*/
var states = new List();
var tankStateBit = Util.ConvertHexBcdStrToBytes(this.bytes.Skip(3).Take(4).ToArray());
if (tankStateBit.Last().GetBit(0) == 1)
states.Add(TankState.DeliveryInProgress_LSB);
if (tankStateBit.Last().GetBit(1) == 1)
states.Add(TankState.LeakTestInProgress);
if (tankStateBit.Last().GetBit(2) == 1)
states.Add(TankState.InvalidFuelHeighAlarm_MagProbesOnly);
return states;
}
}
public int? NumberOfEightCharDataFieldsToFollow
{
get
{
var nn = int.Parse(Encoding.ASCII.GetString(this.bytes.Skip(7).Take(2).ToArray()));
//this.QueryInTankInventoryReportDatas = new List(nn);
return nn;
}
}
public Dictionary TankReadingDatas
{
get
{
var datas = new Dictionary();
for (int i = 0; i < this.NumberOfEightCharDataFieldsToFollow.Value; i++)
{
var asciiEncodedBytes = Util.ConvertHexBcdStrToBytes(this.bytes.Skip(9 + 8 * i).Take(8).ToArray());
var dataValue =
Util.ConvertIEEEWith4BytesToDouble(asciiEncodedBytes.ToArray());
switch (i + 1)
{
case 1: // VOLUME
datas.Add(TankReadingDataName.Volume, dataValue);
break;
case 2: // TC VOLUME
datas.Add(TankReadingDataName.TC_Volume, dataValue);
break;
case 3: // ULLAGE
datas.Add(TankReadingDataName.Ullage, dataValue);
break;
case 4: // HEIGHT
datas.Add(TankReadingDataName.Height, dataValue);
break;
case 5: // WATER HEIGHT
datas.Add(TankReadingDataName.Water, dataValue);
break;
case 6: // TEMPERATURE
datas.Add(TankReadingDataName.Temperature, dataValue);
break;
case 7: // WATER VOLUME
datas.Add(TankReadingDataName.WaterVolume, dataValue);
break;
}
}
return datas;
}
}
public string ToFullLogString()
{
return "Tank with Number: " + (this.TankNumber ?? -1) + " with ProductCode: " + (this.ProductCode ?? ' ')
+ " with States: " +
(this.States != null && this.States.Any() ? this.States.Select(s => s.ToString()).Aggregate((acc, n) => acc + "-" + n) : "")
+ ", data read: "
+ this.TankReadingDatas.Select(s => s.Key.ToString() + "-" + s.Value).Aggregate((acc, n) => acc + " | " + n);
}
public string ToSimpleLogString()
{
return "Tank with Number: " + (this.TankNumber ?? -1) + " has ProductCode: " + (this.ProductCode ?? ' ');
}
}
}
}