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:
1:45cec6aea002
Parent:
0:5a0b43f3b143
Child:
2:9db840d12557
diff -r 5a0b43f3b143 -r 45cec6aea002 main.cpp
--- a/main.cpp	Sun Aug 23 21:28:18 2015 +0000
+++ b/main.cpp	Thu Sep 03 23:36:45 2015 +0000
@@ -26,11 +26,14 @@
 // /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;
+//static uint8_t config_frequency_sub_band = 1;
 
 // mDot/dev board activity LED
-#define ACTIVITY_LED PA_0
-#define DATA_PIN     PC_13
+//#define ACTIVITY_LED PA_0
+// D13
+#define DATA_PIN     PA_5
+// A0
+//#define DATA_PIN     PB_1
 
 // must use the hardware SPI pins
 //SPI device(SPI_MOSI, SPI_MISO, SPI_SCK);
@@ -55,75 +58,104 @@
     std::vector<uint8_t> send_data;
     std::vector<uint8_t> recv_data;
 
-    int32_t next_tx;
-    int32_t wait_time = 2;
+//    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
+//    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
+    /*    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();
+    logInfo("Checking Config");
+
+    // Test if we've already saved the config
+    std::string configNetworkName = dot->getNetworkName();
+
+    // Check pin, if low then reset config.
+    
+    
+    if( config_network_name.compare(configNetworkName) != 0 ) {
+        // Not saved config, reset
+        logInfo("Setting Config");
 
-    // Set byte order - AEP less than 1.0.30, currently using 1.0.25Beta
-    dot->setJoinByteOrder(mDot::MSB);
+        // reset to default config so we know what state we're in
+        dot->resetConfig();
+
+        // Set byte order - AEP less than 1.0.30
+//    dot->setJoinByteOrder(mDot::MSB);
+        dot->setJoinByteOrder(mDot::LSB);
 
-    // If on developer board then you can enable activity LED
-    // Currently no spare pins that LEDs are connected too.
+        logInfo("setting Join mode");
+        if ((ret = dot->setJoinMode(mDot::AUTO_OTA)) != mDot::MDOT_OK) {
+            logError("failed to set Join Mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        }
+
+        // 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
+        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;
+//    Not applicable for 868MHz in EU
+//    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("failed to set network name %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        }
 
-    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("failed to set network password %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        }
+
+        logInfo("Saving Config");
+
+        // Save config
+        if (! dot->saveConfig()) {
+            logError("failed to save configuration");
+        }
+    } else {
+        logInfo("Using existing Config");
     }
-    
-    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) {
@@ -131,19 +163,19 @@
         //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 );
+        sprintf(dataBuf, "{\"tmp\":%3.1f}", temperature );
         send_data.clear();
         // probably not the most efficent way to do this
         for( int i=0; i< strlen(dataBuf); i++ )
@@ -151,37 +183,27 @@
 
         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.
+        // Should  sleep here and wakeup after a set interval.
+
+        uint32_t sleep_time = 60;           //(dot->getNextTxMs() / 1000) + 10;
+        logInfo("going to sleep...");
 
-        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);
+        // go to sleep and wake up automatically sleep_time seconds later
+        dot->sleep(sleep_time, mDot::RTC_ALARM, false);
+        /*
+                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;