| 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)}");            }        }    }}
 |