فهرست منبع

Reworked digital matter stuff

Kenric Nugteren 2 سال پیش
والد
کامیت
84e2ce625f
24فایلهای تغییر یافته به همراه639 افزوده شده و 436 حذف شده
  1. 304 158
      inabox.digitalmatter/DMBuffer.cs
  2. 59 13
      inabox.digitalmatter/DMFactory.cs
  3. 11 11
      inabox.digitalmatter/DMField.cs
  4. 15 15
      inabox.digitalmatter/DMMessage.cs
  5. 30 19
      inabox.digitalmatter/DMObject.cs
  6. 22 19
      inabox.digitalmatter/DMRecord.cs
  7. 23 23
      inabox.digitalmatter/Fields/Bluetooth/DMBluetoothTagData.cs
  8. 6 6
      inabox.digitalmatter/Fields/Bluetooth/DMBluetoothTagList.cs
  9. 20 20
      inabox.digitalmatter/Fields/Bluetooth/DMBluetoothTagListItem.cs
  10. 10 10
      inabox.digitalmatter/Fields/Bluetooth/DMGenericBluetoothTag.cs
  11. 10 10
      inabox.digitalmatter/Fields/Bluetooth/DMGuppyBluetoothTag.cs
  12. 14 14
      inabox.digitalmatter/Fields/Bluetooth/DMIBeaconBluetoothTag.cs
  13. 27 29
      inabox.digitalmatter/Fields/Bluetooth/DMSensorNodeBluetoothTag.cs
  14. 4 4
      inabox.digitalmatter/Fields/Bluetooth/DMUnknownBluetoothTag.cs
  15. 5 5
      inabox.digitalmatter/Fields/DMAnalogueDataField.cs
  16. 8 8
      inabox.digitalmatter/Fields/DMDigitalDataField.cs
  17. 23 23
      inabox.digitalmatter/Fields/DMGPSField.cs
  18. 6 6
      inabox.digitalmatter/Fields/DMOperatorField.cs
  19. 6 6
      inabox.digitalmatter/Fields/DMTripDataField.cs
  20. 2 2
      inabox.digitalmatter/Messages/DMConfirmRequest.cs
  21. 4 4
      inabox.digitalmatter/Messages/DMConfirmResponse.cs
  22. 6 7
      inabox.digitalmatter/Messages/DMDataRequest.cs
  23. 18 18
      inabox.digitalmatter/Messages/DMHelloRequest.cs
  24. 6 6
      inabox.digitalmatter/Messages/DMHelloResponse.cs

+ 304 - 158
inabox.digitalmatter/DMBuffer.cs

@@ -1,106 +1,177 @@
-using System;
+using NPOI.SS.Formula.Functions;
+using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Collections.Immutable;
 using System.Linq;
 using System.Text;
 
 namespace InABox.DigitalMatter
 {
-    public class DMBuffer
+    public interface IDMBuffer
     {
-        public byte[] Buffer
+        /// <summary>
+        /// The remaining size of the buffer.
+        /// </summary>
+        public ushort BufferSize { get; }
+
+
+        #region Bit Manipulation
+
+        private static bool[] DecodeBits(byte[] value, int index, int length)
         {
-            get => _buffer.ToArray();
-            set => _buffer = value.ToList();
+            var result = new List<bool>();
+            var array = new BitArray(value);
+            for (var i = index; i < index + length && i < array.Count; i++)
+                result.Add(array[i]);
+            return result.ToArray();
         }
 
-        public ushort BufferSize => (ushort)_buffer.Count;
+        private static byte[] EncodeBits(byte[] source, int index, bool[] bits)
+        {
+            var array = new BitArray(source);
+            for (var i = 0; i < bits.Length; i++)
+                array.Set(index + i, bits[i]);
+            var result = new byte[source.Length];
+            array.CopyTo(result, 0);
+            return result;
+        }
 
-        public virtual void Reset()
+        public static bool[] GetBits(byte[] value, int index, int length)
         {
-            _buffer = new List<byte>();
+            return DecodeBits(value, index, length);
         }
 
-        public ushort AddByte(byte value)
+        public static byte[] SetBits(byte[] value, int index, bool[] bits)
         {
-            return Add(new[] { value });
+            return EncodeBits(value, index, bits);
         }
 
-        public ushort AddBytes(byte[] value)
+        public static bool[] DecodeByte(byte value, int index, int length)
         {
-            return Add(value);
+            return DecodeBits(new[] { value }, index, length);
         }
 
-        public ushort AddInt8(sbyte value)
+        public static bool[] DecodeBytes(byte[] value, int index, int length)
         {
-            return Add(BitConverter.GetBytes(value));
+            return DecodeBits(value, index, length);
         }
 
-        public ushort AddUInt16(ushort value)
+        public static bool[] DecodeInt8(sbyte value, int index, int length)
         {
-            return Add(BitConverter.GetBytes(value));
+            return DecodeBits(new[] { Convert.ToByte(value) }, index, length);
         }
 
-        public ushort AddInt16(short value)
+        public static bool[] DecodeInt16(short value, int index, int length)
         {
-            return Add(BitConverter.GetBytes(value));
+            return DecodeBits(BitConverter.GetBytes(value), index, length);
         }
 
-        public ushort AddUInt32(uint value)
+        public static bool[] DecodeUInt16(ushort value, int index, int length)
         {
-            return Add(BitConverter.GetBytes(value));
+            return DecodeBits(BitConverter.GetBytes(value), index, length);
         }
 
-        public ushort AddInt32(int value)
+        public static bool[] DecodeInt32(int value, int index, int length)
         {
-            return Add(BitConverter.GetBytes(value));
+            return DecodeBits(BitConverter.GetBytes(value), index, length);
         }
 
-        public ushort AddString(string value, int length)
+        public static bool[] DecodeUInt32(uint value, int index, int length)
         {
-            return Add(FixedLengthString(value, length));
+            return DecodeBits(BitConverter.GetBytes(value), index, length);
         }
 
-        public ushort InsertByte(int index, byte value)
+        public static byte EncodeByte(bool[] bits)
         {
-            return Insert(index, new[] { value });
+            return EncodeBits(new byte[] { default }, 0, bits).First();
         }
 
-        public ushort InsertBytes(int index, byte[] value)
+        public static byte[] EncodeBytes(bool[] bits, int size)
         {
-            return Insert(index, value);
+            return EncodeBits(Array.CreateInstance(typeof(byte), size).OfType<byte>().ToArray(), 0, bits);
         }
 
-        public ushort InsertInt8(int index, sbyte value)
+        public static sbyte EncodeInt8(bool[] bits)
         {
-            return Insert(index, BitConverter.GetBytes(value));
+            return Convert.ToSByte(EncodeBits(new[] { Convert.ToByte(default(sbyte)) }, 0, bits).First());
         }
 
-        public ushort InsertUInt16(int index, ushort value)
+        public static short EncodeInt16(bool[] bits)
         {
-            return Insert(index, BitConverter.GetBytes(value));
+            return BitConverter.ToInt16(EncodeBits(BitConverter.GetBytes(default(short)), 0, bits), 0);
         }
 
-        public ushort InsertInt16(int index, short value)
+        public static ushort EncodeUInt16(bool[] bits)
         {
-            return Insert(index, BitConverter.GetBytes(value));
+            return BitConverter.ToUInt16(EncodeBits(BitConverter.GetBytes(default(ushort)), 0, bits), 0);
         }
 
-        public ushort InsertUInt32(int index, uint value)
+        public static int EncodeInt32(bool[] bits)
         {
-            return Insert(index, BitConverter.GetBytes(value));
+            return BitConverter.ToInt32(EncodeBits(BitConverter.GetBytes(default(int)), 0, bits), 0);
         }
 
-        public ushort InsertInt32(int index, int value)
+        public static uint EncodeUInt32(bool[] bits)
         {
-            return Insert(index, BitConverter.GetBytes(value));
+            return BitConverter.ToUInt32(EncodeBits(BitConverter.GetBytes(default(uint)), 0, bits), 0);
         }
 
-        public ushort InsertString(int index, string value, int length)
+        public static byte UpdateByte(byte value, int index, bool[] bits)
         {
-            return Insert(index, FixedLengthString(value, length));
+            return EncodeBits(new[] { value }, index, bits).First();
+        }
+
+        public static byte[] UpdateBytes(byte[] value, int index, bool[] bits, int size)
+        {
+            return EncodeBits(value, 0, bits);
+        }
+
+        public static sbyte UpdateInt8(sbyte value, int index, bool[] bits)
+        {
+            return Convert.ToSByte(EncodeBits(new[] { Convert.ToByte(value) }, 0, bits).First());
+        }
+
+        public static short UpdateInt16(short value, int index, bool[] bits)
+        {
+            return BitConverter.ToInt16(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
         }
 
+        public static ushort UpdateUInt16(ushort value, int index, bool[] bits)
+        {
+            return BitConverter.ToUInt16(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
+        }
+
+        public static int UpdateInt32(int value, int index, bool[] bits)
+        {
+            return BitConverter.ToInt32(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
+        }
+
+        public static uint UpdateUInt32(uint value, int index, bool[] bits)
+        {
+            return BitConverter.ToUInt32(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
+        }
+
+        #endregion
+    }
+
+    public interface IDMReadBuffer : IDMBuffer
+    {
+        /// <summary>
+        /// Read <paramref name="length"/> bytes, starting at <paramref name="index"/>, but don't advance the read pointer.
+        /// </summary>
+        /// <param name="index">Index to start the read.</param>
+        /// <param name="length">Number of bytes to read.</param>
+        /// <returns>The bytes read.</returns>
+        protected byte[] Peek(int index, int length);
+
+        /// <summary>
+        /// Read <paramref name="length"/> bytes, advancing the read pointer by <paramref name="length"/>.
+        /// </summary>
+        /// <param name="length">Number of bytes to read.</param>
+        /// <returns>The bytes read.</returns>
+        protected byte[] Take(int length);
+
         public byte PeekByte(int index)
         {
             return Peek(index, sizeof(byte)).First();
@@ -142,262 +213,337 @@ namespace InABox.DigitalMatter
             return Encoding.Default.GetString(Peek(index, length)).Trim();
         }
 
-        public byte TakeByte(int index)
+        public byte TakeByte()
         {
-            return Take(index, sizeof(byte)).First();
+            return Take(sizeof(byte)).First();
         }
 
-        public byte[] TakeBytes(int index, int length)
+        public byte[] TakeBytes(int length)
         {
-            return Take(index, length);
+            return Take(length);
         }
 
-        public sbyte TakeInt8(int index)
+        public sbyte TakeInt8()
         {
-            return unchecked((sbyte)TakeByte(index));
+            return unchecked((sbyte)TakeByte());
             //hmmm...
         }
 
-        public ushort TakeUInt16(int index)
+        public ushort TakeUInt16()
         {
-            return BitConverter.ToUInt16(Take(index, sizeof(ushort)), 0);
+            return BitConverter.ToUInt16(Take(sizeof(ushort)), 0);
         }
 
-        public short TakeInt16(int index)
+        public short TakeInt16()
         {
-            return BitConverter.ToInt16(Take(index, sizeof(short)), 0);
+            return BitConverter.ToInt16(Take(sizeof(short)), 0);
         }
 
-        public uint TakeUInt32(int index)
+        public uint TakeUInt32()
         {
-            return BitConverter.ToUInt32(Take(index, sizeof(uint)), 0);
+            return BitConverter.ToUInt32(Take(sizeof(uint)), 0);
         }
 
-        public int TakeInt32(int index)
+        public int TakeInt32()
         {
-            return BitConverter.ToInt32(Take(index, sizeof(int)), 0);
+            return BitConverter.ToInt32(Take(sizeof(int)), 0);
         }
 
-        public string TakeString(int index, int length)
+        public string TakeString(int length)
         {
-            return Encoding.Default.GetString(Take(index, length)).Trim();
+            return Encoding.Default.GetString(Take(length)).Trim();
         }
+    }
 
-        public byte TakeByte()
+    public interface IDMWriteBuffer : IDMBuffer
+    {
+        protected ushort Add(byte[] bytes);
+
+        protected ushort Insert(int index, byte[] bytes);
+
+        void Reset();
+
+        public ushort AddByte(byte value)
         {
-            return TakeByte(0);
+            return Add(new[] { value });
         }
 
-        public byte[] TakeBytes(int length)
+        public ushort AddBytes(byte[] value)
         {
-            return TakeBytes(0, length);
+            return Add(value);
         }
 
-        public sbyte TakeInt8()
+        public ushort AddInt8(sbyte value)
         {
-            return TakeInt8(0);
-            //hmmm...
+            return Add(BitConverter.GetBytes(value));
         }
 
-        public ushort TakeUInt16()
+        public ushort AddUInt16(ushort value)
         {
-            return TakeUInt16(0);
+            return Add(BitConverter.GetBytes(value));
         }
 
-        public short TakeInt16()
+        public ushort AddInt16(short value)
         {
-            return TakeInt16(0);
+            return Add(BitConverter.GetBytes(value));
         }
 
-        public uint TakeUInt32()
+        public ushort AddUInt32(uint value)
         {
-            return TakeUInt32(0);
+            return Add(BitConverter.GetBytes(value));
         }
 
-        public int TakeInt32()
+        public ushort AddInt32(int value)
         {
-            return TakeInt32(0);
+            return Add(BitConverter.GetBytes(value));
         }
 
-        public string TakeString(int length)
+        public ushort AddString(string value, int length)
         {
-            return TakeString(0, length);
+            return Add(FixedLengthString(value, length));
         }
 
-        #region Private Members
+        public ushort InsertByte(int index, byte value)
+        {
+            return Insert(index, new[] { value });
+        }
 
-        private List<byte> _buffer = new();
+        public ushort InsertBytes(int index, byte[] value)
+        {
+            return Insert(index, value);
+        }
 
-        private ushort Add(byte[] bytes)
+        public ushort InsertInt8(int index, sbyte value)
         {
-            _buffer.AddRange(bytes);
-            return BufferSize;
+            return Insert(index, BitConverter.GetBytes(value));
         }
 
-        private ushort Insert(int index, byte[] bytes)
+        public ushort InsertUInt16(int index, ushort value)
         {
-            _buffer.InsertRange(index, bytes);
-            return BufferSize;
+            return Insert(index, BitConverter.GetBytes(value));
         }
 
-        private byte[] Peek(int index, int length)
+        public ushort InsertInt16(int index, short value)
         {
-            return _buffer.Skip(index).Take(length).ToArray();
+            return Insert(index, BitConverter.GetBytes(value));
         }
 
-        private byte[] Take(int index, int length)
+        public ushort InsertUInt32(int index, uint value)
         {
-            var result = Peek(index, length);
-            _buffer.RemoveRange(index, length);
-            return result;
+            return Insert(index, BitConverter.GetBytes(value));
         }
 
-        private byte[] FixedLengthString(string value, int length)
+        public ushort InsertInt32(int index, int value)
         {
-            var result = Encoding.Default.GetBytes(value).ToList();
-            while (result.Count < length)
-                result.Add(0x00);
-            return result.ToArray();
+            return Insert(index, BitConverter.GetBytes(value));
         }
 
-        private bool[] DecodeBits(byte[] value, int index, int length)
+        public ushort InsertString(int index, string value, int length)
         {
-            var result = new List<bool>();
-            var array = new BitArray(value);
-            for (var i = index; i < index + length && i < array.Count; i++)
-                result.Add(array[i]);
-            return result.ToArray();
+            return Insert(index, FixedLengthString(value, length));
         }
 
-        private byte[] EncodeBits(byte[] source, int index, bool[] bits)
+        #region Private Members
+
+        private static byte[] FixedLengthString(string value, int length)
         {
-            var array = new BitArray(source);
-            for (var i = 0; i < bits.Length; i++)
-                array.Set(index + i, bits[i]);
-            var result = new byte[source.Length];
-            array.CopyTo(result, 0);
-            return result;
+            var result = Encoding.Default.GetBytes(value).ToList();
+            while (result.Count < length)
+                result.Add(0x00);
+            return result.ToArray();
         }
 
         #endregion
+    }
 
-        #region Bit Manipulation
+    public class DMArrayReadBuffer : IDMReadBuffer
+    {
+        private byte[] _buffer { get; set; }
+        private int _offset;
 
-        public bool[] GetBits(byte[] value, int index, int length)
-        {
-            return DecodeBits(value, index, length);
-        }
+        public ushort BufferSize => (ushort)(_buffer.Length - _offset);
 
-        public byte[] SetBits(byte[] value, int index, bool[] bits)
+        public DMArrayReadBuffer(byte[] buffer)
         {
-            return EncodeBits(value, index, bits);
+            _buffer = buffer;
+            _offset = 0;
         }
 
-        public bool[] DecodeByte(byte value, int index, int length)
+        byte[] IDMReadBuffer.Peek(int index, int length)
         {
-            return DecodeBits(new[] { value }, index, length);
+            index += _offset;
+            length = Math.Min(length, _buffer.Length - index);
+            var newBytes = new byte[length];
+            Buffer.BlockCopy(_buffer, index, newBytes, 0, length);
+            return newBytes;
         }
 
-        public bool[] DecodeBytes(byte[] value, int index, int length)
+        byte[] IDMReadBuffer.Take(int length)
         {
-            return DecodeBits(value, index, length);
+            length = Math.Min(length, _buffer.Length - _offset);
+            var newBytes = new byte[length];
+            Buffer.BlockCopy(_buffer, _offset, newBytes, 0, length);
+            _offset += length;
+            return newBytes;
         }
+    }
+    public class DMListReadBuffer : IDMReadBuffer
+    {
+        private List<byte> _buffer { get; set; }
+        private int _offset;
 
-        public bool[] DecodeInt8(sbyte value, int index, int length)
-        {
-            return DecodeBits(new[] { Convert.ToByte(value) }, index, length);
-        }
+        public ushort BufferSize => (ushort)(_buffer.Count - _offset);
 
-        public bool[] DecodeInt16(short value, int index, int length)
+        public DMListReadBuffer(List<byte> buffer)
         {
-            return DecodeBits(BitConverter.GetBytes(value), index, length);
+            _buffer = buffer;
+            _offset = 0;
         }
 
-        public bool[] DecodeUInt16(ushort value, int index, int length)
+        byte[] IDMReadBuffer.Peek(int index, int length) => Peek(index, length);
+
+        private byte[] Peek(int index, int length)
         {
-            return DecodeBits(BitConverter.GetBytes(value), index, length);
+            index += _offset;
+            length = Math.Min(length, _buffer.Count - index);
+            var newBytes = new byte[length];
+            _buffer.CopyTo(index, newBytes, 0, length);
+            return newBytes;
         }
-
-        public bool[] DecodeInt32(int value, int index, int length)
+        
+        byte[] IDMReadBuffer.Take(int length)
         {
-            return DecodeBits(BitConverter.GetBytes(value), index, length);
+            var result = Peek(0, length);
+            _offset += length;
+            return result;
         }
+    }
+
+    public class DMPartialReadBuffer : IDMReadBuffer
+    {
+        private ushort _offset;
+        private ushort _length;
+
+        public IDMReadBuffer Buffer { get; }
+        public ushort BufferSize => (ushort)(_length - (Offset - _offset));
+        public ushort Offset { get; private set; }
 
-        public bool[] DecodeUInt32(uint value, int index, int length)
+        public DMPartialReadBuffer(IDMReadBuffer buffer, ushort offset, ushort length)
         {
-            return DecodeBits(BitConverter.GetBytes(value), index, length);
+            _length = length;
+            _offset = offset;
+            Offset = offset;
+            Buffer = buffer;
         }
 
-        public byte EncodeByte(bool[] bits)
+        byte[] IDMReadBuffer.Peek(int index, int length) => Peek(index, length);
+
+        private byte[] Peek(int index, int length)
         {
-            return EncodeBits(new byte[] { default }, 0, bits).First();
+            index += Offset;
+            length = Math.Min(length, _offset + _length - index);
+            return Buffer.PeekBytes(index, length);
         }
 
-        public byte[] EncodeBytes(bool[] bits, int size)
+        byte[] IDMReadBuffer.Take(int length)
         {
-            return EncodeBits(Array.CreateInstance(typeof(byte), size).OfType<byte>().ToArray(), 0, bits);
+            var bytes = Peek(0, length);
+            Offset += (ushort)bytes.Length;
+            return bytes;
         }
+    }
+
+    public class DMListWriteBuffer : IDMWriteBuffer
+    {
+        private List<byte> _buffer { get; set; }
+        private int _offset;
+
+        public List<byte> Buffer => _buffer;
+
+        public ushort BufferSize => (ushort)(_buffer.Count - _offset);
 
-        public sbyte EncodeInt8(bool[] bits)
+        public DMListWriteBuffer(List<byte> buffer)
         {
-            return Convert.ToSByte(EncodeBits(new[] { Convert.ToByte(default(sbyte)) }, 0, bits).First());
+            _buffer = buffer;
+            _offset = 0;
         }
 
-        public short EncodeInt16(bool[] bits)
+        public void Reset()
         {
-            return BitConverter.ToInt16(EncodeBits(BitConverter.GetBytes(default(short)), 0, bits), 0);
+            _buffer.Clear();
         }
 
-        public ushort EncodeUInt16(bool[] bits)
+        ushort IDMWriteBuffer.Add(byte[] bytes)
         {
-            return BitConverter.ToUInt16(EncodeBits(BitConverter.GetBytes(default(ushort)), 0, bits), 0);
+            _buffer.AddRange(bytes);
+            return BufferSize;
         }
 
-        public int EncodeInt32(bool[] bits)
+        ushort IDMWriteBuffer.Insert(int index, byte[] bytes)
         {
-            return BitConverter.ToInt32(EncodeBits(BitConverter.GetBytes(default(int)), 0, bits), 0);
+            _buffer.InsertRange(index, bytes);
+            return BufferSize;
         }
+    }
 
-        public uint EncodeUInt32(bool[] bits)
+    public class DMBuffer : IDMReadBuffer, IDMWriteBuffer
+    {
+        public byte[] Buffer
         {
-            return BitConverter.ToUInt32(EncodeBits(BitConverter.GetBytes(default(uint)), 0, bits), 0);
+            get => _buffer.ToArray();
+            set => _buffer = value.ToList();
         }
 
-        public byte UpdateByte(byte value, int index, bool[] bits)
+        public DMBuffer() { }
+
+        public DMBuffer(byte[] buffer)
         {
-            return EncodeBits(new[] { value }, index, bits).First();
+            Buffer = buffer;
         }
 
-        public byte[] UpdateBytes(byte[] value, int index, bool[] bits, int size)
+        public DMBuffer(List<byte> buffer)
         {
-            return EncodeBits(value, 0, bits);
+            _buffer = buffer;
         }
 
-        public sbyte UpdateInt8(sbyte value, int index, bool[] bits)
+        public ushort BufferSize => (ushort)_buffer.Count;
+
+        public void Reset()
         {
-            return Convert.ToSByte(EncodeBits(new[] { Convert.ToByte(value) }, 0, bits).First());
+            _buffer = new List<byte>();
         }
 
-        public short UpdateInt16(short value, int index, bool[] bits)
+
+        #region Private Members
+
+        private List<byte> _buffer = new();
+
+        ushort IDMWriteBuffer.Add(byte[] bytes)
         {
-            return BitConverter.ToInt16(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
+            _buffer.AddRange(bytes);
+            return BufferSize;
         }
 
-        public ushort UpdateUInt16(ushort value, int index, bool[] bits)
+        ushort IDMWriteBuffer.Insert(int index, byte[] bytes)
         {
-            return BitConverter.ToUInt16(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
+            _buffer.InsertRange(index, bytes);
+            return BufferSize;
         }
-
-        public int UpdateInt32(int value, int index, bool[] bits)
+        private byte[] Peek(int index, int length)
         {
-            return BitConverter.ToInt32(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
+            return _buffer.Skip(index).Take(length).ToArray();
         }
 
-        public uint UpdateUInt32(uint value, int index, bool[] bits)
+        byte[] IDMReadBuffer.Peek(int index, int length) => Peek(index, length);
+
+        byte[] IDMReadBuffer.Take(int length)
         {
-            return BitConverter.ToUInt32(EncodeBits(BitConverter.GetBytes(value), 0, bits), 0);
+            var result = Peek(0, length);
+            _buffer.RemoveRange(0, length);
+            return result;
         }
 
         #endregion
+
     }
 }

+ 59 - 13
inabox.digitalmatter/DMFactory.cs

@@ -6,6 +6,7 @@ using System.Threading;
 using System.Windows.Interop;
 using InABox.Core;
 using NPOI.HPSF;
+using NPOI.SS.Formula.Functions;
 using PRSServer;
 
 namespace InABox.DigitalMatter
@@ -95,12 +96,19 @@ namespace InABox.DigitalMatter
             _messages[identifier] = typeof(TMessage);
         }
 
-        public static DMMessage ParseMessage(byte[] data)
+        public static int PeekPayloadLength(IList<byte> data)
         {
-            if (data.Length < 3)
-                throw new Exception("Invalid Packet Length");
+            if(data.Count < 5)
+            {
+                return 0;
+            }
+            return BitConverter.ToUInt16(new byte[] { data[3], data[4] }, 0);
+        }
 
-            var buffer = new DMBuffer { Buffer = data };
+        private static DMMessage ParseMessage(IDMReadBuffer buffer)
+        {
+            if (buffer.BufferSize < 3)
+                throw new Exception("Invalid Packet Length");
 
             var magicnumber = buffer.PeekBytes(0, 2);
             if (magicnumber[0] != 0x02 || magicnumber[1] != 0x55)
@@ -117,18 +125,23 @@ namespace InABox.DigitalMatter
             var message = (Activator.CreateInstance(_messages[messagetype]) as DMMessage)!;
             try
             {
-                message.Decode(data);
+                message.Decode(buffer);
             }
             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,
+                    Environment.CurrentManagedThreadId.ToString(),
+                    string.Format("Unable to Parse Message: {0} Data=({1})", e.Message,
                         BitConverter.ToString(buffer.PeekBytes(0, payloadlength + 3)))
                 );
             }
 
+            return message;
+        }
+
+        private static void DumpMessageBytes(byte[] data, DMMessage message)
+        {
             switch (_dumpFormat)
             {
                 case DumpFormat.Raw:
@@ -139,17 +152,52 @@ namespace InABox.DigitalMatter
                     }
                     break;
                 case DumpFormat.SemiParsed:
-                    using(var stream = DumpStream())
+                    using (var stream = DumpStream())
                     {
                         stream.Write(message.Dump()); // Write message dump
                         stream.WriteByte(0x0a); // Newline
                     }
                     break;
             }
+        }
+        private static void DumpMessageBytes(List<byte> data, DMMessage message)
+        {
+            switch (_dumpFormat)
+            {
+                case DumpFormat.Raw:
+                    using (var stream = DumpStream())
+                    {
+                        stream.Write(data.ToArray()); // 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;
+            }
+        }
+
+        public static DMMessage ParseMessage(byte[] data)
+        {
+            var buffer = new DMArrayReadBuffer(data);
+            var message = ParseMessage(buffer);
+            DumpMessageBytes(data, message);
 
             return message;
         }
 
+        public static DMMessage ParseMessage(List<byte> data)
+        {
+            var buffer = new DMListReadBuffer(data);
+            var message = ParseMessage(buffer);
+            DumpMessageBytes(data, message);
+            return message;
+        }
+
         public static void RegisterField<TField>(byte identifier, string name) where TField : DMField
         {
             _fields[identifier] = new Tuple<Type, string>(typeof(TField), name);
@@ -162,20 +210,18 @@ namespace InABox.DigitalMatter
             return string.Format("Unknown Field (0x{0})", BitConverter.ToString(new[] { identifier }));
         }
 
-        public static DMField ParseField(byte[] data)
+        public static DMField ParseField(IDMReadBuffer buffer)
         {
-            if (data.Length < 2)
+            if (buffer.BufferSize < 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);
+            field.Decode(buffer);
             return field;
         }
 

+ 11 - 11
inabox.digitalmatter/DMField.cs

@@ -9,24 +9,24 @@ namespace InABox.DigitalMatter
 
         public ushort Length { get; set; }
 
-        protected override void BeforeEncode()
+        protected override void BeforeEncode(IDMWriteBuffer buffer)
         {
-            base.BeforeEncode();
-            _payloadaddress = AddByte(Type);
+            base.BeforeEncode(buffer);
+            _payloadaddress = buffer.AddByte(Type);
         }
 
-        protected override void AfterEncode()
+        protected override void AfterEncode(IDMWriteBuffer buffer)
         {
-            base.AfterEncode();
-            Length = BufferSize;
-            InsertUInt16(_payloadaddress, Length);
+            base.AfterEncode(buffer);
+            Length = buffer.BufferSize;
+            buffer.InsertUInt16(_payloadaddress, Length);
         }
 
-        protected override void BeforeDecode()
+        protected override void BeforeDecode(IDMReadBuffer buffer)
         {
-            base.BeforeDecode();
-            int type = TakeByte();
-            Length = PeekByte(0) == 255 ? TakeUInt16() : TakeByte();
+            base.BeforeDecode(buffer);
+            int type = buffer.TakeByte();
+            Length = buffer.PeekByte(0) == 255 ? buffer.TakeUInt16() : buffer.TakeByte();
         }
 
         public abstract bool IsValid();

+ 15 - 15
inabox.digitalmatter/DMMessage.cs

@@ -11,28 +11,28 @@ namespace InABox.DigitalMatter
 
         public ushort CheckSum { get; set; }
 
-        protected override void BeforeEncode()
+        protected override void BeforeEncode(IDMWriteBuffer buffer)
         {
-            base.BeforeEncode();
-            AddByte(0x02);
-            AddByte(0x55);
-            headerlength = AddByte(Type);
+            base.BeforeEncode(buffer);
+            buffer.AddByte(0x02);
+            buffer.AddByte(0x55);
+            headerlength = buffer.AddByte(Type);
         }
 
-        protected override void AfterEncode()
+        protected override void AfterEncode(IDMWriteBuffer buffer)
         {
-            base.AfterEncode();
-            var payloadlength = (ushort)(BufferSize - headerlength);
-            InsertUInt16(headerlength, payloadlength);
+            base.AfterEncode(buffer);
+            var payloadlength = (ushort)(buffer.BufferSize - headerlength);
+            buffer.InsertUInt16(headerlength, payloadlength);
         }
 
-        protected override void BeforeDecode()
+        protected override void BeforeDecode(IDMReadBuffer buffer)
         {
-            base.BeforeDecode();
-            var id1 = TakeByte();
-            var id2 = TakeByte();
-            var type = TakeByte();
-            CheckSum = TakeUInt16();
+            base.BeforeDecode(buffer);
+            var id1 = buffer.TakeByte();
+            var id2 = buffer.TakeByte();
+            var type = buffer.TakeByte();
+            CheckSum = buffer.TakeUInt16();
         }
 
         public virtual byte[] Dump()

+ 30 - 19
inabox.digitalmatter/DMObject.cs

@@ -1,30 +1,41 @@
 using System;
+using System.Collections.Generic;
 
 namespace InABox.DigitalMatter
 {
     public interface IDMObject
     {
         void Decode(byte[] data);
-        byte[] Encode();
+        byte[] EncodeArray();
     }
 
-    public abstract class DMObject : DMBuffer, IDMObject
+    public abstract class DMObject : IDMObject
     {
-        public void Decode(byte[] data)
+
+        public void Decode(IDMReadBuffer readBuffer)
+        {
+            BeforeDecode(readBuffer);
+            DoDecode(readBuffer);
+            AfterDecode(readBuffer);
+        }
+        public void Decode(List<byte> data) => Decode(new DMListReadBuffer(data));
+
+        public void Decode(byte[] data) => Decode(new DMArrayReadBuffer(data));
+
+        public byte[] EncodeArray() => EncodeList().ToArray();
+
+        public void Encode(IDMWriteBuffer buffer)
         {
-            Buffer = data;
-            BeforeDecode();
-            DoDecode();
-            AfterDecode();
+            BeforeEncode(buffer);
+            DoEncode(buffer);
+            AfterEncode(buffer);
         }
 
-        public byte[] Encode()
+        public List<byte> EncodeList()
         {
-            Reset();
-            BeforeEncode();
-            DoEncode();
-            AfterEncode();
-            return Buffer;
+            var buffer = new DMListWriteBuffer(new List<byte>());
+            Encode(buffer);
+            return buffer.Buffer;
         }
 
         protected uint SecondsSince2013UTC()
@@ -40,23 +51,23 @@ namespace InABox.DigitalMatter
             return new DateTime(2013, 1, 1).AddSeconds(timestamp).ToLocalTime();
         }
 
-        protected virtual void BeforeEncode()
+        protected virtual void BeforeEncode(IDMWriteBuffer buffer)
         {
         }
 
-        protected abstract void DoEncode();
+        protected abstract void DoEncode(IDMWriteBuffer buffer);
 
-        protected virtual void AfterEncode()
+        protected virtual void AfterEncode(IDMWriteBuffer buffer)
         {
         }
 
-        protected virtual void BeforeDecode()
+        protected virtual void BeforeDecode(IDMReadBuffer buffer)
         {
         }
 
-        protected abstract void DoDecode();
+        protected abstract void DoDecode(IDMReadBuffer buffer);
 
-        protected virtual void AfterDecode()
+        protected virtual void AfterDecode(IDMReadBuffer buffer)
         {
         }
     }

+ 22 - 19
inabox.digitalmatter/DMRecord.cs

@@ -21,43 +21,46 @@ namespace InABox.DigitalMatter
             set => _fields = value.ToList();
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
             //Logger.Send(LogType.Information, Thread.CurrentThread.ManagedThreadId.ToString(), String.Format("- Length: Size is [{0}]",BufferSize));
-            Length = TakeUInt16();
+            Length = buffer.TakeUInt16();
             //Logger.Send(LogType.Information, Thread.CurrentThread.ManagedThreadId.ToString(), String.Format("- Sequence: Size is [{0}]", BufferSize));
-            Sequence = TakeUInt32();
+            Sequence = buffer.TakeUInt32();
             //Logger.Send(LogType.Information, Thread.CurrentThread.ManagedThreadId.ToString(), String.Format("- TimeStamp: Size is [{0}]", BufferSize));
-            TimeStamp = TakeUInt32();
+            TimeStamp = buffer.TakeUInt32();
             //Logger.Send(LogType.Information, Thread.CurrentThread.ManagedThreadId.ToString(), String.Format("- LogReason: Size is [{0}]", BufferSize));
-            LogReason = TakeByte();
+            LogReason = buffer.TakeByte();
 
-            ushort bytestaken = 0;
             _fields.Clear();
-            while (bytestaken < Length && BufferSize > 0)
+
+            int bytesTaken = 0;
+            while (buffer.BufferSize > 0 && bytesTaken < Length)
             {
-                var fieldid = PeekByte(0);
-                var fieldsize = PeekByte(1) == 255 ? PeekUInt16(1) : PeekByte(1);
+                var fieldid = buffer.PeekByte(0);
+                var fieldsize = buffer.PeekByte(1) == 255 ? buffer.PeekUInt16(1) : buffer.PeekByte(1);
                 //Logger.Send(LogType.Information, Thread.CurrentThread.ManagedThreadId.ToString(), String.Format("{0}: Field ID is [{1}] Size is [{2}]", _fields.Count, fieldid, fieldsize));
-                var field = DMFactory.ParseField(Buffer);
+                var field = DMFactory.ParseField(new DMPartialReadBuffer(buffer, 0, buffer.BufferSize));
                 _fields.Add(field);
-                var bytestotake = field.Length > 255 ? field.Length + 3 : field.Length + 2;
-                TakeBytes(bytestotake);
-                bytestaken += (ushort)bytestotake;
+
+                var bytesToTake = field.Length > 255 ? field.Length + 3 : field.Length + 2;
+                buffer.TakeBytes(bytesToTake);
+
+                bytesTaken += bytesToTake;
             }
             //Logger.Send(LogType.Information, Thread.CurrentThread.ManagedThreadId.ToString(), String.Format("- Done!: Size is [{0}]", BufferSize));
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt32(Sequence);
-            AddUInt32(TimeStamp);
-            AddByte(LogReason);
+            buffer.AddUInt32(Sequence);
+            buffer.AddUInt32(TimeStamp);
+            buffer.AddByte(LogReason);
 
             foreach (var field in _fields)
-                AddBytes(field.Encode());
+                field.Encode(buffer);
 
-            InsertUInt16(0, BufferSize);
+            buffer.InsertUInt16(0, buffer.BufferSize);
         }
 
         public string Dump()

+ 23 - 23
inabox.digitalmatter/Fields/Bluetooth/DMBluetoothTagData.cs

@@ -20,37 +20,37 @@
             return true;
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            var header = TakeByte();
-            DataLength = EncodeByte(DecodeByte(header, 0, 6));
-            LogReason = EncodeByte(DecodeByte(header, 6, 2));
-            TagType = TakeByte();
-            RSSI = TakeInt8();
-            TimeStamp = TakeUInt32();
-            Latitude = TakeInt32();
-            Longitude = TakeInt32();
-            GPSAccuracy = TakeByte();
-            var data = TakeBytes(DataLength);
+            var header = buffer.TakeByte();
+            DataLength = IDMBuffer.EncodeByte(IDMBuffer.DecodeByte(header, 0, 6));
+            LogReason = IDMBuffer.EncodeByte(IDMBuffer.DecodeByte(header, 6, 2));
+            TagType = buffer.TakeByte();
+            RSSI = buffer.TakeInt8();
+            TimeStamp = buffer.TakeUInt32();
+            Latitude = buffer.TakeInt32();
+            Longitude = buffer.TakeInt32();
+            GPSAccuracy = buffer.TakeByte();
+            var data = buffer.TakeBytes(DataLength);
             Tag = DMFactory.ParseBluetoothTag(TagType, data);
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddByte(TagType);
-            AddInt8(RSSI);
-            AddUInt32(TimeStamp);
-            AddInt32(Latitude);
-            AddInt32(Longitude);
-            AddByte(GPSAccuracy);
+            buffer.AddByte(TagType);
+            buffer.AddInt8(RSSI);
+            buffer.AddUInt32(TimeStamp);
+            buffer.AddInt32(Latitude);
+            buffer.AddInt32(Longitude);
+            buffer.AddByte(GPSAccuracy);
 
-            var data = Tag.Encode();
-            AddBytes(data);
+            var data = Tag.EncodeArray();
+            buffer.AddBytes(data);
 
             DataLength = (byte)data.Length;
-            var header = EncodeByte(DecodeByte(DataLength, 0, 6));
-            header = UpdateByte(header, 6, DecodeByte(LogReason, 0, 2));
-            InsertByte(0, header);
+            var header = IDMBuffer.EncodeByte(IDMBuffer.DecodeByte(DataLength, 0, 6));
+            header = IDMBuffer.UpdateByte(header, 6, IDMBuffer.DecodeByte(LogReason, 0, 2));
+            buffer.InsertByte(0, header);
         }
 
         public override string ToString()

+ 6 - 6
inabox.digitalmatter/Fields/Bluetooth/DMBluetoothTagList.cs

@@ -14,24 +14,24 @@ namespace InABox.DigitalMatter
             set => _items = value.ToList();
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
             var bytestaken = 0;
             _items.Clear();
-            while (bytestaken < Length && BufferSize > 0)
+            while (buffer.BufferSize > 0 && bytestaken < Length)
             {
                 var item = new DMBluetoothTagListItem();
-                item.Decode(Buffer);
+                item.Decode(new DMPartialReadBuffer(buffer, 0, buffer.BufferSize));
                 _items.Add(item);
-                TakeBytes(item.DataLength + 3);
+                buffer.TakeBytes(item.DataLength + 3);
                 bytestaken += item.DataLength + 3;
             }
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
             foreach (var tag in _items)
-                AddBytes(tag.Encode());
+                tag.Encode(buffer);
         }
 
         public override string ToString()

+ 20 - 20
inabox.digitalmatter/Fields/Bluetooth/DMBluetoothTagListItem.cs

@@ -12,40 +12,40 @@
 
         public DMBluetoothTag Tag { get; set; }
 
-        protected override void BeforeDecode()
+        protected override void BeforeDecode(IDMReadBuffer buffer)
         {
-            base.BeforeDecode();
-            var header = TakeByte();
-            DataLength = EncodeByte(DecodeByte(header, 0, 6));
-            LogReason = EncodeByte(DecodeByte(header, 6, 2));
-            TagType = TakeByte();
-            RSSI = TakeInt8();
+            base.BeforeDecode(buffer);
+            var header = buffer.TakeByte();
+            DataLength = IDMBuffer.EncodeByte(IDMBuffer.DecodeByte(header, 0, 6));
+            LogReason = IDMBuffer.EncodeByte(IDMBuffer.DecodeByte(header, 6, 2));
+            TagType = buffer.TakeByte();
+            RSSI = buffer.TakeInt8();
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            var data = TakeBytes(DataLength);
+            var data = buffer.TakeBytes(DataLength);
             Tag = DMFactory.ParseBluetoothTag(TagType, data);
         }
 
-        protected override void BeforeEncode()
+        protected override void BeforeEncode(IDMWriteBuffer buffer)
         {
-            base.BeforeEncode();
-            AddByte(TagType);
-            AddInt8(RSSI);
+            base.BeforeEncode(buffer);
+            buffer.AddByte(TagType);
+            buffer.AddInt8(RSSI);
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddBytes(Tag.Encode());
+            buffer.AddBytes(Tag.EncodeArray());
         }
 
-        protected override void AfterEncode()
+        protected override void AfterEncode(IDMWriteBuffer buffer)
         {
-            base.AfterEncode();
-            var header = EncodeByte(DecodeByte(DataLength, 0, 6));
-            header = UpdateByte(header, 6, DecodeByte(LogReason, 0, 2));
-            InsertByte(0, header);
+            base.AfterEncode(buffer);
+            var header = IDMBuffer.EncodeByte(IDMBuffer.DecodeByte(DataLength, 0, 6));
+            header = IDMBuffer.UpdateByte(header, 6, IDMBuffer.DecodeByte(LogReason, 0, 2));
+            buffer.InsertByte(0, header);
         }
 
         public override string ToString()

+ 10 - 10
inabox.digitalmatter/Fields/Bluetooth/DMGenericBluetoothTag.cs

@@ -10,20 +10,20 @@ namespace InABox.DigitalMatter
         public byte PayloadLength { get; private set; }
         public byte[] Payload { get; set; }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            TagType = TakeUInt16();
-            MacAddress = TakeBytes(6);
-            PayloadLength = TakeByte();
-            Payload = TakeBytes(DataLength);
+            TagType = buffer.TakeUInt16();
+            MacAddress = buffer.TakeBytes(6);
+            PayloadLength = buffer.TakeByte();
+            Payload = buffer.TakeBytes(DataLength);
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt16(TagType);
-            AddBytes(MacAddress);
-            AddByte(PayloadLength);
-            AddBytes(Payload);
+            buffer.AddUInt16(TagType);
+            buffer.AddBytes(MacAddress);
+            buffer.AddByte(PayloadLength);
+            buffer.AddBytes(Payload);
         }
 
         public override string ID()

+ 10 - 10
inabox.digitalmatter/Fields/Bluetooth/DMGuppyBluetoothTag.cs

@@ -26,20 +26,20 @@ namespace InABox.DigitalMatter
             return "Guppy";
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            SerialNumber = TakeUInt32();
-            TxPower = TakeInt8();
-            BatteryVoltage = TakeByte();
-            InternalTemperature = TakeInt8();
+            SerialNumber = buffer.TakeUInt32();
+            TxPower = buffer.TakeInt8();
+            BatteryVoltage = buffer.TakeByte();
+            InternalTemperature = buffer.TakeInt8();
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt32(SerialNumber);
-            AddInt8(TxPower);
-            AddByte(BatteryVoltage);
-            AddInt8(InternalTemperature);
+            buffer.AddUInt32(SerialNumber);
+            buffer.AddInt8(TxPower);
+            buffer.AddByte(BatteryVoltage);
+            buffer.AddInt8(InternalTemperature);
         }
     }
 }

+ 14 - 14
inabox.digitalmatter/Fields/Bluetooth/DMIBeaconBluetoothTag.cs

@@ -21,30 +21,30 @@ namespace InABox.DigitalMatter
                 : string.Format("{0}.{1}", MajorID, MinorID);
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            UUID = TakeBytes(16);
-            MajorID = TakeUInt16();
-            MinorID = TakeUInt16();
-            TxPower = TakeInt8();
+            UUID = buffer.TakeBytes(16);
+            MajorID = buffer.TakeUInt16();
+            MinorID = buffer.TakeUInt16();
+            TxPower = buffer.TakeInt8();
             if (DataLength == 27)
-                MacAddress = TakeBytes(6);
+                MacAddress = buffer.TakeBytes(6);
         }
 
-        protected override void BeforeEncode()
+        protected override void BeforeEncode(IDMWriteBuffer buffer)
         {
-            base.BeforeEncode();
+            base.BeforeEncode(buffer);
             DataLength = (byte)(MacAddress == null ? 21 : 27);
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddBytes(UUID);
-            AddUInt16(MajorID);
-            AddUInt16(MinorID);
-            AddInt8(TxPower);
+            buffer.AddBytes(UUID);
+            buffer.AddUInt16(MajorID);
+            buffer.AddUInt16(MinorID);
+            buffer.AddInt8(TxPower);
             if (MacAddress != null)
-                AddBytes(MacAddress);
+                buffer.AddBytes(MacAddress);
         }
 
         public override string Type()

+ 27 - 29
inabox.digitalmatter/Fields/Bluetooth/DMSensorNodeBluetoothTag.cs

@@ -37,50 +37,48 @@ namespace InABox.DigitalMatter
             return "SensorNode";
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            SerialNumber = TakeUInt32();
-            TxPower = TakeInt8();
-            BatteryVoltage = TakeByte();
-            InternalTemperature = TakeInt8();
-            Probe1 = TakeInt16();
-            Probe2 = TakeInt16();
-            TemperatureProbe = TakeInt16();
-            HumidityProbe = TakeInt16();
+            SerialNumber = buffer.TakeUInt32();
+            TxPower = buffer.TakeInt8();
+            BatteryVoltage = buffer.TakeByte();
+            InternalTemperature = buffer.TakeInt8();
+            Probe1 = buffer.TakeInt16();
+            Probe2 = buffer.TakeInt16();
+            TemperatureProbe = buffer.TakeInt16();
+            HumidityProbe = buffer.TakeInt16();
 
-            var digital = TakeByte();
+            var digital = buffer.TakeByte();
             Digital1 = (digital & (0x1 << 0)) != 0;
             Digital2 = (digital & (0x1 << 1)) != 0;
 
-            Analog1 = TakeUInt16();
-            Analog2 = TakeUInt16();
+            Analog1 = buffer.TakeUInt16();
+            Analog2 = buffer.TakeUInt16();
 
-            var unused_reserved = TakeByte();
+            var unused_reserved = buffer.TakeByte();
             
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt32(SerialNumber);
-            AddInt8(TxPower);
-            AddByte(BatteryVoltage);
-            AddInt8(InternalTemperature);
+            buffer.AddUInt32(SerialNumber);
+            buffer.AddInt8(TxPower);
+            buffer.AddByte(BatteryVoltage);
+            buffer.AddInt8(InternalTemperature);
             
-            AddInt16(Probe1);
-            AddInt16(Probe2);
-            TakeInt16(TemperatureProbe);
-            TakeInt16(HumidityProbe);
+            buffer.AddInt16(Probe1);
+            buffer.AddInt16(Probe2);
+            buffer.AddInt16(TemperatureProbe);
+            buffer.AddInt16(HumidityProbe);
 
             byte[] digital = new byte[1];
-            digital = SetBits(digital, 0, new bool[] { Digital1, Digital2 });
-            AddByte(digital[0]);
+            digital = IDMBuffer.SetBits(digital, 0, new bool[] { Digital1, Digital2 });
+            buffer.AddByte(digital[0]);
             
-            AddUInt16(Analog1);
-            AddUInt16(Analog2);
+            buffer.AddUInt16(Analog1);
+            buffer.AddUInt16(Analog2);
 
-            AddByte(0);
-            
-            
+            buffer.AddByte(0);
         }
     }
 }

+ 4 - 4
inabox.digitalmatter/Fields/Bluetooth/DMUnknownBluetoothTag.cs

@@ -9,14 +9,14 @@
             return "N/A";
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            Payload = TakeBytes(DataLength);
+            Payload = buffer.TakeBytes(DataLength);
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddBytes(Payload);
+            buffer.AddBytes(Payload);
         }
     }
 

+ 5 - 5
inabox.digitalmatter/Fields/DMAnalogueDataField.cs

@@ -21,18 +21,18 @@ namespace InABox.DigitalMatter
         public double LoadedVoltage => Data.ContainsKey(5) ? (double)Data[5] / 100.0F : 0.0F;
         public double? BatteryStrength => Data.ContainsKey(6) ? (double)Data[6] / 100.0F : new double?();
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
             for (var i = 0; i < Length; i += 3)
-                Data[TakeByte()] = TakeInt16();
+                Data[buffer.TakeByte()] = buffer.TakeInt16();
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
             foreach (var key in Data.Keys)
             {
-                AddByte(key);
-                AddInt16(Data[key]);
+                buffer.AddByte(key);
+                buffer.AddInt16(Data[key]);
             }
         }
 

+ 8 - 8
inabox.digitalmatter/Fields/DMDigitalDataField.cs

@@ -10,18 +10,18 @@
 
         public ushort Status { get; set; }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            Inputs = TakeUInt32();
-            Outputs = TakeUInt16();
-            Status = TakeUInt16();
+            Inputs = buffer.TakeUInt32();
+            Outputs = buffer.TakeUInt16();
+            Status = buffer.TakeUInt16();
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt32(Inputs);
-            AddUInt16(Outputs);
-            AddUInt16(Status);
+            buffer.AddUInt32(Inputs);
+            buffer.AddUInt16(Outputs);
+            buffer.AddUInt16(Status);
         }
 
         public override string ToString()

+ 23 - 23
inabox.digitalmatter/Fields/DMGPSField.cs

@@ -27,7 +27,7 @@ namespace InABox.DigitalMatter
         public GPSStatus[] StatusFlags()
         {
             var result = new List<GPSStatus>();
-            var flags = DecodeByte(Status, 1, 8);
+            var flags = IDMBuffer.DecodeByte(Status, 1, 8);
             if (flags[0])
                 result.Add(GPSStatus.Valid);
             if (flags[1])
@@ -49,32 +49,32 @@ namespace InABox.DigitalMatter
                 (double)Latitude / 10000000.0F, (double)Longitude / 10000000.0F, string.Join(",", StatusFlags()));
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            TimeStamp = TakeUInt32();
-            Latitude = TakeInt32();
-            Longitude = TakeInt32();
-            Altitude = TakeInt16();
-            Speed = TakeByte();
-            SpeedAccuracy = TakeByte();
-            Heading = TakeByte();
-            PDOP = TakeByte();
-            GPSAccuracy = TakeByte();
-            Status = TakeByte();
+            TimeStamp = buffer.TakeUInt32();
+            Latitude = buffer.TakeInt32();
+            Longitude = buffer.TakeInt32();
+            Altitude = buffer.TakeInt16();
+            Speed = buffer.TakeByte();
+            SpeedAccuracy = buffer.TakeByte();
+            Heading = buffer.TakeByte();
+            PDOP = buffer.TakeByte();
+            GPSAccuracy = buffer.TakeByte();
+            Status = buffer.TakeByte();
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt32(TimeStamp);
-            AddInt32(Latitude);
-            AddInt32(Longitude);
-            AddInt16(Altitude);
-            AddUInt16(Speed);
-            AddByte(SpeedAccuracy);
-            AddByte(Heading);
-            AddByte(PDOP);
-            AddByte(GPSAccuracy);
-            AddByte(Status);
+            buffer.AddUInt32(TimeStamp);
+            buffer.AddInt32(Latitude);
+            buffer.AddInt32(Longitude);
+            buffer.AddInt16(Altitude);
+            buffer.AddUInt16(Speed);
+            buffer.AddByte(SpeedAccuracy);
+            buffer.AddByte(Heading);
+            buffer.AddByte(PDOP);
+            buffer.AddByte(GPSAccuracy);
+            buffer.AddByte(Status);
         }
     }
 }

+ 6 - 6
inabox.digitalmatter/Fields/DMOperatorField.cs

@@ -11,16 +11,16 @@
 
         public byte[] Data { get; set; }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            int type = TakeByte();
-            Data = TakeBytes(BufferSize - 1);
+            int type = buffer.TakeByte();
+            Data = buffer.TakeBytes(buffer.BufferSize - 1);
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddByte(Type);
-            AddBytes(Data);
+            buffer.AddByte(Type);
+            buffer.AddBytes(Data);
         }
 
         public override bool IsValid()

+ 6 - 6
inabox.digitalmatter/Fields/DMTripDataField.cs

@@ -7,16 +7,16 @@
         public byte Reason { get; set; }
         public ushort Trimming { get; set; }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            Reason = TakeByte();
-            Trimming = TakeUInt16();
+            Reason = buffer.TakeByte();
+            Trimming = buffer.TakeUInt16();
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddByte(Reason);
-            AddUInt16(Trimming);
+            buffer.AddByte(Reason);
+            buffer.AddUInt16(Trimming);
         }
 
         public override bool IsValid()

+ 2 - 2
inabox.digitalmatter/Messages/DMConfirmRequest.cs

@@ -4,11 +4,11 @@
     {
         public override byte Type => 0x05;
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
         }
     }

+ 4 - 4
inabox.digitalmatter/Messages/DMConfirmResponse.cs

@@ -6,14 +6,14 @@
 
         public byte Status { get; set; }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            Status = TakeByte();
+            Status = buffer.TakeByte();
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddByte(Status);
+            buffer.AddByte(Status);
         }
     }
 }

+ 6 - 7
inabox.digitalmatter/Messages/DMDataRequest.cs

@@ -16,26 +16,25 @@ namespace InABox.DigitalMatter
             set => _records = value.ToList();
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
             _records.Clear();
             ushort bytestaken = 0;
             while (bytestaken < CheckSum)
             {
-                var length = PeekUInt16(0);
+                var length = buffer.PeekUInt16(0);
                 var record = new DMRecord();
-                var buf = TakeBytes(length);
+                record.Decode(new DMPartialReadBuffer(buffer, 0, length));
                 bytestaken += length;
-                record.Decode(buf);
                 _records.Add(record);
             }
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
             foreach (var record in _records)
-                AddBytes(record.Encode());
-            InsertUInt16(0, BufferSize);
+                record.Encode(buffer);
+            buffer.InsertUInt16(0, buffer.BufferSize);
         }
 
         public override byte[] Dump()

+ 18 - 18
inabox.digitalmatter/Messages/DMHelloRequest.cs

@@ -22,28 +22,28 @@ namespace InABox.DigitalMatter
 
         public uint Flags { get; set; }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            SerialNumber = TakeUInt32();
-            IMEI = TakeString(16);
-            ICCID = TakeString(21);
-            ProductID = TakeByte();
-            HardwareRevision = TakeByte();
-            FirmwareMajor = TakeByte();
-            FirmwareMinor = TakeByte();
-            Flags = TakeUInt32();
+            SerialNumber = buffer.TakeUInt32();
+            IMEI = buffer.TakeString(16);
+            ICCID = buffer.TakeString(21);
+            ProductID = buffer.TakeByte();
+            HardwareRevision = buffer.TakeByte();
+            FirmwareMajor = buffer.TakeByte();
+            FirmwareMinor = buffer.TakeByte();
+            Flags = buffer.TakeUInt32();
         }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt32(SerialNumber);
-            AddString(IMEI, 16);
-            AddString(ICCID, 21);
-            AddByte(ProductID);
-            AddByte(HardwareRevision);
-            AddByte(FirmwareMajor);
-            AddByte(FirmwareMinor);
-            AddUInt32(Flags);
+            buffer.AddUInt32(SerialNumber);
+            buffer.AddString(IMEI, 16);
+            buffer.AddString(ICCID, 21);
+            buffer.AddByte(ProductID);
+            buffer.AddByte(HardwareRevision);
+            buffer.AddByte(FirmwareMajor);
+            buffer.AddByte(FirmwareMinor);
+            buffer.AddUInt32(Flags);
         }
 
         public override byte[] Dump()

+ 6 - 6
inabox.digitalmatter/Messages/DMHelloResponse.cs

@@ -13,16 +13,16 @@
 
         public uint Flags { get; set; }
 
-        protected override void DoEncode()
+        protected override void DoEncode(IDMWriteBuffer buffer)
         {
-            AddUInt32(TimeStamp);
-            AddUInt32(Flags);
+            buffer.AddUInt32(TimeStamp);
+            buffer.AddUInt32(Flags);
         }
 
-        protected override void DoDecode()
+        protected override void DoDecode(IDMReadBuffer buffer)
         {
-            TimeStamp = TakeUInt32();
-            Flags = TakeUInt32();
+            TimeStamp = buffer.TakeUInt32();
+            Flags = buffer.TakeUInt32();
         }
     }
 }