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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoraComms.cpp Source File

LoraComms.cpp

00001 #include "LoraComms.h"
00002 #include "MTSLog.h"
00003 #include "MTSText.h"
00004 
00005 #define CHANNEL_PLAN lora::ChannelPlan_AU915()
00006 #define REQUEST_ACK_AFTER 1 // Only request ACK from gateway every x packets
00007 #define DISCONNECT_AFTER_LOST 5 // Disconnect from network after x failed acks
00008 #define JOIN_RETRIES 5
00009 #define JOIN_DELAY 1 // Seconds to wait for ack when joining network
00010 
00011 static std::string network_name = "UQ_St_Lucia";
00012 static std::string network_passphrase = "xxxxx";
00013 static uint8_t frequency_sub_band = 7;
00014 static lora::NetworkType network_type = lora::PRIVATE_MTS;
00015 static bool adr = false;
00016 
00017 mDot* initializeLora() {
00018     
00019     mDot* dot = mDot::getInstance(new CHANNEL_PLAN);
00020     
00021     if (!dot->getStandbyFlag()) {
00022         // start from a well-known state
00023         logInfo("defaulting Dot configuration");
00024         dot->resetConfig();
00025         dot->resetNetworkSession();
00026     
00027         // make sure library logging is turned on
00028         dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
00029         
00030         // update configuration if necessary
00031         if (dot->getJoinMode() != mDot::OTA) {
00032             logInfo("changing network join mode to OTA");
00033             if (dot->setJoinMode(mDot::OTA) != mDot::MDOT_OK) {
00034                 logError("failed to set network join mode to OTA");
00035             }
00036         }
00037         
00038         update_ota_config_name_phrase(dot, network_name, network_passphrase,
00039                 frequency_sub_band, network_type, JOIN_RETRIES);
00040         
00041         // configure network link checks
00042         // network link checks are a good alternative to requiring the gateway 
00043         // to ACK every packet and should allow a single gateway to handle more
00044         // Dots.
00045         update_network_link_check_config(dot, DISCONNECT_AFTER_LOST,
00046                 REQUEST_ACK_AFTER);
00047         
00048         // enable or disable Adaptive Data Rate
00049         dot->setAdr(adr);
00050 
00051         // Configure the join delay
00052         dot->setJoinDelay(JOIN_DELAY);
00053     
00054         // save changes to configuration
00055         logInfo("saving configuration");
00056         if (!dot->saveConfig()) {
00057             logError("failed to save configuration");
00058         }
00059     
00060         // display configuration
00061         display_config(dot);
00062     } else {
00063         // restore the saved session if the dot woke from deepsleep mode
00064         // useful to use with deepsleep because session info is otherwise lost 
00065         // when the dot enters deepsleep
00066         logInfo("restoring network session from NVM");
00067         dot->restoreNetworkSession();
00068     }
00069     
00070     return dot;
00071 }
00072 
00073 // Copyright multitech
00074 void display_config(mDot* dot) {
00075     // display configuration and library version information
00076     logInfo("=====================");
00077     logInfo("general configuration");
00078     logInfo("=====================");
00079     logInfo("version ------------------ %s", dot->getId().c_str());
00080     logInfo("device ID/EUI ------------ %s", mts::Text::bin2hexString(dot->getDeviceId()).c_str());
00081     logInfo("default channel plan ----- %s", mDot::FrequencyBandStr(dot->getDefaultFrequencyBand()).c_str());
00082     logInfo("current channel plan ----- %s", mDot::FrequencyBandStr(dot->getFrequencyBand()).c_str());
00083     if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
00084         logInfo("frequency sub band ------- %u", dot->getFrequencySubBand());
00085     }
00086 
00087     std::string network_mode_str("Undefined");
00088     uint8_t network_mode = dot->getPublicNetwork();
00089     if (network_mode == lora::PRIVATE_MTS)
00090         network_mode_str = "Private MTS";
00091     else if (network_mode == lora::PUBLIC_LORAWAN)
00092         network_mode_str = "Public LoRaWAN";
00093     else if (network_mode == lora::PRIVATE_LORAWAN)
00094         network_mode_str = "Private LoRaWAN";
00095     logInfo("public network ----------- %s", network_mode_str.c_str());
00096 
00097     logInfo("=========================");
00098     logInfo("credentials configuration");
00099     logInfo("=========================");
00100     logInfo("device class ------------- %s", dot->getClass().c_str());
00101     logInfo("network join mode -------- %s", mDot::JoinModeStr(dot->getJoinMode()).c_str());
00102     if (dot->getJoinMode() == mDot::MANUAL || dot->getJoinMode() == mDot::PEER_TO_PEER) {
00103     logInfo("network address ---------- %s", mts::Text::bin2hexString(dot->getNetworkAddress()).c_str());
00104     logInfo("network session key------- %s", mts::Text::bin2hexString(dot->getNetworkSessionKey()).c_str());
00105     logInfo("data session key---------- %s", mts::Text::bin2hexString(dot->getDataSessionKey()).c_str());
00106     } else {
00107     logInfo("network name ------------- %s", dot->getNetworkName().c_str());
00108     logInfo("network phrase ----------- %s", dot->getNetworkPassphrase().c_str());
00109     logInfo("network EUI -------------- %s", mts::Text::bin2hexString(dot->getNetworkId()).c_str());
00110     logInfo("network KEY -------------- %s", mts::Text::bin2hexString(dot->getNetworkKey()).c_str());
00111     }
00112     logInfo("========================");
00113     logInfo("communication parameters");
00114     logInfo("========================");
00115     if (dot->getJoinMode() == mDot::PEER_TO_PEER) {
00116     logInfo("TX frequency ------------- %lu", dot->getTxFrequency());
00117     } else {
00118     logInfo("acks --------------------- %s, %u attempts", dot->getAck() > 0 ? "on" : "off", dot->getAck());
00119     }
00120     logInfo("TX datarate -------------- %s", mDot::DataRateStr(dot->getTxDataRate()).c_str());
00121     logInfo("TX power ----------------- %lu dBm", dot->getTxPower());
00122     logInfo("antenna gain ------------- %u dBm", dot->getAntennaGain());
00123     logInfo("LBT ---------------------- %s", dot->getLbtTimeUs() ? "on" : "off");
00124     if (dot->getLbtTimeUs()) {
00125     logInfo("LBT time ----------------- %lu us", dot->getLbtTimeUs());
00126     logInfo("LBT threshold ------------ %d dBm", dot->getLbtThreshold());
00127     }
00128 }
00129 
00130 // Copyright multitech
00131 void update_ota_config_name_phrase(mDot* dot,
00132                                 std::string network_name,
00133                                 std::string network_passphrase,
00134                                 uint8_t frequency_sub_band,
00135                                 lora::NetworkType network_type,
00136                                 uint8_t ack) {
00137     std::string current_network_name = dot->getNetworkName();
00138     std::string current_network_passphrase = dot->getNetworkPassphrase();
00139     uint8_t current_frequency_sub_band = dot->getFrequencySubBand();
00140     uint8_t current_network_type = dot->getPublicNetwork();
00141     uint8_t current_ack = dot->getAck();
00142     
00143     if (current_network_name != network_name) {
00144         logInfo("changing network name from \"%s\" to \"%s\"", 
00145                 current_network_name.c_str(), network_name.c_str());
00146         if (dot->setNetworkName(network_name) != mDot::MDOT_OK) {
00147             logError("failed to set network name to \"%s\"",
00148                     network_name.c_str());
00149         }
00150     }
00151     
00152     if (current_network_passphrase != network_passphrase) {
00153         logInfo("changing network passphrase from \"%s\" to \"%s\"", current_network_passphrase.c_str(), network_passphrase.c_str());
00154         if (dot->setNetworkPassphrase(network_passphrase) != mDot::MDOT_OK) {
00155             logError("failed to set network passphrase to \"%s\"", network_passphrase.c_str());
00156         }
00157     }
00158     
00159     if (lora::ChannelPlan::IsPlanFixed(dot->getFrequencyBand())) {
00160         if (current_frequency_sub_band != frequency_sub_band) {
00161             logInfo("changing frequency sub band from %u to %u", 
00162                     current_frequency_sub_band, frequency_sub_band);
00163             if (dot->setFrequencySubBand(frequency_sub_band) != mDot::MDOT_OK) {
00164                 logError("failed to set frequency sub band to %u",
00165                         frequency_sub_band);
00166             }
00167         }
00168     }
00169 
00170     if (current_network_type != network_type) {
00171         if (dot->setPublicNetwork(network_type) != mDot::MDOT_OK) {
00172             logError("failed to set network type");
00173         }
00174     }
00175 
00176     if (current_ack != ack) {
00177         logInfo("changing acks from %u to %u", current_ack, ack);
00178         if (dot->setAck(ack) != mDot::MDOT_OK) {
00179             logError("failed to set acks to %u", ack);
00180         }
00181     }
00182 }
00183 
00184 // Copyright multitech
00185 void update_network_link_check_config(mDot* dot, uint8_t link_check_count,
00186         uint8_t link_check_threshold) {
00187     uint8_t current_link_check_count = dot->getLinkCheckCount();
00188     uint8_t current_link_check_threshold = dot->getLinkCheckThreshold();
00189 
00190     if (current_link_check_count != link_check_count) {
00191     logInfo("changing link check count from %u to %u", current_link_check_count,
00192             link_check_count);
00193     if (dot->setLinkCheckCount(link_check_count) != mDot::MDOT_OK) {
00194         logError("failed to set link check count to %u", link_check_count);
00195     }
00196     }
00197 
00198     if (current_link_check_threshold != link_check_threshold) {
00199         logInfo("changing link check threshold from %u to %u",
00200                 current_link_check_threshold, link_check_threshold);
00201         if (dot->setLinkCheckThreshold(link_check_threshold) != mDot::MDOT_OK) {
00202             logError("failed to set link check threshold to %u",
00203                     link_check_threshold);
00204         }
00205     }
00206 }
00207 
00208 // Copyright multitech
00209 void join_network(mDot* dot) {
00210     int32_t j_attempts = 0;
00211     int32_t ret = mDot::MDOT_ERROR;
00212     
00213     // attempt to join the network
00214     while (ret != mDot::MDOT_OK) {
00215         logInfo("attempt %d to join network", ++j_attempts);
00216         ret = dot->joinNetwork();
00217         if (ret != mDot::MDOT_OK) {
00218             logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
00219             // in some frequency bands we need to wait until another channel is available before transmitting again
00220             uint32_t delay_s = (dot->getNextTxMs() / 1000) + 1;
00221             if (delay_s < 5) {
00222                 logInfo("waiting %lu s until next free channel", delay_s);
00223                 wait(delay_s);
00224             } else {
00225                 logInfo("sleeping %lu s until next free channel", delay_s);
00226                 dot->sleep(delay_s, mDot::RTC_ALARM, false);
00227             }
00228         }
00229     }
00230 }