diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9c355..1b20e33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Single Channel LoRaWAN Gateway -Version 5.3.1, June 30, 2018 +Version 5.3.2, July 07, 2018 Author: M. Westenberg (mw12554@hotmail.com) Copyright: M. Westenberg (mw12554@hotmail.com) @@ -16,6 +16,16 @@ Maintained by Maarten Westenberg (mw12554@hotmail.com) # Release Notes +New features in version 5.3.2 (July 07, 2018) +- Support for local decoding of sensor messages received by the gateway. + Use #define _LOCALSERVER 1, to enable this functionality. Also specify for each node that you want + to inspect the messages from the NwkSKey and AppSKey in the sensor.h file. + NOTE: the heap of the ESP32 is much larger than of the ESP8266. SO please be careful not to add too many + features to the "old" gateway modules +- As a result reworked the sensor functions and changes such as adding/changing DevAddrm NwkSKEY + and AppSKey parameters to several functions +- Several in-line documentaton enhancements and typos were fixed + New features in version 5.3.1 (June 30, 2018) - Included support for T-Beam board including on board GPS sensor (_sensor.ino). #define GATEWAYNODE 1 will turn the gateway into a node as well. Remember to set the address etc in ESP-sc-gway.h. diff --git a/ESP-sc-gway/ESP-sc-gway.h b/ESP-sc-gway/ESP-sc-gway.h index 6cc0441..3a7d897 100644 --- a/ESP-sc-gway/ESP-sc-gway.h +++ b/ESP-sc-gway/ESP-sc-gway.h @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 H -// Date: 2018-06-30 +// Version 5.3.2 H +// Date: 2018-07-07 // // Based on work done by Thomas Telkamp for Raspberry PI 1ch gateway and many others. // Contibutions of Dorijan Morelj and Andreas Spies for OLED support. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains a number of compile-time settings that can be set on (=1) or off (=0) @@ -19,13 +21,13 @@ // // ---------------------------------------------------------------------------------------- -#define VERSION "V.5.3.1.H; 180630a" +#define VERSION "V.5.3.2.H; 1800707a" // This value of DEBUG determines whether some parts of code get compiled. // Also this is the initial value of debug parameter. // The value can be changed using the admin webserver // For operational use, set initial DEBUG vaulue 0 -#define DEBUG 0 +#define DEBUG 1 // Debug message will be put on Serial is this one is set. // If set to 0, not USB Serial prints are done @@ -76,7 +78,7 @@ // connect with USB. #define A_OTA 1 -// We support two pin-out configurations out-of-the-box: HALLARD and COMPRESULT. +// We support a few pin-out configurations out-of-the-box: HALLARD, COMPRESULT and TTGO ESP32. // If you use one of these two, just set the parameter to the right value. // If your pin definitions are different, update the loraModem.h file to reflect these settings. // 1: HALLARD @@ -185,6 +187,10 @@ //#define _THINGPORT // e.g. 1700 //#define _THINGSERVER "" // Server URL of the LoRa-udp.js handler +// This defines whether or not we would use the gateway as +// as sort of backend system which decodes messages (see sensor.h file) +#define _LOCALSERVER 0 // See server definitions for decodes + // Gateway Ident definitions #define _DESCRIPTION "ESP Gateway" // Name of the gateway #define _EMAIL "mw12554@hotmail.com" // Owner @@ -233,28 +239,8 @@ // 2: Same as 1, but is nodes NOT in the nodes list below they are NOT // forwarded or counted! (not yet fully implemented) #define TRUSTED_NODES 1 -#if TRUSTED_NODES >= 1 -struct nodex { - uint32_t id; - char nm[32]; -}; +#define TRUSTED_DECODE 1 -// Add all your named and trusted nodes to this list -nodex nodes[] = { - { 0x260116BD , "lora-34 PIR node" }, // F=0 - { 0x26011152 , "lora-35 temp+humi node" }, // F=0 - { 0x2601148C , "lora-36 test node" }, // F=0 - { 0x26011B90 , "lora-39 temp DS18B20" }, // F=1 - { 0x260119A6 , "lora-40 airquality" }, // F=0 - { 0x2601117D , "lora-41 temp+humi SR04T" }, - { 0x26011514 , "lora-43 ch1, no sensors" }, // F=1 - { 0x26011D77 , "lora-45 not sensor" }, - { 0x2601160F , "lora-46 HTU21 metal case" }, // F=0 - { 0x26011E52 , "lora-53 gas sensor" }, // F=ALL - { 0x02020441 , "lora-65 Waterproof temp humi" },// F=0 - { 0x26011999 , "lora-901 distance sensor" } // F=0 -}; -#endif // Wifi definitions // WPA is an array with SSID and password records. Set WPA size to number of entries in array diff --git a/ESP-sc-gway/ESP-sc-gway.ino b/ESP-sc-gway/ESP-sc-gway.ino index a46915e..86308bf 100644 --- a/ESP-sc-gway/ESP-sc-gway.ino +++ b/ESP-sc-gway/ESP-sc-gway.ino @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // Author: Maarten Westenberg (mw12554@hotmail.com) // // Based on work done by Thomas Telkamp for Raspberry PI 1-ch gateway and many others. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // The protocols and specifications used for this 1ch gateway: // 1. LoRA Specification version V1.0 and V1.1 for Gateway-Node communication // @@ -53,6 +55,7 @@ // Local include files #include "loraModem.h" #include "loraFiles.h" +#include "sensor.h" #include "oLED.h" extern "C" { diff --git a/ESP-sc-gway/_WiFi.ino b/ESP-sc-gway/_WiFi.ino index 1082c2a..ff3bd8f 100644 --- a/ESP-sc-gway/_WiFi.ino +++ b/ESP-sc-gway/_WiFi.ino @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // // based on work done by Thomas Telkamp for Raspberry PI 1ch gateway // and many others. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains the LoRa filesystem specific code diff --git a/ESP-sc-gway/_gatewayMgt.ino b/ESP-sc-gway/_gatewayMgt.ino index 69baf57..ddbc568 100644 --- a/ESP-sc-gway/_gatewayMgt.ino +++ b/ESP-sc-gway/_gatewayMgt.ino @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // // Based on work done by Thomas Telkamp for Raspberry PI 1ch gateway // and many others. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg // // This file contains the functions to do management over UDP diff --git a/ESP-sc-gway/_loraFiles.ino b/ESP-sc-gway/_loraFiles.ino index 4da74c7..3918249 100644 --- a/ESP-sc-gway/_loraFiles.ino +++ b/ESP-sc-gway/_loraFiles.ino @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // // based on work done by Thomas Telkamp for Raspberry PI 1ch gateway // and many others. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains the LoRa filesystem specific code @@ -34,6 +36,21 @@ void id_print (String id, String val) { #endif } +// ---------------------------------------------------------------------------- +// INITCONFIG; Init the gateway configuration file +// Espcecially when calling SPIFFS.format() the gateway is left in an init +// which is not very well defined. This function will init some of the settings +// to well known settings. +// ---------------------------------------------------------------------------- +int initConfig(struct espGwayConfig *c) { + (*c).ch = 0; + (*c).sf = SF8; + (*c).debug = 1; + (*c).pdebug = P_GUI; + (*c).cad = _CAD; + (*c).hop = false; +} + // ---------------------------------------------------------------------------- // Read the gateway configuration file @@ -52,6 +69,7 @@ int readConfig(const char *fn, struct espGwayConfig *c) { Serial.print(F(" does not exist .. Formatting")); #endif SPIFFS.format(); + initConfig(c); return(-1); } @@ -78,6 +96,7 @@ int readConfig(const char *fn, struct espGwayConfig *c) { Serial.println(F("Formatting")); #endif SPIFFS.format(); + initConfig(c); f = SPIFFS.open(fn, "r"); tries = 0; } @@ -209,15 +228,20 @@ int writeGwayCfg(const char *fn) { } // ---------------------------------------------------------------------------- -// Write the configuration ad found in the espGwayConfig structure +// Write the configuration as found in the espGwayConfig structure // to SPIFFS +// Parameters: +// fn; Filename +// c; struct config +// Returns: +// 1 when successful, -1 on error // ---------------------------------------------------------------------------- int writeConfig(const char *fn, struct espGwayConfig *c) { if (!SPIFFS.exists(fn)) { Serial.print("WARNING:: writeConfig, file not exists, formatting "); SPIFFS.format(); - // XXX make all initial declarations here if config vars need to have a value + initConfig(c); // XXX make all initial declarations here if config vars need to have a value Serial.println(fn); } File f = SPIFFS.open(fn, "w"); @@ -256,12 +280,17 @@ int writeConfig(const char *fn, struct espGwayConfig *c) { } // ---------------------------------------------------------------------------- -// Add a line with statitics to the log. +// Add a line with statistics to the log. // // We put the check in the function to protect against calling // the function without STAT_LOG being proper defined // ToDo: Store the fileNo and the fileRec in the status file to save for // restarts +// Parameters: +// line; char array with characters to write to log +// cnt; +// Returns: +// // ---------------------------------------------------------------------------- void addLog(const unsigned char * line, int cnt) { @@ -312,8 +341,10 @@ void addLog(const unsigned char * line, int cnt) Serial.println(fn); } #endif + return; // If file open failed, return } + int i; #if DUSB>=1 if (( debug>=1 ) && ( pdebug & P_GUI )) { Serial.print(F("addLog:: fileno=")); @@ -322,8 +353,8 @@ void addLog(const unsigned char * line, int cnt) Serial.print(gwayConfig.logFileRec); Serial.print(F(": ")); - int i; - for (i=0; i< 12; i++) { // The first 12 bytes contain non printble characters + + for (i=0; i< 12; i++) { // The first 12 bytes contain non printable characters Serial.print(line[i],HEX); Serial.print(' '); } @@ -333,12 +364,12 @@ void addLog(const unsigned char * line, int cnt) } #endif //DUSB - int i; - for (i=0; i< 12; i++) { // The first 12 bytes contain non printble characters + + for (i=0; i< 12; i++) { // The first 12 bytes contain non printable characters // f.print(line[i],HEX); f.print('*'); } - f.write(&line[i], cnt-12); // write/append the line to the file + f.write(&(line[i]), cnt-12); // write/append the line to the file f.print('\n'); f.close(); // Close the file after appending to it diff --git a/ESP-sc-gway/_loraModem.ino b/ESP-sc-gway/_loraModem.ino index 4727a1a..ea7276f 100644 --- a/ESP-sc-gway/_loraModem.ino +++ b/ESP-sc-gway/_loraModem.ino @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // // based on work done by Thomas Telkamp for Raspberry PI 1ch gateway // and many others. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains the LoRa modem specific code enabling to receive @@ -371,6 +373,15 @@ void hop() { // UP function // This is the "lowlevel" receive function called by stateMachine() // dealing with the radio specific LoRa functions +// +// Parameters: +// Payload: uint8_t[] message. when message is read it is returned in payload. +// Returns: +// Length of payload received +// +// 9 bytes header +// followed by data N bytes +// 4 bytes MIC end // ---------------------------------------------------------------------------- uint8_t receivePkt(uint8_t *payload) { @@ -390,15 +401,11 @@ uint8_t receivePkt(uint8_t *payload) { #if DUSB>=1 if (( debug>=0) && ( pdebug & P_RADIO )) { - Serial.print(F("RxPkt:: Err CRC, =")); + Serial.print(F("rxPkt:: Err CRC, =")); SerialTime(); Serial.println(); } #endif - // Reset CRC flag 0x20 - //writeRegister(REG_IRQ_FLAGS, (uint8_t)(IRQ_LORA_CRCERR_MASK | IRQ_LORA_RXDONE_MASK)); // 0x12; clear CRC (== 0x20) flag - //writeRegister(REG_IRQ_FLAGS_MASK, (uint8_t) 0x00); - //writeRegister(REG_IRQ_FLAGS, (uint8_t) 0xFF); // XXX 180324 done in state machine return 0; } @@ -409,7 +416,7 @@ uint8_t receivePkt(uint8_t *payload) { #if DUSB>=1 if (( debug>=0) && ( pdebug & P_RADIO )) { - Serial.println(F("RxPkt:: Err HEADER")); + Serial.println(F("rxPkt:: Err HEADER")); } #endif // Reset VALID-HEADER flag 0x10 @@ -423,7 +430,7 @@ uint8_t receivePkt(uint8_t *payload) cp_nb_rx_ok++; // Receive OK statistics counter if (readRegister(REG_FIFO_RX_CURRENT_ADDR) != readRegister(REG_FIFO_RX_BASE_AD)) { - if (debug>=1) { + if (( debug>=0 ) && ( pdebug & P_RADIO )) { Serial.print(F("RX BASE <")); Serial.print(readRegister(REG_FIFO_RX_BASE_AD)); Serial.print(F("> != RX CURRENT <")); @@ -460,6 +467,9 @@ uint8_t receivePkt(uint8_t *payload) } writeRegister(REG_IRQ_FLAGS, (uint8_t) 0xFF); // Reset ALL interrupts + + // A long as DUSB is enabled, and RX debug messages are selected, + //the received packet is displayed on the output. #if DUSB>=1 if (( debug>=0 ) && ( pdebug & P_RX )){ @@ -482,23 +492,89 @@ uint8_t receivePkt(uint8_t *payload) Serial.print(F(", len=")); Serial.print(receivedCount); + // If debug level 1 is specified, we display the content of the message as well + // We need to decode the message as well will it make any sense + + if (debug>=1) { // Must be 1 for operational use +#if _TRUSTED_DECODE==2 + int index; // The index of the codex struct to decode + String response=""; + + uint8_t data[receivedCount]; + + uint8_t DevAddr [4]; + DevAddr[0] = payload[4]; + DevAddr[1] = payload[3]; + DevAddr[2] = payload[2]; + DevAddr[3] = payload[1]; + + if ((index = inDecodes((char *)(payload+1))) >=0 ) { + Serial.print(F(", Ind=")); + Serial.print(index); + //Serial.println(); + } + else if (debug>=1) { + Serial.print(F(", No Index")); + Serial.println(); + return(receivedCount); + } + + // ------------------------------ + + Serial.print(F(", data=")); + for (int i=0; i=1 + if (debug>=0) + Serial.print(F("LoRaSensors:: ")); +#endif + #if _BATTERY==1 #if DUSB>=1 if (debug>=0) - Serial.println(F("LoRaSensors:: Battery")); + Serial.print(F("Battery ")); #endif - buf[tchars] = 0x80; // 128; lCode code - buf[tchars+1] = 0x3F; // 63; lCode code /30 - tchars+=2; +#if defined(ARDUINO_ARCH_ESP8266) || defined(ESP32) + // For ESP there is no standard battery library + // What we do is to measure GPIO35 pin which has a 100K voltage divider + pinMode(35, INPUT); +#if defined(ESP32) + int devider=4095; +#else + int devider=1023; +#endif //ESP32 + float volts=3.3 * analogRead(35) / 4095 * 2; // T_Beam connects to GPIO35 +#else + // For ESP8266 no sensor defined + float volts=0; +#endif + tchars += lcode.eBattery(volts, buf + tchars); #endif #if _GPS==1 #if DUSB>=1 if (debug>=0) - Serial.println(F("LoRaSensors:: GPS")); + Serial.print(F("GPS ")); - if (debug>=1) { - Serial.print("Latitude : "); + if (( debug>=1 ) && ( pdebug & P_MAIN )) { + Serial.print("\tLatitude : "); Serial.println(gps.location.lat(), 5); - Serial.print("Longitude : "); + Serial.print("\tLongitude : "); Serial.println(gps.location.lng(), 4); - Serial.print("Satellites: "); + Serial.print("\tSatellites: "); Serial.println(gps.satellites.value()); - Serial.print("Altitude : "); + Serial.print("\tAltitude : "); Serial.print(gps.altitude.feet() / 3.2808); Serial.println("M"); - Serial.print("Time : "); + Serial.print("\tTime : "); Serial.print(gps.time.hour()); Serial.print(":"); Serial.print(gps.time.minute()); @@ -113,15 +140,19 @@ static int LoRaSensors(uint8_t *buf) { } // Assuming we have a value, put it in the buf - // The layout of thi message is specific to the user, + // The layout of this message is specific to the user, // so adapt as needed. tchars += lcode.eGpsL(gps.location.lat(), gps.location.lng(), gps.altitude.value(), gps.satellites.value(), buf + tchars); #endif - // If all sensor data is encoded, we encode the buffer - +#if DUSB>=1 + if (debug>=0) + Serial.println(); +#endif + + // If all sensor data is encoded, we encode the buffer lcode.eMsg(buf, tchars); // Fill byte 0 with bytecount and Parity return(tchars); // return the number of bytes added to payload @@ -215,9 +246,19 @@ static void generate_subkey(uint8_t *key, uint8_t *k1, uint8_t *k2) { // // cmac = aes128_encrypt(K, Block_A[i]) // ---------------------------------------------------------------------------- -uint8_t encodePacket(uint8_t *Data, uint8_t DataLength, uint16_t FrameCount, uint8_t Direction) { +uint8_t encodePacket(uint8_t *Data, uint8_t DataLength, uint16_t FrameCount, uint8_t *DevAddr, uint8_t *AppSKey, uint8_t Direction) { - unsigned char AppSKey[16] = _APPSKEY ; // see ESP-sc-gway.h +#if DUSB>=1 + if (debug>=2) { + Serial.print(F("encodePacket:: DevAddr=")); + for (int i=0; i<4; i++ ) { Serial.print(DevAddr[i],HEX); Serial.print(' '); } + Serial.print(F("encodePacket:: AppSKey=")); + for (int i=0; i<16; i++ ) { Serial.print(AppSKey[i],HEX); Serial.print(' '); } + Serial.println(); + } +#endif + + //unsigned char AppSKey[16] = _APPSKEY ; // see ESP-sc-gway.h uint8_t i, j; uint8_t Block_A[16]; uint8_t bLen=16; // Block length is 16 except for last block in message @@ -288,10 +329,10 @@ uint8_t encodePacket(uint8_t *Data, uint8_t DataLength, uint16_t FrameCount, uin // MIC is cmac [0:3] of ( aes128_cmac(NwkSKey, B0 | Data ) // // ---------------------------------------------------------------------------- -uint8_t micPacket(uint8_t *data, uint8_t len, uint16_t FrameCount, uint8_t dir) { +uint8_t micPacket(uint8_t *data, uint8_t len, uint16_t FrameCount, uint8_t * NwkSKey, uint8_t dir) { - unsigned char NwkSKey[16] = _NWKSKEY ; + //uint8_t NwkSKey[16] = _NWKSKEY; uint8_t Block_B[16]; uint8_t X[16]; uint8_t Y[16]; @@ -365,7 +406,7 @@ uint8_t micPacket(uint8_t *data, uint8_t len, uint16_t FrameCount, uint8_t dir) // ------------------------------------ // Step 4: If there is a rest Block, padd it - // Last block. We move step4 to the end as we need Y + // Last block. We move step 4 to the end as we need Y // to compute the last block // if (restBits) { @@ -410,6 +451,7 @@ uint8_t micPacket(uint8_t *data, uint8_t len, uint16_t FrameCount, uint8_t dir) // ---------------------------------------------------------------------------- static void checkMic(uint8_t *buf, uint8_t len, uint8_t *key) { uint8_t cBuf[len+1]; + uint8_t NwkSKey[16] = _NWKSKEY; if (debug>=2) { Serial.print(F("old=")); @@ -423,7 +465,7 @@ static void checkMic(uint8_t *buf, uint8_t len, uint8_t *key) { len -=4; uint16_t FrameCount = ( cBuf[7] * 256 ) + cBuf[6]; - len += micPacket(cBuf, len, FrameCount, 0); + len += micPacket(cBuf, len, FrameCount, NwkSKey, 0); if (debug>=2) { Serial.print(F("new=")); @@ -433,8 +475,9 @@ static void checkMic(uint8_t *buf, uint8_t len, uint8_t *key) { } Serial.println(); } + // Mic is only checked, but len is not corrected } -#endif +#endif //_CHECK_MIC // ---------------------------------------------------------------------------- // SENSORPACKET @@ -469,6 +512,9 @@ int sensorPacket() { uint8_t mlength = 0; uint32_t tmst = micros(); struct LoraUp LUP; + uint8_t NwkSKey[16] = _NWKSKEY; + uint8_t AppSKey[16] = _APPSKEY; + uint8_t DevAddr[4] = _DEVADDR; // Init the other LoraUp fields LUP.sf = 8; // Send with SF8 @@ -508,11 +554,34 @@ int sensorPacket() { // See LoRa spec para 4.3.2 // You can add any byte string below based on you personal choice of sensors etc. // + // Payload bytes in this example are encoded in the LoRaCode(c) format uint8_t PayLength = LoRaSensors((uint8_t *)(LUP.payLoad + LUP.payLength)); + +#if DUSB>=1 + if ((debug>=2) && (pdebug & P_RADIO )) { + Serial.print(F("old: ")); + for (int i=0; i=1 + if ((debug>=2) && (pdebug & P_RADIO )) { + Serial.print(F("new: ")); + for (int i=0; i=1 + if ((debug>=2) && (pdebug & P_RADIO )) { + Serial.print(F("mic: ")); + for (int i=0; i0) Serial.println(F("sensorPacket:: ERROR buffer size too large")); return(-1); } - + +#ifdef _TTNSERVER if (!sendUdp(ttnServer, _TTNPORT, buff_up, buff_index)) { return(-1); } +#endif #ifdef _THINGSERVER if (!sendUdp(thingServer, _THINGPORT, buff_up, buff_index)) { return(-1); } #endif +#if DUSB>=1 + // If all is right, we should after decoding (which is the same as encoding) get + // the original message back again. + if ((debug>=2) && (pdebug & P_RADIO )) { + CodeLength = encodePacket((uint8_t *)(LUP.payLoad + 9), PayLength, (uint16_t)frameCount-1, DevAddr, AppSKey, 0); + Serial.print(F("rev: ")); + for (int i=0; i=1 +#if _TRUSTED_NODES>=1 uint32_t id = ((a[0]<<24) | (a[1]<<16) | (a[2]<<8) | a[3]); int i; @@ -191,4 +193,23 @@ int SerialName(char * a, String& response) return(-1); // If no success OR is TRUSTED NODES not defined } +// ---------------------------------------------------------------------------- +// inDecodes(id) +// Find the id in Decodes array, and return the index of the item +// Parameters: +// id: The first field in the array (normally DevAddr id). Must be char[4] +// Returns: +// The index of the ID in the Array. Returns -1 if not found +// ---------------------------------------------------------------------------- +int inDecodes(char * id) { + uint32_t ident = ((id[3]<<24) | (id[2]<<16) | (id[1]<<8) | id[0]); + + int i; + for ( i=0; i< (sizeof(decodes)/sizeof(codex)); i++) { + if (ident == decodes[i].id) { + return(i); + } + } + return(-1); +} diff --git a/ESP-sc-gway/_wwwServer.ino b/ESP-sc-gway/_wwwServer.ino index 298517c..8370186 100644 --- a/ESP-sc-gway/_wwwServer.ino +++ b/ESP-sc-gway/_wwwServer.ino @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // // based on work done by many people and making use of several libraries. // @@ -10,6 +10,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains the webserver code for the ESP Single Channel Gateway. @@ -77,10 +79,14 @@ boolean YesNo(String s) // ---------------------------------------------------------------------------- -// WWWFILES +// WWWFILE // This function will open a pop-up in the browser and then // display the contents of a file in that window // Output is sent to server.sendContent() +// Parameters: +// fn; String with filename +// Returns: +// // ---------------------------------------------------------------------------- void wwwFile(String fn) { @@ -91,7 +97,7 @@ void wwwFile(String fn) { #endif return; } -#if DUSB>=1 +#if DUSB>=2 else { Serial.print(F("wwwButtons:: File existist= ")); Serial.println(fn); @@ -119,16 +125,17 @@ void wwwFile(String fn) { // ---------------------------------------------------------------------------- // Button function Stat, display statistics +// This is a button on the top of the GUI screen. // ---------------------------------------------------------------------------- void buttonStat() { - Serial.print(F("Log")); - Serial.println(); + //Serial.print(F("Log")); + //Serial.println(); - printLog(); + //printLog(); String response = ""; - response+= "alert('Log');"; + response+= ""; server.sendContent(response); } @@ -136,6 +143,7 @@ void buttonStat() // ---------------------------------------------------------------------------- // Button gunction Log displays logfiles. +// This is a button on the top of the GUI screen // ---------------------------------------------------------------------------- void buttonLog() { @@ -177,6 +185,11 @@ static void wwwButtons() // results are sent back to the web client. // Commands: DEBUG, ADDRESS, IP, CONFIG, GETTIME, SETTIME // The webpage is completely built response and then printed on screen. +// Parameters: +// cmd: Contains a character array with the command to execute +// arg: Contains the parameter value of that command +// Returns: +// // ---------------------------------------------------------------------------- static void setVariables(const char *cmd, const char *arg) { @@ -329,7 +342,7 @@ static void openWebPage() response += ""; response +="

ESP Gateway Config

"; @@ -774,6 +787,16 @@ static void statisticsData() // ---------------------------------------------------------------------------- // SENSORDATA // If enabled, display the sensorHistory on the current webserver Page. +// In this GUI section a number of statr[x] records are displayed such as: +// +// Time, The time the sensor message was received +// Node, the DevAddr or even Node name for Trusted nodes, +// Data (Localserver), when _LOCALSERVER is enabled contains decoded data +// C, Channel frequency on which the sensor was received +// Freq, The frequency of the channel +// SF, Spreading Factor +// pRSSI, Packet RSSI +// // Parameters: // - // Returns: @@ -789,6 +812,9 @@ static void sensorData() response += ""; response += "Time"; response += "Node"; +#if _LOCALSERVER==1 + response += "Data"; +#endif response += "C"; response += "Freq"; response += "SF"; @@ -806,16 +832,26 @@ static void sensorData() response = ""; - response += String() + ""; + response += String() + ""; // Tmst stringTime((statr[i].tmst), response); // XXX Change tmst not to be millis() dependent response += ""; - response += String() + ""; - - if (SerialName((char *)(& (statr[i].node)), response) < 0) { // works with TRUSTED_NODES >= 1 - printHEX((char *)(& (statr[i].node)),' ',response); // else + + response += String() + ""; // Node + if (SerialName((char *)(& (statr[i].node)), response) < 0) { // works with TRUSTED_NODES >= 1 + printHEX((char *)(& (statr[i].node)),' ',response); // else } - response += ""; + +#if _LOCALSERVER==1 + response += String() + ""; // Data + for (int j=0; j" + statr[i].ch + ""; response += String() + "" + freqs[statr[i].ch] + ""; response += String() + "" + statr[i].sf + ""; @@ -1000,6 +1036,7 @@ void setupWWW() server.on("/FORMAT", []() { Serial.print(F("FORMAT ...")); SPIFFS.format(); // Normally disabled. Enable only when SPIFFS corrupt + initConfig(&gwayConfig); Serial.println(F("DONE")); }); @@ -1260,9 +1297,10 @@ void setupWWW() #endif // Display Statistics server.on("/STAT", []() { - server.sendHeader("Location", String("/"), true); buttonStat(); - server.send ( 302, "text/plain", ""); + //server.sendHeader("Location", String("/"), true); + + //server.send ( 302, "text/plain", ""); }); server.on("/LOG", []() { server.sendHeader("Location", String("/"), true); diff --git a/ESP-sc-gway/loraFiles.h b/ESP-sc-gway/loraFiles.h index b5949cc..66f36bd 100644 --- a/ESP-sc-gway/loraFiles.h +++ b/ESP-sc-gway/loraFiles.h @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // // based on work done by Thomas Telkamp for Raspberry PI 1ch gateway // and many others. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains a number of compile-time settings that can be set on (=1) or off (=0) diff --git a/ESP-sc-gway/loraModem.h b/ESP-sc-gway/loraModem.h index 2e18f18..30c3566 100644 --- a/ESP-sc-gway/loraModem.h +++ b/ESP-sc-gway/loraModem.h @@ -1,7 +1,7 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // // based on work done by Thomas Telkamp for Raspberry PI 1ch gateway // and many other contributors. @@ -11,6 +11,8 @@ // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains a number of compile-time settings and declarations that are @@ -254,7 +256,11 @@ struct stat_t { #if RSSI==1 int8_t rssi; // XXX Can be < -128 #endif - int8_t prssi; // XXX Can be < -128 + int8_t prssi; // XXX Can be < -128 +#if _LOCALSERVER==1 + uint8_t data[23]; // For memory purposes, only 23 chars + uint8_t datal; // Length of decoded message 1 char +#endif } stat_t; @@ -294,6 +300,9 @@ struct stat_c statc; // History of received uplink messages from nodes struct stat_t statr[MAX_STAT]; + + + #else // STATISTICS==0 struct stat_t statr[1]; // Always have at least one element to store in #endif diff --git a/ESP-sc-gway/oLED.h b/ESP-sc-gway/oLED.h index 9bb5b5d..91be79d 100644 --- a/ESP-sc-gway/oLED.h +++ b/ESP-sc-gway/oLED.h @@ -1,16 +1,18 @@ // 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 -// Version 5.3.1 -// Date: 2018-06-30 +// Version 5.3.2 +// Date: 2018-07-07 // -// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway -// and many others. +// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway +// and many others. // // All rights reserved. This program and the accompanying materials // are made available under the terms of the MIT License // which accompanies this distribution, and is available at // https://opensource.org/licenses/mit-license.php // +// NO WARRANTY OF ANY KIND IS PROVIDED +// // Author: Maarten Westenberg (mw12554@hotmail.com) // // This file contains a number of compile-time settings and definitions for OLED support. diff --git a/ESP-sc-gway/sensor.h b/ESP-sc-gway/sensor.h new file mode 100644 index 0000000..bc00942 --- /dev/null +++ b/ESP-sc-gway/sensor.h @@ -0,0 +1,80 @@ +// sensor.h; 1-channel LoRa Gateway for ESP8266 +// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 +// Version 5.3.2 +// Date: 2018-07-07 +// +// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway +// and many other contributors. +// +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the MIT License +// which accompanies this distribution, and is available at +// https://opensource.org/licenses/mit-license.php +// +// NO WARRANTY OF ANY KIND IS PROVIDED +// +// Author: Maarten Westenberg (mw12554@hotmail.com) +// +// This file contains a number of compile-time settings and declarations that are +// specific to the LoRa rfm95, sx1276, sx1272 radio of the gateway. +// +// +// ------------------------------------------------------------------------------------ + +#if _TRUSTED_NODES >= 1 +struct nodex { + uint32_t id; // This i sthe decide ID (coded in 4 bytes uint32_t + char nm[32]; +}; + +// Add all your named and trusted nodes to this list +nodex nodes[] = { + { 0x260116BD , "lora-34 PIR node" }, // F=0 + { 0x26011152 , "lora-35 temp+humi node" }, // F=0 + { 0x2601148C , "lora-36 test node" }, // F=0 + { 0x26011B90 , "lora-39 temp DS18B20" }, // F=1 + { 0x260119A6 , "lora-40 airquality" }, // F=0 + { 0x2601117D , "lora-41 temp+humi SR04T" }, + { 0x26011514 , "lora-43 ch1, no sensors" }, // F=1 + { 0x26011D77 , "lora-45 not sensor" }, + { 0x2601160F , "lora-46 HTU21 metal case" }, // F=0 + { 0x26011E71 , "lora-47 Dallas temperature" }, // F=0 + { 0x26011E52 , "lora-53 gas sensor" }, // F=ALL + { 0x02020441 , "lora-65 Waterproof temp humi" }, // F=0 + { 0x26011b96 , "lora-50 Internal T-Beam gway" }, // F=0 + { 0x26011999 , "lora-901 distance sensor" } // F=0 +}; + + +#endif //_TRUSTED_NODES + +#if _LOCALSERVER==1 + +struct codex { + uint32_t id; // This is the device ID (coded in 4 bytes uint32_t + char nm[32]; // A name string which is free to choose + uint8_t nwkKey[16]; // The Network Session Key + uint8_t appKey[16]; // The Application Session Key +}; + +// Sometimes we want to decode the sensor completely as we do in the TTN server +// This means that for all nodes we want to view the dara of, we need to provide +// he AppsSKey and the NwkSKey + +// Definition of all nodes that we want to decode locally on the gateway. +// +codex decodes[] = { + { 0x2601148C , "lora-36", // F=0 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x02, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { 0x26011b96 , "lora-50", // F=0 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x02, 0x04, 0x32, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 } + }, + { 0x26011999 , "lora-901", // F=0 + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x02, 0x02, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + } +}; +#endif //_LOCALSERVER diff --git a/README.md b/README.md index d289c3f..3ca7414 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Single Channel LoRaWAN Gateway -Version 5.3.1, June 30, 2018 +Version 5.3.2, July 07, 2018 Author: M. Westenberg (mw12554@hotmail.com) Copyright: M. Westenberg (mw12554@hotmail.com) @@ -49,18 +49,11 @@ under the Gateway chapter. ## testing -This Gateway code has been tested on the following boards: - -- Wemos D1 Mini + Hallard board with RFM95 -- Wemos D1 Mini + Comresult board with RFM95 -- TTGO T-Beam board, ESP32, SX1276, Battery and GPS -- TTGO ESP32 V1 board, SX1276 on EU868 -- TTGO ESP32 V1 board, SX1278, OLED on 433MHz - +The single channel gateway has been tested on a gateway with the Wemos D1 Mini, using a HopeRF RFM95W transceiver. The LoRa nodes tested againts this gateway are: - TeensyLC with HopeRF RFM95 radio -- Arduino Pro-Mini (default Atmega328 model, 8MHz 3.3V and 16MHz 3.3V) +- Arduino Pro-Mini (default Armega328 model, 8MHz 3.3V and 16MHz 3.3V) - ESP8266 based nodes with RFM95 transceivers. The code has been tested on at least 8 separate gateway boards both based on the Hallard and the Comresult boards. @@ -400,9 +393,9 @@ The following things are still on my wish list to make to the single channel gat - Receive downstream message with commands from the server. These can be used to configure the gateway through downlink messages (such as setting the SF) -- Support for ESP32 and RFM95 on 915 MHz +- Support for ESP32 and RFM95 on 433 MHz - Use the SPIFFS for storing .css files -- Use the SPIFFS for storing node data (for later analysis) +- Look at CLass B and C support