You are viewing an Archived item in your Knowledge Base, it is not publicly accessible.

    Contact Us

    If you still have questions or prefer to get help directly from an agent, please submit a request.
    We’ll get back to you as soon as possible.

    Please fill out the contact form below and we will reply as soon as possible.

    • Digital Matter Site
    • Contact Us

    Decoding The Oyster Sigfox Payload - Javascript example code

    Written by Matthew Clark-Massera

    Updated at March 5th, 2025

      Contact Us

      If you still have questions or prefer to get help directly from an agent, please submit a request.
      We’ll get back to you as soon as possible.

      Contact Support
      • Home
      • Devices

      Click this link to check out the Oyster Sigfox on the Digital Matter Website.

      Below is some code that will allow you to parse the body of the Sigfox message.

      e.g. parseSigFox('10b67dcc0006efda3d9816c2')

      Note: All the code is also in the attached js file.

      To start off with, you would need to decipher which message is being transmitted by looking at the low nibble in the first bit.

      function parseSigFox(data) {
       var buffer = hex2Bytes(data);
       if (!buffer) {
       return null;
       }
       var recordType = buffer[0] & 0x0f;
       switch (recordType) {
       case 0: //positional data
       return parsePositionalData(buffer);
       case 1: //downlink ACK
       return parseDownlinkAck(buffer);
       case 2: //device data
       return parseDeviceStats(buffer);
       default:
       return null;
       }
      }
      JavaScript

      From here we can parse the individual messages.

      Positional Data Message

      function parsePositionalData(buffer) {
       var flags = buffer[0] & 0xf0;
       var inTrip = (flags & 0x10) > 0;
       var lastFixFailed = (flags & 0x20) > 0;
       var latitudeRaw = parseLittleEndianInt32(buffer, 1);
       var longitudeRaw = parseLittleEndianInt32(buffer, 5);
       var headingRaw = buffer[9];
       var speedRaw = buffer[10];
       var batteryRaw = buffer[11];
       return {
       MessageType: 0,
       InTrip: inTrip,
       LastFixFailed: lastFixFailed,
       Latitude: latitudeRaw * 1e-7,
       Longitude: longitudeRaw * 1e-7,
       Heading: headingRaw * 2,
       SpeedKmH: speedRaw,
       BatteryVoltage: (batteryRaw * 25) / 1000.0
       };
      }
      JavaScript

      Downlink ACK Message

      function parseDownlinkAck(buffer) {
       var flags = buffer[0] & 0xf0;
       var downlinkAccepted = (flags & 0x10) > 0;
       var firmwareMajor = buffer[2];
       var firmwareMinor = buffer[3];
       var data = [];
       for (var i = 0; i < 8; i++) {
       data.push(i + 4);
       }
       return {
       MessageType: 1,
       DownlinkAccepted: downlinkAccepted,
       FirmwareVersion: firmwareMajor + '.' + firmwareMinor,
       DownlinkData: data
       };
      }
      JavaScript

      Device Stats Message

      function parseDeviceStats(buffer) {
       var uptimeWeeks = parseLittleEndianInt16Bits(buffer, 0, 4, 9/*bits*/);
       var txCountRaw = parseLittleEndianInt16Bits(buffer, 1, 5, 11 /*bits*/);
       var rxCountRaw = buffer[3];
       var tripCountRaw = parseLittleEndianInt16Bits(buffer, 4, 0, 13 /*bits*/);
       var gpsSuccessRaw = parseLittleEndianInt16Bits(buffer, 5, 5, 10 /*bits*/);
       var gpsFailuresRaw = parseLittleEndianInt16Bits(buffer, 6, 7, 8 /*bits*/);
       var averageFixTime = parseLittleEndianInt16Bits(buffer, 7, 7, 9/*bits*/);
       var averageFailTime = parseLittleEndianInt16Bits(buffer, 9, 0, 9/*bits*/);
       var averageFreshenTime = parseLittleEndianInt16Bits(buffer, 10, 1, 8/*bits*/);
       var wakeupsPerTrip = buffer[11] >> 1;
       return {
       MessageType: 2,
       UptimeWeeks: uptimeWeeks,
       TxCount: txCountRaw * 32,
       RxCount: rxCountRaw * 32,
       TripCount: tripCountRaw * 32,
       GpsSuccessCount: gpsSuccessRaw * 32,
       GpsFailureCount: gpsFailuresRaw * 32,
       AverageFixTimeSeconds: averageFixTime,
       AverageFailTimeSeconds: averageFailTime,
       AverageFreshenTimeSeconds: averageFreshenTime,
       WakeUpsPerTrip: wakeupsPerTrip
       };
      }
      JavaScript

      Extended Positional Data Message

      function parseExtendedData(buffer) {
       var headingRaw = buffer[0] >> 4;
       var latitudeRaw = buffer[1] + buffer[2] * 256 + buffer[3] * 65536;
       if (latitudeRaw >= 0x800000) // 2^23
       latitudeRaw -= 0x1000000; // 2^24
       var longitudeRaw = buffer[4] + buffer[5] * 256 + buffer[6] * 65536;
       if (longitudeRaw >= 0x800000) // 2^23
       longitudeRaw -= 0x1000000; // 2^24
       var posAccRaw = buffer[7];
       var batteryRaw = buffer[8];
       var speedRaw = buffer[9] & 0x3F;
       var inTrip = (buffer[9] & 0x40) > 0;
       var lastFixFailed = (buffer[9] & 0x80) > 0;
       return {
       MessageType: 3,
       Heading: headingRaw * 22.5,
       Latitude: (latitudeRaw * 256) / 1e7,
       Longitude: (longitudeRaw * 256) / 1e7,
       PosAccM: posAccRaw * 1,
       BatteryVoltage: (batteryRaw * 25) / 1000.0,
       SpeedKmH: speedRaw * 2.5,
       InTrip: inTrip,
       LastFixFailed: lastFixFailed
       };
      }
      JavaScript

      Additional Parsing Methods

      Additional methods used in parsing the basic data are shown below

      function hex2Bytes(val) {
       if (!val) {
       return [];
       }
       val = val.trim();
       if (val.startsWith('0x')) {
       val = val.substring(2); //get rid of starting '0x'
       }
       var numBytes = val.length / 2;
       var bytes = [];
       for (var i = 0; i < numBytes; i++) {
       bytes.push(parseInt(val.substring(i*2, (i*2) + 2), 16));
       }
       return bytes;
      }
      JavaScript

      Read a 32 bit integer from the array of bytes:

      function parseLittleEndianInt32(buffer, offset) {
       return (buffer[offset + 3] << 24) +
       (buffer[offset + 2] << 16) +
       (buffer[offset + 1] << 8) +
       (buffer[offset]);
      }
      JavaScript

      Read a 16 bit integer from the array of bytes:

      function parseLittleEndianInt16(buffer, offset) {
       return (buffer[offset + 1] << 8) +
       (buffer[offset]);
      }
      JavaScript

      Read some bits from the array of bytes:

      function parseLittleEndianInt16Bits(buffer, offset, bitOffset, bitLength) {
       var temp = parseLittleEndianInt16(buffer, offset);
       temp = temp >> bitOffset;
       var mask = 0xffff >> (16 - bitLength);
       return temp & mask;
      }
      JavaScript
      sigfox decoding oyster payload

      Was this article helpful?

      Yes
      No
      Give feedback about this article

      Related Articles

      • Hawk and Card - Firmware Release Notes
      • Immobilisation Install - Asset can be immobilised from server
      • SIM Providers: LTE-M/Nb-IoT + Roaming, and Setup

      Subscribe to Partner News

      Subscribe to our mailing list to receive Digital Matter news, product and tehnical updates, and more.

      Subscribe

      Copyright © Digital Matter . All Rights Reserved.

      Privacy Contact Support

      Knowledge Base Software powered by Helpjuice

      DM Logo
      Expand