123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- using Edge.Core.IndustryStandardInterface.ATG;
- using System;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Linq;
- using System.Text;
- namespace VeederRoot_ATG_Console.MessageEntity.Incoming
- {
- /// <summary>
- /// i|I20C
- /// </summary>
- public class QueryInTankMostRecentDeliveryReportResponse : IncomingMessageBase
- {
- public int? TankNumberInFunctionCode
- {
- get
- {
- if (base.FunctionCode.Item1 == MessageFormat.Display)
- return null;
- var r = int.Parse(base.FunctionCode.Item3);
- return r;
- }
- }
- 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 List<DeliveriesForTank> DeliveriesForTanks
- {
- get
- {
- /* 2 layer nested structure */
- // 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);
- var datas = new List<DeliveriesForTank>();
- int previousTankElapsedByteCount = 0;
- while (true)
- {
- var buffer = rawDataBody.Skip(previousTankElapsedByteCount);
- if (!buffer.Any()) return datas;
- /*
- * TT - Tank Number (Decimal, 00=all) - 2 bytes
- * p - Product Code (one ASCII character [20h-7Eh]) - 1 bytes
- * dd - Number of Deliveries to follow (Decimal, 00 if no data available for this tank) - 2 bytes
- *
- * ABOVE TOTAL LEN IS fixed 5
- */
- //each tank section length is decided by a fixed length + variable length.
- var noOfDeliversToFollow =
- Util.ConvertHexBcdStrToBytes(buffer.Skip(3).Take(2).ToArray()).First();
- int previousDeliveryElapsedByteCount = 0;
- if (noOfDeliversToFollow == 0) { }
- else
- {
- int deliveriesProcessed = 0;
- //var deliveriesForTank = buffer.Skip(previousTankElapsedByteCount + 5);
- while (true)
- {
- if (deliveriesProcessed == noOfDeliversToFollow) break;
- var nextDelivery = buffer.Skip(5 + previousDeliveryElapsedByteCount + 10 + 10);
- if (!nextDelivery.Any()) throw new ArgumentException("Empty bytes for continue parsing Delivery");
- var numberOfEightCharDataFieldsValue
- = Util.ConvertHexBcdStrToBytes(nextDelivery.Take(2).ToArray()).First();
- previousDeliveryElapsedByteCount += 20 + 2 + numberOfEightCharDataFieldsValue * 8;
- deliveriesProcessed++;
- }
- };
- previousTankElapsedByteCount += 5 + previousDeliveryElapsedByteCount;
- datas.Add(new DeliveriesForTank(
- buffer.Take(previousDeliveryElapsedByteCount + 5).ToArray()));
- }
- }
- }
- public override string ToLogString()
- {
- return this.GetType().Name + " Deliveries: " +
- (DeliveriesForTanks != null && DeliveriesForTanks.Any() ?
- DeliveriesForTanks.Select(d => d.ToLogString()).Aggregate((acc, n) => acc + "||" + n)
- : "");
- }
- public class DeliveriesForTank
- {
- private byte[] bytes;
- /// <summary>
- ///
- /// </summary>
- /// <param name="bytes">TankNumber(2 bytes) + ProductCode(1 byte) + NoOfDeliveries(2 bytes)+ 20+2+No*8</param>
- public DeliveriesForTank(byte[] bytes)
- {
- this.bytes = bytes;
- }
- public int? TankNumber
- {
- get
- {
- var r = Encoding.ASCII.GetString(this.bytes.Take(2).ToArray());
- return int.Parse(r);
- }
- }
- public char? ProductCode
- {
- get
- {
- return
- Encoding.ASCII.GetString(this.bytes.Skip(2).Take(1).ToArray()).First();
- }
- }
- public int? NumberOfDeliveriesToFollow
- {
- get
- {
- var nn = Util.ConvertHexBcdStrToBytes(this.bytes.Skip(3).Take(2).ToArray()).First();
- return nn;
- }
- }
- public List<Delivery> Deliveries
- {
- get
- {
- if (this.NumberOfDeliveriesToFollow == 0) return null;
- // exclude 5 bytes of TT + p + dd.
- var loopParts = this.bytes.Skip(5);
- var datas = new List<Delivery>();
- int previousDeliveryByteCount = 0;
- while (true)
- {
- var numberOfEightCharDataFieldsValue
- = Util.ConvertHexBcdStrToBytes(
- loopParts.Skip(previousDeliveryByteCount + 20).Take(2).ToArray()).First();
- //if (numberOfEightCharDataFieldsValue < 1 || numberOfEightCharDataFieldsValue > 10)
- // throw new ArgumentException("number Of Eight Char DataFields to follow must range from 1 to 10, but now is: " + numberOfEightCharDataFieldsValue);
- datas.Add(
- new Delivery(this.TankNumber,
- loopParts.Skip(previousDeliveryByteCount)
- .Take(10 + 10 + 2 + 8 * numberOfEightCharDataFieldsValue).ToArray()));
- previousDeliveryByteCount += 10 + 10 + 2 + 8 * numberOfEightCharDataFieldsValue;
- if (previousDeliveryByteCount == loopParts.Count()) break;
- }
- return datas;
- }
- }
- public string ToLogString()
- {
- return "Tank with Number: " + (this.TankNumber ?? -1) + " has ProductCode: " + (this.ProductCode ?? ' ')
- + ", its NumberOfDeliveriesToFollow: " + (this?.NumberOfDeliveriesToFollow ?? 0)
- + " and details-> " +
- (Deliveries != null && Deliveries.Any() ?
- Deliveries.Select(d => d.ToFullLogString()).Aggregate((acc, n) => acc + "||" + n)
- : "");
- }
- }
- public class Delivery
- {
- //public enum ReadingDataName
- //{
- // StartingVolume = 1,
- // StartingTcVolume = 2,
- // StartingWater = 3,
- // StartingTemp = 4,
- // EndingVolume = 5,
- // EndingTcVolume = 6,
- // EndingWater = 7,
- // EndingTemp = 8,
- // StartingHeight = 9,
- // EndingHeight = 10,
- //}
- private byte[] bytes;
- public Delivery(int? tankNumber, byte[] bytes)
- {
- this.TankNumber = tankNumber;
- this.bytes = bytes;
- }
- public int? TankNumber { get; }
- public DateTime? StartingDateTime
- {
- get
- {
- return DateTime.ParseExact(
- Encoding.ASCII.GetString(this.bytes.Take(10).ToArray()),
- "yyMMddHHmm", CultureInfo.InvariantCulture);
- }
- }
- public DateTime? EndingDateTime
- {
- get
- {
- return DateTime.ParseExact(
- Encoding.ASCII.GetString(this.bytes.Take(10).ToArray()),
- "yyMMddHHmm", CultureInfo.InvariantCulture);
- }
- }
- public int? NumberOfEightCharDataFieldsToFollow
- {
- get
- {
- var nn = Util.ConvertHexBcdStrToBytes(this.bytes.Skip(20).Take(2).ToArray()).First();
- return nn;
- }
- }
- /// <summary>
- /// Get list of DelieveryReadingDataName:Value
- /// </summary>
- public Dictionary<DeliveryReadingDataName, double> Datas
- {
- get
- {
- var datas = new Dictionary<DeliveryReadingDataName, double>();
- for (int i = 0; i < this.NumberOfEightCharDataFieldsToFollow.Value; i++)
- {
- var asciiEncodedBytes = Util.ConvertHexBcdStrToBytes(this.bytes.Skip(20 + 2 + 8 * i).Take(8).ToArray());
- var dataValue =
- Util.ConvertIEEEWith4BytesToDouble(asciiEncodedBytes.ToArray());
- switch (i + 1)
- {
- case 1: // Starting Volume
- datas.Add(DeliveryReadingDataName.StartingVolume, dataValue);
- break;
- case 2: // Starting TC Volume
- datas.Add(DeliveryReadingDataName.StartingTcVolume, dataValue);
- break;
- case 3: // Starting Water
- datas.Add(DeliveryReadingDataName.StartingWater, dataValue);
- break;
- case 4: // Starting Temp
- datas.Add(DeliveryReadingDataName.StartingTemp, dataValue);
- break;
- case 5: // Ending Volume
- datas.Add(DeliveryReadingDataName.EndingVolume, dataValue);
- break;
- case 6: // Ending TC Volume
- datas.Add(DeliveryReadingDataName.EndingTcVolume, dataValue);
- break;
- case 7: // Ending Water
- datas.Add(DeliveryReadingDataName.EndingWater, dataValue);
- break;
- case 8: // Ending Temp
- datas.Add(DeliveryReadingDataName.EndingTemp, dataValue);
- break;
- case 9: // Starting Height
- datas.Add(DeliveryReadingDataName.StartingHeight, dataValue);
- break;
- case 10: // Ending Height
- datas.Add(DeliveryReadingDataName.EndingHeight, dataValue);
- break;
- default:
- // by seeing the real data from console, it may still hit here
- // the reason is the "Number of eight character Data Fields to follow (Hex)" > 10.
- // and meanwhile, extra bytes will be send in, may the VeederRoot leave it for extention
- // in future?
- break;
- }
- }
- return datas;
- }
- }
- public string ToFullLogString()
- {
- return "DeliveryDetail StartingDateTime: " + (this?.StartingDateTime?.ToString("yyMMddHHmm") ?? "")
- + ", EndingDateTime: " + (this?.EndingDateTime?.ToString("yyMMddHHmm") ?? "")
- + ", data(ReadingData:Value)-> "
- + this.Datas.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 ?? ' ');
- //}
- }
- }
- }
|