Using personalization mode for the Multitech mDot. Works out of the box with f.e. LORIOT (just copy in DevAddr and the Keys).

Dependencies:   libmDot mbed-rtos mbed

Fork of mDot_LoRa_Sleep_Example by MultiTech

Revision:
5:9788d9d9875d
Parent:
4:ac599fe6bc41
Child:
6:12850c60134e
--- a/main.cpp	Wed Sep 30 20:06:52 2015 +0000
+++ b/main.cpp	Thu Mar 31 13:08:26 2016 +0000
@@ -4,22 +4,95 @@
 #include <string>
 #include <vector>
 #include <algorithm>
+#include "mbed.h"
 
-// these options must match the settings on your Conduit
-// uncomment the following lines and edit their values to match your configuration
-//static std::string config_network_name = "<lora network id>";
-//static std::string config_network_pass = "<lora network key>";
-//static uint8_t config_frequency_sub_band = 1;
+static const char LORIOT_DEV_ADDR[]  = "AABBCCDD"; // Use the big endian version here
+static const char LORIOT_NWK_S_KEY[] = "E8A25EBD07F85800E08478A041FACBA7"; // NWKSKEY
+static const char LORIOT_APP_S_KEY[] = "BE8EF84E745D0AB14D4507B0BA600555"; // APPSKEY
+
+static mDot* dot;
+
+void parseKeys() {
+    int32_t ret;
+    
+    // parse devkey
+    static uint8_t NwkSKey[16];
+    static int ni;
+    for (ni = 0; ni < 16; ni++)
+    {
+        char *non_numeric_ptr;
+        const char hex[] = { '0', 'x', LORIOT_NWK_S_KEY[ni * 2], LORIOT_NWK_S_KEY[ni * 2 + 1] };
+        NwkSKey[ni] = strtoul(hex, &non_numeric_ptr, 16);
+        free(non_numeric_ptr);
+    }
+    const std::vector<uint8_t> loriot_nwk_skey (NwkSKey, NwkSKey + sizeof(NwkSKey) / sizeof(NwkSKey[0]) );
+
+    // parse appkey
+    static uint8_t ArtSKey[16];
+    static int ai;
+    for (ai = 0; ai < 16; ai++)
+    {
+        char *non_numeric_ptr;
+        const char hex[] = { '0', 'x', LORIOT_APP_S_KEY[ai * 2], LORIOT_APP_S_KEY[ai * 2 + 1] };
+        ArtSKey[ai] = strtoul(hex, &non_numeric_ptr, 16);
+        free(non_numeric_ptr);
+    }
+    const std::vector<uint8_t> loriot_app_skey (ArtSKey, ArtSKey + sizeof(ArtSKey) / sizeof(ArtSKey[0]) );
+    
+    // parse dev addr
+    static uint8_t DevAddr[4];
+    for (ai = 0; ai < 4; ai++)
+    {
+        char *non_numeric_ptr;
+        const char hex[] = { '0', 'x', LORIOT_DEV_ADDR[ai * 2], LORIOT_DEV_ADDR[ai * 2 + 1] };
+        DevAddr[ai] = strtoul(hex, &non_numeric_ptr, 16);
+        free(non_numeric_ptr);
+    }
+    const std::vector<uint8_t> loriot_dev_addr (DevAddr, DevAddr + sizeof(DevAddr) / sizeof(DevAddr[0]) );
+    
+    logInfo("setting network address");
+    if ((ret = dot->setNetworkAddress(loriot_dev_addr)) != mDot::MDOT_OK) {
+        logError("failed to set network address %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    logInfo("setting network session key");
+    if ((ret = dot->setNetworkSessionKey(loriot_nwk_skey)) != mDot::MDOT_OK) {
+        logError("failed to set network session key %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+    
+    logInfo("setting app session key");
+    if ((ret = dot->setDataSessionKey(loriot_app_skey)) != mDot::MDOT_OK) {
+        logError("failed to set app session key %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    }
+}
+
+static int8_t counter = 0;
+void send_data(void) {
+    int32_t ret;
+    
+    std::vector<uint8_t> data;
+    data.push_back(++counter);
+    
+    logInfo("sending data 0x%02x", counter);
+    if ((ret = dot->send(data)) != mDot::MDOT_OK) {
+        logError("failed to send %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+        
+        uint32_t sleep_time = std::max((uint32_t)10000, (uint32_t)dot->getNextTxMs()) / 1000;
+        logError("if no free channel, please wait %d seconds", sleep_time);
+    } else {
+        logInfo("successfully sent data to gateway");
+    }
+}
 
 int main() {
     int32_t ret;
-    mDot* dot;
-    std::vector<uint8_t> data;
-    std::string data_str = "hello!";
+    printf("Entering main()\r\n");
     
     // get a mDot handle
     dot = mDot::getInstance();
     
+    dot->setLogLevel(mts::MTSLog::DEBUG_LEVEL);
+    
     // print library version information
     logInfo("version: %s", dot->getId().c_str());
 
@@ -29,29 +102,30 @@
     // reset to default config so we know what state we're in
     dot->resetConfig();
     
-    dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+    logInfo("frequencyBand: %d", dot->getFrequencyBand());
 
     // 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()
-    
-    // frequency sub band is only applicable in the 915 (US) frequency band
-    // if using a MultiTech Conduit gateway, use the same sub band as your Conduit (1-8) - the mDot will use the 8 channels in that sub band
-    // if using a gateway that supports all 64 channels, use sub band 0 - the mDot will use all 64 channels
-    logInfo("setting frequency sub band");
-    if ((ret = dot->setFrequencySubBand(config_frequency_sub_band)) != mDot::MDOT_OK) {
-        logError("failed to set frequency sub band %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+
+    // 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 network name");
-    if ((ret = dot->setNetworkName(config_network_name)) != mDot::MDOT_OK) {
-        logError("failed to set network name %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());
     }
     
-    logInfo("setting network password");
-    if ((ret = dot->setNetworkPassphrase(config_network_pass)) != mDot::MDOT_OK) {
-        logError("failed to set network password %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    logInfo("setting tx power to 20");
+    if ((ret = dot->setTxPower(20)) != mDot::MDOT_OK) {
+        logError("failed to set tx power %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
     }
     
+    // set up the network keys
+    parseKeys();
+    
     // a higher spreading factor allows for longer range but lower throughput
     // in the 915 (US) frequency band, spreading factors 7 - 10 are available
     // in the 868 (EU) frequency band, spreading factors 7 - 12 are available
@@ -61,15 +135,14 @@
     }
     
     // request receive confirmation of packets from the gateway
-    logInfo("enabling ACKs");
-    if ((ret = dot->setAck(1)) != mDot::MDOT_OK) {
-        logError("failed to enable ACKs %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    logInfo("disabling ACKs");
+    if ((ret = dot->setAck(0)) != mDot::MDOT_OK) {
+        logError("failed to disable ACKs %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
     }
     
-    // set join mode to AUTO_OTA so the mDot doesn't have to rejoin after sleeping
-    logInfo("setting join mode to AUTO_OTA");
-    if ((ret = dot->setJoinMode(mDot::AUTO_OTA)) != mDot::MDOT_OK) {
-        logError("failed to set join mode %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
+    logInfo("enabling ADR");
+    if ((ret = dot->setAdr(0)) != mDot::MDOT_OK) {
+        logError("failed to enable ADR %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
     }
     
     // save this configuration to the mDot's NVM
@@ -81,36 +154,16 @@
     // end of configuration
     //*******************************************
 
-    // format data for sending to the gateway
-    for (std::string::iterator it = data_str.begin(); it != data_str.end(); it++)
-        data.push_back((uint8_t) *it);
-
-    // join the network if not joined
-    if (!dot->getNetworkJoinStatus()) {
-        logInfo("network not joined, joining network");
-        if ((ret = dot->joinNetwork()) != mDot::MDOT_OK) {
-            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
-        }
+    while (true) {
+        send_data();
+        
+        uint32_t sleep_time = std::max((uint32_t)10000, (uint32_t)dot->getNextTxMs()) / 1000;
+        logInfo("going to sleep for %d seconds", sleep_time);
+    
+        // go to deepsleep and wake up automatically sleep_time seconds later
+        dot->sleep(sleep_time, mDot::RTC_ALARM);
     }
-    if (dot->getNetworkJoinStatus()) {
-        // send the data
-        // ACKs are enabled by default, so we're expecting to get one back
-        if ((ret = dot->send(data)) != mDot::MDOT_OK) {
-            logError("failed to send %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
-        } else {
-            logInfo("successfully sent data to gateway");
-        }
-    }
-
-    // in the 868 (EU) frequency band, we need to wait until another channel is available before transmitting again
-    uint32_t sleep_time = std::max((uint32_t)10000, (uint32_t)dot->getNextTxMs()) / 1000;
-    logInfo("going to sleep...");
-
-    // go to deepsleep and wake up automatically sleep_time seconds later
-    dot->sleep(sleep_time, mDot::RTC_ALARM);
 
     // go to deepsleep and wake up on rising edge of WKUP pin (PA0/XBEE_CTS/XBEE_DIO7)
     // dot->sleep(0, mDot::INTERRUPT);
-
-    return 0;
 }