A simple program that connects to University of Queensland's Lora network and requests a joke, then prints the joke to usb serial.

Dependencies:   fota-mdot libmDot MTS-Serial

src/LoraComms.cpp

Committer:
WilliamAF
Date:
2019-09-28
Revision:
1:ca2d24ec97ba
Parent:
0:fa546fb96b80

File content as of revision 1:ca2d24ec97ba:

#include "LoraComms.h"
#include "MTSLog.h"
#include "MTSText.h"

#define CHANNEL_PLAN lora::ChannelPlan_AU915()
#define REQUEST_ACK_AFTER 1 // Only request ACK from gateway every x packets
#define DISCONNECT_AFTER_LOST 5 // Disconnect from network after x failed acks
#define JOIN_RETRIES 5
#define JOIN_DELAY 1 // Seconds to wait for ack when joining network

static std::string network_name = "UQ_St_Lucia";
static std::string network_passphrase = "xxxxx";
static uint8_t frequency_sub_band = 7;
static lora::NetworkType network_type = lora::PRIVATE_MTS;
static bool adr = false;

mDot* initializeLora() {
    
    mDot* dot = mDot::getInstance(new CHANNEL_PLAN);
    
    if (!dot->getStandbyFlag()) {
        // start from a well-known state
        logInfo("defaulting Dot configuration");
        dot->resetConfig();
        dot->resetNetworkSession();
    
        // make sure library logging is turned on
        dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
        
        // update configuration if necessary
        if (dot->getJoinMode() != mDot::OTA) {
            logInfo("changing network join mode to OTA");
            if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) {
                logError("failed to set network join mode to OTA");
            }
        }
        
        update_ota_config_name_phrase(dot, network_name, network_passphrase,
                frequency_sub_band, network_type, JOIN_RETRIES);
        
        // configure network link checks
        // network link checks are a good alternative to requiring the gateway 
        // to ACK every packet and should allow a single gateway to handle more
        // Dots.
        update_network_link_check_config(dot, DISCONNECT_AFTER_LOST,
                REQUEST_ACK_AFTER);
        
        // enable or disable Adaptive Data Rate
        dot->setAdr(adr);

        // Configure the join delay
        dot->setJoinDelay(JOIN_DELAY);
    
        // save changes to configuration
        logInfo("saving configuration");
        if (!dot->saveConfig()) {
            logError("failed to save configuration");
        }
    
        // display configuration
        display_config(dot);
    } else {
        // restore the saved session if the dot woke from deepsleep mode
        // useful to use with deepsleep because session info is otherwise lost 
        // when the dot enters deepsleep
        logInfo("restoring network session from NVM");
        dot->restoreNetworkSession();
    }
    
    return dot;
}

// Copyright multitech
void display_config(mDot* dot) {
    // display configuration and library version information
    logInfo("=====================");
    logInfo("general configuration");
    logInfo("=====================");
    logInfo("version ------------------ %s", dot->getId().c_str());
    logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
    logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
    logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
        logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
    }

    std::string network_mode_str("Undefined");
    uint8_t network_mode = dot->getPublicNetwork();
    if (network_mode == lora::PRIVATE_MTS)
        network_mode_str = "Private MTS";
    else if (network_mode == lora::PUBLIC_LORAWAN)
        network_mode_str = "Public LoRaWAN";
    else if (network_mode == lora::PRIVATE_LORAWAN)
        network_mode_str = "Private LoRaWAN";
    logInfo("public network ----------- %s", network_mode_str.c_str());

    logInfo("=========================");
    logInfo("credentials configuration");
    logInfo("=========================");
    logInfo("device class ------------- %s", dot->getClass().c_str());
    logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
    if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
    logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
    logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
    logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
    } else {
    logInfo("network name ------------- %s", dot->getNetworkName().c_str());
    logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
    logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
    logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
    }
    logInfo("========================");
    logInfo("communication parameters");
    logInfo("========================");
    if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
    logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
    } else {
    logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
    }
    logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
    logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
    logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
    logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
    if (dot->getLbtTimeUs()) {
    logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
    logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
    }
}

// Copyright multitech
void update_ota_config_name_phrase(mDot* dot,
                                std::string network_name,
                                std::string network_passphrase,
                                uint8_t frequency_sub_band,
                                lora::NetworkType network_type,
                                uint8_t ack) {
    std::string current_network_name = dot->getNetworkName();
    std::string current_network_passphrase = dot->getNetworkPassphrase();
    uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
    uint8_t current_network_type = dot->getPublicNetwork();
    uint8_t current_ack = dot->getAck();
    
    if (current_network_name != network_name) {
        logInfo("changing network name from \"%s\" to \"%s\"", 
                current_network_name.c_str(), network_name.c_str());
        if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
            logError("failed to set network name to \"%s\"",
                    network_name.c_str());
        }
    }
    
    if (current_network_passphrase != network_passphrase) {
        logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
        if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
            logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
        }
    }
    
    if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
        if (current_frequency_sub_band != frequency_sub_band) {
            logInfo("changing frequency sub band from %u to %u", 
                    current_frequency_sub_band, frequency_sub_band);
            if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
                logError("failed to set frequency sub band to %u",
                        frequency_sub_band);
            }
        }
    }

    if (current_network_type != network_type) {
        if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
            logError("failed to set network type");
        }
    }

    if (current_ack != ack) {
        logInfo("changing acks from %u to %u", current_ack, ack);
        if (dot->setAck(ack) != mDot::MDOT_OK) {
            logError("failed to set acks to %u", ack);
        }
    }
}

// Copyright multitech
void update_network_link_check_config(mDot* dot, uint8_t link_check_count,
        uint8_t link_check_threshold) {
    uint8_t current_link_check_count = dot->getLinkCheckCount();
    uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();

    if (current_link_check_count != link_check_count) {
    logInfo("changing link check count from %u to %u", current_link_check_count,
            link_check_count);
    if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
        logError("failed to set link check count to %u", link_check_count);
    }
    }

    if (current_link_check_threshold != link_check_threshold) {
        logInfo("changing link check threshold from %u to %u",
                current_link_check_threshold, link_check_threshold);
        if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
            logError("failed to set link check threshold to %u",
                    link_check_threshold);
        }
    }
}

// Copyright multitech
void join_network(mDot* dot) {
    int32_t j_attempts = 0;
    int32_t ret = mDot::MDOT_ERROR;
    
    // attempt to join the network
    while (ret != mDot::MDOT_OK) {
        logInfo("attempt %d to join network", ++j_attempts);
        ret = dot->joinNetwork();
        if (ret != mDot::MDOT_OK) {
            logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
            // in some frequency bands we need to wait until another channel is available before transmitting again
            uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
            if (delay_s < 5) {
                logInfo("waiting %lu s until next free channel", delay_s);
                wait(delay_s);
            } else {
                logInfo("sleeping %lu s until next free channel", delay_s);
                dot->sleep(delay_s, mDot::RTC_ALARM, false);
            }
        }
    }
}