Giorgos Tsapparellas / Mbed 2 deprecated LoRaWAN_mbed_lmic_agriculture_app

Dependencies:   DHT11 LMiC SX1272Lib mbed

Fork of LoRaWAN-lmic-app by Semtech

Revision:
7:8ffc2f64b0f8
Parent:
6:3758685f4b75
Child:
8:f307640ed331
--- a/main.cpp	Mon Apr 02 12:16:01 2018 +0000
+++ b/main.cpp	Mon Apr 02 16:09:01 2018 +0000
@@ -42,26 +42,25 @@
  *
  * - Through required integration, The Things Network Cloud Server passes 
  * playload data to All Things Talk Maker API which visualizes the data in 
- * a meaningful way for end-user's reference.         
+ * a meaningful way for end-user's reference.  
+ *
+ * - Fully reset device through RESET BUTTON pressed.       
  * 
  * @Author: Giorgos Tsapparellas
- * @Revisions:
- *  v0.1 -- sensors gathering on FRDM-K64F
- *  v0.2 -- attach sx1272 and take as a transmitter
- *  v0.3 --   
  * 
- * Porgram available at: 1) GITHUB LINK
- *                       2) MBED LINK
+ * Code available at: 1) GITHUB LINK
+ *                    2) MBED LINK
  *
- * SEE readME file for instructions of how to compile and run the program.
+ * SEE readME.txt file for instructions of how to compile and run the program.
  *
  *******************************************************************************/
- // ADD revisions and links above
- // ADD IFDEF, AND events, comments
+ // ADD links above
  // ADD LED FLASHING
- // BUTTON PRESSED-RESET SEND A LORA PACKET
+ // ADD to mbed
  // ADD to git hub as well
+ // write readME.txt file 
  // TEST THE CODE IF OK
+ // fill in logbook
 
 #include <mbed.h>
 #include <lmic.h>
@@ -74,6 +73,7 @@
 // DEFINITION DECLARATIONS                      //
 /////////////////////////////////////////////////
 
+#define MAX_EU_CHANNELS 16     // Frequency channels automatically initialized for EU reqion. 
 #define SINGLE_CHANNEL_GATEWAY // Force it to use 868.1 MHz frequency band only due to Dragino LG01-P LoRa Gateway hardware limitation.   
 #define TRANSMIT_INTERVAL 1800 // Transmit interval in seconds, too often may get traffic ignored.
 #define DEBUG_LEVEL 0          // Set debug level to 1 for outputting messages to the UART Terminal (e.g. Tera Term).
@@ -87,8 +87,37 @@
 // Transmit interval in seconds.
 uint16_t transmit_interval = TRANSMIT_INTERVAL;
 
+// Static osjob_t sendjob variable used by loop function
+static osjob_t sendjob;
+
+// Unsigned integer packet counter used by transmit function.
+unsigned int packetCounter = 1;
+
+// Disable data rate adaption.
+// Set to 1 in order to enable data rate adaption.
+static const bit_t disableAdrMode = 0; 
+
+// Disable link check validadtion.
+// Set to 1 in order to enable link check validation.
+static const bit_t disableLinkCheck = 0; 
+
+// Set LoRa Node's transmission power to 14 dBm.
+static const s1_t txPower = 14;
+
+// Set LoRa Node's network id to 0x1.
+static const u4_t NETID = 0x1;
+
+/* LMiC frame initializations. */
+
 // Playload frame length of size 8. 
-uint8_t LMIC_FRAME_LENGTH = 8;
+static const u1_t LMIC_FRAME_LENGTH = 8;
+
+// Set listening port to 1.
+static const u1_t LMIC_PORT = 1;
+
+// Disable confirmation of transmitted LMiC data.
+// Set to 1 in order to enable confirmation of transmitted LMiC data.
+static const u1_t LMIC_CONFIRMED = 0;
 
 #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied.
 
@@ -120,6 +149,8 @@
 DigitalOut BLUE_LED(PTB21);                 // PTB21 = Blue pin -- Indicates MCU is sleeping
 */
 
+/* Sensor declarations. */
+
 // Digital Input pin of temperature and humidity sensor set to D6.
 DHT sensorTempHum(D6, DHT11);
 
@@ -130,10 +161,201 @@
 AnalogIn sensorSoilMoisture(A3);
 
 ///////////////////////////////////////////////////
+// LMiC APPLICATION CALLBACKS                   //
+/////////////////////////////////////////////////
+
+/* 
+ * os_getArtEui callback of type void.
+ *
+ * Copies application ID (8 bytes) of The Things Network Cloud Server into
+ * memory if OTAA(Over The Air Activation) is applied.
+ *
+ * Input parameters: unsigned char buf of APPEUI. 
+ *
+ */ 
+void os_getArtEui (u1_t* buf) {
+    #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied.
+        memcpy(buf, APPEUI, 8);
+    #endif
+}// end of os_getArtEui callback.
+
+/* 
+ * os_getDevEui callback of type void.
+ *
+ * Copies device ID (8 bytes) of The Things Network Cloud Server into
+ * memory if OTAA(Over The Air Activation) is applied.
+ *
+ * Input parameters: unsigned char buf of DEVEUI. 
+ *
+ */ 
+void os_getDevEui (u1_t* buf) {
+    #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied.
+        memcpy(buf, DEVEUI, 8);
+    #endif
+}// end of os_getDevEui callback.
+
+/* 
+ * os_getDevKey callback of type void.
+ *
+ * Copies device network session ID (16 bytes) of The Things Network Cloud Server
+ * into memory.
+ *
+ * Input parameters: unsigned char buf of NWKSKEY. 
+ *
+ */ 
+void os_getDevKey (u1_t* buf) {
+    memcpy(buf, NWKSKEY, 16);
+}// end of os_getDevKey callback.
+
+/* 
+ * onEvent callback of type void.
+ *
+ * Outputs UART message depending on
+ * related event.
+ *
+ * NOTICE THAT: Not all events are being
+ * used due to significant set up 
+ * of LMiC environment.
+ *
+ * Input parameters: ev_t event. 
+ *
+ */ 
+void onEvent (ev_t ev) {
+    //debug_event(ev);
+
+    switch(ev) { // Switch events.
+        case EV_SCAN_TIMEOUT:
+            printf("EV_SCAN_TIMEOUT\n"); // Scan timeout.
+            break;
+        case EV_BEACON_FOUND:
+            printf("EV_BEACON_FOUND\n"); // Beacon found.
+            break;
+        case EV_BEACON_MISSED:
+            printf("EV_BEACON_MISSED\n"); // Beacon missed.
+            break;
+        case EV_BEACON_TRACKED:
+            printf("EV_BEACON_TRACKED\n"); // Beacon tracked.
+            break;
+        case EV_JOINING:
+            printf("EV_JOINING\n"); // Joining the network.
+            break;
+        case EV_JOINED:
+            printf("EV_JOINED\n"); // Network joined.
+            break;
+        case EV_RFU1:
+            printf("EV_RFU1\n"); // RFU1 event.
+            break;
+        case EV_JOIN_FAILED:
+            printf("EV_JOIN_FAILED\n"); // Joining failed.
+            break;
+        case EV_REJOIN_FAILED:
+            printf("EV_REJOIN_FAILED\n"); // Re-joining failed.
+            break;
+        case EV_TXCOMPLETE:
+            printf("EV_TXCOMPLETE (waiting for RX windows)\n"); // Transmission complete.
+            if (LMIC.txrxFlags & TXRX_ACK) // Check if acknowledgment received.
+            {
+                printf("Received ack\n");
+            }
+            if(LMIC.dataLen) // Output playload's data length.
+            {
+                printf("Received ");
+                printf("%u", LMIC.dataLen);
+                printf(" bytes of payload\n");
+            }
+            break;
+        case EV_LOST_TSYNC:
+            printf("EV_LOST_TSYNC\n"); // Lost transmision sync.
+            break;
+        case EV_RESET:
+            printf("EV_RESET\n"); // Reset.
+            break;
+        case EV_RXCOMPLETE:
+            printf("EV_RXCOMPLETE\n"); // Reception complete.
+            break;
+        case EV_LINK_DEAD:
+            printf("EV_LINK_DEAD\n"); // Link dead.
+            break;
+        case EV_LINK_ALIVE:
+            printf("EV_LINK_ALIVE\n"); // Link alive.
+            break;
+       default:
+            printf("Unknown event\n"); // Default unknown event.
+            break;
+    }
+}// end of onEvent callback.
+
+///////////////////////////////////////////////////
 // LOCAL FUNCTIONS DECLARATIONS                 //
 /////////////////////////////////////////////////
 
 /* 
+ * setUp function of type void.
+ *
+ * Initializes mbed OS, LMiC OS as well as
+ * disabling all channels but 0 (868.1 MHz) for single-channel 
+ * gateway compatibility.  
+ *
+ * Input parameters: None.
+ *
+ */ 
+void setUp() {
+    
+    #if DEBUG_LEVEL == 1
+        printf("IoT smart monitoring device for agriculture using LoRaWAN technology\n\n");
+    #endif
+    // Initializes OS.
+    os_init(); 
+    
+    #if DEBUG_LEVEL == 1
+        printf("OS_INIT\n\n");
+    #endif
+    
+    // Reset the MAC state. Session and pending data transfers are being discarded.
+    LMIC_reset();
+  
+    // Set static session parameters. Instead of dynamically establishing a session
+    // by joining the network, precomputed session parameters are be provided.
+    LMIC_setSession (NETID, DEVADDR, (uint8_t*)NWKSKEY, (uint8_t*)APPSKEY);
+  
+    // Disable data rate adaptation.
+    LMIC_setAdrMode(disableAdrMode);
+  
+    // Disable link check validation.
+    LMIC_setLinkCheckMode(disableLinkCheck);
+  
+    // Disable beacon tracking.
+    LMIC_disableTracking();
+  
+    // Stop listening for downstream data (periodical reception) as LoRa Node
+    // is only transmitting data to the Gateway.
+    LMIC_stopPingable();
+     
+    // Set data rate and transmit power.
+    LMIC_setDrTxpow(DR_SF7,txPower);
+
+    //fflush(stdout);
+    
+    // If single-channel gateway is being used disable 
+    // all the other channels except channel 0. 
+    #ifdef SINGLE_CHANNEL_GATEWAY
+        #if DEBUG_LEVEL == 1
+            printf("      ----->Disabling all channels but 0 (868.1 MHz) for single-channel gateway compatibility\n\n\n");
+        #endif
+    
+        for (int i=1; i < MAX_EU_CHANNELS; i++)
+        {
+            LMIC_disableChannel(i);
+        }
+    #endif
+  
+    #if DEBUG_LEVEL == 1
+        printf("//////////Entering into TIME-TRIGGERED packet sending through LoRaWAN//////////\n");
+        printf("---------------------Packets to be sent every %u seconds----------------------\n\n", transmit_interval);
+    #endif
+}// end of setUp function.
+
+/* 
  * getTemperatureHumidity function of type void.
  *
  * Gets temperature (celcius) and humidity (relative humidity %)
@@ -230,7 +452,7 @@
     
     // Read soil moisture 16-bit analogue value.
     soilMoistureAnalogue = sensorSoilMoisture.read_u16();
-    //Convert the soil moisture analog reading (which goes from 0 - 65536) to a voltage (0 - 5V).
+    // Convert the soil moisture analog reading (which goes from 0 - 65536) to a voltage (0 - 5V).
     soilMoistureVoltage = (float) soilMoistureAnalogue*(5.0/65536.0);
     
     // Output soil moisture voltage as well as soil moisture analogue value on UART Terminal.
@@ -240,195 +462,135 @@
     #endif
 }// end of getSoilMoisture function.
 
-///////////////////////////////////////////////////
-// LMiC APPLICATION CALLBACKS                   //
-/////////////////////////////////////////////////
-static osjob_t sendjob;
-unsigned int xmit_count = 1;
-
-// provide application router ID (8 bytes, LSBF)
-void os_getArtEui (u1_t* buf) {
-    #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied.
-        memcpy(buf, APPEUI, 8);
-    #endif
-}
-
-// provide device ID (8 bytes, LSBF)
-void os_getDevEui (u1_t* buf) {
-    #if ACTIVATION_METHOD == 1 // if OTAA (Over The Air Activation) is applied.
-        memcpy(buf, DEVEUI, 8);
+/* 
+ * transmit function of type void.
+ *
+ * Checking if channel is ready.
+ * If no, waiting until channel becomes free.
+ * If yes, calling getTemperatureHumidity,
+ * getLightIntensity and getSoilMoisture functions 
+ * to gather measuring parameters. Then, prepares 
+ * the LoRa packet and finally sending the packet
+ * using os_setTimedCallback LMiC callback.
+ * 
+ * Input parameters: osjob_t* j
+ *
+ */ 
+void transmit(osjob_t* j)
+{
+    // Define sensor measuring parameters.
+    float temperature, humidity, lightIntensity, soilMoisture;
+    
+    #if DEBUG_LEVEL == 1
+        printf("txChannel: %u , Channel Ready? ", LMIC.txChnl);
     #endif
-}
-
-// provide device key (16 bytes)
-void os_getDevKey (u1_t* buf) {
-    memcpy(buf, NWKSKEY, 16);
-}
-
-
-void onEvent (ev_t ev) {
-    debug_event(ev);
-
-    switch(ev) {
-        case EV_SCAN_TIMEOUT:
-            printf("EV_SCAN_TIMEOUT\n");
-            break;
-        case EV_BEACON_FOUND:
-            printf("EV_BEACON_FOUND\n");
-            break;
-        case EV_BEACON_MISSED:
-            printf("EV_BEACON_MISSED\n");
-            break;
-        case EV_BEACON_TRACKED:
-            printf("EV_BEACON_TRACKED\n");
-            break;
-        case EV_JOINING:
-            printf("EV_JOINING\n");
-            break;
-        case EV_JOINED:
-            printf("EV_JOINED\n");
-            break;
-        case EV_RFU1:
-            printf("EV_RFU1\n");
-            break;
-        case EV_JOIN_FAILED:
-            printf("EV_JOIN_FAILED\n");
-            break;
-        case EV_REJOIN_FAILED:
-            printf("EV_REJOIN_FAILED\n");
-            break;
-        case EV_TXCOMPLETE:
-            printf("EV_TXCOMPLETE (waiting for RX windows)\n");
-            if (LMIC.txrxFlags & TXRX_ACK)
-            {
-                printf("Received ack\n");
-            }
-            if(LMIC.dataLen)
-            { // data received in rx slot after tx
-                printf("Received ");
-                printf("%u", LMIC.dataLen);
-                printf(" bytes of payload\n");
-            }
-            break;
-        case EV_LOST_TSYNC:
-            printf("EV_LOST_TSYNC\n");
-            break;
-        case EV_RESET:
-            printf("EV_RESET\n");
-            break;
-        case EV_RXCOMPLETE:
-            // data received in ping slot
-            printf("EV_RXCOMPLETE\n");
-            break;
-        case EV_LINK_DEAD:
-            printf("EV_LINK_DEAD\n");
-            break;
-        case EV_LINK_ALIVE:
-            printf("EV_LINK_ALIVE\n");
-            break;
-       default:
-          printf("Unknown event\n");
-          break;
-    }
-}
-
-
-void transmit(osjob_t* j){
-    //printf("txCnhl: %u , Channel Ready? ", LMIC.txChnl);
-    if (LMIC.opmode & (1 << 7)) 
+    
+    if (LMIC.opmode & (1 << 7)) // Is channel ready for transmission?
     {
         printf("NO, waiting...\n\n");
     } 
     else 
     {
-    //printf("YES, sensor readings...\n\n");
-      // Prepare upstream data transmission at the next possible time.
-      //   LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
-
-      float temperature, humidity, lightIntensity, soilMoisture;
-      getTemperatureHumidity(temperature, humidity);
-      getLightIntensity(lightIntensity);
-      getSoilMoisture(soilMoisture); 
-
-      int16_t temp = temperature*100;
-      int16_t hum = humidity*100;
-      int16_t light = lightIntensity*100;
-      int16_t soil = soilMoisture*100;
+        #if DEBUG_LEVEL == 1
+            printf("YES, sensor readings...\n\n");
+        #endif
+        
+        // Gather sensor readings.
+        getTemperatureHumidity(temperature, humidity);
+        getLightIntensity(lightIntensity);
+        getSoilMoisture(soilMoisture); 
       
-      //printf("      ----->Preparing packet...\n");
+        #if DEBUG_LEVEL == 1
+            printf("      ----->Preparing LoRa packet...\n");
+        #endif
+        
+        // Prepare upstream data transmission at the next possible time.
+        // Multiply all sensor readings by 100.
+        int16_t temp = temperature*100;
+        int16_t hum = humidity*100;
+        int16_t light = lightIntensity*100;
+        int16_t soil = soilMoisture*100;
       
-      LMIC.frame[0] = temp >> 8;
-      LMIC.frame[1] = temp & 0xFF;
-      LMIC.frame[2] = hum >> 8;
-      LMIC.frame[3] = hum & 0xFF; 
-      LMIC.frame[4] = light >> 8;
-      LMIC.frame[5] = light & 0xFF;
-      LMIC.frame[6] = soil >> 8;
-      LMIC.frame[7] = soil & 0xFF;
+        // Allocate measurements into LMIC frame array ready for transmission.
+        // Each sensor measurement allocates 2 positions in frame array.
+        // First, value is right shifted for 8 bits, while on the next 
+        // array's position least significant bits are taken as the desired 
+        // value for each sensor measurement.
+        // This procedure is required in order to send playload data
+        // to The Things Network Cloud Server.
+        // Data will then be converted in a meaningful way through 
+        // All Things Talk ABCL custom JSON binary conversion script.  
+        LMIC.frame[0] = temp >> 8;
+        LMIC.frame[1] = temp & 0xFF;
+        LMIC.frame[2] = hum >> 8;
+        LMIC.frame[3] = hum & 0xFF; 
+        LMIC.frame[4] = light >> 8;
+        LMIC.frame[5] = light & 0xFF;
+        LMIC.frame[6] = soil >> 8;
+        LMIC.frame[7] = soil & 0xFF;
       
-      //printf("      ----->Packet READY\n\n");
-      LMIC_setTxData2(1, LMIC.frame, 8, 0);
-      //printf("      ----->Sending packet %u of byte size %u\n\n", xmit_count++, LMIC_FRAME_LENGTH);
+        // Set the transmission data.
+        LMIC_setTxData2(LMIC_PORT, LMIC.frame, LMIC_FRAME_LENGTH, LMIC_CONFIRMED);
+        
+        #if DEBUG_LEVEL == 1
+            printf("      ----->LoRa Packet READY\n\n");
+            printf("      ----->Sending LoRa packet %u of byte size %u\n\n", packetCounter++, LMIC_FRAME_LENGTH);
+        #endif
     }
-    // Schedule a timed job to run at the given timestamp (absolute system time)
+    // Schedule a time-triggered job to run based on TRANSMIT_INTERVAL time value.
     os_setTimedCallback(j, os_getTime()+sec2osticks(TRANSMIT_INTERVAL), transmit);
-
-}
-
-void setUp() {
-
-  //printf("IoT smart monitoring device for agriculture using LoRaWAN technology\n\n");
-  //printf("setting up\n");
+    
+}// end of transmit function.
 
-  os_init();
-  //printf("MBED_OS_INIT\n\n");
-  //printf("os_init\n");
-  
-  // Reset the MAC state. Session and pending data transfers will be discarded.
-  LMIC_reset();
-  
-  // Set static session parameters. Instead of dynamically establishing a session
-  // by joining the network, precomputed session parameters are be provided.
-  LMIC_setSession (0x1, DEVADDR, (uint8_t*)NWKSKEY, (uint8_t*)APPSKEY);
-  
-  // Disable data rate adaptation
-  LMIC_setAdrMode(0);
-  
-  // Disable link check validation
-  LMIC_setLinkCheckMode(0);
-  
-  // Disable beacon tracking
-  LMIC_disableTracking ();
-  
-  // Stop listening for downstream data (periodical reception)
-  LMIC_stopPingable();
-  
-  // Set data rate and transmit power (note: txpow seems to be ignored by the library)
-  LMIC_setDrTxpow(DR_SF7,14);
-  
-  //printf("LMiC_LoRa_MAC_INIT\n\n");
+/* 
+ * loop function of type void.
+ *
+ * Calling transmit as well as os_runloop_once functions
+ * for a repeatedly time-triggered behaviour 
+ * program execution.
+ *
+ * Input parameters: None.
+ *
+ */ 
+void loop()
+{
+    // Calling transmit local function for acquiring next transmission
+    // job of LoRa Node.
+    transmit(&sendjob);
 
-  fflush(stdout);
-  #ifdef SINGLE_CHANNEL_GATEWAY
-  //printf("      ----->Disabling all channels but 0 (868.1 MHz) for single-channel gateway compatibility\n\n\n");
-  for (int i=1; i<16; i++)
-   LMIC_disableChannel(i);
-  #endif
-  //printf("//////////Entering into TIME-TRIGGERED packet sending through LoRaWAN//////////\n");
-  //printf("---------------------Packets to be sent every %u seconds----------------------\n\n", transmit_interval);
-}
-
-void loop() {
+    // Super loop running os_runloop_once LMiC callback in a time-triggered behaviour. 
+    while(1)
+    {
+        // Calling LMiC os_runloop_once callback.
+        os_runloop_once();
+        // Delay of 20 ms.
+        wait_ms(20);
+    }
+    // Never arives here!
+    
+}// end of loop function.
 
-transmit(&sendjob);
-
-while(1) {
-  os_runloop_once();
-  wait_ms(20);
-  }
-  }
-
-int main(int argc, char **argv) {
+/* 
+ * main function of type integer.
+ *
+ * Calling setUp as well as loop functions
+ * for a repeatedly time-triggered behaviour 
+ * program execution.
+ *
+ * Input parameters: integer argc.
+ *                   char **argv. 
+ *
+ */ 
+int main(int argc, char **argv) 
+{
+    // Calling setUp local function for OS initialization.
     setUp();
-    while(1) loop();
-    }
\ No newline at end of file
+    
+    // Super loop running loop local funcion in a time-triggered behaviour.
+    while(1)
+    { 
+        loop();
+    }    
+    // Never arrives here!
+    
+} // end of main function. 
\ No newline at end of file