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

main.cpp

Committer:
janjongboom
Date:
2016-03-31
Revision:
5:9788d9d9875d
Parent:
4:ac599fe6bc41
Child:
6:12850c60134e

File content as of revision 5:9788d9d9875d:

#include "mbed.h"
#include "mDot.h"
#include "MTSLog.h"
#include <string>
#include <vector>
#include <algorithm>
#include "mbed.h"

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;
    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());

    //*******************************************
    // configuration
    //*******************************************
    // reset to default config so we know what state we're in
    dot->resetConfig();
    
    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()

    // 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());
    }
    
    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
    logInfo("setting TX spreading factor");
    if ((ret = dot->setTxDataRate(mDot::SF_10)) != mDot::MDOT_OK) {
        logError("failed to set TX datarate %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
    }
    
    // request receive confirmation of packets from the gateway
    logInfo("disabling ACKs");
    if ((ret = dot->setAck(0)) != mDot::MDOT_OK) {
        logError("failed to disable ACKs %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
    logInfo("saving config");
    if (! dot->saveConfig()) {
        logError("failed to save configuration");
    }
    //*******************************************
    // end of configuration
    //*******************************************

    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);
    }

    // go to deepsleep and wake up on rising edge of WKUP pin (PA0/XBEE_CTS/XBEE_DIO7)
    // dot->sleep(0, mDot::INTERRUPT);
}