public static GSatMicroPosition ParseTenBytePosition(byte[] payload, DateTime? packetDateUtc = null)
        {
            if (payload.Length < 10)
                throw new ApplicationException("Position must be at least 10 bytes in length.");
            var position = new GSatMicroPosition() { Format = GSatMicroReportFormat.TenByte };
            //var payloadBits = new BitArray(payload);
            //OutputBits(payloadBits);

            position.MagicNumber = GetIntFromBits(0, 3, payload);
            var longitude = GetIntFromBits(3, 23, payload);
            position.Longitude = (((double)longitude) / 23301) - 180;
            position.Course = GetIntFromBits(26, 6, payload) * 5;

            // hours since midnight + 2 minute intervals
            var time = GetIntFromBits(32, 10, payload);
            if (!packetDateUtc.HasValue)
                packetDateUtc = DateTime.UtcNow;
            var baseDateUtc = new DateTime(packetDateUtc.Value.Year, packetDateUtc.Value.Month, packetDateUtc.Value.Day, 0, 0, 0, DateTimeKind.Utc);
            position.TimeUtc = baseDateUtc.AddMinutes((time * 2));

            // if over 12 hours different, subtract a day as it crossed midnight
            if (position.TimeUtc.Subtract(packetDateUtc.Value).Duration() > TimeSpan.FromHours(12))
                position.TimeUtc = position.TimeUtc.AddDays(-1);

            var latitude = GetIntFromBits(42, 22, payload);
            position.Latitude = (((double)latitude) / 23301) - 90;
            position.Speed = GetIntFromBits(64, 6, payload);
            position.Altitude = GetIntFromBits(70, 10, payload) * 5;
            if (payload.Length >= 11)
            {
                position.BatteryPercentage = GetIntFromBits(80, 5, payload) * 3;
                position.IsOnExternalPower = Convert.ToBoolean(GetIntFromBits(85, 1, payload));
                position.IsCheckin = Convert.ToBoolean(GetIntFromBits(86, 1, payload));
                position.IsDistress = Convert.ToBoolean(GetIntFromBits(87, 1, payload));
            }
            return position;
        }
        public static GSatMicroPosition ParseEighteenBytePosition(byte[] payload)
        {
            if (payload.Length < 18)
                throw new ApplicationException("Position must be at least 18 bytes in length.");

            var position = new GSatMicroPosition() { Format = GSatMicroReportFormat.EighteenByte };
            //var payloadBits = new BitArray(payload);
            //OutputBits(payloadBits);

            position.MagicNumber = GetIntFromBits(0, 3, payload);
            var longitude = GetIntFromBits(3, 26, payload);
            position.Longitude = (((double)longitude)/186413)-180;
            position.IsOnExternalPower = Convert.ToBoolean(GetIntFromBits(29, 1, payload));
            position.IsDistress = Convert.ToBoolean(GetIntFromBits(30, 1, payload));
            position.IsCheckin = Convert.ToBoolean(GetIntFromBits(31, 1, payload));

            position.TimeUtc = EPOCH_START.AddSeconds(GetIntFromBits(32, 29, payload));
            position.Satellites = GetIntFromBits(61, 3, payload);
            var latitude = GetIntFromBits(64, 25, payload);
            position.Latitude = (((double)latitude) / 186413) - 90;
            position.Course = GetIntFromBits(89, 6, payload) * 5;
            position.Accuracy = GetIntFromBits(95, 6, payload);
            position.ClimbRate = (GetIntFromBits(101, 11, payload) - (2 ^ 10)) / 20;
            position.BatteryPercentage = (GetIntFromBits(112, 5, payload) * 3);
            position.Speed = GetIntFromBits(117, 11, payload);
            position.Altitude = GetIntFromBits(128, 16, payload);
            return position;
        }