Due to sigfox limitation of 12 Bytes per message, the firmware is designed to send as much data as possible in one message using a bit of creativity. It can be a bit confusing when integrating at first but the principle is simple.
The device can be configured to transmit at any set interval. When it transmits, it sends the current TOTAL COUNTS and 3 previous COUNT OFFSETS. This is done so that 4 readings can fit in one message. It is not possible to put the 3 previous TOTAL COUNTS and the CURRENT TOTAL COUNT in one message due to the sigfox limitation on 12 Bytes.
This is best explain with an example
If the device transmits(tx) every 4 hours(See protocol txFlag), it will send:
CURRENT TOTAL COUNTS
Current time now
123456789 (The reading which appears on the physical meter)
PREVIOUS OFFSET1
Offset value time now less 1 hour
eg 1 pulse
Therefore 1 hour ago the value was 123456788
PREVIOUS OFFSET2
Offset value time now less 2 hours
eg 2 pulse
Therefore 2 hours ago the value was 123456786
PREVIOUS OFFSET3
Offset value time now less 3 hours
eg 1 pulse
Therefore 3 hours ago the value was 123456785
In the example above the values would be 123456789 - 1 - 2 - 1 = 123456785 (The starting value 4 hours ago.
If the device is configured to tx every 1 hour then the offsets would be 15 minute intervals
If the device is configured to tx every 8 hour then the offsets would be 2 hour intervals
etc
Protocol - Pulse MBUS / Monitor (Type: 13 / 14)
The data (DATA in the JSON object) is as follows: Big endian (MSB first) two hex characters per byte.
Periodic Update Message:
Txflags (1 Byte)
Battery (1 Byte)
Counter (4 Bytes)
Counter Offset at ¾ tx period (2 Bytes)
Counter Offset at ½ tx period (2 Bytes)
Counter Offset at ¼ tx period (2 Bytes)
Description:
Txflags (8 bit) is a bit mask as follows:
0 (1) = Periodic Update (Sent as per Tx Update Timer Value)
1 (2) = MBUS communications CRC error, type 13 only. Type 14 not applicable
2 (4) = MBUS communications NO RESPONSE error, type 13 only. Type 14 not applicable
3 (8) = Leak State
4 (16) = Tamper State
5 (32) = Tx Update Timer
6 (64) = Tx Update Timer
7 (128) = Tx Update Timer
Tx Update Timer Interval (Binary Value of Tx Update Timer bits):
0 = 1 Hour Tx 15 minute record offset
1 = 2 Hour Tx 30 minute record offset
2 = 4 Hour Tx 1 hour record offset
3 = 8 Hour Tx 2 hour record offset
4 = 12 Hour Tx 3 hour record offset
5 = 16 Hour Tx 4 hour record offset
6 = 20 Hour Tx 5 hour record offset
7 = 24 Hour Tx 6 hour record offset
Battery (8 bit)
Is the converted value of the battery apply the following formula to get back to volts
V = Value X 0.02
Counter (32 bit)
Counter increments at one count per pulse, scaling to be done server side.
Counter Offset 1 (16 bit)
Number of pulses less than main count at ¾ transmit period
Counter Offset 2 (16 bit)
Number of pulses less than main count at ½ transmit period
Counter Offset 3 (16 bit)
Number of pulses less than main count at ¼ transmit period
Transmit encoding:
SF.Serial.TxBuffer[0] = char_to_hex((uint8_t)((txflags >> 4) & 15));
SF.Serial.TxBuffer[1] = char_to_hex((uint8_t)((txflags) & 15));
SF.Serial.TxBuffer[2] = char_to_hex((uint8_t)((Sensor.Battery >> 4) & 15));
SF.Serial.TxBuffer[3] = char_to_hex((uint8_t)((Sensor.Battery) & 15));
SF.Serial.TxBuffer[4] = char_to_hex((uint8_t)((Sensor.Counter1.Value >> 28) & 15));
SF.Serial.TxBuffer[5] = char_to_hex((uint8_t)((Sensor.Counter1.Value >> 24) & 15));
SF.Serial.TxBuffer[6] = char_to_hex((uint8_t)((Sensor.Counter1.Value >> 20) & 15));
SF.Serial.TxBuffer[7] = char_to_hex((uint8_t)((Sensor.Counter1.Value >> 16) & 15));
SF.Serial.TxBuffer[8] = char_to_hex((uint8_t)((Sensor.Counter1.Value >> 12) & 15));
SF.Serial.TxBuffer[9] = char_to_hex((uint8_t)((Sensor.Counter1.Value >> 8) & 15));
SF.Serial.TxBuffer[10] = char_to_hex((uint8_t)((Sensor.Counter1.Value >> 4) & 15));
SF.Serial.TxBuffer[11] = char_to_hex((uint8_t)((Sensor.Counter1.Value) & 15));
count_offset = Sensor.Counter1.Value - Sensor.Counter1Store[2];
SF.Serial.TxBuffer[12] = char_to_hex((uint8_t)((count_offset >> 12) & 15));
SF.Serial.TxBuffer[13] = char_to_hex((uint8_t)((count_offset >> 8) & 15));
SF.Serial.TxBuffer[14] = char_to_hex((uint8_t)((count_offset >> 4) & 15));
SF.Serial.TxBuffer[15] = char_to_hex((uint8_t)((count_offset) & 15));
count_offset = Sensor.Counter1.Value - Sensor.Counter1Store[1];
SF.Serial.TxBuffer[16] = char_to_hex((uint8_t)((count_offset >> 12) & 15));
SF.Serial.TxBuffer[17] = char_to_hex((uint8_t)((count_offset >> 8) & 15));
SF.Serial.TxBuffer[18] = char_to_hex((uint8_t)((count_offset >> 4) & 15));
SF.Serial.TxBuffer[19] = char_to_hex((uint8_t)((count_offset) & 15));
count_offset = Sensor.Counter1.Value - Sensor.Counter1Store[0];
SF.Serial.TxBuffer[20] = char_to_hex((uint8_t)((count_offset >> 12) & 15));
SF.Serial.TxBuffer[21] = char_to_hex((uint8_t)((count_offset >> 8) & 15));
SF.Serial.TxBuffer[22] = char_to_hex((uint8_t)((count_offset >> 4) & 15));
SF.Serial.TxBuffer[23] = char_to_hex((uint8_t)((count_offset) & 15));
Power Up / Forced Transmit Message / Tamper / Leak Message:
Tx Flags (1 Byte)
Battery (1 Byte)
Counter (4 Bytes)
Tx Info (1 Byte)
Tamper Level (1 Byte)
Status Detailed (1 Byte)
Description:
Tx Flags (8 bit) is a bit mask as follows:
0 (1) = Periodic Update (Sent as per Tx Update Timer Value)
1 (2) = Forced Transmit/Power Up
2 (4) = Leak/Tamper Alert
3 (8) = Leak State
4 (16) = Tamper State
5 (32) = Tx Update Timer
6 (64) = Tx Update Timer
7 (128) = Tx Update Timer
Tx Update Timer Interval (Binary Value of Tx Update Timer bits):
0 = 1 Hour Tx 15 minute record offset
1 = 2 Hour Tx 30 minute record offset
2 = 4 Hour Tx 1 hour record offset
3 = 8 Hour Tx 2 hour record offset
4 = 12 Hour Tx 3 hour record offset
5 = 16 Hour Tx 4 hour record offset
6 = 20 Hour Tx 5 hour record offset
7 = 24 Hour Tx 6 hour record offset
Battery (8 bit)
Is the converted value of the battery apply the following formula to get back to volts
V = Value X 0.02
Counter (32 bit)
Counter increments at one count per pulse, scaling to be done server side.
Tx Info (8 bit) is a bit mask as follows:
0 (1) = Tx initiated by Power Up
1 (2) = Tx initiated by Forced Transmit
2 (4) = Tx initiated by Fast Leak Alert 1 Change
3 (8) = Tx initiated by Fast Leak Alert 2 Change
4 (16) = Tx initiated by Slow Leak Alert Change
5 (32) = Tx initiated by Cable Fault Tamper Change.
6 (64) = Tx initiated by Light Tamper Change.
7 (128) = Unused
Tamper Level (8 bit)
Value from 0 – 255 representing 0 – 100% of supply voltage as measured at the tamper input
Status Detailed Info (8 bit) is a bit mask as follows:
0 (1) = Fast Leak Alert 1 Active
1 (2) = Fast Leak Alert 2 Active
2 (4) = Slow Leak Alert Active
3 (8) = Cable Fault Tamper Active
4 (16) = Light Tamper Active.
5 (32) = Unused
6 (64) = P1 Active
7 (128) = P2 Active
Transmit encoding:
SF.Serial.TxBuffer[0] = char_to_hex((uint8_t)((txflags >> 4) & 15));
SF.Serial.TxBuffer[1] = char_to_hex((uint8_t)((txflags) & 15));
SF.Serial.TxBuffer[2] = char_to_hex((uint8_t)((Sensor.Battery >> 4) & 15));
SF.Serial.TxBuffer[3] = char_to_hex((uint8_t)((Sensor.Battery) & 15));
SF.Serial.TxBuffer[4] = char_to_hex((uint8_t)((status >> 4) & 15));
SF.Serial.TxBuffer[5] = char_to_hex((uint8_t)((status) & 15));
SF.Serial.TxBuffer[6] = char_to_hex((uint8_t)((Sensor.Level >> 12) & 15));
SF.Serial.TxBuffer[7] = char_to_hex((uint8_t)((Sensor.Level >> 8) & 15));
SF.Serial.TxBuffer[8] = char_to_hex((uint8_t)((Sensor.Level >> 4) & 15));
SF.Serial.TxBuffer[9] = char_to_hex((uint8_t)((Sensor.Level) & 15));
SF.Serial.TxBuffer[10] = char_to_hex((uint8_t)((txinfo >> 12) & 15));
SF.Serial.TxBuffer[11] = char_to_hex((uint8_t)((txinfo >> 8) & 15));
SF.Serial.TxBuffer[12] = char_to_hex((uint8_t)((txinfo >> 4) & 15));
SF.Serial.TxBuffer[13] = char_to_hex((uint8_t)((txinfo) & 15));
Take a look at our Open-Source Driver on GitHub
Devices transmit their messages via the sigfox radio network to a base station. The base station back hauls the data to sigfox servers. The sigfox servers are configured to relay the messages to external servers via an API Callback.
Ensure you have a secure Restful API which can accept incoming HTTP POST from the sigfox servers. You ideally want to have authentication tokens implemented using an authentication server to make sure only valid servers can access the API.
The sigfox server POSTS application/json payloads to the external API in the following JSON format:
{
"device" : "FFFFFF",
"data" : "419b00000008000000000000",
"time" : "1601953241",
"rssi" : "-76.00"
}
"device": This is the sigfox device id in HEX format
"data": This is the payload from the device as per the PROTOCOL detailed above
"time": This is the EPOCH timestamp
"rssi": The signal strength of the device
We offer professional consulting services at affordable rates. We are here to help. We specialise in IIoT and system integration including SCADA, PLCs and Web Services.
We are a Real Telematics approved System Integrator.
0828863782
The easiest way to integrate is to place our sigfox to sql router on your network. The router has the API detailed above built into the router with authentication and security built in. Data from the sigfox network is processed and written directly to your SQL database.