private ArgosFix[] GetFixes(DateTime transmissionDateTime, ICollection<byte> message)
        {
            if (message == null)
                return new ArgosFix[0];

            //Get the message header
            bool messageHasSensorData = message.BooleanAt(0);
            //ignore sensor or error messages
            if (messageHasSensorData)
                return new ArgosFix[0];
            if (message.Count < 9) //72 bits (9 bytes) required for a full absolute fix
                return new[] { new ArgosFix { ConditionCode = ArgosConditionCode.Invalid } };

            //Get the absolute Fix
            byte reportedCrc = message.ByteAt(1, 6);
            byte fixBufferType = message.ByteAt(7, 2);
            uint longitudeBits = message.UInt32At(9, 22);
            double longitude = longitudeBits.TwosComplement(22, 4);
            uint latitudeBits = message.UInt32At(31, 21);
            double latitude = latitudeBits.TwosComplement(21, 4);
            ushort julian = message.UInt16At(52, 9);
            byte hour = message.ByteAt(61, 5);
            byte minute = message.ByteAt(66, 6);
            DateTime fixDate = CalculateFixDate(transmissionDateTime, julian, hour, minute);

            // Cyclical Redundancy Check
            var crc = new Crc();
            crc.Update(fixBufferType, 2);
            crc.Update((int)longitudeBits, 22);
            crc.Update((int)latitudeBits, 21);
            crc.Update(julian, 9);
            crc.Update(hour, 5);
            crc.Update(minute, 6);
            ArgosConditionCode cCode = crc.Value == reportedCrc ? ArgosConditionCode.Good : ArgosConditionCode.Bad;

            var fixes = new List<ArgosFix>
                    {
                        new ArgosFix
                            {
                                ConditionCode = cCode,
                                Longitude = longitude,
                                Latitude = latitude,
                                DateTime = fixDate
                            }
                    };

            //Setup for the relative fixes
            if (fixBufferType > 3)
                throw new InvalidDataException("Argos Message has invalid Fix Buffer Type.");
            int numberOfRelativeFixes = new[] { 0, 3, 4, 5 }[fixBufferType];
            int doubleLength = new[] { 0, 17, 12, 9 }[fixBufferType];
            int relativeFixLength = new[] { 0, 46, 36, 30 }[fixBufferType];

            //Get the relative fixes
            for (var i = 0; i < numberOfRelativeFixes; i++)
            {
                int firstBit = 72 + i * relativeFixLength;
                int bytesRequired = (firstBit + relativeFixLength + 7) / 8; //+7 to round up
                if (message.Count < bytesRequired)
                    break;
                reportedCrc = message.ByteAt(firstBit, 6);
                firstBit += 6;
                longitudeBits = message.UInt32At(firstBit, doubleLength);
                double longitudeDelta = longitudeBits.TwosComplement(doubleLength, 4);
                firstBit += doubleLength;
                latitudeBits = message.UInt32At(firstBit, doubleLength);
                double latitudeDelta = latitudeBits.TwosComplement(doubleLength, 4);
                firstBit += doubleLength;
                //Get the time of the relative fixes
                byte delay = message.ByteAt(firstBit, 6);

                TimeSpan timeOffset = TimeSpan.FromMinutes((i + 1) * Period.TotalMinutes);
                fixDate = fixDate.AddMinutes(-fixDate.Minute); //Round down to the hour

                // Cyclical Redundancy Check
                crc = new Crc();
                crc.Update((int)longitudeBits, doubleLength);
                crc.Update((int)latitudeBits, doubleLength);
                crc.Update(delay, 6);
                cCode = crc.Value == reportedCrc ? ArgosConditionCode.Good : ArgosConditionCode.Bad;

                //If the CRC is good we still need to check for values out of range
                if (cCode == ArgosConditionCode.Good)
                {
                    //if the 6 bits of delay are all ones the fix could not be acquired
                    if ((delay & 0x3F) == 0x3F)
                        cCode = ArgosConditionCode.Unavailable;
                }
                if (delay > 59) //59 min is max delay
                    delay = 0;
                //NOTE: In some cases Unavailable is reported when CRC was bad, but usually not.

                DateTime relFixDate;
                if (fixDate == default(DateTime))
                    relFixDate = new DateTime(); // use default value
                else
                    relFixDate = fixDate - timeOffset + TimeSpan.FromMinutes(delay);

                fixes.Add(
                    new ArgosFix
                    {
                        ConditionCode = cCode,
                        Longitude = longitude + longitudeDelta,
                        Latitude = latitude + latitudeDelta,
                        DateTime = relFixDate
                    }
                );
            }

            return fixes.ToArray();
        }
示例#2
0
        private ArgosFix[] GetFixes(DateTime transmissionDateTime, ICollection <byte> message)
        {
            if (message == null)
            {
                return(new ArgosFix[0]);
            }

            //Get the message header
            bool messageHasSensorData = message.BooleanAt(0);

            //ignore sensor or error messages
            if (messageHasSensorData)
            {
                return(new ArgosFix[0]);
            }
            if (message.Count < 9) //72 bits (9 bytes) required for a full absolute fix
            {
                return new[] { new ArgosFix {
                                   ConditionCode = ArgosConditionCode.Invalid
                               } }
            }
            ;

            //Get the absolute Fix
            byte     reportedCrc   = message.ByteAt(1, 6);
            byte     fixBufferType = message.ByteAt(7, 2);
            uint     longitudeBits = message.UInt32At(9, 22);
            double   longitude     = longitudeBits.TwosComplement(22, 4);
            uint     latitudeBits  = message.UInt32At(31, 21);
            double   latitude      = latitudeBits.TwosComplement(21, 4);
            ushort   julian        = message.UInt16At(52, 9);
            byte     hour          = message.ByteAt(61, 5);
            byte     minute        = message.ByteAt(66, 6);
            DateTime fixDate       = CalculateFixDate(transmissionDateTime, julian, hour, minute);

            // Cyclical Redundancy Check
            var crc = new Crc();

            crc.Update(fixBufferType, 2);
            crc.Update((int)longitudeBits, 22);
            crc.Update((int)latitudeBits, 21);
            crc.Update(julian, 9);
            crc.Update(hour, 5);
            crc.Update(minute, 6);
            ArgosConditionCode cCode = crc.Value == reportedCrc ? ArgosConditionCode.Good : ArgosConditionCode.Bad;


            var fixes = new List <ArgosFix>
            {
                new ArgosFix
                {
                    ConditionCode = cCode,
                    Longitude     = longitude,
                    Latitude      = latitude,
                    DateTime      = fixDate
                }
            };

            //Setup for the relative fixes
            if (fixBufferType > 3)
            {
                throw new InvalidDataException("Argos Message has invalid Fix Buffer Type.");
            }
            int numberOfRelativeFixes = new[] { 0, 3, 4, 5 }[fixBufferType];
            int doubleLength          = new[] { 0, 17, 12, 9 }[fixBufferType];
            int relativeFixLength     = new[] { 0, 46, 36, 30 }[fixBufferType];

            //Get the relative fixes
            for (var i = 0; i < numberOfRelativeFixes; i++)
            {
                int firstBit      = 72 + i * relativeFixLength;
                int bytesRequired = (firstBit + relativeFixLength + 7) / 8; //+7 to round up
                if (message.Count < bytesRequired)
                {
                    break;
                }
                reportedCrc   = message.ByteAt(firstBit, 6);
                firstBit     += 6;
                longitudeBits = message.UInt32At(firstBit, doubleLength);
                double longitudeDelta = longitudeBits.TwosComplement(doubleLength, 4);
                firstBit    += doubleLength;
                latitudeBits = message.UInt32At(firstBit, doubleLength);
                double latitudeDelta = latitudeBits.TwosComplement(doubleLength, 4);
                firstBit += doubleLength;
                //Get the time of the relative fixes
                byte delay = message.ByteAt(firstBit, 6);

                TimeSpan timeOffset = TimeSpan.FromMinutes((i + 1) * Period.TotalMinutes);
                fixDate = fixDate.AddMinutes(-fixDate.Minute); //Round down to the hour

                // Cyclical Redundancy Check
                crc = new Crc();
                crc.Update((int)longitudeBits, doubleLength);
                crc.Update((int)latitudeBits, doubleLength);
                crc.Update(delay, 6);
                cCode = crc.Value == reportedCrc ? ArgosConditionCode.Good : ArgosConditionCode.Bad;

                //If the CRC is good we still need to check for values out of range
                if (cCode == ArgosConditionCode.Good)
                {
                    //if the 6 bits of delay are all ones the fix could not be acquired
                    if ((delay & 0x3F) == 0x3F)
                    {
                        cCode = ArgosConditionCode.Unavailable;
                    }
                }
                if (delay > 59) //59 min is max delay
                {
                    delay = 0;
                }
                //NOTE: In some cases Unavailable is reported when CRC was bad, but usually not.

                DateTime relFixDate;
                if (fixDate == default(DateTime))
                {
                    relFixDate = new DateTime(); // use default value
                }
                else
                {
                    relFixDate = fixDate - timeOffset + TimeSpan.FromMinutes(delay);
                }

                fixes.Add(
                    new ArgosFix
                {
                    ConditionCode = cCode,
                    Longitude     = longitude + longitudeDelta,
                    Latitude      = latitude + latitudeDelta,
                    DateTime      = relFixDate
                }
                    );
            }

            return(fixes.ToArray());
        }