MultiTech / Mbed 2 deprecated mDot_LoRa_CLASS_C_P2P

Dependencies:   libmDot-dev-mbed2-deprecated mbed-rtos mbed

Fork of mDot_LoRa_PEER_TO_PEER by Jason Reiss

This example will setup a peer to peer node, copy program to two dots Uplink packets will be sent every 5 seconds, however communication is half-duplex An mDot cannot receive while transmitting

This example also demonstrates asynchronous receive through libmDot using the event framework.

Received packets will be sent to the Serial port on pins 2 and 3 baud rate for serial ports is set to 115200

Revision:
5:1ad91719506b
Parent:
4:ac599fe6bc41
Child:
6:ebaf55285f73
--- a/main.cpp	Wed Sep 30 20:06:52 2015 +0000
+++ b/main.cpp	Thu Jul 07 18:49:44 2016 +0000
@@ -1,81 +1,184 @@
 #include "mbed.h"
 #include "mDot.h"
+#include "mDotEvent.h"
 #include "MTSLog.h"
 #include <string>
 #include <vector>
 #include <algorithm>
 
+// This example will setup a class C node, the node must be configured at the network server for class c operation as well
+// Uplink packets will be sent every 15 seconds
+// Received packets will be sent to the Serial port on pins 2 and 3
+// baud rate for serial ports is set to 115200
+
+
 // 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 std::string config_network_name = "<NETWORK_NAME>";
+// static std::string config_network_pass = "<NETWORK_PASS>";
+// static uint8_t config_frequency_sub_band = 1;
+
+Serial _serial(XBEE_DOUT, XBEE_DIN);
+Serial debug(USBTX, USBRX);
+
+// Custom event handler for receiving Class C packets
+
+class RadioEvent : public mDotEvent
+{
+
+
+public:
+    RadioEvent() {}
+
+    virtual ~RadioEvent() {}
+
+    /*!
+     * MAC layer event callback prototype.
+     *
+     * \param [IN] flags Bit field indicating the MAC events occurred
+     * \param [IN] info  Details about MAC events occurred
+     */
+    virtual void MacEvent(LoRaMacEventFlags* flags, LoRaMacEventInfo* info) {
 
-int main() {
+        if (mts::MTSLog::getLogLevel() == mts::MTSLog::TRACE_LEVEL) {
+            std::string msg = "OK";
+            switch (info->Status) {
+                case LORAMAC_EVENT_INFO_STATUS_ERROR:
+                    msg = "ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT:
+                    msg = "TX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_TIMEOUT:
+                    msg = "RX_TIMEOUT";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_RX_ERROR:
+                    msg = "RX_ERROR";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL:
+                    msg = "JOIN_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_DOWNLINK_FAIL:
+                    msg = "DOWNLINK_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL:
+                    msg = "ADDRESS_FAIL";
+                    break;
+                case LORAMAC_EVENT_INFO_STATUS_MIC_FAIL:
+                    msg = "MIC_FAIL";
+                    break;
+                default:
+                    break;
+            }
+            logTrace("Event: %s", msg.c_str());
+
+            logTrace("Flags Tx: %d Rx: %d RxData: %d RxSlot: %d LinkCheck: %d JoinAccept: %d",
+                     flags->Bits.Tx, flags->Bits.Rx, flags->Bits.RxData, flags->Bits.RxSlot, flags->Bits.LinkCheck, flags->Bits.JoinAccept);
+            logTrace("Info: Status: %d ACK: %d Retries: %d TxDR: %d RxPort: %d RxSize: %d RSSI: %d SNR: %d Energy: %d Margin: %d Gateways: %d",
+                     info->Status, info->TxAckReceived, info->TxNbRetries, info->TxDatarate, info->RxPort, info->RxBufferSize,
+                     info->RxRssi, info->RxSnr, info->Energy, info->DemodMargin, info->NbGateways);
+        }
+
+        if (flags->Bits.Rx) {
+            
+            logDebug("Rx %d bytes", info->RxBufferSize);
+            if (info->RxBufferSize > 0) {
+                
+                for (int i = 0; i < info->RxBufferSize; i++) {
+                    _serial.putc(info->RxBuffer[i]);
+                }
+            }
+            
+            delete[] info->RxBuffer;
+        }
+    }
+};
+
+
+int main()
+{
     int32_t ret;
     mDot* dot;
     std::vector<uint8_t> data;
     std::string data_str = "hello!";
-    
+
+    RadioEvent events;
+
+    debug.baud(115200);
+    _serial.baud(115200);
+
     // get a mDot handle
     dot = mDot::getInstance();
-    
+
+    // Set custom events handler for receiving Class C packets
+    dot->setEvents(&events);
+
     // 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();
-    
-    dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+    // if device is not configured for AUTO_OTA or not joined
+    if (dot->getJoinMode() != mDot::AUTO_OTA || !dot->getNetworkJoinStatus()) {
+        //*******************************************
+        // configuration
+        //*******************************************
+        // reset to default config so we know what state we're in
+        dot->resetConfig();
+
+        dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
+
+        // 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());
+        }
+
+        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 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());
+        }
 
-    // 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());
-    }
-    
-    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 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());
-    }
-    
-    // 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("enabling ACKs");
-    if ((ret = dot->setAck(1)) != mDot::MDOT_OK) {
-        logError("failed to enable 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());
-    }
-    
-    // save this configuration to the mDot's NVM
-    logInfo("saving config");
-    if (! dot->saveConfig()) {
-        logError("failed to save configuration");
+        // 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("enabling ACKs");
+        if ((ret = dot->setAck(1)) != mDot::MDOT_OK) {
+            logError("failed to enable 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("setting class C");
+        if ((ret = dot->setClass("C")) != mDot::MDOT_OK) {
+            logError("failed to set class C mode %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
@@ -85,32 +188,27 @@
     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) {
+        // 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());
+            }
         }
+    
+        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");
+            }
+        }
+
+        wait(15.0);
     }
-    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;
 }