This software example demonstrates the downlink capabilities of the SIGFOX network.

Dependencies:   QW_Sensors mbed

Fork of QW-Downlink by Quicksand

Information

This example demonstrates how you can use SIGFOX downlinks on your QW development kit.

When the device boots, all leds are turned on. After successful initialization the LEDs are turned off again. A bidirectional message is sent to the SIGFOX cloud when the user pushes either SW1 or SW2. All the leds light up during SIGFOX transmission.

The Downstream messages are, in fact, frame acknowledgment. It means that to receive a message on the device, you have to send one indicating the SIGFOX network you are expecting an acknowledgement.

The device is sending a message with ack flag activated and then turns into receive mode during 25 seconds, looking for the network acknowledgment. Between the end of the send and the begin of the receive you have about 15 seconds of sleep.

A moving LED animation is displayed while the modem waits to begin listening for its downlink packet. The first LED and the last LED start burning continuously when the modem is listening for a downlink packet.

When reception is complete, the signal strength (RSSI) of your SIGFOX device is displayed on the led's.

  • 1 LEDs = maximum -130dBm or lower
  • 2 LEDs = maximum -110dBm or lower
  • 3 LEDs = maximum -90dBm or lower
  • 4 LEDs = higher than -90dBm

This is the RSSI at which the original uplink transmission was received on the basestation. You can also read what basestation received the uplink message if you connect to the virtual com-port of your QW development kit (9600 baud, 8-N-1)

/media/uploads/quicksand/downlink_0.jpg

If something goes wrong, all leds will blink together for 5 seconds. If no downlink message was received you will get the following notification in your terminal window:

/media/uploads/quicksand/downlink_1.jpg

SIGFOX Backend settings

This example makes use of the "default downlink settings" when you create a device type. This is a static "direct" message, no calls to an external server are used when using this type of downlink callback. The first 4 bytes of the downlink message contains the tap id that received your message, the next 2 bytes are user-payload, in this case 0x0000, the last 2 bytes contain the RSSI.

SIGFOX downlink messages are always limited to 8 bytes total!

/media/uploads/quicksand/downlink_2.jpg

You can alter this example to send your own type of payload back to the device. The sent back data can also be the result of a callback to your own server.

Your own server as downlink data provider

You can find more information about setting callbacks here: https://lpwan.be/wp/faq/#toggle-id-6 Basically you will need to create a BIDIR callback if you want to send data to your server and receive a response to send back to the device, from the same server.

The backend server will receive a new parameter : ack. The value will be “false” or “true”. When true is set, an acknowledgment is expected.

Then you have two choices :

  • You can refuse to respond to the ack, for this you have two ways:

The first one is to respond with a HTTP 204 (no Content) ; this can be done in php simply executing

<?php
header("HTTP/1.0 204 No Content");
?>

The second way is to use the standard json way indicating you do not want to ack. For this you can use something like this :

<?php
   $_id = $_GET["id"];
   $_time = $_GET["time"];
   $_ack = $_GET["ack"];
   $_data = $_GET["data"];

   if ( $_ack == "true" ) {
     echo "{";
     echo "\"". $_id ."\" : { \"noData\" : true }";
     echo "}";
   }
?>
  • You can answer to the acknowledgment by a 8 byte message like this

<?php
   $_id = $_GET["id"];
   $_time = $_GET["time"];
   $_ack = $_GET["ack"];
   $_data = $_GET["data"];

   if ( $_ack == "true" ) {
     echo "{";
     echo "\"". $_id ."\" : { \"downlinkData\" : \"0102030405060708\" }";
     echo "}";
   } 
   header("HTTP/1.0 200 OK");
   header("Content-Type : application/json");
?>

Battery consumption

During the RX period, the device is consuming 15mA until the message is received. This has to be added to the device consumption and it reduce the battery life if you are expecting potential acknowledgment on every message.

If no ack is sent, the system will listen for 25 seconds. If an ack is sent, the device will transmit again and consume an extra 45mA during less than a second.

The number of downlink messages is limited

The number of message in downlink depends on your contract, it can be up to 4 on platinum contract. You can send more than that but it will be transferred on best effort – meaning you have no insurance it will be transmitted or not. In the future there might be penalties involved.

Nothing however limits the number of downlink requests. This can be every SIGFOX message, but you would only be allowed to reply 4 times per day.

Committer:
quicksand
Date:
Fri Oct 30 14:10:26 2015 +0000
Revision:
0:49858c4c3500
Child:
1:897a1b3f0955
First version of a simple code-example using the QW GPS Shield

Who changed what in which revision?

UserRevisionLine numberNew contents of line
quicksand 0:49858c4c3500 1 #include "mbed.h"
quicksand 0:49858c4c3500 2
quicksand 0:49858c4c3500 3 DigitalOut LED_0 (PB_6);
quicksand 0:49858c4c3500 4 DigitalOut LED_1 (PA_7);
quicksand 0:49858c4c3500 5 DigitalOut LED_2 (PA_6);
quicksand 0:49858c4c3500 6 DigitalOut LED_3 (PA_5);
quicksand 0:49858c4c3500 7 InterruptIn SW1(PB_10);
quicksand 0:49858c4c3500 8 InterruptIn SW2(PA_8);
quicksand 0:49858c4c3500 9
quicksand 0:49858c4c3500 10 Ticker hartbeat;
quicksand 0:49858c4c3500 11
quicksand 0:49858c4c3500 12 typedef struct{
quicksand 0:49858c4c3500 13 bool busy;
quicksand 0:49858c4c3500 14 char button;
quicksand 0:49858c4c3500 15 } TX_BUTTON;
quicksand 0:49858c4c3500 16
quicksand 0:49858c4c3500 17 TX_BUTTON Button_tx;
quicksand 0:49858c4c3500 18
quicksand 0:49858c4c3500 19 void beat() {
quicksand 0:49858c4c3500 20 LED_0 = !LED_0;
quicksand 0:49858c4c3500 21 }
quicksand 0:49858c4c3500 22
quicksand 0:49858c4c3500 23 //Virtual serial port over USB
quicksand 0:49858c4c3500 24 Serial pc(USBTX, USBRX);
quicksand 0:49858c4c3500 25 Serial modem(PA_9, PA_10);
quicksand 0:49858c4c3500 26
quicksand 0:49858c4c3500 27 void sw1interrupt(){
quicksand 0:49858c4c3500 28 pc.printf("Button 1 pressed, sending sigfox message (command is AT$SF=42 55 54 54 4f 4e 20 31 00 00 00 00,2,0)\n");
quicksand 0:49858c4c3500 29 modem.printf("AT$SF=42 55 54 54 4f 4e 20 31 00 00 00 00,2,0\n");
quicksand 0:49858c4c3500 30 LED_1 = 0;
quicksand 0:49858c4c3500 31 wait(0.25);
quicksand 0:49858c4c3500 32 // Flush the echo of the command:
quicksand 0:49858c4c3500 33 while(modem.readable()) modem.getc();
quicksand 0:49858c4c3500 34 Button_tx.busy = true;
quicksand 0:49858c4c3500 35 Button_tx.button = 1;
quicksand 0:49858c4c3500 36 }
quicksand 0:49858c4c3500 37
quicksand 0:49858c4c3500 38 void sw2interrupt(){
quicksand 0:49858c4c3500 39 pc.printf("Button 2 pressed, sending sigfox message (command is AT$SF=42 55 54 54 4f 4e 20 32 00 00 00 00,2,0)\n");
quicksand 0:49858c4c3500 40 modem.printf("AT$SF=42 55 54 54 4f 4e 20 32 00 00 00 00,2,0\n");
quicksand 0:49858c4c3500 41 LED_2 = 0;
quicksand 0:49858c4c3500 42 wait(0.25);
quicksand 0:49858c4c3500 43 // Flush the echo of the command:
quicksand 0:49858c4c3500 44 while(modem.readable()) modem.getc();
quicksand 0:49858c4c3500 45 Button_tx.busy = true;
quicksand 0:49858c4c3500 46 Button_tx.button = 2;
quicksand 0:49858c4c3500 47 }
quicksand 0:49858c4c3500 48
quicksand 0:49858c4c3500 49 int main() {
quicksand 0:49858c4c3500 50
quicksand 0:49858c4c3500 51 LED_0 = 1;
quicksand 0:49858c4c3500 52 LED_1 = 1;
quicksand 0:49858c4c3500 53 LED_2 = 1;
quicksand 0:49858c4c3500 54 LED_3 = 1;
quicksand 0:49858c4c3500 55 hartbeat.attach(&beat, 0.5);
quicksand 0:49858c4c3500 56 Button_tx.busy = false;
quicksand 0:49858c4c3500 57 Button_tx.button = 0;
quicksand 0:49858c4c3500 58 SW2.fall(&sw1interrupt);
quicksand 0:49858c4c3500 59 SW1.fall(&sw2interrupt);
quicksand 0:49858c4c3500 60 char responsebuffer[2];
quicksand 0:49858c4c3500 61 char c;
quicksand 0:49858c4c3500 62 while(1) {
quicksand 0:49858c4c3500 63 if(pc.readable()) {
quicksand 0:49858c4c3500 64 modem.putc(pc.getc());
quicksand 0:49858c4c3500 65 }
quicksand 0:49858c4c3500 66
quicksand 0:49858c4c3500 67 if(modem.readable()) {
quicksand 0:49858c4c3500 68 c = modem.getc();
quicksand 0:49858c4c3500 69 responsebuffer[0] = responsebuffer[1];
quicksand 0:49858c4c3500 70 responsebuffer[1] = c;
quicksand 0:49858c4c3500 71 if(Button_tx.busy)
quicksand 0:49858c4c3500 72 {
quicksand 0:49858c4c3500 73 if(responsebuffer[0] == 'O' && responsebuffer[1] == 'K' )
quicksand 0:49858c4c3500 74 {
quicksand 0:49858c4c3500 75 // Everything went fine, turn off the LED
quicksand 0:49858c4c3500 76 Button_tx.busy = false;
quicksand 0:49858c4c3500 77 if(Button_tx.button == 1) LED_1 = 1;
quicksand 0:49858c4c3500 78 if(Button_tx.button == 2) LED_2 = 1;
quicksand 0:49858c4c3500 79 }
quicksand 0:49858c4c3500 80 }
quicksand 0:49858c4c3500 81 pc.putc(c);
quicksand 0:49858c4c3500 82 }
quicksand 0:49858c4c3500 83 }
quicksand 0:49858c4c3500 84 }