Version 5.3.3; Several ahnhancement, confirm in GUI, button for documentation, added expart/basic button for GUI etc.

pull/49/merge
platenspeler 2018-08-26 11:03:07 +02:00
rodzic 4726a40e4a
commit 88113e8455
20 zmienionych plików z 698 dodań i 534 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
# Single Channel LoRaWAN Gateway
Version 5.3.2, July 07, 2018
Version 5.3.3, August 25, 2018
Author: M. Westenberg (mw12554@hotmail.com)
Copyright: M. Westenberg (mw12554@hotmail.com)
@ -16,6 +16,15 @@ Maintained by Maarten Westenberg (mw12554@hotmail.com)
# Release Notes
New features in version 5.3.3 (August 25, 2018)
- Bug Fixing SPIFFS Format in GUI
- Included a confirm dialog in RESET, BOOT and STATISTICS buttons for user to confirm
- Repaired WlanConnect issues
- Improved Downlink function. Work for SF8-SF10. Does not work reliable for SF7, SF11, SF12
- Provided documentation button o top of page
- Added expert mode button in GUI (Wifi, System and Interrupt data is only shown in expert mode)
- bug fixes and documentation
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
@ -169,7 +178,7 @@ New features in version 3.3.0 (January 1, 2017)):
New features in version 3.2.2 (December 29, 2016)):
- Repair the situation where WIFIMANAGER was set to 0 in the ESP-sc-gway.h file. The sketch would not compile which is now repaired
- The compiler would issue a set of warnings related to the ssid and passw setting in the ESP-sc-geway.h file. Compiler was complaining (and it should) because char* were statically initialised and modified in the code.
- The compiler would issue a set of warnings related to the ssid and passw setting in the ESP-sc-gway.h file. Compiler was complaining (and it should) because char* were statically initialised and modified in the code.
New features in version 3.2.1 (December 20, 2016)):

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2 H
// Date: 2018-07-07
// Version 5.3.3 H
// Date: 2018-08-25
//
// 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.
@ -21,7 +21,7 @@
//
// ----------------------------------------------------------------------------------------
#define VERSION "V.5.3.2.H; 1800707a"
#define VERSION "V.5.3.3.H; 180825a"
// This value of DEBUG determines whether some parts of code get compiled.
// Also this is the initial value of debug parameter.
@ -216,7 +216,7 @@
#if GATEWAYNODE==1
#define _DEVADDR { 0x26, 0x01, 0x01, 0x01 }
#define _APPSKEY { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define _APPSKEY { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define _NWKSKEY { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define _SENSOR_INTERVAL 300
// For ESP32 based TTGO boards these two are normally included

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
// Author: Maarten Westenberg (mw12554@hotmail.com)
//
// Based on work done by Thomas Telkamp for Raspberry PI 1-ch gateway and many others.
@ -72,7 +72,7 @@ extern "C" {
#endif
// ----------- Specific ESP32 stuff --------------
#if ESP32_ARCH==1 // IF ESP32
#include "WiFi.h"
@ -88,6 +88,7 @@ extern "C" {
#include <ArduinoOTA.h>
#endif//OTA
// ----------- Generic ESP8266 stuff --------------
#else
#include <ESP8266WiFi.h> // Which is specific for ESP8266
@ -106,7 +107,8 @@ extern "C" {
#endif//OTA
#endif//ESP_ARCH
// ----------- Declaration of vars --------------
uint8_t debug=1; // Debug level! 0 is no msgs, 1 normal, 2 extensive
uint8_t pdebug=0xFF; // Allow all atterns (departments)
@ -130,7 +132,6 @@ using namespace std;
byte currentMode = 0x81;
//char b64[256];
bool sx1272 = true; // Actually we use sx1276/RFM95
uint32_t cp_nb_rx_rcv; // Number of messages received by gateway
@ -393,7 +394,7 @@ time_t getNtpTime()
if (!sendNtpRequest(ntpServer)) // Send the request for new time
{
if (( debug>=0 ) && ( pdebug & P_MAIN ))
Serial.println(F("sendNtpRequest failed"));
Serial.println(F("M sendNtpRequest failed"));
return(0);
}
@ -434,7 +435,7 @@ time_t getNtpTime()
gwayConfig.ntpErrTime = now();
#if DUSB>=1
if (( debug>=0 ) && ( pdebug & P_MAIN )) {
Serial.println(F("getNtpTime:: read failed"));
Serial.println(F("M getNtpTime:: read failed"));
}
#endif
return(0); // return 0 if unable to get the time
@ -503,7 +504,7 @@ int readUdp(int packetSize)
// In practice however this can be any sender!
if (Udp.read(buff_down, packetSize) < packetSize) {
#if DUSB>=1
Serial.println(F("readUsb:: Reading less chars"));
Serial.println(F("A readUsb:: Reading less chars"));
return(-1);
#endif
}
@ -517,8 +518,8 @@ int readUdp(int packetSize)
if (remotePortNo == 123) {
// This is an NTP message arriving
#if DUSB>=1
if (debug>0) {
Serial.println(F("readUdp:: NTP msg rcvd"));
if ( debug>=0 ) {
Serial.println(F("A readUdp:: NTP msg rcvd"));
}
#endif
gwayConfig.ntpErr++;
@ -533,6 +534,13 @@ int readUdp(int packetSize)
token = buff_down[2]*256 + buff_down[1];
ident = buff_down[3];
#if DUSB>=1
if ((debug>1) && (pdebug & P_MAIN)) {
Serial.print(F("M readUdp:: message waiting="));
Serial.print(ident);
Serial.println();
}
#endif
// now parse the message type from the server (if any)
switch (ident) {
@ -560,8 +568,8 @@ int readUdp(int packetSize)
// (sensor) message sent with the code above.
case PKT_PUSH_ACK: // 0x01 DOWN
#if DUSB>=1
if (debug >= 2) {
Serial.print(F("PKT_PUSH_ACK:: size "));
if (( debug>=2) && (pdebug & P_MAIN )) {
Serial.print(F("M PKT_PUSH_ACK:: size "));
Serial.print(packetSize);
Serial.print(F(" From "));
Serial.print(remoteIpNo);
@ -585,20 +593,25 @@ int readUdp(int packetSize)
// XXX This message format may also be used for other downstream communucation
case PKT_PULL_RESP: // 0x03 DOWN
#if DUSB>=1
if (debug>=0) {
Serial.println(F("PKT_PULL_RESP:: received"));
if (( debug>=0 ) && ( pdebug & P_MAIN )) {
Serial.println(F("M readUdp:: PKT_PULL_RESP received"));
}
#endif
// lastTmst = micros(); // Store the tmst this package was received
// Send to the LoRa Node first (timing) and then do messaging
// Send to the LoRa Node first (timing) and then do reporting to Serial
_state=S_TX;
sendTime = micros(); // record when we started sending the message
if (sendPacket(data, packetSize-4) < 0) {
#if DUSB>=1
if ( debug>=0 ) {
Serial.println(F("A readUdp:: Error: PKT_PULL_RESP sendPacket failed"));
}
#endif
return(-1);
}
// Now respond with an PKT_TX_ACK; 0x04 UP
buff[0]=buff_down[0];
buff[1]=buff_down[1];
@ -616,7 +629,7 @@ int readUdp(int packetSize)
buff[12]=0;
#if DUSB>=1
if (( debug >= 2 ) && ( pdebug & P_MAIN )) {
Serial.println(F("readUdp:: TX buff filled"));
Serial.println(F("M readUdp:: TX buff filled"));
}
#endif
// Only send the PKT_PULL_ACK to the UDP socket that just sent the data!!!
@ -624,13 +637,13 @@ int readUdp(int packetSize)
if (Udp.write((unsigned char *)buff, 12) != 12) {
#if DUSB>=1
if (debug>=0)
Serial.println("PKT_PULL_ACK:: Error UDP write");
Serial.println("A readUdp:: Error: PKT_PULL_ACK UDP write");
#endif
}
else {
#if DUSB>=1
if (debug>=0) {
Serial.print(F("PKT_TX_ACK:: tmst="));
if (( debug>=0 ) && ( pdebug & P_TX )) {
Serial.print(F("M PKT_TX_ACK:: micros="));
Serial.println(micros());
}
#endif
@ -638,15 +651,16 @@ int readUdp(int packetSize)
if (!Udp.endPacket()) {
#if DUSB>=1
if (debug>=0)
Serial.println(F("PKT_PULL_DATALL Error Udp.endpaket"));
if (( debug>=0 ) && ( pdebug & P_MAIN )) {
Serial.println(F("M PKT_PULL_DATALL Error Udp.endpaket"));
}
#endif
}
yield();
#if DUSB>=1
if (debug >=1) {
Serial.print(F("PKT_PULL_RESP:: size "));
if (( debug >=1 ) && (pdebug & P_MAIN )) {
Serial.print(F("M PKT_PULL_RESP:: size "));
Serial.print(packetSize);
Serial.print(F(" From "));
Serial.print(remoteIpNo);
@ -663,8 +677,8 @@ int readUdp(int packetSize)
case PKT_PULL_ACK: // 0x04 DOWN; the server sends a PULL_ACK to confirm PULL_DATA receipt
#if DUSB>=1
if (debug >= 2) {
Serial.print(F("PKT_PULL_ACK:: size ")); Serial.print(packetSize);
if (( debug >= 2 ) && (pdebug & P_MAIN )) {
Serial.print(F("M PKT_PULL_ACK:: size ")); Serial.print(packetSize);
Serial.print(F(" From ")); Serial.print(remoteIpNo);
Serial.print(F(", port ")); Serial.print(remotePortNo);
Serial.print(F(", data: "));
@ -720,8 +734,10 @@ int sendUdp(IPAddress server, int port, uint8_t *msg, int length) {
// Check whether we are conected to Wifi and the internet
if (WlanConnect(3) < 0) {
#if DUSB>=1
Serial.print(F("sendUdp: ERROR connecting to WiFi"));
Serial.flush();
if (( debug>=0 ) && ( pdebug & P_MAIN )) {
Serial.print(F("M sendUdp: ERROR connecting to WiFi"));
Serial.flush();
}
#endif
Udp.flush();
yield();
@ -732,12 +748,15 @@ int sendUdp(IPAddress server, int port, uint8_t *msg, int length) {
//send the update
#if DUSB>=1
if (debug>=2) Serial.println(F("WiFi connected"));
if (( debug>=3 ) && ( pdebug & P_MAIN )) {
Serial.println(F("M WiFi connected"));
}
#endif
if (!Udp.beginPacket(server, (int) port)) {
#if DUSB>=1
if (debug>=1) Serial.println(F("sendUdp:: Error Udp.beginPacket"));
if (( debug>=1 ) && ( pdebug & P_MAIN )) {
Serial.println(F("M sendUdp:: Error Udp.beginPacket"));
}
#endif
return(0);
}
@ -747,7 +766,9 @@ int sendUdp(IPAddress server, int port, uint8_t *msg, int length) {
if (Udp.write((unsigned char *)msg, length) != length) {
#if DUSB>=1
Serial.println(F("sendUdp:: Error write"));
if (( debug<=1 ) && ( pdebug & P_MAIN )) {
Serial.println(F("M sendUdp:: Error write"));
}
#endif
Udp.endPacket(); // Close UDP
return(0); // Return error
@ -857,9 +878,9 @@ void pullData() {
#endif
#if DUSB>=1
if (debug>= 2) {
if (( debug>=2 ) && ( pdebug & P_MAIN )) {
yield();
Serial.print(F("PKT_PULL_DATA request, len=<"));
Serial.print(F("M PKT_PULL_DATA request, len=<"));
Serial.print(pullIndex);
Serial.print(F("> "));
for (i=0; i<pullIndex; i++) {
@ -931,15 +952,18 @@ void sendstat() {
stat_index += j;
status_report[stat_index] = 0; // add string terminator, for safety
if (debug>=2) {
Serial.print(F("stat update: <"));
#if DUSB>=1
if (( debug>=2 ) && ( pdebug & P_MAIN )) {
Serial.print(F("M stat update: <"));
Serial.print(stat_index);
Serial.print(F("> "));
Serial.println((char *)(status_report+12)); // DEBUG: display JSON stat
}
#endif
if (stat_index > STATUS_SIZE) {
Serial.println(F("sendstat:: ERROR buffer too big"));
#if DUSB>=1
Serial.println(F("A sendstat:: ERROR buffer too big"));
#endif
return;
}
@ -1012,7 +1036,7 @@ void setup() {
#if _SPIFF_FORMAT>=1
#if DUSB>=1
if (( debug >= 0 ) && ( pdebug & P_MAIN )) {
Serial.println(F("Format Filesystem ... "));
Serial.println(F("M Format Filesystem ... "));
}
#endif
SPIFFS.format(); // Normally disabled. Enable only when SPIFFS corrupt
@ -1173,7 +1197,7 @@ void setup() {
while (timeStatus() == timeNotSet) {
#if DUSB>=1
if (( debug>=0 ) && ( pdebug & P_MAIN ))
Serial.println(F("setupTime:: Time not set (yet)"));
Serial.println(F("M setupTime:: Time not set (yet)"));
#endif
delay(500);
time_t newTime;
@ -1268,27 +1292,26 @@ void loop ()
// in userspace in loop().
//
stateMachine(); // do the state machine
// After a quiet period, make sure we reinit the modem and state machine.
// The interval is in seconds (about 15 seconds) as this re-init
// is a heavy operation.
// SO it will kick in if there are not many messages for the gatway.
// Note: Be carefull that it does not happen too often in normal operation.
// SO it will kick in if there are not many messages for the gateway.
// Note: Be careful that it does not happen too often in normal operation.
//
if ( ((nowSeconds - statr[0].tmst) > _MSG_INTERVAL ) &&
(msgTime < statr[0].tmst) )
(msgTime <= statr[0].tmst) )
{
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_MAIN )) {
Serial.print("REINIT:: ");
Serial.print("M REINIT:: ");
Serial.print( _MSG_INTERVAL );
Serial.print(F(" "));
SerialStat(0);
}
#endif
// startReveiver() ??
// startReceiver() ??
if ((_cad) || (_hop)) {
_state = S_SCAN;
sf = SF7;
@ -1313,7 +1336,7 @@ void loop ()
#if A_OTA==1
// Perform Over the Air (OTA) update if enabled and requested by user.
// It is important to put this function at the start of loop() as it is
// It is important to put this function early in loop() as it is
// not called frequently but it should always run when called.
//
yield();
@ -1325,7 +1348,9 @@ void loop ()
// reloop here for timing purposes.
// Do as less yield() as possible.
// XXX 180326
if (_event == 1) return;
if (_event == 1) {
return;
}
else yield();
@ -1334,7 +1359,7 @@ void loop ()
if (WlanConnect(1) < 0) {
#if DUSB>=1
if (( debug >= 0 ) && ( pdebug & P_MAIN ))
Serial.println(F("loop: ERROR reconnect WLAN"));
Serial.println(F("M ERROR reconnect WLAN"));
#endif
yield();
return; // Exit loop if no WLAN connected
@ -1351,35 +1376,23 @@ void loop ()
#if DUSB>=2
Serial.println(F("loop:: readUdp calling"));
#endif
// DOWNSTREAM
// Packet may be PKT_PUSH_ACK (0x01), PKT_PULL_ACK (0x03) or PKT_PULL_RESP (0x04)
// This command is found in byte 4 (buffer[3])
if (readUdp(packetSize) <= 0) {
#if DUSB>=1
if (( debug>0 ) && ( pdebug & P_MAIN ))
Serial.println(F("readUDP error"));
Serial.println(F("M readUDP error"));
#endif
break;
}
// Now we know we succesfull received message from host
// Now we know we succesfully received message from host
else {
//_event=1; // Could be done double if more messages received
}
}
}
// After sending a message with S_TX, we have to receive a TXDONE interrupt
// within 7 seconds according to spec, of we have a problem.
if ( sendTime > micros() ) sendTime = 0;
if (( _state == S_TXDONE ) && (( micros() - sendTime) > 7000000 )) {
startReceiver();
#if DUSB>=1
if (( debug >= 1 ) && ( pdebug & P_MAIN )) {
Serial.println(F("Main:: reset TX"));
}
#endif
}
yield(); // XXX 26/12/2017
// stat PUSH_DATA message (*2, par. 4)
@ -1388,14 +1401,14 @@ void loop ()
if ((nowSeconds - statTime) >= _STAT_INTERVAL) { // Wake up every xx seconds
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_MAIN )) {
Serial.print(F("STAT:: ..."));
Serial.print(F("M STAT:: ..."));
Serial.flush();
}
#endif
sendstat(); // Show the status message and send to server
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_MAIN )) {
Serial.println(F("done"));
Serial.println(F(" done"));
if (debug>=2) Serial.flush();
}
#endif
@ -1407,7 +1420,7 @@ void loop ()
//
#if GATEWAYNODE==1
if (gwayConfig.isNode) {
// Give way to internal Admin if necessary
// Give way to internal some Admin if necessary
yield();
// If the 1ch gateway is a sensor itself, send the sensor values
@ -1432,18 +1445,13 @@ void loop ()
if ((nowSeconds - pulltime) >= _PULL_INTERVAL) { // Wake up every xx seconds
#if DUSB>=1
if (( debug>=2) && ( pdebug & P_MAIN )) {
Serial.print(F("PULL <"));
Serial.println(F("M PULL"));
if (debug>=1) Serial.flush();
}
#endif
pullData(); // Send PULL_DATA message to server
startReceiver();
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_MAIN )) {
Serial.println(F(">"));
if (debug>=2) Serial.flush();
}
#endif
pulltime = nowSeconds;
}

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -35,8 +35,8 @@ int WlanStatus() {
switch (WiFi.status()) {
case WL_CONNECTED:
#if DUSB>=1
if (debug>=0) {
Serial.print(F("WlanCStatus:: CONNECTED to")); // 3
if ( debug>=0 ) {
Serial.print(F("A WlanStatus:: CONNECTED to ")); // 3
Serial.println(WiFi.SSID());
}
#endif
@ -48,8 +48,8 @@ int WlanStatus() {
// The ESP is configured to reconnect to the last router in memory.
case WL_DISCONNECTED:
#if DUSB>=1
if (debug>=0) {
Serial.print(F("WlanStatus:: DISCONNECTED, IP=")); // 6
if ( debug>=0 ) {
Serial.print(F("A WlanStatus:: DISCONNECTED, IP=")); // 6
Serial.println(WiFi.localIP());
}
#endif
@ -63,8 +63,9 @@ int WlanStatus() {
// When still pocessing
case WL_IDLE_STATUS:
#if DUSB>=1
if (debug>=0)
Serial.println(F("WlanStatus:: IDLE")); // 0
if ( debug>=0 ) {
Serial.println(F("A WlanStatus:: IDLE")); // 0
}
#endif
break;
@ -72,31 +73,31 @@ int WlanStatus() {
// Whene detected, the program will search for a better AP in range
case WL_NO_SSID_AVAIL:
#if DUSB>=1
if (debug>=0)
if ( debug>=0 )
Serial.println(F("WlanStatus:: NO SSID")); // 1
#endif
break;
case WL_CONNECT_FAILED:
#if DUSB>=1
if (debug>=0)
Serial.println(F("WlanStatus:: FAILED")); // 4
if ( debug>=0 )
Serial.println(F("A WlanStatus:: FAILED")); // 4
#endif
break;
// Never seen this code
case WL_SCAN_COMPLETED:
#if DUSB>=1
if (debug>=0)
Serial.println(F("WlanStatus:: SCAN COMPLETE")); // 2
if ( debug>=0 )
Serial.println(F("A WlanStatus:: SCAN COMPLETE")); // 2
#endif
break;
// Never seen this code
case WL_CONNECTION_LOST:
#if DUSB>=1
if (debug>=0)
Serial.println(F("WlanStatus:: LOST")); // 5
if ( debug>=0 )
Serial.println(F("A WlanStatus:: LOST")); // 5
#endif
break;
@ -104,22 +105,23 @@ int WlanStatus() {
// before accessing WiFi functions
case WL_NO_SHIELD:
#if DUSB>=1
if (debug>=0)
Serial.println(F("WlanStatus:: WL_NO_SHIELD")); //
if ( debug>=0 )
Serial.println(F("A WlanStatus:: WL_NO_SHIELD")); //
#endif
break;
default:
default:
#if DUSB>=1
if (debug>=0) {
Serial.print(F("WlanStatus:: code="));
if ( debug>=0 ) {
Serial.print(F("A WlanStatus Error:: code="));
Serial.println(WiFi.status()); // 255 means ERROR
}
#endif
break;
}
return(-1);
}
} // WlanStatus
// ----------------------------------------------------------------------------
// config.txt is a text file that contains lines(!) with WPA configuration items
@ -173,7 +175,7 @@ int WlanWriteWpa( char* ssid, char *pass) {
#if DUSB>=1
if (( debug >=0 ) && ( pdebug & P_MAIN )) {
Serial.print(F("WlanWriteWpa:: ssid="));
Serial.print(F("M WlanWriteWpa:: ssid="));
Serial.print(ssid);
Serial.print(F(", pass="));
Serial.print(pass);
@ -266,6 +268,8 @@ int WlanConnect(int maxTry) {
Serial.print(i);
Serial.print(':');
Serial.print(j);
Serial.print(':');
Serial.print(sizeof(wpa)/sizeof(wpa[0]));
Serial.print(F(". WiFi connect SSID="));
Serial.print(ssid);
if ( debug>=1 ) {
@ -291,7 +295,7 @@ int WlanConnect(int maxTry) {
// -1 = No SSID or other cause
int stat = WlanStatus();
if ( stat == 1) {
writeGwayCfg(CONFIGFILE); // XXX Write cnfiguration to SPIFFS
writeGwayCfg(CONFIGFILE); // XXX Write configuration to SPIFFS
return(1);
}
@ -307,8 +311,10 @@ int WlanConnect(int maxTry) {
}
#endif
}
if ( WiFi.status() == WL_DISCONNECTED) return(0); // wait
#if DUSB>=1
Serial.println();
#endif
//if ( WiFi.status() == WL_DISCONNECTED) return(0); // XXX 180811 removed
// Make sure that we can connect to different AP's than 1

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// Based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -49,6 +49,7 @@ int initConfig(struct espGwayConfig *c) {
(*c).pdebug = P_GUI;
(*c).cad = _CAD;
(*c).hop = false;
(*c).expert = false;
}
@ -63,10 +64,10 @@ int readConfig(const char *fn, struct espGwayConfig *c) {
#endif
if (!SPIFFS.exists(fn)) {
#if DUSB>=1
if (( debug >= 0 ) && ( pdebug & P_MAIN ))
Serial.print(F("ERROR:: readConfig, file="));
if (( debug>=0 ) && ( pdebug & P_MAIN ))
Serial.print(F("M ERR:: readConfig, file="));
Serial.print(fn);
Serial.print(F(" does not exist .. Formatting"));
Serial.println(F(" does not exist .. Formatting"));
#endif
SPIFFS.format();
initConfig(c);
@ -92,7 +93,7 @@ int readConfig(const char *fn, struct espGwayConfig *c) {
if (tries >= 10) {
f.close();
#if DUSB>=1
if (( debug >= 0 ) && ( pdebug & P_MAIN ))
if (( debug>=0 ) && ( pdebug & P_MAIN ))
Serial.println(F("Formatting"));
#endif
SPIFFS.format();
@ -186,11 +187,15 @@ int readConfig(const char *fn, struct espGwayConfig *c) {
}
else if (id == "FILEREC") { // FILEREC setting
id_print(id, val);
(*c).logFileRec = (uint8_t) val.toInt();
(*c).logFileRec = (uint16_t) val.toInt();
}
else if (id == "FILENUM") { // FILEREC setting
id_print(id, val);
(*c).logFileNum = (uint8_t) val.toInt();
(*c).logFileNum = (uint16_t) val.toInt();
}
else if (id == "EXPERT") { // FILEREC setting
id_print(id, val);
(*c).expert = (uint8_t) val.toInt();
}
else {
tries++;
@ -274,6 +279,7 @@ int writeConfig(const char *fn, struct espGwayConfig *c) {
f.print("FILEREC"); f.print('='); f.print((*c).logFileRec); f.print('\n');
f.print("FILENO"); f.print('='); f.print((*c).logFileNo); f.print('\n');
f.print("FILENUM"); f.print('='); f.print((*c).logFileNum); f.print('\n');
f.print("EXPERT"); f.print('='); f.print((*c).expert); f.print('\n');
f.close();
return(1);
@ -309,8 +315,10 @@ void addLog(const unsigned char * line, int cnt)
if (gwayConfig.logFileNum > LOGFILEMAX){
sprintf(fn,"/log-%d", gwayConfig.logFileNo - LOGFILEMAX);
#if DUSB>=1
Serial.print(F("addLog:: Too many logfile, deleting="));
Serial.println(fn);
if (( debug>=0 ) && ( pdebug & P_GUI )) {
Serial.print(F("G addLog:: Too many logfile, deleting="));
Serial.println(fn);
}
#endif
SPIFFS.remove(fn);
gwayConfig.logFileNum--;
@ -324,7 +332,7 @@ void addLog(const unsigned char * line, int cnt)
if (!SPIFFS.exists(fn)) {
#if DUSB>=1
if (( debug >= 1 ) && ( pdebug & P_GUI )) {
Serial.print(F("ERROR:: addLog:: file="));
Serial.print(F("G ERROR:: addLog:: file="));
Serial.print(fn);
Serial.print(F(" does not exist .. rec="));
Serial.print(gwayConfig.logFileRec);
@ -336,8 +344,8 @@ void addLog(const unsigned char * line, int cnt)
File f = SPIFFS.open(fn, "a");
if (!f) {
#if DUSB>=1
if (debug>=1) {
Serial.println("file open failed=");
if (( debug>=1 ) && ( pdebug & P_GUI )) {
Serial.println("G file open failed=");
Serial.println(fn);
}
#endif
@ -347,7 +355,7 @@ void addLog(const unsigned char * line, int cnt)
int i;
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_GUI )) {
Serial.print(F("addLog:: fileno="));
Serial.print(F("G addLog:: fileno="));
Serial.print(gwayConfig.logFileNo);
Serial.print(F(", rec="));
Serial.print(gwayConfig.logFileRec);

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -392,7 +392,9 @@ uint8_t receivePkt(uint8_t *payload)
uint8_t crcUsed = readRegister(REG_HOP_CHANNEL);
if (crcUsed & 0x40) {
#if DUSB>=1
if (debug>=2) Serial.println(F("rxPkt:: CRC used"));
if (( debug>=2) && (pdebug & P_RX )) {
Serial.println(F("R rxPkt:: CRC used"));
}
#endif
}
@ -618,30 +620,60 @@ bool sendPkt(uint8_t *payLoad, uint8_t payLength)
// As we use delay() only when there is still enough time to wait and we use micros()
// to make sure that delay() did not take too much time this works.
//
// Parameter: uint32-t tmst gives the micros() value when transmission should start.
// Parameter: uint32-t tmst gives the micros() value when transmission should start. (!!!)
// Note: We assume LoraDown.sfTx contains the SF we will use for downstream message.
// ----------------------------------------------------------------------------
void loraWait(uint32_t tmst)
void loraWait(const uint32_t timestamp)
{
uint32_t startMics = micros(); // Start of the loraWait function
tmst += txDelay;
uint32_t tmst = timestamp;
// XXX
int32_t adjust=0;
switch (LoraDown.sfTx) {
case 7: adjust= 60000; break; // Make time for SF7 longer
case 8: break; // Around 60ms
case 9: break;
case 10: break;
case 11: break;
case 12: break;
default:
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_TX )) {
Serial.print(F("T loraWait:: unknown SF="));
Serial.print(LoraDown.sfTx);
}
#endif
}
tmst = tmst + txDelay + adjust; // tmst based on txDelay and spreading factor
uint32_t waitTime = tmst - micros();
if (waitTime<0) {
Serial.println(F("loraWait:: Error wait time < 0"));
return;
}
// For larger delay times we use delay() since that is for > 15ms
// This is the most efficient way
while (waitTime > 16000) {
delay(15); // ms delay including yield, slightly shorter
waitTime= tmst - micros();
}
// The remaining wait time is less tan 15000 uSecs
// And we use delayMicroseconds() to wait
if (waitTime>0) delayMicroseconds(waitTime);
#if DUSB>=2
#if DUSB>=1
else if ((waitTime+20) < 0) {
Serial.println(F("loraWait TOO LATE"));
Serial.println(F("loraWait:: TOO LATE")); // Never happens
}
if (debug >=1) {
Serial.print(F("start: "));
if (( debug>=2 ) && ( pdebug & P_TX )) {
Serial.print(F("T start: "));
Serial.print(startMics);
Serial.print(F(", end: "));
Serial.print(F(", tmst: ")); // tmst
Serial.print(tmst);
Serial.print(F(", end: ")); // This must be micros(), and equal to tmst
Serial.print(micros());
Serial.print(F(", waited: "));
Serial.print(tmst - startMics);
Serial.print(F(", delay="));
@ -1032,8 +1064,9 @@ void startReceiver() {
initLoraModem(); // XXX 180326, after adapting this function
if (_cad) {
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_MAIN )) {
Serial.print(F("PULL:: _state set to S_SCAN"));
if (( debug>=1 ) && ( pdebug & P_SCAN )) {
Serial.println(F("S PULL:: _state set to S_SCAN"));
if (debug>=2) Serial.flush();
}
#endif
_state = S_SCAN;

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -31,10 +31,11 @@ void init_oLED()
{
#if defined OLED_RST
pinMode(OLED_RST,OUTPUT);
digitalWrite(OLED_RST, LOW); // low to reset OLED
digitalWrite(OLED_RST, LOW); // low to reset OLED
delay(50);
digitalWrite(OLED_RST, HIGH); // must be high to turn on OLED
digitalWrite(OLED_RST, HIGH); // must be high to turn on OLED
delay(50);
#else
#endif
// Initialising the UI will init the display too.
display.init();

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
//
// All rights reserved. This program and the accompanying materials
@ -75,7 +75,7 @@ void setupOta(char *hostname) {
#endif
// Only if the Webserver is active also
#if A_SERVER==2 // Displaed for the moment
#if A_SERVER==2 // Displayed for the moment
ESPhttpUpdate.rebootOnUpdate(false);
server.on("/esp", HTTP_POST, [&](){

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg
// Verison 5.3.2
// Date: 2018-07-07
// Verison 5.3.3
// Date: 2018-08-25
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the MIT License

Wyświetl plik

@ -1,7 +1,7 @@
// sensor.ino; 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg
// Verison 5.3.2
// Date: 2018-07-07
// Verison 5.3.3
// Date: 2018-08-25
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the MIT License
@ -105,7 +105,7 @@ static int LoRaSensors(uint8_t *buf) {
#if _GPS==1
#if DUSB>=1
if (debug>=0)
Serial.print(F("GPS "));
Serial.print(F("M GPS "));
if (( debug>=1 ) && ( pdebug & P_MAIN )) {
Serial.print("\tLatitude : ");
@ -611,10 +611,10 @@ int sensorPacket() {
uint8_t encodePacket(uint8_t *Data, uint8_t DataLength, uint16_t FrameCount, uint8_t *DevAddr, uint8_t *AppSKey, uint8_t Direction) {
#if DUSB>=1
if (debug>=2) {
Serial.print(F("encodePacket:: DevAddr="));
if (( debug>=2 ) && ( pdebug & P_GUI )) {
Serial.print(F("G encodePacket:: DevAddr="));
for (int i=0; i<4; i++ ) { Serial.print(DevAddr[i],HEX); Serial.print(' '); }
Serial.print(F("encodePacket:: AppSKey="));
Serial.print(F("G encodePacket:: AppSKey="));
for (int i=0; i<16; i++ ) { Serial.print(AppSKey[i],HEX); Serial.print(' '); }
Serial.println();
}

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -77,14 +77,15 @@ void stateMachine()
uint8_t flags = readRegister(REG_IRQ_FLAGS);
uint8_t mask = readRegister(REG_IRQ_FLAGS_MASK);
uint8_t intr = flags & ( ~ mask ); // Only react on non masked interrupts
uint8_t rssi;
_event=0; // Reset the interrupt detector
#if DUSB>=1
if (intr != flags) {
Serial.print(F("FLAG ::"));
SerialStat(intr);
}
#endif
uint8_t rssi;
_event=0; // Reset the interrupt detector
// If Hopping is selected AND if there is NO event interrupt detected
// and the state machine is called anyway
@ -730,7 +731,7 @@ void stateMachine()
// which is normall an indication of RXDONE
//writeRegister(REG_IRQ_FLAGS, IRQ_LORA_HEADER_MASK);
#if DUSB>=1
if (( debug>=2 ) && ( pdebug & P_RX )) {
if (( debug>=3 ) && ( pdebug & P_RX )) {
Serial.print(F("RX HEADER:: "));
SerialStat(intr);
}
@ -739,13 +740,13 @@ void stateMachine()
}
// If we did not receive a hard interrupt
// The probably do not do anythings, because in the S_RX
// state there e always comes a RXTOUT or RXDONE interrupt
// Then probably do not do anything, because in the S_RX
// state there always comes a RXTOUT or RXDONE interrupt
//
else if (intr == 0x00) {
#if DUSB>=1
if (( debug>=2) && ( pdebug & P_RX )) {
Serial.print(F("S_RX noINTR:: "));
if (( debug>=3) && ( pdebug & P_RX )) {
Serial.print(F("S_RX no INTR:: "));
SerialStat(intr);
}
#endif
@ -813,7 +814,7 @@ void stateMachine()
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_TX )) {
Serial.print(F("TX done:: "));
Serial.print(F("T TX done:: "));
SerialStat(intr);
}
#endif
@ -830,13 +831,18 @@ void stateMachine()
// was successful.
// If we receive an interrupt on dio0 _state==S_TX it is a TxDone interrupt
// Do nothing with the interrupt, it is just an indication.
// sendPacket switch back to scanner mode after transmission finished OK
// send Packet switch back to scanner mode after transmission finished OK
//
case S_TXDONE:
if (intr & IRQ_LORA_TXDONE_MASK) {
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_TX )) {
Serial.println(F("TXDONE:: interrupt"));
if (( debug>=0 ) && ( pdebug & P_TX )) {
Serial.print(F("T TXDONE:: rcvd="));
Serial.print(micros());
Serial.print(F(", diff="));
Serial.println(micros()-LoraDown.tmst);
if (debug>=2) Serial.flush();
}
#endif
// After transmission reset to receiver
@ -855,9 +861,8 @@ void stateMachine()
writeRegister(REG_IRQ_FLAGS_MASK, (uint8_t) 0x00);
writeRegister(REG_IRQ_FLAGS, (uint8_t) 0xFF); // reset interrupt flags
#if DUSB>=1
if (( debug>=0 ) && ( pdebug & P_TX )) {
Serial.println(F("TXDONE:: finished OK"));
if (debug>=2) Serial.flush();
if (( debug>=1 ) && ( pdebug & P_TX )) {
Serial.println(F("T TXDONE:: done OK"));
}
#endif
}
@ -866,7 +871,7 @@ void stateMachine()
else if ( intr != 0 ) {
#if DUSB>=1
if (( debug>=0 ) && ( pdebug & P_TX )) {
Serial.print(F("TXDONE:: unknown int:"));
Serial.print(F("T TXDONE:: unknown int:"));
SerialStat(intr);
}
#endif
@ -875,12 +880,26 @@ void stateMachine()
_event=0;
_state=S_SCAN;
}
// intr == 0
else {
#if DUSB>=1
// Increase timer. If timer exceeds certain value (7 seconds!), reset
if (( debug>=2 ) && ( pdebug & P_TX )) {
Serial.println(F("TXDONE:: No Interrupt"));
// After sending a message with S_TX, we have to receive a TXDONE interrupt
// within 7 seconds according to spec, of here is a problem.
if ( sendTime > micros() ) sendTime = 0; // This could be omitted for usigned ints
if (( _state == S_TXDONE ) && (( micros() - sendTime) > 7000000 )) {
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_TX )) {
Serial.println(F("T TXDONE:: reset TX"));
Serial.flush();
}
#endif
startReceiver();
}
#if DUSB>=1
if (( debug>=3 ) && ( pdebug & P_TX )) {
Serial.println(F("T TXDONE:: No Interrupt"));
}
#endif
}
@ -909,8 +928,8 @@ void stateMachine()
#endif
_state = S_SCAN;
sf = SF7;
cadScanner();
_event=1; // XXX Restart the state machine
cadScanner(); // Restart the state machine
_event=0;
}
else // Single channel AND single SF
{

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -29,6 +29,9 @@
// This function is used for regular downstream messages and for JOIN_ACCEPT
// messages.
// NOTE: This is not an interrupt function, but is started by loop().
// The _status is set an the end of the function to TX and in _stateMachine
// function the actual transmission function is executed.
// The LoraDown.tmst contains the timestamp that the tranmission should finish.
// ----------------------------------------------------------------------------
int sendPacket(uint8_t *buf, uint8_t length)
{
@ -74,12 +77,14 @@ int sendPacket(uint8_t *buf, uint8_t length)
if (!root.success()) {
#if DUSB>=1
Serial.print (F("sendPacket:: ERROR Json Decode"));
if (debug>=2) {
Serial.print(':');
Serial.println(bufPtr);
if (( debug>=1) && (pdebug & P_TX)) {
Serial.print (F("T sendPacket:: ERROR Json Decode"));
if (debug>=2) {
Serial.print(':');
Serial.println(bufPtr);
}
Serial.flush();
}
Serial.flush();
#endif
return(-1);
}
@ -88,109 +93,118 @@ int sendPacket(uint8_t *buf, uint8_t length)
// Meta Data sent by server (example)
// {"txpk":{"codr":"4/5","data":"YCkEAgIABQABGmIwYX/kSn4Y","freq":868.1,"ipol":true,"modu":"LORA","powe":14,"rfch":0,"size":18,"tmst":1890991792,"datr":"SF7BW125"}}
// Used in the protocol:
const char * data = root["txpk"]["data"];
// Used in the protocol of Gateway:
const char * data = root["txpk"]["data"]; // Downstream Payload
uint8_t psize = root["txpk"]["size"];
bool ipol = root["txpk"]["ipol"];
uint8_t powe = root["txpk"]["powe"];
uint32_t tmst = (uint32_t) root["txpk"]["tmst"].as<unsigned long>();
// Not used in the protocol:
const char * datr = root["txpk"]["datr"]; // eg "SF7BW125"
uint8_t powe = root["txpk"]["powe"]; // e.g. 14 or 27
LoraDown.tmst = (uint32_t) root["txpk"]["tmst"].as<unsigned long>();
const float ff = root["txpk"]["freq"]; // eg 869.525
// Not used in the protocol of Gateway TTN:
const char * datr = root["txpk"]["datr"]; // eg "SF7BW125"
const char * modu = root["txpk"]["modu"]; // =="LORA"
const char * codr = root["txpk"]["codr"];
const char * codr = root["txpk"]["codr"]; // e.g. "4/5"
//if (root["txpk"].containsKey("imme") ) {
// const bool imme = root["txpk"]["imme"]; // Immediate Transmit (tmst don't care)
//}
if (data != NULL) {
if ( data != NULL ) {
#if DUSB>=1
if (debug>=2) {
Serial.print(F("data: "));
if (( debug>=2 ) && ( pdebug & P_TX )) {
Serial.print(F("T data: "));
Serial.println((char *) data);
if (debug>=2) Serial.flush();
}
#endif
}
else {
else { // There is data!
#if DUSB>=1
Serial.println(F("sendPacket:: ERROR: data is NULL"));
if (debug>=2) Serial.flush();
if ((debug>0) && ( pdebug & P_TX )) {
Serial.println(F("T sendPacket:: ERROR: data is NULL"));
if (debug>=2) Serial.flush();
}
#endif
return(-1);
}
uint8_t iiq = (ipol? 0x40: 0x27); // if ipol==true 0x40 else 0x27
uint8_t crc = 0x00; // switch CRC off for TX
uint8_t payLength = base64_dec_len((char *) data, strlen(data));
// Fill payload with decoded message
base64_decode((char *) payLoad, (char *) data, strlen(data));
LoraDown.sfTx = atoi(datr+2); // Convert "SF9BW125" or what is received from gateway to number
LoraDown.iiq = (ipol? 0x40: 0x27); // if ipol==true 0x40 else 0x27
LoraDown.crc = 0x00; // switch CRC off for TX
LoraDown.payLength = base64_dec_len((char *) data, strlen(data));// Length of the Payload data
base64_decode((char *) payLoad, (char *) data, strlen(data)); // Fill payload w decoded message
// Compute wait time in microseconds
uint32_t w = (uint32_t) (tmst - micros());
uint32_t w = (uint32_t) (LoraDown.tmst - micros()); // Wait Time compute
// _STRICT_1CH determines ho we will react on downstream messages.
// If STRICT==0, we will receive messags from the TTN gateway presumably on SF12/869.5MHz
// And since the Gateway is a single channel gateway, and its nodes are probably
// single channle too. They will not listen to that frequency.
// When STRICT==1, we will answer (in the RX1 timeslot) on the frequency we receive on.
//
#if _STRICT_1CH == 1
// Use RX1 timeslot as this is our frequency.
// If possible use RX1 timeslot as this is our frequency.
// Do not use RX2 or JOIN2 as they contain other frequencies
if ((w>1000000) && (w<3000000)) { tmst-=1000000; }
else if ((w>6000000) && (w<7000000)) { tmst-=1000000; }
const uint8_t sfTx = sfi; // Take care, TX sf not to be mixed with SCAN
const uint32_t fff = freq;
if ((w>1000000) && (w<3000000)) {
LoraDown.tmst-=1000000;
} // Is tmst correction necessary
else if ((w>6000000) && (w<7000000)) {
LoraDown.tmst-=500000;
}
LoraDown.powe = 14; // On all freqs except 869.5MHz power is limited
//LoraDown.sfTx = sfi; // Take care, TX sf not to be mixed with SCAN
LoraDown.fff = freq; // Use the current frequency
#else
const uint8_t sfTx = atoi(datr+2); // Convert "SF9BW125" to 9
// convert double frequency (MHz) into uint32_t frequency in Hz.
const uint32_t fff = (uint32_t) ((uint32_t)((ff+0.000035)*1000)) * 1000;
#endif
// All data is in Payload and parameters and need to be transmitted.
// The function is called in user-space
_state = S_TX; // _state set to transmit
LoraDown.payLoad = payLoad;
LoraDown.payLength = payLength;
LoraDown.tmst = tmst; // Downstream in milis
LoraDown.sfTx = sfTx;
LoraDown.powe = powe;
LoraDown.fff = fff;
LoraDown.crc = crc;
LoraDown.iiq = iiq;
Serial.println(F("sendPacket:: LoraDown filled"));
// convert double frequency (MHz) into uint32_t frequency in Hz.
LoraDown.fff = (uint32_t) ((uint32_t)((ff+0.000035)*1000)) * 1000;
#endif
LoraDown.payLoad = payLoad;
#if DUSB>=1
if (debug>=2) {
Serial.print(F("Request:: "));
Serial.print(F(" tmst=")); Serial.print(tmst); Serial.print(F(" wait=")); Serial.println(w);
if (( debug>=1 ) && ( pdebug & P_TX)) {
Serial.print(F("T LoraDown tmst="));
Serial.print(LoraDown.tmst);
//Serial.print(F(", w="));
//Serial.print(w);
Serial.print(F(" strict=")); Serial.print(_STRICT_1CH);
Serial.print(F(" datr=")); Serial.println(datr);
Serial.print(F(" freq=")); Serial.print(freq); Serial.print(F(" ->")); Serial.println(fff);
Serial.print(F(" sf =")); Serial.print(sf); Serial.print(F(" ->")); Serial.print(sfTx);
if ( debug>=2 ) {
Serial.print(F(" Request:: "));
Serial.print(F(" tmst=")); Serial.print(LoraDown.tmst); Serial.print(F(" wait=")); Serial.println(w);
Serial.print(F(" modu=")); Serial.print(modu);
Serial.print(F(" powe=")); Serial.print(powe);
Serial.print(F(" codr=")); Serial.println(codr);
Serial.print(F(" strict=")); Serial.print(_STRICT_1CH);
Serial.print(F(" datr=")); Serial.println(datr);
Serial.print(F(" Rfreq=")); Serial.print(freq); Serial.print(F(", Request=")); Serial.print(freq); Serial.print(F(" ->")); Serial.println(LoraDown.fff);
Serial.print(F(" sf =")); Serial.print(atoi(datr+2)); Serial.print(F(" ->")); Serial.println(LoraDown.sfTx);
Serial.print(F(" modu=")); Serial.println(modu);
Serial.print(F(" powe=")); Serial.println(powe);
Serial.print(F(" codr=")); Serial.println(codr);
Serial.print(F(" ipol=")); Serial.println(ipol);
Serial.println(); // empty line between messages
Serial.print(F(" ipol=")); Serial.println(ipol);
}
Serial.println();
}
#endif
if (payLength != psize) {
if (LoraDown.payLength != psize) {
#if DUSB>=1
Serial.print(F("sendPacket:: WARNING payLength: "));
Serial.print(payLength);
Serial.print(LoraDown.payLength);
Serial.print(F(", psize="));
Serial.println(psize);
if (debug>=2) Serial.flush();
#endif
}
#if DUSB>=1
else if (debug >= 2) {
for (i=0; i<payLength; i++) {
else if (( debug >= 2 ) && ( pdebug & P_TX )) {
Serial.print(F("T Payload="));
for (i=0; i<LoraDown.payLength; i++) {
Serial.print(payLoad[i],HEX);
Serial.print(':');
}
@ -201,8 +215,15 @@ int sendPacket(uint8_t *buf, uint8_t length)
cp_up_pkt_fwd++;
#if DUSB>=1
Serial.println(F("sendPacket:: fini OK"));
#endif // DISB
if (( debug>=2 ) && ( pdebug & P_TX )) {
Serial.println(F("T sendPacket:: fini OK"));
}
#endif // DUSB
// All data is in Payload and parameters and need to be transmitted.
// The function is called in user-space
_state = S_TX; // _state set to transmit
return 1;
}//sendPacket
@ -360,7 +381,7 @@ int buildPacket(uint32_t tmst, uint8_t *buff_up, struct LoraUp LoraUp, bool inte
#if DUSB>=1
if (( debug>=2 ) && ( pdebug & P_RADIO )){
Serial.print(F("buildPacket:: pRSSI="));
Serial.print(F("R buildPacket:: pRSSI="));
Serial.print(prssi-rssicorr);
Serial.print(F(" RSSI: "));
Serial.print(_rssi - rssicorr);
@ -420,8 +441,8 @@ int buildPacket(uint32_t tmst, uint8_t *buff_up, struct LoraUp LoraUp, bool inte
// Encode message with messageLength into b64
int encodedLen = base64_enc_len(messageLength); // max 341
#if DUSB>=1
if ((debug>=1) && (encodedLen>255)) {
Serial.print(F("buildPacket:: b64 err, len="));
if ((debug>=1) && (encodedLen>255) && ( pdebug & P_RADIO )) {
Serial.print(F("R buildPacket:: b64 err, len="));
Serial.println(encodedLen);
if (debug>=2) Serial.flush();
return(-1);
@ -461,7 +482,7 @@ int buildPacket(uint32_t tmst, uint8_t *buff_up, struct LoraUp LoraUp, bool inte
++buff_index;
j = snprintf((char *)(buff_up + buff_index), TX_BUFF_SIZE-buff_index, "\"tmst\":%u", tmst);
#if DUSB>=1
if ((j<0) && (debug>=1)) {
if ((j<0) && ( debug>=1 ) && ( pdebug & P_RADIO )) {
Serial.println(F("buildPacket:: Error "));
}
#endif
@ -546,12 +567,10 @@ int buildPacket(uint32_t tmst, uint8_t *buff_up, struct LoraUp LoraUp, bool inte
#endif
#if DUSB>=1
if (debug>=2) {
Serial.print(F("RXPK:: "));
if (( debug>=2 ) && ( pdebug & P_RX )) {
Serial.print(F("R RXPK:: "));
Serial.println((char *)(buff_up + 12)); // debug: display JSON payload
}
if (debug>= 2) {
Serial.print(F("RXPK:: package length="));
Serial.print(F("R RXPK:: package length="));
Serial.println(buff_index);
}
#endif
@ -655,27 +674,28 @@ int receivePacket()
uint16_t frameCount=LoraUp.payLoad[7]*256 + LoraUp.payLoad[6];
#if DUSB>=1
if (( debug>=1 ) && ( pdebug & P_RX )) {
Serial.print(F("R receivePacket:: Ind="));
Serial.print(index);
Serial.print(F(", Len="));
Serial.print(LoraUp.payLength);
Serial.print(F(", A="));
for (int i=0; i<4; i++) {
if (DevAddr[i]<0x0F) Serial.print('0');
Serial.print(DevAddr[i],HEX);
//Serial.print(' ');
}
Serial.print(F("receivePacket:: Ind="));
Serial.print(index);
Serial.print(F(", Len="));
Serial.print(LoraUp.payLength);
Serial.print(F(", A="));
for (int i=0; i<4; i++) {
if (DevAddr[i]<0x0F) Serial.print('0');
Serial.print(DevAddr[i],HEX);
//Serial.print(' ');
Serial.print(F(", Msg="));
for (int i=0; (i<statr[0].datal) && (i<23); i++) {
if (statr[0].data[i]<0x0F) Serial.print('0');
Serial.print(statr[0].data[i],HEX);
Serial.print(' ');
}
Serial.println();
}
Serial.print(F(", Msg="));
for (int i=0; (i<statr[0].datal) && (i<23); i++) {
if (statr[0].data[i]<0x0F) Serial.print('0');
Serial.print(statr[0].data[i],HEX);
Serial.print(' ');
}
Serial.println();
}
else if (debug>=2) {
else if (( debug>=2 ) && ( pdebug & P_RX )) {
Serial.println(F("receivePacket:: No Index"));
}
#endif //DUSB

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -176,8 +176,8 @@ int SerialName(char * a, String& response)
if (id == nodes[i].id) {
#if DUSB >=1
if (debug>=2) {
Serial.print(F("Name="));
if (( debug>=3 ) && ( pdebug & P_GUI )) {
Serial.print(F("G Name="));
Serial.print(nodes[i].nm);
Serial.print(F(" for node=0x"));
Serial.print(nodes[i].id,HEX);

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by many people and making use of several libraries.
//
@ -66,14 +66,43 @@ static void printIP(IPAddress ipa, const char sep, String& response)
// ----------------------------------------------------------------------------
// Used by all functions requiring user confirmation
// Displays a menu by user and two buttons "YES" and "CANCEL"
// The function returns true for YES and false for CANCEL
// Displays a menu by user and two buttons "OK" and "CANCEL"
// The function returns true for OK and false for CANCEL
// Usage: Call this function ONCE during startup to declare and init
// the ynDialog JavaScript function, and call the function
// from the program when needed.
// Paramters of the JavaScript function:
// s: Th strig contining the question to be answered
// o: The OK tab for the webpage where to go to
// c: The Cancel string (optional)
// ----------------------------------------------------------------------------
boolean YesNo(String s)
boolean YesNo()
{
boolean ret = false;
//Serial.println(F("Renew Web Page"));
//sendWebPage("","");
String response = "";
response += "<script>";
response += "var ch = \"\"; "; // Init ch oice
response += "function ynDialog(s,y) {";
response += " try { adddlert(s); }";
response += " catch(err) {";
response += " ch = \" \" + s + \".\\n\\n\"; ";
response += " ch += \"Click OK to continue,\\n\"; ";
response += " ch += \"or Cancel\\n\\n\"; ";
response += " if(!confirm(ch)) { ";
response += " javascript:window.location.reload(true);";
response += " } ";
response += " else { ";
response += " document.location.href = '/'+y; ";
response += " } ";
response += " }";
response += "}";
response += "</script>";
server.sendContent(response);
// Put something like this in the ESP program
// response += "<input type=\"button\" value=\"YesNo\" onclick=\"ynDialog()\" />";
return(ret);
}
@ -92,14 +121,14 @@ void wwwFile(String fn) {
if (!SPIFFS.exists(fn)) {
#if DUSB>=1
Serial.print(F("wwwButtons:: ERROR: file not found="));
Serial.print(F("wwwFile:: ERROR: file not found="));
Serial.println(fn);
#endif
return;
}
#if DUSB>=2
else {
Serial.print(F("wwwButtons:: File existist= "));
Serial.print(F("wwwFile:: File existist= "));
Serial.println(fn);
}
#endif
@ -124,25 +153,37 @@ void wwwFile(String fn) {
}
// ----------------------------------------------------------------------------
// Button function Stat, display statistics
// Button function Docu, display the documentation pages.
// This is a button on the top of the GUI screen.
// ----------------------------------------------------------------------------
void buttonStat()
void buttonDocu()
{
//Serial.print(F("Log"));
//Serial.println();
//printLog();
String response = "";
response+= "<script> confirm('Confirm Log'); </script>";
response += "<script>";
response += "var txt = \"\";";
response += "function showDocu() {";
response += " try { adddlert(\"Welcome,\"); }";
response += " catch(err) {";
response += " txt = \"Do you want the documentation page.\\n\\n\"; ";
response += " txt += \"Click OK to continue viewing documentation,\\n\"; ";
response += " txt += \"or Cancel to return to the home page.\\n\\n\"; ";
response += " if(confirm(txt)) { ";
response += " document.location.href = \"https://things4u.github.io/UserGuide/One%20Channel%20Gateway/Introduction%205.html\"; ";
response += " }";
response += " }";
response += "}";
response += "</script>";
server.sendContent(response);
}
// ----------------------------------------------------------------------------
// Button gunction Log displays logfiles.
// Button function Log displays logfiles.
// This is a button on the top of the GUI screen
// ----------------------------------------------------------------------------
void buttonLog()
@ -169,11 +210,18 @@ void buttonLog()
static void wwwButtons()
{
String response = "";
String mode = (gwayConfig.expert ? "Basic Mode" : "Expert Mode");
response += "<a href=\"STAT\" download><button type=\"button\">Stat</button></a>";
response += "<a href=\"LOG\" download><button type=\"button\">Log</button></a>";
YesNo(); // Init the Yes/No function
buttonDocu();
server.sendContent(response); // Send to the screen
response += "<input type=\"button\" value=\"Documentation\" onclick=\"showDocu()\" >";
response += "<a href=\"EXPERT\" download><button type=\"button\">" + mode + "</button></a>";
response += "<a href=\"LOG\" download><button type=\"button\">Log Files</button></a>";
server.sendContent(response); // Send to the screen
}
@ -552,18 +600,18 @@ static void settingsData()
// Format the Filesystem
response +="<tr><td class=\"cell\">Format SPIFFS</td>";
response +=String() + "<td class=\"cell\" colspan=\"2\" >"+""+"</td>";
response +="<td colspan=\"2\" class=\"cell\"><a href=\"/FORMAT\"><button>FORMAT</button></a></td></tr>";
response +="<td colspan=\"2\" class=\"cell\"><input type=\"button\" value=\"FORMAT\" onclick=\"ynDialog(\'Do you really want to format?\',\'FORMAT\')\" /></td></tr>";
// Reset all statistics
#if STATISTICS >= 1
response +="<tr><td class=\"cell\">Statistics</td>";
response +=String() + "<td class=\"cell\" colspan=\"2\" >"+statc.resets+"</td>";
response +="<td colspan=\"2\" class=\"cell\"><a href=\"/RESET\"><button>RESET</button></a></td></tr>";
response +="<td colspan=\"2\" class=\"cell\"><input type=\"button\" value=\"RESET\" onclick=\"ynDialog(\'Do you really want to reset statistics?\',\'RESET\')\" /></td></tr>";
// Reset
response +="<tr><td class=\"cell\">Boots and Resets</td>";
response +=String() + "<td class=\"cell\" colspan=\"2\" >"+gwayConfig.boots+"</td>";
response +="<td colspan=\"2\" class=\"cell\"><a href=\"/BOOT\"><button>RESET</button></a></td></tr>";
response +="<td colspan=\"2\" class=\"cell\"><input type=\"button\" value=\"RESET\" onclick=\"ynDialog(\'Do you want to reset boots?\',\'BOOT\')\" /></td></tr>";
#endif
response +="</table>";
@ -572,84 +620,6 @@ static void settingsData()
}
// ----------------------------------------------------------------------------
// INTERRUPT DATA
// Display interrupt data, but only for debug >= 2
//
// ----------------------------------------------------------------------------
static void interruptData()
{
uint8_t flags = readRegister(REG_IRQ_FLAGS);
uint8_t mask = readRegister(REG_IRQ_FLAGS_MASK);
if (debug >= 2) {
String response="";
response +="<h2>System State and Interrupt</h2>";
response +="<table class=\"config_table\">";
response +="<tr>";
response +="<th class=\"thead\">Parameter</th>";
response +="<th class=\"thead\">Value</th>";
response +="<th colspan=\"2\" class=\"thead\">Set</th>";
response +="</tr>";
response +="<tr><td class=\"cell\">_state</td>";
response +="<td class=\"cell\">";
switch (_state) { // See loraModem.h
case S_INIT: response +="INIT"; break;
case S_SCAN: response +="SCAN"; break;
case S_CAD: response +="CAD"; break;
case S_RX: response +="RX"; break;
case S_TX: response +="TX"; break;
default: response +="unknown"; break;
}
response +="</td></tr>";
response +="<tr><td class=\"cell\">flags (8 bits)</td>";
response +="<td class=\"cell\">0x";
if (flags <16) response += "0";
response +=String(flags,HEX); response+="</td></tr>";
response +="<tr><td class=\"cell\">mask (8 bits)</td>";
response +="<td class=\"cell\">0x";
if (mask <16) response += "0";
response +=String(mask,HEX); response+="</td></tr>";
response +="<tr><td class=\"cell\">Re-entrant cntr</td>";
response +="<td class=\"cell\">";
response += String() + gwayConfig.reents;
response +="</td></tr>";
response +="<tr><td class=\"cell\">ntp call cntr</td>";
response +="<td class=\"cell\">";
response += String() + gwayConfig.ntps;
response+="</td></tr>";
response +="<tr><td class=\"cell\">ntpErr cntr</td>";
response +="<td class=\"cell\">";
response += String() + gwayConfig.ntpErr;
response +="</td>";
response +="<td colspan=\"2\" style=\"border: 1px solid black;\">";
stringTime(gwayConfig.ntpErrTime, response);
response +="</td>";
response +="</tr>";
response +="<tr><td class=\"cell\">Time Correction (uSec)</td><td class=\"cell\">";
response += txDelay;
response +="</td>";
response +="<td class=\"cell\"><a href=\"DELAY=-1\"><button>-</button></a></td>";
response +="<td class=\"cell\"><a href=\"DELAY=1\"><button>+</button></a></td>";
response +="</tr>";
response +="</table>";
server.sendContent(response);
}// if debug>=2
}
// ----------------------------------------------------------------------------
// STATISTICS DATA
//
@ -858,7 +828,7 @@ static void sensorData()
response += String() + "<td class=\"cell\">" + statr[i].prssi + "</td>";
#if RSSI==1
if (debug > 1) {
if (debug >= 2) {
response += String() + "<td class=\"cell\">" + statr[i].rssi + "</td>";
}
#endif
@ -871,107 +841,12 @@ static void sensorData()
#endif
}
// ----------------------------------------------------------------------------
// SYSTEMDATA
//
// ----------------------------------------------------------------------------
static void systemData()
{
String response="";
response +="<h2>System Status</h2>";
response +="<table class=\"config_table\">";
response +="<tr>";
response +="<th class=\"thead\">Parameter</th>";
response +="<th class=\"thead\">Value</th>";
response +="<th colspan=\"2\" class=\"thead\">Set</th>";
response +="</tr>";
response +="<tr><td style=\"border: 1px solid black; width:120px;\">Gateway ID</td>";
response +="<td class=\"cell\">";
if (MAC_array[0]< 0x10) response +='0'; response +=String(MAC_array[0],HEX); // The MAC array is always returned in lowercase
if (MAC_array[1]< 0x10) response +='0'; response +=String(MAC_array[1],HEX);
if (MAC_array[2]< 0x10) response +='0'; response +=String(MAC_array[2],HEX);
response +="FFFF";
if (MAC_array[3]< 0x10) response +='0'; response +=String(MAC_array[3],HEX);
if (MAC_array[4]< 0x10) response +='0'; response +=String(MAC_array[4],HEX);
if (MAC_array[5]< 0x10) response +='0'; response +=String(MAC_array[5],HEX);
response+="</tr>";
response +="<tr><td class=\"cell\">Free heap</td><td class=\"cell\">"; response+=ESP.getFreeHeap(); response+="</tr>";
// XXX We Shoudl find an ESP32 alternative
#if !defined ESP32_ARCH
response +="<tr><td class=\"cell\">ESP speed</td><td class=\"cell\">"; response+=ESP.getCpuFreqMHz();
response +="<td style=\"border: 1px solid black; width:40px;\"><a href=\"SPEED=80\"><button>80</button></a></td>";
response +="<td style=\"border: 1px solid black; width:40px;\"><a href=\"SPEED=160\"><button>160</button></a></td>";
response+="</tr>";
response +="<tr><td class=\"cell\">ESP Chip ID</td><td class=\"cell\">"; response+=ESP.getChipId(); response+="</tr>";
#endif
response +="<tr><td class=\"cell\">OLED</td><td class=\"cell\">"; response+=OLED; response+="</tr>";
#if STATISTICS>=1
response +="<tr><td class=\"cell\">WiFi Setups</td><td class=\"cell\">"; response+=gwayConfig.wifis; response+="</tr>";
response +="<tr><td class=\"cell\">WWW Views</td><td class=\"cell\">"; response+=gwayConfig.views; response+="</tr>";
#endif
response +="</table>";
server.sendContent(response);
}
// ----------------------------------------------------------------------------
// WIFIDATA
// Display the most important Wifi parameters gathered
//
// ----------------------------------------------------------------------------
static void wifiData()
{
String response="";
response +="<h2>WiFi Config</h2>";
response +="<table class=\"config_table\">";
response +="<tr><th class=\"thead\">Parameter</th><th class=\"thead\">Value</th></tr>";
response +="<tr><td class=\"cell\">WiFi host</td><td class=\"cell\">";
#if ESP32_ARCH==1
response +=WiFi.getHostname(); response+="</tr>";
#else
response +=wifi_station_get_hostname(); response+="</tr>";
#endif
response +="<tr><td class=\"cell\">WiFi SSID</td><td class=\"cell\">";
response +=WiFi.SSID(); response+="</tr>";
response +="<tr><td class=\"cell\">IP Address</td><td class=\"cell\">";
printIP((IPAddress)WiFi.localIP(),'.',response);
response +="</tr>";
response +="<tr><td class=\"cell\">IP Gateway</td><td class=\"cell\">";
printIP((IPAddress)WiFi.gatewayIP(),'.',response);
response +="</tr>";
response +="<tr><td class=\"cell\">NTP Server</td><td class=\"cell\">"; response+=NTP_TIMESERVER; response+="</tr>";
response +="<tr><td class=\"cell\">LoRa Router</td><td class=\"cell\">"; response+=_TTNSERVER; response+="</tr>";
response +="<tr><td class=\"cell\">LoRa Router IP</td><td class=\"cell\">";
printIP((IPAddress)ttnServer,'.',response);
response +="</tr>";
#ifdef _THINGSERVER
response +="<tr><td class=\"cell\">LoRa Router 2</td><td class=\"cell\">"; response+=_THINGSERVER;
response += String() + ":" + _THINGPORT + "</tr>";
response +="<tr><td class=\"cell\">LoRa Router 2 IP</td><td class=\"cell\">";
printIP((IPAddress)thingServer,'.',response);
response +="</tr>";
#endif
response +="</table>";
server.sendContent(response);
}
// ----------------------------------------------------------------------------
// SEND WEB PAGE()
// Call the webserver and send the standard content and the content that is
// passed by the parameter.
// passed by the parameter. Each time a variable is changed, this function is
// called to display the webpage again/
//
// NOTE: This is the only place where yield() or delay() calls are used.
//
@ -1004,8 +879,9 @@ void sendWebPage(const char *cmd, const char *arg)
// ----------------------------------------------------------------------------
// setupWWW is the main function for webserver functions/
// SetupWWW function called by main setup() program to setup webserver
// It does actually not much more than installing the callback handlers
// It does actually not much more than installing all the callback handlers
// for messages sent to the webserver
//
// Implemented is an interface like:
@ -1035,9 +911,15 @@ void setupWWW()
// Format the filesystem
server.on("/FORMAT", []() {
Serial.print(F("FORMAT ..."));
SPIFFS.format(); // Normally disabled. Enable only when SPIFFS corrupt
initConfig(&gwayConfig);
writeConfig( CONFIGFILE, &gwayConfig);
#if DUSB>=1
Serial.println(F("DONE"));
#endif
server.sendHeader("Location", String("/"), true);
server.send ( 302, "text/plain", "");
});
@ -1166,12 +1048,12 @@ void setupWWW()
// Set delay in microseconds
server.on("/DELAY=1", []() {
txDelay+=1000;
txDelay+=5000;
server.sendHeader("Location", String("/"), true);
server.send ( 302, "text/plain", "");
});
server.on("/DELAY=-1", []() {
txDelay-=1000;
txDelay-=5000;
server.sendHeader("Location", String("/"), true);
server.send ( 302, "text/plain", "");
});
@ -1295,19 +1177,31 @@ void setupWWW()
server.send ( 302, "text/plain", "");
});
#endif
// Display Statistics
server.on("/STAT", []() {
buttonStat();
//server.sendHeader("Location", String("/"), true);
// Display Documentation pages
server.on("/DOCU", []() {
//server.send ( 302, "text/plain", "");
server.sendHeader("Location", String("/"), true);
buttonDocu();
server.send ( 302, "text/plain", "");
});
server.on("/LOG", []() {
server.sendHeader("Location", String("/"), true);
#if DUSB>=1
Serial.println(F("LOG button"));
#endif
buttonLog();
server.send ( 302, "text/plain", "");
});
// Display Expert mode or Simple mode
server.on("/EXPERT", []() {
server.sendHeader("Location", String("/"), true);
gwayConfig.expert = bool(1 - (int) gwayConfig.expert) ;
server.send ( 302, "text/plain", "");
});
// Update the sketch. Not yet implemented
server.on("/UPDATE=1", []() {
#if A_OTA==1
@ -1327,7 +1221,186 @@ void setupWWW()
Serial.print(F("WWW Server started on port "));
Serial.println(A_SERVERPORT);
return;
}
} // setupWWW
// ----------------------------------------------------------------------------
// WIFI CONFIG
// wifiData() displays the most important Wifi parameters gathered
//
// ----------------------------------------------------------------------------
static void wifiData()
{
if (gwayConfig.expert) {
String response="";
response +="<h2>WiFi Config</h2>";
response +="<table class=\"config_table\">";
response +="<tr><th class=\"thead\">Parameter</th><th class=\"thead\">Value</th></tr>";
response +="<tr><td class=\"cell\">WiFi host</td><td class=\"cell\">";
#if ESP32_ARCH==1
response +=WiFi.getHostname(); response+="</tr>";
#else
response +=wifi_station_get_hostname(); response+="</tr>";
#endif
response +="<tr><td class=\"cell\">WiFi SSID</td><td class=\"cell\">";
response +=WiFi.SSID(); response+="</tr>";
response +="<tr><td class=\"cell\">IP Address</td><td class=\"cell\">";
printIP((IPAddress)WiFi.localIP(),'.',response);
response +="</tr>";
response +="<tr><td class=\"cell\">IP Gateway</td><td class=\"cell\">";
printIP((IPAddress)WiFi.gatewayIP(),'.',response);
response +="</tr>";
response +="<tr><td class=\"cell\">NTP Server</td><td class=\"cell\">"; response+=NTP_TIMESERVER; response+="</tr>";
response +="<tr><td class=\"cell\">LoRa Router</td><td class=\"cell\">"; response+=_TTNSERVER; response+="</tr>";
response +="<tr><td class=\"cell\">LoRa Router IP</td><td class=\"cell\">";
printIP((IPAddress)ttnServer,'.',response);
response +="</tr>";
#ifdef _THINGSERVER
response +="<tr><td class=\"cell\">LoRa Router 2</td><td class=\"cell\">"; response+=_THINGSERVER;
response += String() + ":" + _THINGPORT + "</tr>";
response +="<tr><td class=\"cell\">LoRa Router 2 IP</td><td class=\"cell\">";
printIP((IPAddress)thingServer,'.',response);
response +="</tr>";
#endif
response +="</table>";
server.sendContent(response);
} // gwayConfig.expert
} // wifiData
// ----------------------------------------------------------------------------
// SYSTEMDATA
// This section contain a number of system specific data such as heap size etc.
// ----------------------------------------------------------------------------
static void systemData()
{
if (gwayConfig.expert) {
String response="";
response +="<h2>System Status</h2>";
response +="<table class=\"config_table\">";
response +="<tr>";
response +="<th class=\"thead\">Parameter</th>";
response +="<th class=\"thead\">Value</th>";
response +="<th colspan=\"2\" class=\"thead\">Set</th>";
response +="</tr>";
response +="<tr><td style=\"border: 1px solid black; width:120px;\">Gateway ID</td>";
response +="<td class=\"cell\">";
if (MAC_array[0]< 0x10) response +='0'; response +=String(MAC_array[0],HEX); // The MAC array is always returned in lowercase
if (MAC_array[1]< 0x10) response +='0'; response +=String(MAC_array[1],HEX);
if (MAC_array[2]< 0x10) response +='0'; response +=String(MAC_array[2],HEX);
response +="FFFF";
if (MAC_array[3]< 0x10) response +='0'; response +=String(MAC_array[3],HEX);
if (MAC_array[4]< 0x10) response +='0'; response +=String(MAC_array[4],HEX);
if (MAC_array[5]< 0x10) response +='0'; response +=String(MAC_array[5],HEX);
response+="</tr>";
response +="<tr><td class=\"cell\">Free heap</td><td class=\"cell\">"; response+=ESP.getFreeHeap(); response+="</tr>";
// XXX We Shoudl find an ESP32 alternative
#if !defined ESP32_ARCH
response +="<tr><td class=\"cell\">ESP speed</td><td class=\"cell\">"; response+=ESP.getCpuFreqMHz();
response +="<td style=\"border: 1px solid black; width:40px;\"><a href=\"SPEED=80\"><button>80</button></a></td>";
response +="<td style=\"border: 1px solid black; width:40px;\"><a href=\"SPEED=160\"><button>160</button></a></td>";
response+="</tr>";
response +="<tr><td class=\"cell\">ESP Chip ID</td><td class=\"cell\">"; response+=ESP.getChipId(); response+="</tr>";
#endif
response +="<tr><td class=\"cell\">OLED</td><td class=\"cell\">"; response+=OLED; response+="</tr>";
#if STATISTICS>=1
response +="<tr><td class=\"cell\">WiFi Setups</td><td class=\"cell\">"; response+=gwayConfig.wifis; response+="</tr>";
response +="<tr><td class=\"cell\">WWW Views</td><td class=\"cell\">"; response+=gwayConfig.views; response+="</tr>";
#endif
response +="</table>";
server.sendContent(response);
} // gwayConfig.expert
} // systemData
// ----------------------------------------------------------------------------
// INTERRUPT DATA
// Display interrupt data, but only for debug >= 2
//
// ----------------------------------------------------------------------------
static void interruptData()
{
if (gwayConfig.expert) {
uint8_t flags = readRegister(REG_IRQ_FLAGS);
uint8_t mask = readRegister(REG_IRQ_FLAGS_MASK);
String response="";
response +="<h2>System State and Interrupt</h2>";
response +="<table class=\"config_table\">";
response +="<tr>";
response +="<th class=\"thead\">Parameter</th>";
response +="<th class=\"thead\">Value</th>";
response +="<th colspan=\"2\" class=\"thead\">Set</th>";
response +="</tr>";
response +="<tr><td class=\"cell\">_state</td>";
response +="<td class=\"cell\">";
switch (_state) { // See loraModem.h
case S_INIT: response +="INIT"; break;
case S_SCAN: response +="SCAN"; break;
case S_CAD: response +="CAD"; break;
case S_RX: response +="RX"; break;
case S_TX: response +="TX"; break;
default: response +="unknown"; break;
}
response +="</td></tr>";
response +="<tr><td class=\"cell\">flags (8 bits)</td>";
response +="<td class=\"cell\">0x";
if (flags <16) response += "0";
response +=String(flags,HEX); response+="</td></tr>";
response +="<tr><td class=\"cell\">mask (8 bits)</td>";
response +="<td class=\"cell\">0x";
if (mask <16) response += "0";
response +=String(mask,HEX); response+="</td></tr>";
response +="<tr><td class=\"cell\">Re-entrant cntr</td>";
response +="<td class=\"cell\">";
response += String() + gwayConfig.reents;
response +="</td></tr>";
response +="<tr><td class=\"cell\">ntp call cntr</td>";
response +="<td class=\"cell\">";
response += String() + gwayConfig.ntps;
response+="</td></tr>";
response +="<tr><td class=\"cell\">ntpErr cntr</td>";
response +="<td class=\"cell\">";
response += String() + gwayConfig.ntpErr;
response +="</td>";
response +="<td colspan=\"2\" style=\"border: 1px solid black;\">";
stringTime(gwayConfig.ntpErrTime, response);
response +="</td>";
response +="</tr>";
response +="<tr><td class=\"cell\">Time Correction (uSec)</td><td class=\"cell\">";
response += txDelay;
response +="</td>";
response +="<td class=\"cell\"><a href=\"DELAY=-1\"><button>-</button></a></td>";
response +="<td class=\"cell\"><a href=\"DELAY=1\"><button>+</button></a></td>";
response +="</tr>";
response +="</table>";
server.sendContent(response);
}// if gwayConfig.expert
} // interruptData
#endif // A_SERVER==1

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -71,6 +71,7 @@ struct espGwayConfig {
bool hop; // Is HOP enabled (Note: default be disabled)
bool isNode; // Is gateway node enabled
bool refresh; // Is WWW browser refresh enabled
bool expert;
String ssid; // SSID of the last connected WiFi Network
String pass; // Password of WiFi network

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many other contributors.

Wyświetl plik

@ -1,7 +1,7 @@
// 1-channel LoRa Gateway for ESP8266
// Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266
// Version 5.3.2
// Date: 2018-07-07
// Version 5.3.3
// Date: 2018-08-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many others.
@ -26,7 +26,7 @@
// The following OLDs are supported:
// 0. No OLED connected
// 1. 0.9" OLED (cheap)
// 2. 1.3" OLED with much better display
// 2. 1.3" OLED with much better and larger display
#if OLED>=1 // If OLED is used
@ -44,7 +44,7 @@
#elif _PIN_OUT==4 // TTGO (onboard version used, also for DIY)
#define OLED_SCL 15 // GPIO15 /
#define OLED_SDA 4 // GPIO4 /
#define OLED_RST 16
#define OLED_RST 16 // Reset pin (Some OLED displays do not have it)
#endif

Wyświetl plik

@ -1,7 +1,7 @@
// 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
// Version 5.3.3
// Date: 2018-05-25
//
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
// and many other contributors.
@ -22,9 +22,9 @@
// ------------------------------------------------------------------------------------
#if _TRUSTED_NODES >= 1
struct nodex {
uint32_t id; // This i sthe decide ID (coded in 4 bytes uint32_t
char nm[32];
struct nodex {
uint32_t id; // This is the LoRa ID (coded in 4 bytes uint32_t
char nm[32]; // Name of the node
};
// Add all your named and trusted nodes to this list
@ -42,14 +42,16 @@ nodex nodes[] = {
{ 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
{ 0x270005AB , "distance-42 sensor for trash"}, // F=0
{ 0x27000599 , "distance-44 sensor for trash"}, // F=0
{ 0x27000596 , "distance-45 sensor for trash"}, // F=0
{ 0x00000000 , "lora-00 well known sensor" } // F=0
};
#endif //_TRUSTED_NODES
#if _LOCALSERVER==1
#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
@ -65,16 +67,28 @@ struct codex {
//
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 }
{ 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 },
{ 0x02, 0x02, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 }
},
{ 0x26011b96 , "lora-50", // F=0
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 },
{ 0x02, 0x02, 0x04, 0x32, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 }
},
{ 0x26011999 , "lora-901", // F=0
{ 0x270005AB , "distance-42",// F=0
{ 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 },
{ 0x02, 0x02, 0x04, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 }
},
{ 0x27000599 , "distance-44",// F=0
{ 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 },
{ 0x02, 0x02, 0x04, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 }
},
{ 0x27000596 , "distance-45",// F=0
{ 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 },
{ 0x02, 0x02, 0x04, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x54, 0x68, 0x69, 0x6E, 0x67, 0x73, 0x34, 0x55 }
},
{ 0x00000000 , "lora-00", // 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 }
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
}
};
#endif //_LOCALSERVER

Wyświetl plik

@ -1,28 +0,0 @@
#Testing the Gateway
## Introduction
This document describes the testing of the single channel gateway. These parameters are set in gthe loraModem.h file and determine its behaviour for switching from S_SCAN state to S_CAD state and the fallback from S_CAD state to scanning if the rssi drop dramatically.
## Optimize for STD
For the standard mode, the folowing values are used for parameter setting:
- RSSI_LIMIT 40
- RSSI_WAIT 275
-
## Optimize for CAD
For the standard mode, the folowing values are used for parameter setting:
## Optimize for HOP
For the HOP mode, the folowing values are used for parameter setting:
- RSSI_LIMIT 39 for the S_SCAN state, and -5 for the S_CAD state
- RSSI_WAIT 250
- RSSI_WAIT_DOWN 225; microseconds to wait before reading RSSI when in S_CAD mode to decide going back to S_SCAN
-