123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- using System.Threading;
- using System.Windows.Interop;
- using InABox.Core;
- using NPOI.HPSF;
- using PRSServer;
- namespace InABox.DigitalMatter
- {
- public static class DMFactory
- {
- private static readonly Dictionary<byte, string> _devices = new();
- private static readonly Dictionary<byte, Type> _messages = new();
- private static readonly Dictionary<byte, Tuple<Type, string>> _fields = new();
- private static readonly Dictionary<byte, Type> _bluetoothtags = new();
- private static DumpFormat _dumpFormat;
- private static string _dumpFile;
- public static void Initialise(DumpFormat dumpFormat, string dumpFile)
- {
- _dumpFormat = dumpFormat;
- _dumpFile = dumpFile;
- RegisterMessage<DMHelloRequest>(0x00);
- RegisterMessage<DMHelloResponse>(0x01);
- RegisterMessage<DMDataRequest>(0x04);
- RegisterMessage<DMConfirmRequest>(0x05);
- RegisterMessage<DMConfirmResponse>(0x06);
- RegisterField<DMGPSField>(0x00, "GPS Data");
- RegisterField<DMDigitalDataField>(0x02, "Digital Data");
- RegisterField<DMOperatorField>(0x03, "Operator Info");
- RegisterField<DMAnalogueDataField16>(0x06, "Analogue Data");
- RegisterField<DMTripDataField>(0x0F, "Trip Data");
- RegisterField<DMBluetoothTagList>(0x1D, "BT Tag List");
- RegisterField<DMBluetoothTagData>(0x1E, "BT Tag Data");
- // Current DMT Devices
- RegisterDevice(0x4B, "Bolt");
- RegisterDevice(0x44, "Dart2");
- RegisterDevice(0x4E, "Eagle");
- RegisterDevice(0x4A, "Falcon");
- RegisterDevice(0x43, "G62 Cellular");
- RegisterDevice(0x4F, "G120");
- RegisterDevice(0x4D, "Oyster2 Cellular");
- RegisterDevice(0x3E, "Remora2");
- RegisterDevice(0x49, "Yabby GPS");
- RegisterDevice(0x48, "Yabby WiFi Cellular");
- //Obsolete DMT Devices
- RegisterDevice(0x22, "Dart");
- RegisterDevice(0x1E, "Flexi1");
- RegisterDevice(0x11, "G52 Solar");
- RegisterDevice(0x17, "G60");
- RegisterDevice(0x1C, "G100");
- RegisterDevice(0x21, "Remora");
- RegisterDevice(0x3A, "Oyster Cellular(v1)");
- RegisterDevice(0x34, "Sting");
- RegisterBluetoothTag<DMGuppyBluetoothTag>(0x00);
- RegisterBluetoothTag<DMIBeaconBluetoothTag>(0x01);
- RegisterBluetoothTag<DMEddystoneBluetoothTag>(0x02);
- RegisterBluetoothTag<DMIngicsiBS01BasicBluetoothTag>(0x03);
- RegisterBluetoothTag<DMIngicsiBS01TemperatureBluetoothTag>(0x04);
- RegisterBluetoothTag<DMSensorNodeBluetoothTag>(0x05);
- RegisterBluetoothTag<DMEddystoneTLMBluetoothTag>(0x06);
- RegisterBluetoothTag<DMTechnotonES7BluetoothTag>(0x07);
- RegisterBluetoothTag<DMGeoboxTPMSBluetoothTag>(0x08);
- RegisterBluetoothTag<DMEscortFuelBluetoothTag>(0x09);
- RegisterBluetoothTag<DMIngicsiBS04BluetoothTag>(0x0A);
- RegisterBluetoothTag<DMGenericBluetoothTag>(0xFF);
- }
- public static void RegisterDevice(byte identifier, string name)
- {
- _devices[identifier] = name;
- }
- public static string GetDeviceName(byte identifier)
- {
- if (_devices.ContainsKey(identifier))
- return _devices[identifier];
- return string.Format("Unknown Device (0x{0})", BitConverter.ToString(new[] { identifier }));
- }
- public static void RegisterMessage<TMessage>(byte identifier) where TMessage : DMMessage
- {
- _messages[identifier] = typeof(TMessage);
- }
- public static DMMessage ParseMessage(byte[] data)
- {
- if (data.Length < 3)
- throw new Exception("Invalid Packet Length");
- var buffer = new DMBuffer { Buffer = data };
- var magicnumber = buffer.PeekBytes(0, 2);
- if (magicnumber[0] != 0x02 || magicnumber[1] != 0x55)
- throw new Exception("Invalid Header");
- var messagetype = buffer.PeekByte(2);
- if (!_messages.ContainsKey(messagetype))
- throw new Exception(string.Format("Invalid Message Type({0})", messagetype));
- var payloadlength = buffer.PeekUInt16(3);
- if (buffer.BufferSize - payloadlength < 5)
- throw new Exception(string.Format("Payload Length Mismatch - Expected: {0} Actual {1}", payloadlength, buffer.BufferSize - 5));
- var message = (Activator.CreateInstance(_messages[messagetype]) as DMMessage)!;
- try
- {
- message.Decode(data);
- }
- catch (Exception e)
- {
- Logger.Send(
- LogType.Error,
- Thread.CurrentThread.ManagedThreadId.ToString(),
- string.Format("Unable to Parse Message: {0} Magic={1} Type={2} Payload={3} Data=({1})", e.Message,
- BitConverter.ToString(buffer.PeekBytes(0, payloadlength + 3)))
- );
- }
- switch (_dumpFormat)
- {
- case DumpFormat.Raw:
- using (var stream = DumpStream())
- {
- stream.Write(data); // Write data
- stream.WriteByte(0x0a); // Newline
- }
- break;
- case DumpFormat.SemiParsed:
- using(var stream = DumpStream())
- {
- stream.Write(message.Dump()); // Write message dump
- stream.WriteByte(0x0a); // Newline
- }
- break;
- }
- return message;
- }
- public static void RegisterField<TField>(byte identifier, string name) where TField : DMField
- {
- _fields[identifier] = new Tuple<Type, string>(typeof(TField), name);
- }
- public static string GetFieldName(byte identifier)
- {
- if (_fields.ContainsKey(identifier))
- return _fields[identifier].Item2;
- return string.Format("Unknown Field (0x{0})", BitConverter.ToString(new[] { identifier }));
- }
- public static DMField ParseField(byte[] data)
- {
- if (data.Length < 2)
- throw new Exception("Invalid Field Length");
- var buffer = new DMBuffer { Buffer = data };
- var type = buffer.PeekByte(0);
- if (!_fields.ContainsKey(type))
- throw new Exception(string.Format("Invalid Field Type ({0})", type));
- var field = Activator.CreateInstance(_fields[type].Item1) as DMField;
- field.Decode(data);
- return field;
- }
- public static void RegisterBluetoothTag<TTagType>(byte identifier) where TTagType : DMBluetoothTag
- {
- _bluetoothtags[identifier] = typeof(TTagType);
- }
- public static DMBluetoothTag ParseBluetoothTag(byte type, byte[] data)
- {
- if (!_bluetoothtags.ContainsKey(type))
- throw new Exception(string.Format("Invalid Bluetooth Tag Type ({0})", type));
- var tag = Activator.CreateInstance(_bluetoothtags[type]) as DMBluetoothTag;
- tag.DataLength = (byte)data.Length;
- tag.Decode(data);
- return tag;
- }
- private static Stream DumpStream()
- {
- return new FileStream(_dumpFile, FileMode.Append);
- }
- private static void DumpData(byte[] data)
- {
- try
- {
- using (var stream = new FileStream(_dumpFile, FileMode.Append))
- {
- stream.Write(data);
- }
- }
- catch (Exception e)
- {
- Logger.Send(LogType.Error, "", $"Error while dumping data: {CoreUtils.FormatException(e)}");
- }
- }
- }
- }
|