Two way data over LoRaWAN using Multitech mDot

Dependencies:   libmDot-mbed5

This is example firmware for the Multitech mDot. It demonstrates how to:

  • Do two-way data.
  • Sleep aggressively and only wake up when the wake-up pin is triggered.
  • Handle errors, retries and duty cycle errors.
  • Cache data in non-volatile storage.

Based on mbed OS 5.1, hard faults against mbed OS 5.3 unfortunately. Can be compiled with GCC and ARMCC (but not IAR).

To do a new transmission, short pin D6 / PA_1.

Revision:
2:ff17ce021cfb
Parent:
0:20fbd6f66b11
Child:
3:ac5101a47080
--- a/main.cpp	Tue Jan 03 13:30:12 2017 +0000
+++ b/main.cpp	Tue Jan 03 16:05:47 2017 +0000
@@ -10,9 +10,8 @@
 #define BUILTIN_LED_ON          0
 #define BUILTIN_LED_OFF         1
 
-static const char LORIOT_DEV_ADDR[]  = "01F83E96"; // Use the big endian version here
-static const char LORIOT_NWK_S_KEY[] = "6B11E4D0814BE7BC5707920B4B3545D6"; // NWKSKEY
-static const char LORIOT_APP_S_KEY[] = "5C79DCD7E2CCB93A83730BC7A9BC6CFE"; // APPSKEY
+static const char APP_EUI[] = "BE7A000000000393";
+static const char APP_KEY[] = "CF977DE56163FB1055A530CF7B82A56A";
 
 static mDot* dot;
 
@@ -74,14 +73,14 @@
             logError("failed to recv %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
             return true; // sending succeeded, just recv failed
         }
-        
+
         if (recv_data.size() > 0) {
             printf("[INFO] received %d bytes:", recv_data.size());
             for (size_t ix = 0; ix < recv_data.size(); ix++) {
                 printf(" %02x", recv_data[ix]);
             }
             printf("\r\n");
-            
+
             if (recv_data[0] == 1) {
                 led = BUILTIN_LED_ON;
             }
@@ -89,16 +88,16 @@
                 led = BUILTIN_LED_OFF;
             }
         }
-        
+
         return true;
     }
 }
 
 static void wakeUpCallback() {
     logInfo("woke up, fromInterrupt=%d", woke_from_interrupt);
-    
+
     bool wfi = woke_from_interrupt;
-    
+
     // if we were woken up by RTC_ALARM, first up the counter
     if (wfi) {
         // reset the interrupt var
@@ -106,23 +105,23 @@
 
         up_counter();
     }
-        
+
 
     bool sent = send_data();
     // not sent? try again in 5 minutes...
     if (!sent) {
         uint32_t sleep_time = 5 * 60;
-        
+
         // if woke from button press, check duty cycle first...
         if (wfi) {
             // hmm.. something went wrong. Probably duty cycle, see next Tx frame
             // get the next transmission frame (in whole seconds)
             sleep_time = ceil(static_cast<float>(dot->getNextTxMs()) / 1000.0f);
-            
+
             // Tx window open, but no success? Try again in 30s.
             if (sleep_time == 0) sleep_time = 30;
         }
-        
+
         logInfo("Going back to sleep (RTC_ALARM), time=%d", sleep_time);
         dot->sleep(sleep_time, mDot::RTC_ALARM, false);
     }
@@ -149,6 +148,10 @@
     // print library version information
     logInfo("version: %s", dot->getId().c_str());
 
+    std::vector<uint8_t> devEui = dot->getDeviceId();
+    logInfo("device eui: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+        devEui[0], devEui[1], devEui[2], devEui[3], devEui[4], devEui[5], devEui[6], devEui[7]);
+
     //*******************************************
     // configuration
     //*******************************************
@@ -160,12 +163,6 @@
     // set up the mDot with our network information: frequency sub band, network name, and network password
     // these can all be saved in NVM so they don't need to be set every time - see mDot::saveConfig()
 
-    // set join mode to MANUAL so the mDot doesn't have to rejoin after sleeping
-    logInfo("setting join mode to MANUAL");
-    if ((ret = dot->setJoinMode(mDot::MANUAL)) != mDot::MDOT_OK) {
-        logError("failed to set join mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
-    }
-
     logInfo("setting public network");
     if ((ret = dot->setPublicNetwork(true)) != mDot::MDOT_OK) {
         logError("failed to set public network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
@@ -177,7 +174,7 @@
     }
 
     // set up the network keys
-    ParseKeys::initialize(dot, LORIOT_DEV_ADDR, LORIOT_NWK_S_KEY, LORIOT_APP_S_KEY);
+    ParseKeys::initializeOta(dot, APP_EUI, APP_KEY);
 
     // a higher spreading factor allows for longer range but lower throughput
     // in the 915 (US) frequency band, spreading factors 7 - 10 are available
@@ -204,6 +201,14 @@
         logError("failed to save configuration");
     }
 
+    // OTA JOIN sequence, remove when using personalized mode
+    logInfo("joining network");
+    if ((ret = dot->joinNetwork()) != mDot::MDOT_OK ) {
+        logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        return false;
+    }
+    logInfo("joined network successfully");
+
     //*******************************************
     // end of configuration
     //*******************************************