Skip to content

LoraWAN serialization/deserialization library for The Things Network

License

Notifications You must be signed in to change notification settings

Deepdone/lora-serialization

 
 

Repository files navigation

Build Status LoRaWAN serialization/deserialization library for The Things Network

This fully unit-tested library allows you to encode your data on the Arduino site and decode it on the TTN side. It provides both a C-based encoder and a JavaScript-based decoder.

Since version 2.2.0 there is also an encoder for the TTN side.

In short

Encoding on Arduino, decoding in TTN

Arduino side:

#include "LoraMessage.h"
LoraMessage message;

message
    .addUnixtime(1467632413)
    .addLatLng(-33.905052, 151.26641);

lora_send_bytes(message.getBytes(), message.getLength());
delete message;

TTN side:

// include src/decoder.js
var json = decode(bytes, [unixtime, latLng], ['time', 'coords']);
// json == {time: unixtime, coords: [latitude, longitude]}

Encoding in TTN

TTN side:

// include src/encoder.js
var bytes = encode([timestamp, [latitude, longitude]], [unixtime, latLng]);
// bytes is of type Buffer

Usage

Unix time (4 bytes)

Serializes/deserializes a unix time (seconds)

byte buffer[4];
LoraEncoder encoder(buffer);
encoder.writeUnixtime(1467632413);
// buffer == {0x1d, 0x4b, 0x7a, 0x57}

and then in the TTN frontend, use the following method:

unixtime(bytes.slice(x, x + 4)) // 1467632413

GPS coordinates (8 bytes)

Serializes/deserializes coordinates (latitude/longitude) with a precision of 6 decimals.

byte buffer[8];
LoraEncoder encoder(buffer);
encoder.writeLatLng(-33.905052, 151.26641);
// buffer == {0x64, 0xa6, 0xfa, 0xfd, 0x6a, 0x24, 0x04, 0x09}

and then in the TTN frontend, use the following method:

latLng(bytes.slice(x, x + 8)) // [-33.905052, 151.26641]

Unsigned 8bit Integer (1 byte)

Serializes/deserializes an unsigned 8bit integer.

byte buffer[1];
LoraEncoder encoder(buffer);
uint8_t i = 10;
encoder.writeUint8(i);
// buffer == {0x0A}

and then in the TTN frontend, use the following method:

uint8(bytes.slice(x, x + 1)) // 10

Unsigned 16bit Integer (2 bytes)

Serializes/deserializes an unsigned 16bit integer.

byte buffer[2];
LoraEncoder encoder(buffer);
uint16_t i = 23453;
encoder.writeUint16(i);
// buffer == {0x9d, 0x5b}

and then in the TTN frontend, use the following method:

uint16(bytes.slice(x, x + 2)) // 23453

Temperature (2 bytes)

Serializes/deserializes a temperature reading between -327.68 and +327.67 (inclusive) with a precision of 2 decimals.

byte buffer[2];
LoraEncoder encoder(buffer);
encoder.writeTemperature(-123.45);
// buffer == {0x39, 0x30}

and then in the TTN frontend, use the following method:

temperature(bytes.slice(x, x + 2)) // -123.45

Humidity (2 bytes)

Serializes/deserializes a humidity reading between 0 and 100 (inclusive) with a precision of 2 decimals.

byte buffer[2];
LoraEncoder encoder(buffer);
encoder.writeHumidity(99.99);
// buffer == {0x0f, 0x27}

and then in the TTN frontend, use the following method:

humidity(bytes.slice(x, x + 2)) // 99.99

Composition

On the Arduino side

The decoder allows you to write more than one value to a byte array:

byte buffer[19];
LoraEncoder encoder(buffer);

encoder.writeUnixtime(1467632413);
encoder.writeLatLng(-33.905052, 151.26641);
encoder.writeUint8(10);
encoder.writeUint16(23453);
encoder.writeTemperature(80.12);
encoder.writeHumidity(99.99);
/* buffer == {
    0x1d, 0x4b, 0x7a, 0x57, // Unixtime
    0x64, 0xa6, 0xfa, 0xfd, 0x6a, 0x24, 0x04, 0x09, // latitude,longitude
    0x0A, // Uint8
    0x9d, 0x5b, // Uint16
    0x4c, 0x1f, // temperature
    0x0f, 0x27 // humidity
}
*/

Convenience class LoraMessage

There is a convenience class that represents a LoraMessage that you can add readings to:

LoraMessage message;

message
    .addUnixtime(1467632413)
    .addLatLng(-33.905052, 151.26641)
    .addUint8(10)
    .addUint16(23453)
    .addTemperature(80.12)
    .addHumidity(99.99);

send(message.getBytes(), message.getLength());
/*
getBytes() == {
    0x1d, 0x4b, 0x7a, 0x57, // Unixtime
    0x64, 0xa6, 0xfa, 0xfd, 0x6a, 0x24, 0x04, 0x09, // latitude,longitude
    0x0A, // Uint8
    0x9d, 0x5b, // Uint16
    0x4c, 0x1f, // temperature
    0x0f, 0x27, // humidity
}
and
getLength() == 19
*/

Composition in the TTN decoder frontend with the decode method

The decode method allows you to specify a mask for the incoming byte buffer (that was generated by this library) and apply decoding functions accordingly.

decode(byte Array, mask Array [,mapping Array])

Example

Paste everything from src/decoder.js into the decoder method and use like this:

function (bytes) {
    // code from src/decoder.js here
    return decode(bytes, [latLng, unixtime], ['coords', 'time']);
}

This maps the incoming byte buffer of 12 bytes to a sequence of one latLng (8 bytes) and one unixtime (4 bytes) sequence and maps the first one to a key coords and the second to a key time.

You can use: 64 A6 FA FD 6A 24 04 09 1D 4B 7A 57 for testing, and it will result in:

{
  "coords": [
    -33.905052,
    151.26641
  ],
  "time": 1467632413
}

Development

  • Run the unit tests (C) via cd test && make clean all test
  • Run the unit tests (JavaScript) via npm test

The CI will kick off once you create a pull request automatically.

About

LoraWAN serialization/deserialization library for The Things Network

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 92.7%
  • JavaScript 2.0%
  • Python 1.7%
  • Objective-C 1.7%
  • Roff 0.7%
  • Objective-C++ 0.4%
  • Other 0.8%