Demonstration TTN OTAA node

Dependencies:   BME280 DS1820 libmDot mbed-rtos mbed

This is an example application for the MultiTech mDot and connects to The Things Network using Over The Air Activation (OTAA). It sends data from a Dallas Semiconductors DS18B20 OneWire temperature sensor.

Register a device and generate a random AppKey for the currently used application Id: (You need to use your own device IDs, the ones shown here are examples only)

./ttnctl devices register 0080000000000000 INFO Generating random AppKey... INFO Registered device AppKey=000102030405060708090A0B0C0D0E0F DevEUI=0080000000000000

or to specify the same AppKey for a new device or to reregister the same device again:

./ttnctl devices register 0080000000000000 000102030405060708090A0B0C0D0E0F

./ttnctl devices info 0080000000000000 Dynamic device:

AppEUI: 70B3D50000000000 {0x70, 0xB3, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00}

DevEUI: 0080000000000000 {0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}

AppKey: 000102030405060708090A0B0C0D0E0F {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}

Copy the AppEUI and AppKey values provided in hex array notation above to the AppEUI and AppKey parameters below.

Revision:
0:5a0b43f3b143
Child:
1:45cec6aea002
diff -r 000000000000 -r 5a0b43f3b143 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Aug 23 21:28:18 2015 +0000
@@ -0,0 +1,194 @@
+/** mDot_display - Uses 160x128 SPI LCD display to show results of message
+ * sending and receiving.
+ * Uses MultiTech mDot developer board http://www.multitech.com/models/94558010LF
+ * Requires a MultiTech MultiConnect Conduit http://www.multitech.com/models/94557203LF
+ *
+ * Example JSON received on Conduit:
+ { "chan": 5, "codr": "4/5", "datr": "SF9BW125", "freq": "869.5",
+ "lsnr": "8.8", "modu": "LORA", "rfch": 1, "rssi": -41, "seqn": 13,
+ "size": 12, "timestamp": "2015-07-22T21:19:11Z", "tmst": 517590990,
+ "payload": "{\"temperature\":21.3}", "eui": "00:80:00:00:00:00:9a:63", "_msg
+ id": "73bcd8dd.8c4328" }
+ *
+ */
+
+#include "mbed.h"
+#include "DS1820.h"
+#include "mDot.h"
+#include "MTSLog.h"
+#include "MTSText.h"
+#include <string>
+#include <vector>
+
+using namespace mts;
+
+// these options must match the settings on your Conduit in
+// /var/config/lora/lora-network-server.conf
+static std::string config_network_name = "ThingInnovations";
+static std::string config_network_pass = "donkey123";
+static uint8_t config_frequency_sub_band = 1;
+
+// mDot/dev board activity LED
+#define ACTIVITY_LED PA_0
+#define DATA_PIN     PC_13
+
+// must use the hardware SPI pins
+//SPI device(SPI_MOSI, SPI_MISO, SPI_SCK);
+
+// SPI device defines
+#define MDOT_MOSI PA_7
+#define MDOT_MISO PA_6
+#define MDOT_SCK  PA_5
+#define MDOT_TFT_CS PA_4
+
+DS1820 probe(DATA_PIN);
+
+//void log_error(mDot* dot, const char* msg, int32_t retval);
+
+Serial pc(USBTX,USBRX);
+
+
+int main()
+{
+    int32_t ret;
+    mDot* dot;
+    std::vector<uint8_t> send_data;
+    std::vector<uint8_t> recv_data;
+
+    int32_t next_tx;
+    int32_t wait_time = 2;
+//    uint8_t iterations = 99;
+    uint16_t txCount = 0;
+    uint16_t txFailCount = 0;
+    uint16_t rxCount = 0;
+    uint16_t rxOkCount = 0;
+    uint16_t noRxCount = 0;
+    uint16_t rxFailCount = 0;
+    bool initStatus = true;      // All intialised OK until told otherwise
+    float temperature = 0.0;
+    
+    pc.baud(115200);
+    pc.printf("mDot LoRa Temperature sensor\n\r");
+/*    wait_ms(5000);
+    for(int i=0; i<10; i++ )
+        pc.printf(".");
+    pc.printf("\n\r");
+*/
+/*    while( 1 ) {
+        // This takes upto 750mS, way too long. Change to 9 bit resolution if not already used.
+        
+        probe.convertTemperature(true, DS1820::all_devices);         //Start temperature conversion, wait until ready
+//        printf("It is %3.1fC\r\n", probe.temperature());
+        // Output data as JSON e.g. {"temperature":"21.3"}
+        temperature = probe.temperature();
+        pc.printf("Temperature %3.1f\r\n", temperature );
+        wait_ms(2000);
+    }
+*/
+//#ifdef bollocks
+    // get a mDot handle
+    dot = mDot::getInstance();
+
+    dot->setLogLevel(MTSLog::TRACE_LEVEL);
+
+    // reset to default config so we know what state we're in
+    dot->resetConfig();
+
+    // Set byte order - AEP less than 1.0.30, currently using 1.0.25Beta
+    dot->setJoinByteOrder(mDot::MSB);
+
+    // If on developer board then you can enable activity LED
+    // Currently no spare pins that LEDs are connected too.
+//    dot->setActivityLedPin( ACTIVITY_LED );
+//    dot->setActivityLedEnable(false);
+
+    dot->setJoinRetries( 5 );
+    dot->setTxDataRate( mDot::SF_9 );
+    dot->setTxPower( 14 );
+//    dot->setAck( 0 );       // 1 retries on Ack, 0 to disable
+
+    if ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
+        initStatus = false;
+//        logError(dot, "failed to set frequency sub band", ret);
+    }
+
+    if ((ret = dot->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
+        initStatus = false;
+//        logError(dot, "failed to set network name", ret);
+    }
+    
+    if ((ret = dot->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
+        initStatus = false;
+//        logError(dot, "failed to set network password", ret);
+    }
+    
+//    wait_ms(2000);
+
+    // Display protocol/connection info
+
+    while ((ret = dot->joinNetwork()) != mDot::MDOT_OK) {
+        logError("failed to join network [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
+        //wait(2);
+        wait_ms(dot->getNextTxMs() + 1);
+    }
+    
+    probe.setResolution(9);
+
+    char dataBuf[50];
+//    for (uint8_t i = 0; i < iterations; i++) {
+    while( 1 ) {
+        // This takes upto 750mS, way too long. Change to 9 bit resolution if not already used.
+        
+        probe.convertTemperature(true, DS1820::all_devices);         //Start temperature conversion, wait until ready
+//        printf("It is %3.1fC\r\n", probe.temperature());
+        // Output data as JSON e.g. {"temperature":"21.3"}
+        temperature = probe.temperature();
+        sprintf(dataBuf, "{\"temperature\":%3.1f}", temperature );
+        send_data.clear();
+        // probably not the most efficent way to do this
+        for( int i=0; i< strlen(dataBuf); i++ )
+            send_data.push_back( dataBuf[i] );
+
+        if ((ret = dot->send(send_data)) != mDot::MDOT_OK) {
+            logError("failed to send: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
+            txFailCount++;
+        } else {
+            txCount++;
+            logInfo("send data: %s", Text::bin2hexString(send_data).c_str());
+            /*
+            if ((ret = dot->recv(recv_data)) != mDot::MDOT_OK) {
+                logError("failed to recv: [%d][%s]", ret, mDot::getReturnCodeString(ret).c_str());
+                noRxCount++;
+            } else {
+                // Received something
+                logInfo("recv data: %s", Text::bin2hexString(recv_data).c_str());
+                rxCount++;
+                if (recv_data == send_data) {
+                    rxOkCount++;
+                    logInfo("recv data matches");
+                } else {
+                    rxFailCount++;
+                    logInfo("recv data failed to match");
+                }
+            }
+            recv_data.clear();
+            */
+        }
+
+// TODO: Should really sleep here and wakeup after a set interval.
+
+        next_tx = dot->getNextTxMs() + 1;
+        logInfo("waiting %ld ms to transmit again", next_tx);
+        wait_ms(next_tx);
+        logInfo("waiting another %d seconds", wait_time);
+        wait(wait_time);
+    }
+//#endif
+    return 0;
+}
+/*
+void log_error(mDot* dot, const char* msg, int32_t retval)
+{
+    printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str());
+}
+*/
\ No newline at end of file