diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 8d4d6d8..6d03f0d 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -13,6 +13,7 @@ #include "digi_utils.h" #include "gps_utils.h" #include "bme_utils.h" +#include "web_utils.h" #include "display.h" #include "utils.h" @@ -20,7 +21,7 @@ Configuration Config; WiFiClient espClient; -String versionDate = "2024.01.28"; +String versionDate = "2024.02.23"; int myWiFiAPIndex = 0; int myWiFiAPSize = Config.wifiAPs.size(); WiFi_AP *currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; @@ -34,8 +35,12 @@ uint32_t lastScreenOn = millis(); uint32_t lastWiFiCheck = 0; bool WiFiConnect = true; +bool WiFiConnected = false; int lastStationModeState = 1; +bool WiFiAutoAPStarted = false; +long WiFiAutoAPTime = false; + String batteryVoltage; std::vector lastHeardStation; @@ -46,55 +51,63 @@ std::vector packetBuffer_temp; String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, iGateBeaconPacket, iGateLoRaBeaconPacket; void setup() { - Serial.begin(115200); - #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) - pinMode(batteryPin, INPUT); - #endif - #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) - pinMode(internalLedPin, OUTPUT); - #endif - if (Config.externalVoltageMeasurement) { - pinMode(Config.externalVoltagePin, INPUT); - } - #if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_2_SX1262) - POWER_Utils::setup(); - #endif - delay(1000); - Utils::setupDisplay(); - WIFI_Utils::setup(); - LoRa_Utils::setup(); - Utils::validateDigiFreqs(); - iGateBeaconPacket = GPS_Utils::generateBeacon(); - iGateLoRaBeaconPacket = GPS_Utils::generateiGateLoRaBeacon(); - Utils::startServer(); - SYSLOG_Utils::setup(); - BME_Utils::setup(); + Serial.begin(115200); + + #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) + pinMode(batteryPin, INPUT); + #endif + #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) + pinMode(internalLedPin, OUTPUT); + #endif + if (Config.externalVoltageMeasurement) { + pinMode(Config.externalVoltagePin, INPUT); + } + #if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_2_SX1262) + POWER_Utils::setup(); + #endif + delay(1000); + Utils::setupDisplay(); + WIFI_Utils::setup(); + LoRa_Utils::setup(); + Utils::validateDigiFreqs(); + iGateBeaconPacket = GPS_Utils::generateBeacon(); + iGateLoRaBeaconPacket = GPS_Utils::generateiGateLoRaBeacon(); + SYSLOG_Utils::setup(); + BME_Utils::setup(); + WEB_Utils::setup(); } void loop() { - if (stationMode==1 || stationMode==2 ) { // iGate (1 Only Rx / 2 Rx+Tx) - WIFI_Utils::checkWiFi(); - if (!espClient.connected()) { - APRS_IS_Utils::connect(); + WEB_Utils::loop(); + + WIFI_Utils::checkIfAutoAPShouldPowerOff(); + + if (!WiFiConnected) { + thirdLine = Utils::getLocalIP(); } - APRS_IS_Utils::loop(); - } else if (stationMode==3 || stationMode==4) { // DigiRepeater (3 RxFreq=TxFreq / 4 RxFreq!=TxFreq) - DIGI_Utils::loop(); - } else if (stationMode==5) { // iGate when WiFi and APRS available , DigiRepeater when not (RxFreq=TxFreq) - Utils::checkWiFiInterval(); - if (WiFi.status() == WL_CONNECTED) { // iGate Mode - thirdLine = Utils::getLocalIP(); - if (!espClient.connected()) { - APRS_IS_Utils::connect(); - } - if (lastStationModeState == 1) { - iGateBeaconPacket = GPS_Utils::generateBeacon(); - lastStationModeState = 0; - Utils::startServer(); - } - APRS_IS_Utils::loop(); - } else { // DigiRepeater Mode - DIGI_Utils::loop(); + + if (stationMode==1 || stationMode==2 ) { // iGate (1 Only Rx / 2 Rx+Tx) + WIFI_Utils::checkWiFi(); + if (!espClient.connected()) { + APRS_IS_Utils::connect(); + } + APRS_IS_Utils::loop(); + } else if (stationMode==3 || stationMode==4) { // DigiRepeater (3 RxFreq=TxFreq / 4 RxFreq!=TxFreq) + DIGI_Utils::loop(); + } else if (stationMode==5) { // iGate when WiFi and APRS available , DigiRepeater when not (RxFreq=TxFreq) + Utils::checkWiFiInterval(); + if (WiFi.status() == WL_CONNECTED) { // iGate Mode + thirdLine = Utils::getLocalIP(); + if (!espClient.connected()) { + APRS_IS_Utils::connect(); + } + if (lastStationModeState == 1) { + iGateBeaconPacket = GPS_Utils::generateBeacon(); + lastStationModeState = 0; + } + APRS_IS_Utils::loop(); + } else { // DigiRepeater Mode + DIGI_Utils::loop(); + } } - } } \ No newline at end of file diff --git a/src/aprs_is_utils.cpp b/src/aprs_is_utils.cpp index c672f1b..23e506e 100644 --- a/src/aprs_is_utils.cpp +++ b/src/aprs_is_utils.cpp @@ -26,213 +26,214 @@ extern String seventhLine; namespace APRS_IS_Utils { - void upload(String line) { - espClient.print(line + "\r\n"); - } - - void connect(){ - int count = 0; - String aprsauth; - Serial.print("Connecting to APRS-IS ... "); - while (!espClient.connect(Config.aprs_is.server.c_str(), Config.aprs_is.port) && count < 20) { - Serial.println("Didn't connect with server..."); - delay(1000); - espClient.stop(); - espClient.flush(); - Serial.println("Run client.stop"); - Serial.println("Trying to connect with Server: " + String(Config.aprs_is.server) + " AprsServerPort: " + String(Config.aprs_is.port)); - count++; - Serial.println("Try: " + String(count)); + void upload(String line) { + espClient.print(line + "\r\n"); } - if (count == 20) { - Serial.println("Tried: " + String(count) + " FAILED!"); - } else { - Serial.println("Connected!\n(Server: " + String(Config.aprs_is.server) + " / Port: " + String(Config.aprs_is.port) +")"); - aprsauth = "user " + Config.callsign + " pass " + Config.aprs_is.passcode + " vers CA2RXU_LoRa_iGate 1.2 filter t/m/" + Config.callsign + "/" + (String)Config.aprs_is.reportingDistance;// + "\r\n"; - upload(aprsauth); - delay(200); - } - } - void checkStatus() { - String wifiState, aprsisState; - if (WiFi.status() == WL_CONNECTED) { - wifiState = "OK"; - } else { - wifiState = "--"; - if (!Config.display.alwaysOn) { - display_toggle(true); - } - lastScreenOn = millis(); - } - if (espClient.connected()) { - aprsisState = "OK"; - } else { - aprsisState = "--"; - if (!Config.display.alwaysOn) { - display_toggle(true); - } - lastScreenOn = millis(); - } - secondLine = "WiFi: " + wifiState + "/ APRS-IS: " + aprsisState; - } - - String createPacket(String packet) { - if (stationMode>1) { - return packet.substring(3, packet.indexOf(":")) + ",qAR," + Config.callsign + packet.substring(packet.indexOf(":"));// + "\n"; - } else { - return packet.substring(3, packet.indexOf(":")) + ",qAO," + Config.callsign + packet.substring(packet.indexOf(":"));// + "\n"; - } - } - - void processLoRaPacket(String packet) { - bool queryMessage = false; - String aprsPacket, Sender, AddresseeAndMessage, Addressee, ackMessage, receivedMessage; - if (packet != "") { - #ifdef TextSerialOutputForApp - Serial.println(packet.substring(3)); - #else - Serial.print("Received Lora Packet : " + String(packet)); - #endif - if ((packet.substring(0,3) == "\x3c\xff\x01") && (packet.indexOf("TCPIP") == -1) && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) { - #ifndef TextSerialOutputForApp - Serial.print(" ---> APRS LoRa Packet!"); - #endif - Sender = packet.substring(3,packet.indexOf(">")); - if (Sender != Config.callsign) { // avoid listening yourself by digirepeating - AddresseeAndMessage = packet.substring(packet.indexOf("::")+2); - Addressee = AddresseeAndMessage.substring(0,AddresseeAndMessage.indexOf(":")); - Addressee.trim(); - - if (stationMode!=1 && Config.igateRepeatsLoRaPackets && Addressee != Config.callsign) { // if its not for me - String digiRepeatedPacket = DIGI_Utils::generateDigiRepeatedPacket(packet.substring(3), Config.callsign); - if (digiRepeatedPacket != "X") { - delay(500); - LoRa_Utils::sendNewPacket("APRS", digiRepeatedPacket); - } - } - - if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me! - if (AddresseeAndMessage.indexOf("{")>0) { // ack? - ackMessage = "ack" + AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{")+1); - ackMessage.trim(); - delay(4000); - //Serial.println(ackMessage); - for(int i = Sender.length(); i < 9; i++) { - Sender += ' '; - } - LoRa_Utils::sendNewPacket("APRS", Config.callsign + ">APLRG1,RFONLY,WIDE1-1::" + Sender + ":" + ackMessage); - receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1, AddresseeAndMessage.indexOf("{")); - } else { - receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1); - } - if (receivedMessage.indexOf("?") == 0) { - queryMessage = true; - delay(2000); - if (!Config.display.alwaysOn) { - display_toggle(true); - } - LoRa_Utils::sendNewPacket("APRS", QUERY_Utils::process(receivedMessage, Sender, "LoRa")); - lastScreenOn = millis(); - show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + Sender, "TYPE --> QUERY", 0); - } - } - if (!queryMessage) { - aprsPacket = createPacket(packet); - if (!Config.display.alwaysOn) { - display_toggle(true); - } - lastScreenOn = millis(); - upload(aprsPacket); - #ifndef TextSerialOutputForApp - Serial.println(" ---> Uploaded to APRS-IS"); - #endif - STATION_Utils::updateLastHeard(Sender); - Utils::typeOfPacket(aprsPacket, "LoRa-APRS"); - show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); - } - } - } else { - #ifndef TextSerialOutputForApp - Serial.println(" ---> LoRa Packet Ignored (first 3 bytes or TCPIP/NOGATE/RFONLY)\n"); - #endif - } - } - } - - void processAPRSISPacket(String packet) { - String Sender, AddresseeAndMessage, Addressee, receivedMessage; - if (!packet.startsWith("#")){ - if (packet.indexOf("::")>0) { - Sender = packet.substring(0,packet.indexOf(">")); - AddresseeAndMessage = packet.substring(packet.indexOf("::")+2); - Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); - Addressee.trim(); - if (Addressee == Config.callsign) { // its for me! - if (AddresseeAndMessage.indexOf("{")>0) { // ack? - String ackMessage = "ack" + AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{")+1); - ackMessage.trim(); - delay(4000); - //Serial.println(ackMessage); - for(int i = Sender.length(); i < 9; i++) { - Sender += ' '; - } - String ackPacket = Config.callsign + ">APLRG1,TCPIP,qAC::" + Sender + ":" + ackMessage;// + "\n"; - upload(ackPacket); - receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1, AddresseeAndMessage.indexOf("{")); - } else { - receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1); - } - if (receivedMessage.indexOf("?") == 0) { - #ifndef TextSerialOutputForApp - Serial.println("Received Query APRS-IS : " + packet); - #endif - String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, "APRSIS"); - //Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n"))); - if (!Config.display.alwaysOn) { - display_toggle(true); - } - lastScreenOn = millis(); - delay(500); - upload(queryAnswer); - SYSLOG_Utils::log("APRSIS Tx", queryAnswer,0,0,0); - fifthLine = "APRS-IS ----> APRS-IS"; - sixthLine = Config.callsign; - for (int j=sixthLine.length();j<9;j++) { - sixthLine += " "; - } - sixthLine += "> " + Sender; - seventhLine = "QUERY = " + receivedMessage; - } - } else { - #ifndef TextSerialOutputForApp - Serial.print("Received from APRS-IS : " + packet); - #endif - if ((stationMode==2 || stationMode==5) && STATION_Utils::wasHeard(Addressee)) { - LoRa_Utils::sendNewPacket("APRS", LoRa_Utils::generatePacket(packet)); - display_toggle(true); - lastScreenOn = millis(); - Utils::typeOfPacket(packet, "APRS-LoRa"); - } + void connect(){ + int count = 0; + String aprsauth; + Serial.print("Connecting to APRS-IS ... "); + while (!espClient.connect(Config.aprs_is.server.c_str(), Config.aprs_is.port) && count < 20) { + Serial.println("Didn't connect with server..."); + delay(1000); + espClient.stop(); + espClient.flush(); + Serial.println("Run client.stop"); + Serial.println("Trying to connect with Server: " + String(Config.aprs_is.server) + " AprsServerPort: " + String(Config.aprs_is.port)); + count++; + Serial.println("Try: " + String(count)); + } + if (count == 20) { + Serial.println("Tried: " + String(count) + " FAILED!"); + } else { + Serial.println("Connected!\n(Server: " + String(Config.aprs_is.server) + " / Port: " + String(Config.aprs_is.port) +")"); + aprsauth = "user " + Config.callsign + " pass " + Config.aprs_is.passcode + " vers CA2RXU_LoRa_iGate 1.3 filter t/m/" + Config.callsign + "/" + (String)Config.aprs_is.reportingDistance;// + "\r\n"; + upload(aprsauth); + delay(200); } - show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); - } } - } - void loop() { - checkStatus(); - show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); - while (espClient.connected()) { - Utils::checkDisplayInterval(); - Utils::checkBeaconInterval(); - processLoRaPacket(LoRa_Utils::receivePacket()); - if (espClient.available()) { - String aprsisPacket; - aprsisPacket.concat(espClient.readStringUntil('\r')); - processAPRSISPacket(aprsisPacket); - } - ElegantOTA.loop(); + void checkStatus() { + String wifiState, aprsisState; + if (WiFi.status() == WL_CONNECTED) { + wifiState = "OK"; + } else { + wifiState = "AP"; + if (!Config.display.alwaysOn) { + display_toggle(true); + } + lastScreenOn = millis(); + } + if (espClient.connected()) { + aprsisState = "OK"; + } else { + aprsisState = "--"; + if (!Config.display.alwaysOn) { + display_toggle(true); + } + lastScreenOn = millis(); + } + secondLine = "WiFi: " + wifiState + "/ APRS-IS: " + aprsisState; } - } + + String createPacket(String packet) { + if (stationMode>1) { + return packet.substring(3, packet.indexOf(":")) + ",qAR," + Config.callsign + packet.substring(packet.indexOf(":"));// + "\n"; + } else { + return packet.substring(3, packet.indexOf(":")) + ",qAO," + Config.callsign + packet.substring(packet.indexOf(":"));// + "\n"; + } + } + + void processLoRaPacket(String packet) { + bool queryMessage = false; + String aprsPacket, Sender, AddresseeAndMessage, Addressee, ackMessage, receivedMessage; + if (packet != "") { + #ifdef TextSerialOutputForApp + Serial.println(packet.substring(3)); + #else + Serial.print("Received Lora Packet : " + String(packet)); + #endif + if ((packet.substring(0,3) == "\x3c\xff\x01") && (packet.indexOf("TCPIP") == -1) && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) { + #ifndef TextSerialOutputForApp + Serial.print(" ---> APRS LoRa Packet!"); + #endif + Sender = packet.substring(3,packet.indexOf(">")); + if (Sender != Config.callsign) { // avoid listening yourself by digirepeating + AddresseeAndMessage = packet.substring(packet.indexOf("::")+2); + Addressee = AddresseeAndMessage.substring(0,AddresseeAndMessage.indexOf(":")); + Addressee.trim(); + + if (stationMode!=1 && Config.igateRepeatsLoRaPackets && Addressee != Config.callsign) { // if its not for me + String digiRepeatedPacket = DIGI_Utils::generateDigiRepeatedPacket(packet.substring(3), Config.callsign); + if (digiRepeatedPacket != "X") { + delay(500); + LoRa_Utils::sendNewPacket("APRS", digiRepeatedPacket); + } + } + + if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me! + if (AddresseeAndMessage.indexOf("{")>0) { // ack? + ackMessage = "ack" + AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{")+1); + ackMessage.trim(); + delay(4000); + //Serial.println(ackMessage); + for(int i = Sender.length(); i < 9; i++) { + Sender += ' '; + } + LoRa_Utils::sendNewPacket("APRS", Config.callsign + ">APLRG1,RFONLY,WIDE1-1::" + Sender + ":" + ackMessage); + receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1, AddresseeAndMessage.indexOf("{")); + } else { + receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1); + } + if (receivedMessage.indexOf("?") == 0) { + queryMessage = true; + delay(2000); + if (!Config.display.alwaysOn) { + display_toggle(true); + } + LoRa_Utils::sendNewPacket("APRS", QUERY_Utils::process(receivedMessage, Sender, "LoRa")); + lastScreenOn = millis(); + show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + Sender, "TYPE --> QUERY", 0); + } + } + if (!queryMessage) { + aprsPacket = createPacket(packet); + if (!Config.display.alwaysOn) { + display_toggle(true); + } + lastScreenOn = millis(); + upload(aprsPacket); + #ifndef TextSerialOutputForApp + Serial.println(" ---> Uploaded to APRS-IS"); + #endif + STATION_Utils::updateLastHeard(Sender); + Utils::typeOfPacket(aprsPacket, "LoRa-APRS"); + show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); + } + } + } else { + #ifndef TextSerialOutputForApp + Serial.println(" ---> LoRa Packet Ignored (first 3 bytes or TCPIP/NOGATE/RFONLY)\n"); + #endif + } + } + } + + void processAPRSISPacket(String packet) { + String Sender, AddresseeAndMessage, Addressee, receivedMessage; + if (!packet.startsWith("#")){ + if (packet.indexOf("::")>0) { + Sender = packet.substring(0,packet.indexOf(">")); + AddresseeAndMessage = packet.substring(packet.indexOf("::")+2); + Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":")); + Addressee.trim(); + if (Addressee == Config.callsign) { // its for me! + if (AddresseeAndMessage.indexOf("{")>0) { // ack? + String ackMessage = "ack" + AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{")+1); + ackMessage.trim(); + delay(4000); + //Serial.println(ackMessage); + for(int i = Sender.length(); i < 9; i++) { + Sender += ' '; + } + String ackPacket = Config.callsign + ">APLRG1,TCPIP,qAC::" + Sender + ":" + ackMessage;// + "\n"; + upload(ackPacket); + receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1, AddresseeAndMessage.indexOf("{")); + } else { + receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1); + } + if (receivedMessage.indexOf("?") == 0) { + #ifndef TextSerialOutputForApp + Serial.println("Received Query APRS-IS : " + packet); + #endif + String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, "APRSIS"); + //Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n"))); + if (!Config.display.alwaysOn) { + display_toggle(true); + } + lastScreenOn = millis(); + delay(500); + upload(queryAnswer); + SYSLOG_Utils::log("APRSIS Tx", queryAnswer,0,0,0); + fifthLine = "APRS-IS ----> APRS-IS"; + sixthLine = Config.callsign; + for (int j=sixthLine.length();j<9;j++) { + sixthLine += " "; + } + sixthLine += "> " + Sender; + seventhLine = "QUERY = " + receivedMessage; + } + } else { + #ifndef TextSerialOutputForApp + Serial.print("Received from APRS-IS : " + packet); + #endif + if ((stationMode==2 || stationMode==5) && STATION_Utils::wasHeard(Addressee)) { + LoRa_Utils::sendNewPacket("APRS", LoRa_Utils::generatePacket(packet)); + display_toggle(true); + lastScreenOn = millis(); + Utils::typeOfPacket(packet, "APRS-LoRa"); + } + } + show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); + } + } + } + + void loop() { + checkStatus(); + show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0); + while (espClient.connected()) { + Utils::checkDisplayInterval(); + Utils::checkBeaconInterval(); + processLoRaPacket(LoRa_Utils::receivePacket()); + if (espClient.available()) { + String aprsisPacket; + aprsisPacket.concat(espClient.readStringUntil('\r')); + processAPRSISPacket(aprsisPacket); + } + ElegantOTA.loop(); + } + } + } \ No newline at end of file diff --git a/src/bme_utils.cpp b/src/bme_utils.cpp index 376562d..6547c08 100644 --- a/src/bme_utils.cpp +++ b/src/bme_utils.cpp @@ -13,144 +13,144 @@ extern String fifthLine; namespace BME_Utils { - #ifdef BME280Sensor - Adafruit_BME280 bme; - #endif - #ifdef BMP280Sensor - Adafruit_BMP280 bme; - #endif - #ifdef BME680Sensor - Adafruit_BME680 bme; - #endif - - void setup() { - if (Config.bme.active) { - bool status; - status = bme.begin(0x76); // Don't forget to join pins for righ direction on BME280! - if (!status) { - Serial.println("Could not find a valid BME280 or BMP280 sensor, check wiring!"); - show_display("ERROR", "", "BME/BMP sensor active", "but no sensor found..."); - while (1); // sacar esto para que quede pegado si no encuentra BME280 - } else { - #ifdef BME280Sensor - Serial.println("init : BME280 Module ... done!"); - #endif - #ifdef BMP280Sensor - Serial.println("init : BMP280 Module ... done!"); - #endif - #ifdef BME680Sensor - Serial.println("init : BME680 Module ... done!"); - #endif - } - } else { - Serial.println("(BME/BMP sensor not 'active' in 'igate_conf.json')"); - } - } - - String generateTempString(float bmeTemp) { - String strTemp; - strTemp = String((int)bmeTemp); - switch (strTemp.length()) { - case 1: - return "00" + strTemp; - break; - case 2: - return "0" + strTemp; - break; - case 3: - return strTemp; - break; - default: - return "-999"; - } - } - - String generateHumString(float bmeHum) { - String strHum; - strHum = String((int)bmeHum); - switch (strHum.length()) { - case 1: - return "0" + strHum; - break; - case 2: - return strHum; - break; - case 3: - if ((int)bmeHum == 100) { - return "00"; - } else { - return "-99"; - } - break; - default: - return "-99"; - } - } - - String generatePresString(float bmePress) { - String strPress; - strPress = String((int)bmePress); - switch (strPress.length()) { - case 1: - return "000" + strPress + "0"; - break; - case 2: - return "00" + strPress + "0"; - break; - case 3: - return "0" + strPress + "0"; - break; - case 4: - return strPress + "0"; - break; - case 5: - return strPress; - break; - default: - return "-99999"; - } - } - - String readDataSensor() { - String wx, tempStr, humStr, presStr; - float newHum; - - float newTemp = bme.readTemperature(); - #if defined(BME280Sensor) || defined(BME680Sensor) - newHum = bme.readHumidity(); + #ifdef BME280Sensor + Adafruit_BME280 bme; #endif #ifdef BMP280Sensor - newHum = 0; + Adafruit_BMP280 bme; #endif - float newPress = (bme.readPressure() / 100.0F); - #ifdef BME680Sensor - float newGas = bme.gas_resistance / 1000.0; // in Kilo ohms + Adafruit_BME680 bme; #endif - - //bme.readAltitude(SEALEVELPRESSURE_HPA) // this is for approximate Altitude Calculation. - - if (isnan(newTemp) || isnan(newHum) || isnan(newPress)) { - Serial.println("BME/BMP Module data failed"); - wx = ".../...g...t...r...p...P...h..b....."; - fifthLine = ""; - return wx; - } else { - tempStr = generateTempString((newTemp * 1.8) + 32); - #if defined(BME280Sensor) || defined(BME680Sensor) - humStr = generateHumString(newHum); - #endif - #ifdef BMP280Sensor - humStr = ".."; - #endif - presStr = generatePresString(newPress + (HEIGHT_CORRECTION/CORRECTION_FACTOR)); - fifthLine = "BME-> " + String(int(newTemp))+"C " + humStr + "% " + presStr.substring(0,4) + "hPa"; - wx = ".../...g...t" + tempStr + "r...p...P...h" + humStr + "b" + presStr; - #ifdef BME680Sensor - wx += "Gas: " + String(newGas) + "Kohms "; - #endif - return wx; + + void setup() { + if (Config.bme.active) { + bool status; + status = bme.begin(0x76); // Don't forget to join pins for righ direction on BME280! + if (!status) { + Serial.println("Could not find a valid BME280 or BMP280 sensor, check wiring!"); + show_display("ERROR", "", "BME/BMP sensor active", "but no sensor found..."); + while (1); // sacar esto para que quede pegado si no encuentra BME280 + } else { + #ifdef BME280Sensor + Serial.println("init : BME280 Module ... done!"); + #endif + #ifdef BMP280Sensor + Serial.println("init : BMP280 Module ... done!"); + #endif + #ifdef BME680Sensor + Serial.println("init : BME680 Module ... done!"); + #endif + } + } else { + Serial.println("(BME/BMP sensor not 'active' in 'igate_conf.json')"); + } + } + + String generateTempString(float bmeTemp) { + String strTemp; + strTemp = String((int)bmeTemp); + switch (strTemp.length()) { + case 1: + return "00" + strTemp; + break; + case 2: + return "0" + strTemp; + break; + case 3: + return strTemp; + break; + default: + return "-999"; + } + } + + String generateHumString(float bmeHum) { + String strHum; + strHum = String((int)bmeHum); + switch (strHum.length()) { + case 1: + return "0" + strHum; + break; + case 2: + return strHum; + break; + case 3: + if ((int)bmeHum == 100) { + return "00"; + } else { + return "-99"; + } + break; + default: + return "-99"; + } + } + + String generatePresString(float bmePress) { + String strPress; + strPress = String((int)bmePress); + switch (strPress.length()) { + case 1: + return "000" + strPress + "0"; + break; + case 2: + return "00" + strPress + "0"; + break; + case 3: + return "0" + strPress + "0"; + break; + case 4: + return strPress + "0"; + break; + case 5: + return strPress; + break; + default: + return "-99999"; + } + } + + String readDataSensor() { + String wx, tempStr, humStr, presStr; + float newHum; + + float newTemp = bme.readTemperature(); + #if defined(BME280Sensor) || defined(BME680Sensor) + newHum = bme.readHumidity(); + #endif + #ifdef BMP280Sensor + newHum = 0; + #endif + float newPress = (bme.readPressure() / 100.0F); + + #ifdef BME680Sensor + float newGas = bme.gas_resistance / 1000.0; // in Kilo ohms + #endif + + //bme.readAltitude(SEALEVELPRESSURE_HPA) // this is for approximate Altitude Calculation. + + if (isnan(newTemp) || isnan(newHum) || isnan(newPress)) { + Serial.println("BME/BMP Module data failed"); + wx = ".../...g...t...r...p...P...h..b....."; + fifthLine = ""; + return wx; + } else { + tempStr = generateTempString((newTemp * 1.8) + 32); + #if defined(BME280Sensor) || defined(BME680Sensor) + humStr = generateHumString(newHum); + #endif + #ifdef BMP280Sensor + humStr = ".."; + #endif + presStr = generatePresString(newPress + (HEIGHT_CORRECTION/CORRECTION_FACTOR)); + fifthLine = "BME-> " + String(int(newTemp))+"C " + humStr + "% " + presStr.substring(0,4) + "hPa"; + wx = ".../...g...t" + tempStr + "r...p...P...h" + humStr + "b" + presStr; + #ifdef BME680Sensor + wx += "Gas: " + String(newGas) + "Kohms "; + #endif + return wx; + } } - } } \ No newline at end of file diff --git a/src/configuration.cpp b/src/configuration.cpp index a073d34..0d95409 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -3,84 +3,229 @@ #include "configuration.h" #include "display.h" -Configuration::Configuration() { - _filePath = "/igate_conf.json"; - if (!SPIFFS.begin(false)) { - Serial.println("SPIFFS Mount Failed"); - return; - } - readFile(SPIFFS, _filePath.c_str()); -} -void Configuration::readFile(fs::FS &fs, const char *fileName) { + +void Configuration::writeFile() { + Serial.println("Saving config.."); + StaticJsonDocument<1536> data; - File configFile = fs.open(fileName, "r"); - DeserializationError error = deserializeJson(data, configFile); - if (error) { - Serial.println("Failed to read file, using default configuration"); + File configFile = SPIFFS.open("/igate_conf.json", "w"); + + if (wifiAPs[0].ssid != "") { // We don't want to save Auto AP empty SSID + for (int i = 0; i < wifiAPs.size(); i++) { + data["wifi"]["AP"][i]["ssid"] = wifiAPs[i].ssid; + data["wifi"]["AP"][i]["password"] = wifiAPs[i].password; + data["wifi"]["AP"][i]["latitude"] = wifiAPs[i].latitude; + data["wifi"]["AP"][i]["longitude"] = wifiAPs[i].longitude; + } } - JsonArray WiFiArray = data["wifi"]["AP"]; - for (int i = 0; i < WiFiArray.size(); i++) { - WiFi_AP wifiap; - wifiap.ssid = WiFiArray[i]["ssid"].as(); - wifiap.password = WiFiArray[i]["password"].as(); - wifiap.latitude = WiFiArray[i]["latitude"].as(); - wifiap.longitude = WiFiArray[i]["longitude"].as(); + data["wifi"]["autoAP"]["password"] = wifiAutoAP.password; + data["wifi"]["autoAP"]["powerOff"] = wifiAutoAP.powerOff; - wifiAPs.push_back(wifiap); - } + data["callsign"] = callsign; + data["stationMode"] = stationMode; + data["iGateComment"] = iGateComment; - callsign = data["callsign"].as(); - stationMode = data["stationMode"].as(); - iGateComment = data["iGateComment"].as(); - beaconInterval = data["other"]["beaconInterval"].as(); - igateSendsLoRaBeacons = data["other"]["igateSendsLoRaBeacons"].as(); - igateRepeatsLoRaPackets = data["other"]["igateRepeatsLoRaPackets"].as(); - rememberStationTime = data["other"]["rememberStationTime"].as(); - sendBatteryVoltage = data["other"]["sendBatteryVoltage"].as(); - externalVoltageMeasurement = data["other"]["externalVoltageMeasurement"].as(); - externalVoltagePin = data["other"]["externalVoltagePin"].as(); + data["other"]["beaconInterval"] = beaconInterval; + data["other"]["igateSendsLoRaBeacons"] = igateSendsLoRaBeacons; + data["other"]["igateRepeatsLoRaPackets"] = igateRepeatsLoRaPackets; + data["other"]["rememberStationTime"] = rememberStationTime; + data["other"]["sendBatteryVoltage"] = sendBatteryVoltage; + data["other"]["externalVoltageMeasurement"] = externalVoltageMeasurement; + data["other"]["externalVoltagePin"] = externalVoltagePin; - digi.comment = data["digi"]["comment"].as(); - digi.latitude = data["digi"]["latitude"].as(); - digi.longitude = data["digi"]["longitude"].as(); + data["digi"]["comment"] = digi.comment; + data["digi"]["latitude"] = digi.latitude; + data["digi"]["longitude"] = digi.longitude; - aprs_is.passcode = data["aprs_is"]["passcode"].as(); - aprs_is.server = data["aprs_is"]["server"].as(); - aprs_is.port = data["aprs_is"]["port"].as(); - aprs_is.reportingDistance = data["aprs_is"]["reportingDistance"].as(); + data["aprs_is"]["passcode"] = aprs_is.passcode; + data["aprs_is"]["server"] = aprs_is.server; + data["aprs_is"]["port"] = aprs_is.port; + data["aprs_is"]["reportingDistance"] = aprs_is.reportingDistance; - loramodule.iGateFreq = data["lora"]["iGateFreq"].as(); - loramodule.digirepeaterTxFreq = data["lora"]["digirepeaterTxFreq"].as(); - loramodule.digirepeaterRxFreq = data["lora"]["digirepeaterRxFreq"].as(); - loramodule.spreadingFactor = data["lora"]["spreadingFactor"].as(); - loramodule.signalBandwidth = data["lora"]["signalBandwidth"].as(); - loramodule.codingRate4 = data["lora"]["codingRate4"].as(); - loramodule.power = data["lora"]["power"].as(); + data["lora"]["iGateFreq"] = loramodule.iGateFreq; + data["lora"]["digirepeaterTxFreq"] = loramodule.digirepeaterTxFreq; + data["lora"]["digirepeaterRxFreq"] = loramodule.digirepeaterRxFreq; + data["lora"]["spreadingFactor"] = loramodule.spreadingFactor; + data["lora"]["signalBandwidth"] = loramodule.signalBandwidth; + data["lora"]["codingRate4"] = loramodule.codingRate4; + data["lora"]["power"] = loramodule.power; - display.alwaysOn = data["display"]["alwaysOn"].as(); - display.timeout = data["display"]["timeout"].as(); - display.turn180 = data["display"]["turn180"].as(); + data["display"]["alwaysOn"] = display.alwaysOn; + data["display"]["timeout"] = display.timeout; + data["display"]["turn180"] = display.turn180; - syslog.active = data["syslog"]["active"].as(); - syslog.server = data["syslog"]["server"].as(); - syslog.port = data["syslog"]["port"].as(); + data["syslog"]["active"] = syslog.active; + data["syslog"]["server"] = syslog.server; + data["syslog"]["port"] = syslog.port; - bme.active = data["bme"]["active"].as(); + data["bme"]["active"] = bme.active; - ota.username = data["ota"]["username"].as(); - ota.password = data["ota"]["password"].as(); + data["ota"]["username"] = ota.username; + data["ota"]["password"] = ota.password; + serializeJson(data, configFile); + configFile.close(); + + Serial.println("Config saved"); } -void Configuration::validateConfigFile(String currentBeaconCallsign) { - if (currentBeaconCallsign == "NOCALL-10") { - Serial.println("Change Callsign in /data/igate_conf.json"); - show_display("------- ERROR -------", "Change your settings", "on 'igate_conf.json'", "--> File System image", 0); - while (true) { - delay(1000); +bool Configuration::readFile() { + Serial.println("Reading config.."); + + File configFile = SPIFFS.open("/igate_conf.json", "r"); + + if (configFile) { + StaticJsonDocument<1536> data; + + DeserializationError error = deserializeJson(data, configFile); + if (error) { + Serial.println("Failed to read file, using default configuration"); + } + + JsonArray WiFiArray = data["wifi"]["AP"]; + for (int i = 0; i < WiFiArray.size(); i++) { + WiFi_AP wifiap; + wifiap.ssid = WiFiArray[i]["ssid"].as(); + wifiap.password = WiFiArray[i]["password"].as(); + wifiap.latitude = WiFiArray[i]["latitude"].as(); + wifiap.longitude = WiFiArray[i]["longitude"].as(); + + wifiAPs.push_back(wifiap); + } + + wifiAutoAP.password = data["wifi"]["autoAP"]["password"].as(); + wifiAutoAP.powerOff = data["wifi"]["autoAP"]["powerOff"].as(); + + callsign = data["callsign"].as(); + stationMode = data["stationMode"].as(); + iGateComment = data["iGateComment"].as(); + beaconInterval = data["other"]["beaconInterval"].as(); + igateSendsLoRaBeacons = data["other"]["igateSendsLoRaBeacons"].as(); + igateRepeatsLoRaPackets = data["other"]["igateRepeatsLoRaPackets"].as(); + rememberStationTime = data["other"]["rememberStationTime"].as(); + sendBatteryVoltage = data["other"]["sendBatteryVoltage"].as(); + externalVoltageMeasurement = data["other"]["externalVoltageMeasurement"].as(); + externalVoltagePin = data["other"]["externalVoltagePin"].as(); + + digi.comment = data["digi"]["comment"].as(); + digi.latitude = data["digi"]["latitude"].as(); + digi.longitude = data["digi"]["longitude"].as(); + + aprs_is.passcode = data["aprs_is"]["passcode"].as(); + aprs_is.server = data["aprs_is"]["server"].as(); + aprs_is.port = data["aprs_is"]["port"].as(); + aprs_is.reportingDistance = data["aprs_is"]["reportingDistance"].as(); + + loramodule.iGateFreq = data["lora"]["iGateFreq"].as(); + loramodule.digirepeaterTxFreq = data["lora"]["digirepeaterTxFreq"].as(); + loramodule.digirepeaterRxFreq = data["lora"]["digirepeaterRxFreq"].as(); + loramodule.spreadingFactor = data["lora"]["spreadingFactor"].as(); + loramodule.signalBandwidth = data["lora"]["signalBandwidth"].as(); + loramodule.codingRate4 = data["lora"]["codingRate4"].as(); + loramodule.power = data["lora"]["power"].as(); + + display.alwaysOn = data["display"]["alwaysOn"].as(); + display.timeout = data["display"]["timeout"].as(); + display.turn180 = data["display"]["turn180"].as(); + + syslog.active = data["syslog"]["active"].as(); + syslog.server = data["syslog"]["server"].as(); + syslog.port = data["syslog"]["port"].as(); + + bme.active = data["bme"]["active"].as(); + + ota.username = data["ota"]["username"].as(); + ota.password = data["ota"]["password"].as(); + + if (wifiAPs.size() == 0) { // If we don't have any WiFi's from config we need to add "empty" SSID for AUTO AP + WiFi_AP wifiap; + wifiap.ssid = ""; + wifiap.password = ""; + wifiap.latitude = 0.0; + wifiap.longitude = 0.0; + + wifiAPs.push_back(wifiap); + } + configFile.close(); + Serial.println("Config read successfuly"); + return true; + } else { + Serial.println("Config file not found"); + return false; } - } +} + +void Configuration::init() { + WiFi_AP wifiap; + wifiap.ssid = ""; + wifiap.password = ""; + wifiap.latitude = 0.0; + wifiap.longitude = 0.0; + wifiAPs.push_back(wifiap); + + wifiAutoAP.password = "1234567890"; + wifiAutoAP.powerOff = 15; + + callsign = "N0CALL"; + stationMode = 1; + iGateComment = "LoRa_APRS_iGate Development"; + + digi.comment = "LoRa_APRS_iGate Development"; + digi.latitude = 0.0; + digi.longitude = 0.0; + + aprs_is.passcode = "XYZVW"; + aprs_is.server = "rotate.aprs2.net"; + aprs_is.port = 14580; + aprs_is.reportingDistance = 30; + + loramodule.iGateFreq = 433775000; + loramodule.digirepeaterTxFreq = 433775000; + loramodule.digirepeaterRxFreq = 433900000; + loramodule.spreadingFactor = 12; + loramodule.signalBandwidth = 125000; + loramodule.codingRate4 = 5; + loramodule.power = 20; + + display.alwaysOn = true; + display.timeout = 4; + display.turn180 = false; + + syslog.active = false; + syslog.server = "192.168.0.100"; + syslog.port = 514; + + bme.active = false; + + ota.username = ""; + ota.password = ""; + + beaconInterval = 15; + igateSendsLoRaBeacons = false; + igateRepeatsLoRaPackets = false; + rememberStationTime = 30; + sendBatteryVoltage = false; + externalVoltageMeasurement = false; + externalVoltagePin = 34; + + Serial.println("todo escrito"); +} + +Configuration::Configuration() { + if (!SPIFFS.begin(false)) { + Serial.println("SPIFFS Mount Failed"); + return; + } else { + Serial.println("montado"); + } + bool exists = SPIFFS.exists("/igate_conf.json"); + if (!exists) { + init(); + writeFile(); + ESP.restart(); + } + readFile(); } \ No newline at end of file diff --git a/src/configuration.h b/src/configuration.h index 91a0405..04ee554 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -7,61 +7,68 @@ class WiFi_AP { public: - String ssid; - String password; - double latitude; - double longitude; + String ssid; + String password; + double latitude; + double longitude; }; +class WiFi_Auto_AP { +public: + String password; + int powerOff; +}; + + class DIGI { public: - String comment; - double latitude; - double longitude; + String comment; + double latitude; + double longitude; }; class APRS_IS { public: - String passcode; - String server; - int port; - int reportingDistance; + String passcode; + String server; + int port; + int reportingDistance; }; class LoraModule { public: - long iGateFreq; - long digirepeaterTxFreq; - long digirepeaterRxFreq; - int spreadingFactor; - long signalBandwidth; - int codingRate4; - int power; + long iGateFreq; + long digirepeaterTxFreq; + long digirepeaterRxFreq; + int spreadingFactor; + long signalBandwidth; + int codingRate4; + int power; }; class Display { public: - bool alwaysOn; - int timeout; - bool turn180; + bool alwaysOn; + int timeout; + bool turn180; }; class SYSLOG { public: - bool active; - String server; - int port; + bool active; + String server; + int port; }; class BME { public: - bool active; + bool active; }; class OTA { public: - String username; - String password; + String username; + String password; }; @@ -69,31 +76,33 @@ public: class Configuration { public: - String callsign; - int stationMode; - String iGateComment; - int beaconInterval; - bool igateSendsLoRaBeacons; - bool igateRepeatsLoRaPackets; - int rememberStationTime; - bool sendBatteryVoltage; - bool externalVoltageMeasurement; - int externalVoltagePin; - std::vector wifiAPs; - DIGI digi; - APRS_IS aprs_is; - LoraModule loramodule; - Display display; - SYSLOG syslog; - BME bme; - OTA ota; + String callsign; + int stationMode; + String iGateComment; + int beaconInterval; + bool igateSendsLoRaBeacons; + bool igateRepeatsLoRaPackets; + int rememberStationTime; + bool sendBatteryVoltage; + bool externalVoltageMeasurement; + int externalVoltagePin; + std::vector wifiAPs; + WiFi_Auto_AP wifiAutoAP; + DIGI digi; + APRS_IS aprs_is; + LoraModule loramodule; + Display display; + SYSLOG syslog; + BME bme; + OTA ota; - - Configuration(); - void validateConfigFile(String currentBeaconCallsign); + void init(); + void writeFile(); + Configuration(); private: - void readFile(fs::FS &fs, const char *fileName) ; - String _filePath; + bool readFile(); + String _filePath; }; + #endif \ No newline at end of file diff --git a/src/display.cpp b/src/display.cpp index 8b60471..1857015 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -10,156 +10,156 @@ Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); extern Configuration Config; void setup_display() { - Wire.begin(OLED_SDA, OLED_SCL); + Wire.begin(OLED_SDA, OLED_SCL); - if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { - Serial.println(F("SSD1306 allocation failed")); - for(;;); // Don't proceed, loop forever - } - if (Config.display.turn180) { - display.setRotation(2); - } - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(1); - display.setCursor(0, 0); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(1000); + if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { + Serial.println(F("SSD1306 allocation failed")); + for(;;); // Don't proceed, loop forever + } + if (Config.display.turn180) { + display.setRotation(2); + } + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0, 0); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(1000); } void display_toggle(bool toggle) { - if (toggle) { - display.ssd1306_command(SSD1306_DISPLAYON); - } else { - display.ssd1306_command(SSD1306_DISPLAYOFF); - } + if (toggle) { + display.ssd1306_command(SSD1306_DISPLAYON); + } else { + display.ssd1306_command(SSD1306_DISPLAYOFF); + } } void show_display(String line1, int wait) { - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(1); - display.setCursor(0, 0); - display.println(line1); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(wait); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0, 0); + display.println(line1); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(wait); } void show_display(String line1, String line2, int wait) { - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(1); - display.setCursor(0, 0); - display.println(line1); - display.setCursor(0, 8); - display.println(line2); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(wait); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0, 0); + display.println(line1); + display.setCursor(0, 8); + display.println(line2); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(wait); } void show_display(String line1, String line2, String line3, int wait) { - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(1); - display.setCursor(0, 0); - display.println(line1); - display.setCursor(0, 8); - display.println(line2); - display.setCursor(0, 16); - display.println(line3); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(wait); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0, 0); + display.println(line1); + display.setCursor(0, 8); + display.println(line2); + display.setCursor(0, 16); + display.println(line3); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(wait); } void show_display(String line1, String line2, String line3, String line4, int wait) { - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(1); - display.setCursor(0, 0); - display.println(line1); - display.setCursor(0, 8); - display.println(line2); - display.setCursor(0, 16); - display.println(line3); - display.setCursor(0, 24); - display.println(line4); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(wait); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0, 0); + display.println(line1); + display.setCursor(0, 8); + display.println(line2); + display.setCursor(0, 16); + display.println(line3); + display.setCursor(0, 24); + display.println(line4); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(wait); } void show_display(String line1, String line2, String line3, String line4, String line5, int wait) { - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(1); - display.setCursor(0, 0); - display.println(line1); - display.setCursor(0, 8); - display.println(line2); - display.setCursor(0, 16); - display.println(line3); - display.setCursor(0, 24); - display.println(line4); - display.setCursor(0, 32); - display.println(line5); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(wait); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0, 0); + display.println(line1); + display.setCursor(0, 8); + display.println(line2); + display.setCursor(0, 16); + display.println(line3); + display.setCursor(0, 24); + display.println(line4); + display.setCursor(0, 32); + display.println(line5); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(wait); } void show_display(String line1, String line2, String line3, String line4, String line5, String line6, int wait) { - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(1); - display.setCursor(0, 0); - display.println(line1); - display.setCursor(0, 8); - display.println(line2); - display.setCursor(0, 16); - display.println(line3); - display.setCursor(0, 24); - display.println(line4); - display.setCursor(0, 32); - display.println(line5); - display.setCursor(0, 40); - display.println(line6); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(wait); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(1); + display.setCursor(0, 0); + display.println(line1); + display.setCursor(0, 8); + display.println(line2); + display.setCursor(0, 16); + display.println(line3); + display.setCursor(0, 24); + display.println(line4); + display.setCursor(0, 32); + display.println(line5); + display.setCursor(0, 40); + display.println(line6); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(wait); } void show_display(String line1, String line2, String line3, String line4, String line5, String line6, String line7, int wait) { - display.clearDisplay(); - display.setTextColor(WHITE); - display.setTextSize(2); - display.setCursor(0, 0); - display.println(line1); - display.setTextSize(1); - display.setCursor(0, 16); - display.println(line2); - display.setCursor(0, 24); - display.println(line3); - display.setCursor(0, 32); - display.println(line4); - display.setCursor(0, 40); - display.println(line5); - display.setCursor(0, 48); - display.println(line6); - display.setCursor(0, 56); - display.println(line7); - display.ssd1306_command(SSD1306_SETCONTRAST); - display.ssd1306_command(1); - display.display(); - delay(wait); + display.clearDisplay(); + display.setTextColor(WHITE); + display.setTextSize(2); + display.setCursor(0, 0); + display.println(line1); + display.setTextSize(1); + display.setCursor(0, 16); + display.println(line2); + display.setCursor(0, 24); + display.println(line3); + display.setCursor(0, 32); + display.println(line4); + display.setCursor(0, 40); + display.println(line5); + display.setCursor(0, 48); + display.println(line6); + display.setCursor(0, 56); + display.println(line7); + display.ssd1306_command(SSD1306_SETCONTRAST); + display.ssd1306_command(1); + display.display(); + delay(wait); } \ No newline at end of file diff --git a/src/gps_utils.cpp b/src/gps_utils.cpp index c868da7..1c7916b 100644 --- a/src/gps_utils.cpp +++ b/src/gps_utils.cpp @@ -11,188 +11,188 @@ String distance; namespace GPS_Utils { - String double2string(double n, int ndec) { - String r = ""; - if (n>-1 && n<0) { - r = "-"; - } - int v = n; - r += v; - r += '.'; - for (int i=0;i-1 && n<0) { + r = "-"; + } + int v = n; + r += v; + r += '.'; + for (int i=0;ilatitude); - stationLongitude = processLongitudeAPRS(currentWiFi->longitude); - beaconPacket = Config.callsign + ">APLRG1,WIDE1-1"; - if (stationMode!=6) { - beaconPacket += ",qAC"; - } - beaconPacket += ":=" + stationLatitude + "L" + stationLongitude; - if (stationMode==1) { - beaconPacket += "&"; - } else { - beaconPacket += "a"; - } - beaconPacket += Config.iGateComment; - } else { //stationMode 3, 4 and 5 - if (stationMode==5) { + String generateBeacon() { + String stationLatitude, stationLongitude, beaconPacket; + if (stationMode==1 || stationMode==2 || (stationMode==5 && WiFi.status()==WL_CONNECTED && espClient.connected())) { + stationLatitude = processLatitudeAPRS(currentWiFi->latitude); + stationLongitude = processLongitudeAPRS(currentWiFi->longitude); + beaconPacket = Config.callsign + ">APLRG1,WIDE1-1"; + if (stationMode!=6) { + beaconPacket += ",qAC"; + } + beaconPacket += ":=" + stationLatitude + "L" + stationLongitude; + if (stationMode==1) { + beaconPacket += "&"; + } else { + beaconPacket += "a"; + } + beaconPacket += Config.iGateComment; + } else { //stationMode 3, 4 and 5 + if (stationMode==5) { + stationLatitude = processLatitudeAPRS(currentWiFi->latitude); + stationLongitude = processLongitudeAPRS(currentWiFi->longitude); + } else { + stationLatitude = processLatitudeAPRS(Config.digi.latitude); + stationLongitude = processLongitudeAPRS(Config.digi.longitude); + } + beaconPacket = Config.callsign + ">APLRG1,WIDE1-1:=" + stationLatitude + "L" + stationLongitude + "#" + Config.digi.comment; + } + return beaconPacket; + } + + String generateiGateLoRaBeacon() { + String stationLatitude, stationLongitude, beaconPacket; stationLatitude = processLatitudeAPRS(currentWiFi->latitude); stationLongitude = processLongitudeAPRS(currentWiFi->longitude); - } else { - stationLatitude = processLatitudeAPRS(Config.digi.latitude); - stationLongitude = processLongitudeAPRS(Config.digi.longitude); - } - beaconPacket = Config.callsign + ">APLRG1,WIDE1-1:=" + stationLatitude + "L" + stationLongitude + "#" + Config.digi.comment; + beaconPacket = Config.callsign + ">APLRG1,RFONLY:=" + stationLatitude + "L" + stationLongitude; + if (Config.bme.active) { + beaconPacket += "_"; + } else { + beaconPacket += "a"; + } + return beaconPacket; } - return beaconPacket; - } - String generateiGateLoRaBeacon() { - String stationLatitude, stationLongitude, beaconPacket; - stationLatitude = processLatitudeAPRS(currentWiFi->latitude); - stationLongitude = processLongitudeAPRS(currentWiFi->longitude); - beaconPacket = Config.callsign + ">APLRG1,RFONLY:=" + stationLatitude + "L" + stationLongitude; - if (Config.bme.active) { - beaconPacket += "_"; - } else { - beaconPacket += "a"; + double calculateDistanceTo(double latitude, double longitude) { + return TinyGPSPlus::distanceBetween(currentWiFi->latitude,currentWiFi->longitude, latitude, longitude) / 1000.0; } - return beaconPacket; - } - double calculateDistanceTo(double latitude, double longitude) { - return TinyGPSPlus::distanceBetween(currentWiFi->latitude,currentWiFi->longitude, latitude, longitude) / 1000.0; - } + String decodeEncodedGPS(String packet) { + String GPSPacket = packet.substring(packet.indexOf(":!")+3); + String encodedLatitude = GPSPacket.substring(0,4); + String encodedLongtitude = GPSPacket.substring(4,8); - String decodeEncodedGPS(String packet) { - String GPSPacket = packet.substring(packet.indexOf(":!")+3); - String encodedLatitude = GPSPacket.substring(0,4); - String encodedLongtitude = GPSPacket.substring(4,8); - - int Y1 = int(encodedLatitude[0]); - int Y2 = int(encodedLatitude[1]); - int Y3 = int(encodedLatitude[2]); - int Y4 = int(encodedLatitude[3]); - float decodedLatitude = 90.0 - ((((Y1-33) * pow(91,3)) + ((Y2-33) * pow(91,2)) + ((Y3-33) * 91) + Y4-33) / 380926.0); - - int X1 = int(encodedLongtitude[0]); - int X2 = int(encodedLongtitude[1]); - int X3 = int(encodedLongtitude[2]); - int X4 = int(encodedLongtitude[3]); - float decodedLongitude = -180.0 + ((((X1-33) * pow(91,3)) + ((X2-33) * pow(91,2)) + ((X3-33) * 91) + X4-33) / 190463.0); - distance = String(calculateDistanceTo(decodedLatitude, decodedLongitude),1); - return String(decodedLatitude,5) + "N / " + String(decodedLongitude,5) + "E / " + distance + "km"; - } - - String getReceivedGPS(String packet) { - String infoGPS; - if (packet.indexOf(":!") > 10) { - infoGPS = packet.substring(packet.indexOf(":!")+2); - } else if (packet.indexOf(":=") > 10) { - infoGPS = packet.substring(packet.indexOf(":=")+2); + int Y1 = int(encodedLatitude[0]); + int Y2 = int(encodedLatitude[1]); + int Y3 = int(encodedLatitude[2]); + int Y4 = int(encodedLatitude[3]); + float decodedLatitude = 90.0 - ((((Y1-33) * pow(91,3)) + ((Y2-33) * pow(91,2)) + ((Y3-33) * 91) + Y4-33) / 380926.0); + + int X1 = int(encodedLongtitude[0]); + int X2 = int(encodedLongtitude[1]); + int X3 = int(encodedLongtitude[2]); + int X4 = int(encodedLongtitude[3]); + float decodedLongitude = -180.0 + ((((X1-33) * pow(91,3)) + ((X2-33) * pow(91,2)) + ((X3-33) * 91) + X4-33) / 190463.0); + distance = String(calculateDistanceTo(decodedLatitude, decodedLongitude),1); + return String(decodedLatitude,5) + "N / " + String(decodedLongitude,5) + "E / " + distance + "km"; } - String Latitude = infoGPS.substring(0,8); - String Longitude = infoGPS.substring(9,18); - float convertedLatitude, convertedLongitude; - String firstLatPart = Latitude.substring(0,2); - String secondLatPart = Latitude.substring(2,4); - String thirdLatPart = Latitude.substring(Latitude.indexOf(".")+1,Latitude.indexOf(".")+3); - String firstLngPart = Longitude.substring(0,3); - String secondLngPart = Longitude.substring(3,5); - String thirdLngPart = Longitude.substring(Longitude.indexOf(".")+1,Longitude.indexOf(".")+3); - convertedLatitude = firstLatPart.toFloat() + (secondLatPart.toFloat()/60) + (thirdLatPart.toFloat()/(60*100)); - convertedLongitude = firstLngPart.toFloat() + (secondLngPart.toFloat()/60) + (thirdLngPart.toFloat()/(60*100)); - - String LatSign = String(Latitude[7]); - String LngSign = String(Longitude[8]); - if (LatSign == "S") { - convertedLatitude = -convertedLatitude; - } - if (LngSign == "W") { - convertedLongitude = -convertedLongitude; - } - distance = String(calculateDistanceTo(convertedLatitude, convertedLongitude),1); - return String(convertedLatitude,5) + "N / " + String(convertedLongitude,5) + "E / " + distance + "km"; - } + String getReceivedGPS(String packet) { + String infoGPS; + if (packet.indexOf(":!") > 10) { + infoGPS = packet.substring(packet.indexOf(":!")+2); + } else if (packet.indexOf(":=") > 10) { + infoGPS = packet.substring(packet.indexOf(":=")+2); + } + String Latitude = infoGPS.substring(0,8); + String Longitude = infoGPS.substring(9,18); - String getDistance(String packet) { - int encodedBytePosition = 0; - if (packet.indexOf(":!") > 10) { - encodedBytePosition = packet.indexOf(":!") + 14; + float convertedLatitude, convertedLongitude; + String firstLatPart = Latitude.substring(0,2); + String secondLatPart = Latitude.substring(2,4); + String thirdLatPart = Latitude.substring(Latitude.indexOf(".")+1,Latitude.indexOf(".")+3); + String firstLngPart = Longitude.substring(0,3); + String secondLngPart = Longitude.substring(3,5); + String thirdLngPart = Longitude.substring(Longitude.indexOf(".")+1,Longitude.indexOf(".")+3); + convertedLatitude = firstLatPart.toFloat() + (secondLatPart.toFloat()/60) + (thirdLatPart.toFloat()/(60*100)); + convertedLongitude = firstLngPart.toFloat() + (secondLngPart.toFloat()/60) + (thirdLngPart.toFloat()/(60*100)); + + String LatSign = String(Latitude[7]); + String LngSign = String(Longitude[8]); + if (LatSign == "S") { + convertedLatitude = -convertedLatitude; + } + if (LngSign == "W") { + convertedLongitude = -convertedLongitude; + } + distance = String(calculateDistanceTo(convertedLatitude, convertedLongitude),1); + return String(convertedLatitude,5) + "N / " + String(convertedLongitude,5) + "E / " + distance + "km"; } - if (packet.indexOf(":=") > 10) { - encodedBytePosition = packet.indexOf(":=") + 14; + + String getDistance(String packet) { + int encodedBytePosition = 0; + if (packet.indexOf(":!") > 10) { + encodedBytePosition = packet.indexOf(":!") + 14; + } + if (packet.indexOf(":=") > 10) { + encodedBytePosition = packet.indexOf(":=") + 14; + } + if (encodedBytePosition != 0) { + if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H") { + return decodeEncodedGPS(packet); + } else { + return getReceivedGPS(packet); + } + } else { + return " _ / _ / _ "; + } } - if (encodedBytePosition != 0) { - if (String(packet[encodedBytePosition]) == "G" || String(packet[encodedBytePosition]) == "Q" || String(packet[encodedBytePosition]) == "[" || String(packet[encodedBytePosition]) == "H") { - return decodeEncodedGPS(packet); - } else { - return getReceivedGPS(packet); - } - } else { - return " _ / _ / _ "; - } - } } \ No newline at end of file diff --git a/src/lora_utils.cpp b/src/lora_utils.cpp index 36e534c..0f91491 100644 --- a/src/lora_utils.cpp +++ b/src/lora_utils.cpp @@ -26,197 +26,197 @@ float snr; namespace LoRa_Utils { - void setFlag(void) { - #ifdef HAS_SX126X - transmissionFlag = true; - #endif - } + void setFlag(void) { + #ifdef HAS_SX126X + transmissionFlag = true; + #endif + } - void setup() { - #ifdef HAS_SX127X - SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); - LoRa.setPins(LORA_CS, LORA_RST, LORA_IRQ); - long freq; - if (stationMode==1 || stationMode==2) { - freq = Config.loramodule.iGateFreq; - } else { - freq = Config.loramodule.digirepeaterTxFreq; + void setup() { + #ifdef HAS_SX127X + SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); + LoRa.setPins(LORA_CS, LORA_RST, LORA_IRQ); + long freq; + if (stationMode==1 || stationMode==2) { + freq = Config.loramodule.iGateFreq; + } else { + freq = Config.loramodule.digirepeaterTxFreq; + } + if (!LoRa.begin(freq)) { + Serial.println("Starting LoRa failed!"); + show_display("ERROR", "Starting LoRa failed!"); + while (true) { + delay(1000); + } + } + LoRa.setSpreadingFactor(Config.loramodule.spreadingFactor); + LoRa.setSignalBandwidth(Config.loramodule.signalBandwidth); + LoRa.setCodingRate4(Config.loramodule.codingRate4); + LoRa.enableCrc(); + LoRa.setTxPower(Config.loramodule.power); + Serial.print("init : LoRa Module ... done!"); + #endif + #ifdef HAS_SX126X + SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN); + float freq = (float)Config.loramodule.iGateFreq/1000000; + int state = radio.begin(freq); + if (state == RADIOLIB_ERR_NONE) { + Serial.print("Initializing SX126X LoRa Module"); + } else { + Serial.println("Starting LoRa failed!"); + while (true); + } + radio.setDio1Action(setFlag); + radio.setSpreadingFactor(Config.loramodule.spreadingFactor); + radio.setBandwidth(Config.loramodule.signalBandwidth); + radio.setCodingRate(Config.loramodule.codingRate4); + #if defined(ESP32_DIY_1W_LoRa) + radio.setRfSwitchPins(RADIO_RXEN, RADIO_TXEN); + #endif + #if defined(HELTEC_V3) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262) + state = radio.setOutputPower(Config.loramodule.power + 2); // values available: 10, 17, 22 --> if 20 in tracker_conf.json it will be updated to 22. + #endif + #ifdef ESP32_DIY_1W_LoRa_GPS + state = radio.setOutputPower(Config.loramodule.power); // max value 20 (when 20dB in setup 30dB in output as 400M30S has Low Noise Amp) + #endif + if (state == RADIOLIB_ERR_NONE) { + Serial.println("init : LoRa Module ... done!"); + } else { + Serial.println("Starting LoRa failed!"); + while (true); + } + #endif } - if (!LoRa.begin(freq)) { - Serial.println("Starting LoRa failed!"); - show_display("ERROR", "Starting LoRa failed!"); - while (true) { - delay(1000); - } - } - LoRa.setSpreadingFactor(Config.loramodule.spreadingFactor); - LoRa.setSignalBandwidth(Config.loramodule.signalBandwidth); - LoRa.setCodingRate4(Config.loramodule.codingRate4); - LoRa.enableCrc(); - LoRa.setTxPower(Config.loramodule.power); - Serial.print("init : LoRa Module ... done!"); - #endif - #ifdef HAS_SX126X - SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN); - float freq = (float)Config.loramodule.iGateFreq/1000000; - int state = radio.begin(freq); - if (state == RADIOLIB_ERR_NONE) { - Serial.print("Initializing SX126X LoRa Module"); - } else { - Serial.println("Starting LoRa failed!"); - while (true); - } - radio.setDio1Action(setFlag); - radio.setSpreadingFactor(Config.loramodule.spreadingFactor); - radio.setBandwidth(Config.loramodule.signalBandwidth); - radio.setCodingRate(Config.loramodule.codingRate4); - #if defined(ESP32_DIY_1W_LoRa) - radio.setRfSwitchPins(RADIO_RXEN, RADIO_TXEN); - #endif - #if defined(HELTEC_V3) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262) - state = radio.setOutputPower(Config.loramodule.power + 2); // values available: 10, 17, 22 --> if 20 in tracker_conf.json it will be updated to 22. - #endif - #ifdef ESP32_DIY_1W_LoRa_GPS - state = radio.setOutputPower(Config.loramodule.power); // max value 20 (when 20dB in setup 30dB in output as 400M30S has Low Noise Amp) - #endif - if (state == RADIOLIB_ERR_NONE) { - Serial.println("init : LoRa Module ... done!"); - } else { - Serial.println("Starting LoRa failed!"); - while (true); - } - #endif - } - void sendNewPacket(const String &typeOfMessage, const String &newPacket) { - #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) - digitalWrite(internalLedPin,HIGH); - #endif - #ifdef HAS_SX127X - LoRa.beginPacket(); - LoRa.write('<'); - if (typeOfMessage == "APRS") { - LoRa.write(0xFF); - } else if (typeOfMessage == "LoRa") { - LoRa.write(0xF8); + void sendNewPacket(const String &typeOfMessage, const String &newPacket) { + #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) + digitalWrite(internalLedPin,HIGH); + #endif + #ifdef HAS_SX127X + LoRa.beginPacket(); + LoRa.write('<'); + if (typeOfMessage == "APRS") { + LoRa.write(0xFF); + } else if (typeOfMessage == "LoRa") { + LoRa.write(0xF8); + } + LoRa.write(0x01); + LoRa.write((const uint8_t *)newPacket.c_str(), newPacket.length()); + LoRa.endPacket(); + #endif + #ifdef HAS_SX126X + int state = radio.transmit("\x3c\xff\x01" + newPacket); + if (state == RADIOLIB_ERR_NONE) { + //Serial.println(F("success!")); + } else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) { + Serial.println(F("too long!")); + } else if (state == RADIOLIB_ERR_TX_TIMEOUT) { + Serial.println(F("timeout!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + } + #endif + #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) + digitalWrite(internalLedPin,LOW); + #endif + SYSLOG_Utils::log("Tx", newPacket,0,0,0); + Serial.print("---> LoRa Packet Tx : "); + Serial.println(newPacket); } - LoRa.write(0x01); - LoRa.write((const uint8_t *)newPacket.c_str(), newPacket.length()); - LoRa.endPacket(); - #endif - #ifdef HAS_SX126X - int state = radio.transmit("\x3c\xff\x01" + newPacket); - if (state == RADIOLIB_ERR_NONE) { - //Serial.println(F("success!")); - } else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) { - Serial.println(F("too long!")); - } else if (state == RADIOLIB_ERR_TX_TIMEOUT) { - Serial.println(F("timeout!")); - } else { - Serial.print(F("failed, code ")); - Serial.println(state); - } - #endif - #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) - digitalWrite(internalLedPin,LOW); - #endif - SYSLOG_Utils::log("Tx", newPacket,0,0,0); - Serial.print("---> LoRa Packet Tx : "); - Serial.println(newPacket); - } - String generatePacket(String aprsisPacket) { - String firstPart, messagePart; - aprsisPacket.trim(); - firstPart = aprsisPacket.substring(0, aprsisPacket.indexOf(",")); - messagePart = aprsisPacket.substring(aprsisPacket.indexOf("::")+2); - return firstPart + ",TCPIP,WIDE1-1," + Config.callsign + "::" + messagePart; - } + String generatePacket(String aprsisPacket) { + String firstPart, messagePart; + aprsisPacket.trim(); + firstPart = aprsisPacket.substring(0, aprsisPacket.indexOf(",")); + messagePart = aprsisPacket.substring(aprsisPacket.indexOf("::")+2); + return firstPart + ",TCPIP,WIDE1-1," + Config.callsign + "::" + messagePart; + } - String packetSanitization(String packet) { - Serial.println(packet); - if (packet.indexOf("\0")>0) { - packet.replace("\0","000"); + String packetSanitization(String packet) { + Serial.println(packet); + if (packet.indexOf("\0")>0) { + packet.replace("\0",""); + } + if (packet.indexOf("\r")>0) { + packet.replace("\r",""); + } + if (packet.indexOf("\n")>0) { + packet.replace("\n",""); + } + return packet; } - if (packet.indexOf("\r")>0) { - packet.replace("\r","RRR"); - } - if (packet.indexOf("\n")>0) { - packet.replace("\n","NNN"); - } - return packet; - } - String receivePacket() { - String loraPacket = ""; - #ifdef HAS_SX127X - int packetSize = LoRa.parsePacket(); - if (packetSize) { - while (LoRa.available()) { - int inChar = LoRa.read(); - loraPacket += (char)inChar; - } - rssi = LoRa.packetRssi(); - snr = LoRa.packetSnr(); - freqError = LoRa.packetFrequencyError(); + String receivePacket() { + String loraPacket = ""; + #ifdef HAS_SX127X + int packetSize = LoRa.parsePacket(); + if (packetSize) { + while (LoRa.available()) { + int inChar = LoRa.read(); + loraPacket += (char)inChar; + } + rssi = LoRa.packetRssi(); + snr = LoRa.packetSnr(); + freqError = LoRa.packetFrequencyError(); + } + #endif + #ifdef HAS_SX126X + if (transmissionFlag) { + transmissionFlag = false; + radio.startReceive(); + int state = radio.readData(loraPacket); + if (state == RADIOLIB_ERR_NONE) { + Serial.println("LoRa Rx ---> " + loraPacket); + rssi = radio.getRSSI(); + snr = radio.getSNR(); + freqError = radio.getFrequencyError(); + } else if (state == RADIOLIB_ERR_RX_TIMEOUT) { + // timeout occurred while waiting for a packet + } else if (state == RADIOLIB_ERR_CRC_MISMATCH) { + Serial.println(F("CRC error!")); + } else { + Serial.print(F("failed, code ")); + Serial.println(state); + } + } + #endif + // // // // // // + if ((loraPacket.indexOf("\0")!=-1) || (loraPacket.indexOf("\r")!=-1) || (loraPacket.indexOf("\n")!=-1)) { + loraPacket = packetSanitization(loraPacket); + } + // // // // // // + #ifndef TextSerialOutputForApp + if (loraPacket!="") { + Serial.println("(RSSI:" +String(rssi) + " / SNR:" + String(snr) + " / FreqErr:" + String(freqError) + ")"); + } + #endif + if (Config.syslog.active && (stationMode==1 || stationMode==2 || (stationMode==5 && WiFi.status()==WL_CONNECTED)) && loraPacket!="") { + SYSLOG_Utils::log("Rx", loraPacket, rssi, snr, freqError); + } + return loraPacket; } - #endif - #ifdef HAS_SX126X - if (transmissionFlag) { - transmissionFlag = false; - radio.startReceive(); - int state = radio.readData(loraPacket); - if (state == RADIOLIB_ERR_NONE) { - Serial.println("LoRa Rx ---> " + loraPacket); - rssi = radio.getRSSI(); - snr = radio.getSNR(); - freqError = radio.getFrequencyError(); - } else if (state == RADIOLIB_ERR_RX_TIMEOUT) { - // timeout occurred while waiting for a packet - } else if (state == RADIOLIB_ERR_CRC_MISMATCH) { - Serial.println(F("CRC error!")); - } else { - Serial.print(F("failed, code ")); - Serial.println(state); - } - } - #endif - // // // // // // - if ((loraPacket.indexOf("\0")!=-1) || (loraPacket.indexOf("\r")!=-1) || (loraPacket.indexOf("\n")!=-1)) { - loraPacket = packetSanitization(loraPacket); - } - // // // // // // - #ifndef TextSerialOutputForApp - if (loraPacket!="") { - Serial.println("(RSSI:" +String(rssi) + " / SNR:" + String(snr) + " / FreqErr:" + String(freqError) + ")"); - } - #endif - if (Config.syslog.active && (stationMode==1 || stationMode==2 || (stationMode==5 && WiFi.status()==WL_CONNECTED)) && loraPacket!="") { - SYSLOG_Utils::log("Rx", loraPacket, rssi, snr, freqError); - } - return loraPacket; - } - void changeFreqTx() { - delay(500); - #ifdef HAS_SX127X - LoRa.setFrequency(Config.loramodule.digirepeaterTxFreq); - #endif - #ifdef HAS_SX126X - float freq = (float)Config.loramodule.digirepeaterTxFreq/1000000; - radio.setFrequency(freq); - #endif - } + void changeFreqTx() { + delay(500); + #ifdef HAS_SX127X + LoRa.setFrequency(Config.loramodule.digirepeaterTxFreq); + #endif + #ifdef HAS_SX126X + float freq = (float)Config.loramodule.digirepeaterTxFreq/1000000; + radio.setFrequency(freq); + #endif + } - void changeFreqRx() { - delay(500); - #ifdef HAS_SX127X - LoRa.setFrequency(Config.loramodule.digirepeaterRxFreq); - #endif - #ifdef HAS_SX126X - float freq = (float)Config.loramodule.digirepeaterRxFreq/1000000; - radio.setFrequency(freq); - #endif - } + void changeFreqRx() { + delay(500); + #ifdef HAS_SX127X + LoRa.setFrequency(Config.loramodule.digirepeaterRxFreq); + #endif + #ifdef HAS_SX126X + float freq = (float)Config.loramodule.digirepeaterRxFreq/1000000; + radio.setFrequency(freq); + #endif + } } \ No newline at end of file diff --git a/src/ota_utils.cpp b/src/ota_utils.cpp new file mode 100644 index 0000000..ffd176e --- /dev/null +++ b/src/ota_utils.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include "configuration.h" +#include "display.h" +#include "ota_utils.h" + +extern Configuration Config; +extern uint32_t lastScreenOn; + +unsigned long ota_progress_millis = 0; + +namespace OTA_Utils { + + void setup(AsyncWebServer *server) { + if (Config.ota.username != "" && Config.ota.password != "") { + ElegantOTA.begin(server, Config.ota.username.c_str(), Config.ota.password.c_str()); + } else { + ElegantOTA.begin(server); + } + + ElegantOTA.setAutoReboot(true); + ElegantOTA.onStart(onOTAStart); + ElegantOTA.onProgress(onOTAProgress); + ElegantOTA.onEnd(onOTAEnd); + } + + void onOTAStart() { + Serial.println("OTA update started!"); + display_toggle(true); + lastScreenOn = millis(); + show_display("", "", "", " OTA update started!", "", "", "", 1000); + } + + void onOTAProgress(size_t current, size_t final) { + if (millis() - ota_progress_millis > 1000) { + display_toggle(true); + lastScreenOn = millis(); + ota_progress_millis = millis(); + Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final); + show_display("", "", " OTA Progress : " + String((current*100)/final) + "%", "", "", "", "", 100); + } + } + + void onOTAEnd(bool success) { + display_toggle(true); + lastScreenOn = millis(); + if (success) { + Serial.println("OTA update finished successfully!"); + show_display("", "", " OTA update success!", "", " Rebooting ...", "", "", 4000); + } else { + Serial.println("There was an error during OTA update!"); + show_display("", "", " OTA update fail!", "", "", "", "", 4000); + } + } +} \ No newline at end of file diff --git a/src/ota_utils.h b/src/ota_utils.h new file mode 100644 index 0000000..3b1acd3 --- /dev/null +++ b/src/ota_utils.h @@ -0,0 +1,16 @@ +#ifndef OTA_UTILS_H_ +#define OTA_UTILS_H_ + +#include +#include + +namespace OTA_Utils { + + void setup(AsyncWebServer *server); + void onOTAStart(); + void onOTAProgress(size_t current, size_t final); + void onOTAEnd(bool success); + +} + +#endif \ No newline at end of file diff --git a/src/power_utils.cpp b/src/power_utils.cpp index c682702..2a3ddee 100644 --- a/src/power_utils.cpp +++ b/src/power_utils.cpp @@ -20,124 +20,121 @@ extern Configuration Config; namespace POWER_Utils { - bool BatteryIsConnected = false; - String batteryVoltage = ""; - String batteryChargeDischargeCurrent = ""; + bool BatteryIsConnected = false; + String batteryVoltage = ""; + String batteryChargeDischargeCurrent = ""; - void activateMeasurement() { - #if defined(HAS_AXP192) || defined(HAS_AXP2101) - PMU.disableTSPinMeasure(); - PMU.enableBattDetection(); - PMU.enableVbusVoltageMeasure(); - PMU.enableBattVoltageMeasure(); - PMU.enableSystemVoltageMeasure(); - #endif - } - - void activateLoRa() { - #ifdef HAS_AXP192 - PMU.setLDO2Voltage(3300); - PMU.enableLDO2(); - #endif - #ifdef HAS_AXP2101 - PMU.setALDO2Voltage(3300); - PMU.enableALDO2(); - #endif - } - - void deactivateLoRa() { - #ifdef HAS_AXP192 - PMU.disableLDO2(); - #endif - #ifdef HAS_AXP2101 - PMU.disableALDO2(); - #endif - } - - bool begin(TwoWire &port) { - #if defined (TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(ESP32_DIY_LoRa) || defined(HELTEC_V3) || defined(ESP32_DIY_1W_LoRa) - return true; - #endif - - #ifdef HAS_AXP192 - bool result = PMU.begin(Wire, AXP192_SLAVE_ADDRESS, I2C_SDA, I2C_SCL); - if (result) { - PMU.disableDC2(); - PMU.disableLDO2(); - PMU.disableLDO3(); - PMU.setDC1Voltage(3300); - PMU.enableDC1(); - PMU.setProtectedChannel(XPOWERS_DCDC3); - PMU.disableIRQ(XPOWERS_AXP192_ALL_IRQ); + void activateMeasurement() { + #if defined(HAS_AXP192) || defined(HAS_AXP2101) + PMU.disableTSPinMeasure(); + PMU.enableBattDetection(); + PMU.enableVbusVoltageMeasure(); + PMU.enableBattVoltageMeasure(); + PMU.enableSystemVoltageMeasure(); + #endif } - return result; - #endif - #ifdef HAS_AXP2101 - bool result = PMU.begin(Wire, AXP2101_SLAVE_ADDRESS, I2C_SDA, I2C_SCL); - if (result) { - PMU.disableDC2(); - PMU.disableDC3(); - PMU.disableDC4(); - PMU.disableDC5(); - PMU.disableALDO1(); - PMU.disableALDO4(); - PMU.disableBLDO1(); - PMU.disableBLDO2(); - PMU.disableDLDO1(); - PMU.disableDLDO2(); - PMU.setDC1Voltage(3300); - PMU.enableDC1(); - PMU.setButtonBatteryChargeVoltage(3300); - PMU.enableButtonBatteryCharge(); - PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ); + void activateLoRa() { + #ifdef HAS_AXP192 + PMU.setLDO2Voltage(3300); + PMU.enableLDO2(); + #endif + #ifdef HAS_AXP2101 + PMU.setALDO2Voltage(3300); + PMU.enableALDO2(); + #endif } - return result; - #endif - } - void setup() { - Wire.end(); - #ifdef HAS_AXP192 - Wire.begin(SDA, SCL); - if (begin(Wire)) { - Serial.println("AXP192 init done!"); - } else { - Serial.println("AXP192 init failed!"); + void deactivateLoRa() { + #ifdef HAS_AXP192 + PMU.disableLDO2(); + #endif + #ifdef HAS_AXP2101 + PMU.disableALDO2(); + #endif } - activateLoRa(); - activateMeasurement(); - PMU.setChargerTerminationCurr(XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT); - PMU.setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2); - PMU.setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_780MA); - PMU.setSysPowerDownVoltage(2600); - #endif - #ifdef HAS_AXP2101 - Wire.begin(SDA, SCL); - if (begin(Wire)) { - Serial.println("AXP2101 init done!"); - } else { - Serial.println("AXP2101 init failed!"); + bool begin(TwoWire &port) { + #if defined(HAS_AXP192) + bool result = PMU.begin(Wire, AXP192_SLAVE_ADDRESS, I2C_SDA, I2C_SCL); + if (result) { + PMU.disableDC2(); + PMU.disableLDO2(); + PMU.disableLDO3(); + PMU.setDC1Voltage(3300); + PMU.enableDC1(); + PMU.setProtectedChannel(XPOWERS_DCDC3); + PMU.disableIRQ(XPOWERS_AXP192_ALL_IRQ); + } + return result; + #elif defined(HAS_AXP2101) + bool result = PMU.begin(Wire, AXP2101_SLAVE_ADDRESS, I2C_SDA, I2C_SCL); + if (result) { + PMU.disableDC2(); + PMU.disableDC3(); + PMU.disableDC4(); + PMU.disableDC5(); + PMU.disableALDO1(); + PMU.disableALDO4(); + PMU.disableBLDO1(); + PMU.disableBLDO2(); + PMU.disableDLDO1(); + PMU.disableDLDO2(); + PMU.setDC1Voltage(3300); + PMU.enableDC1(); + PMU.setButtonBatteryChargeVoltage(3300); + PMU.enableButtonBatteryCharge(); + PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ); + } + return result; + #else + return true; + #endif } - activateLoRa(); - activateMeasurement(); - PMU.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_200MA); - PMU.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA); - PMU.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2); - PMU.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_800MA); - PMU.setSysPowerDownVoltage(2600); - #endif - } - /*void lowerCpuFrequency() { - #if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2) || defined(ESP32_DIY_LoRa_GPS) || defined(TTGO_T_LORA32_V2_1_GPS) || defined(TTGO_T_LORA32_V2_1_TNC) || defined(ESP32_DIY_1W_LoRa_GPS) || defined(TTGO_T_Beam_V1_2_SX1262) - if (setCpuFrequencyMhz(80)) { - logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "CPU frequency set to 80MHz"); - } else { - logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Main", "CPU frequency unchanged"); + + void setup() { + Wire.end(); + #ifdef HAS_AXP192 + Wire.begin(SDA, SCL); + if (begin(Wire)) { + Serial.println("AXP192 init done!"); + } else { + Serial.println("AXP192 init failed!"); + } + activateLoRa(); + activateMeasurement(); + PMU.setChargerTerminationCurr(XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT); + PMU.setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2); + PMU.setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_780MA); + PMU.setSysPowerDownVoltage(2600); + #endif + + #ifdef HAS_AXP2101 + Wire.begin(SDA, SCL); + if (begin(Wire)) { + Serial.println("AXP2101 init done!"); + } else { + Serial.println("AXP2101 init failed!"); + } + activateLoRa(); + activateMeasurement(); + PMU.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_200MA); + PMU.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA); + PMU.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2); + PMU.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_800MA); + PMU.setSysPowerDownVoltage(2600); + #endif } - #endif - }*/ + + /*void lowerCpuFrequency() { + #if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2) || defined(ESP32_DIY_LoRa_GPS) || defined(TTGO_T_LORA32_V2_1_GPS) || defined(TTGO_T_LORA32_V2_1_TNC) || defined(ESP32_DIY_1W_LoRa_GPS) || defined(TTGO_T_Beam_V1_2_SX1262) + if (setCpuFrequencyMhz(80)) { + logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "CPU frequency set to 80MHz"); + } else { + logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Main", "CPU frequency unchanged"); + } + #endif + }*/ } \ No newline at end of file diff --git a/src/power_utils.h b/src/power_utils.h index b57623b..c7d71df 100644 --- a/src/power_utils.h +++ b/src/power_utils.h @@ -6,15 +6,13 @@ namespace POWER_Utils { - void activateMeasurement(); + void activateMeasurement(); + void activateLoRa(); + void deactivateLoRa(); + bool begin(TwoWire &port); + void setup(); + //void lowerCpuFrequency(); - void activateLoRa(); - void deactivateLoRa(); - - bool begin(TwoWire &port); - void setup(); - - //void lowerCpuFrequency(); } #endif diff --git a/src/query_utils.cpp b/src/query_utils.cpp index fe093f4..a20f518 100644 --- a/src/query_utils.cpp +++ b/src/query_utils.cpp @@ -10,40 +10,40 @@ extern int stationMode; namespace QUERY_Utils { - String process(String query, String station, String queryOrigin) { - String answer; - if (query=="?APRS?" || query=="?aprs?" || query=="?Aprs?" || query=="H" || query=="h" || query=="HELP" || query=="Help" || query=="help" || query=="?") { - answer = "?APRSV ?APRSP ?APRSL ?APRSH ?WHERE callsign"; - } else if (query=="?APRSV" || query=="?aprsv" || query=="?Aprsv") { - answer = "CA2RXU_LoRa_iGate 1.2 v" + versionDate + " sM" + String(stationMode); - } else if (query=="?APRSP" || query=="?aprsp" || query=="?Aprsp") { - answer = "iGate QTH: " + String(currentWiFi->latitude,2) + " " + String(currentWiFi->longitude,2); - } else if (query=="?APRSL" || query=="?aprsl" || query=="?Aprsl") { - if (lastHeardStation.size() == 0) { - answer = "No Station Listened in the last " + String(Config.rememberStationTime) + "min."; - } else { - for (int i=0; ilatitude,2) + " " + String(currentWiFi->longitude,2); + } else if (query=="?APRSL" || query=="?aprsl" || query=="?Aprsl") { + if (lastHeardStation.size() == 0) { + answer = "No Station Listened in the last " + String(Config.rememberStationTime) + "min."; + } else { + for (int i=0; i posicion + Serial.println("estaciones escuchadas directo (ultimos 30 min)"); + answer = "?WHERE on development 73!"; + } + for(int i = station.length(); i < 9; i++) { + station += ' '; + } + if (queryOrigin == "APRSIS") { + return Config.callsign + ">APLRG1,TCPIP,qAC::" + station + ":" + answer;// + "\n"; + } else { //} if (queryOrigin == "LoRa") { + return Config.callsign + ">APLRG1,RFONLY,WIDE1-1::" + station + ":" + answer; } - answer.trim(); - } - } else if (query.indexOf("?APRSH") == 0 || query.indexOf("?aprsh") == 0 || query.indexOf("?Aprsh") == 0) { - // sacar callsign despues de ?APRSH - Serial.println("escuchaste a X estacion? en las ultimas 24 o 8 horas?"); - answer = "APRSH on development 73!"; - } else if (query.indexOf("?WHERE") == 0) { - // agregar callsign para completar donde esta X callsign --> posicion - Serial.println("estaciones escuchadas directo (ultimos 30 min)"); - answer = "?WHERE on development 73!"; } - for(int i = station.length(); i < 9; i++) { - station += ' '; - } - if (queryOrigin == "APRSIS") { - return Config.callsign + ">APLRG1,TCPIP,qAC::" + station + ":" + answer;// + "\n"; - } else { //} if (queryOrigin == "LoRa") { - return Config.callsign + ">APLRG1,RFONLY,WIDE1-1::" + station + ":" + answer; - } - } } \ No newline at end of file diff --git a/src/station_utils.cpp b/src/station_utils.cpp index 53bbf68..c45f754 100644 --- a/src/station_utils.cpp +++ b/src/station_utils.cpp @@ -12,93 +12,93 @@ extern String fourthLine; namespace STATION_Utils { - void deleteNotHeard() { - for (int i=0; i Listened Station"); - return true; - } + #ifndef TextSerialOutputForApp ////// This is just for debugging + Serial.print("Stations Near (last " + String(Config.rememberStationTime) + " minutes): "); + for (int k=0; k Station not Heard for last 30 min (Not Tx)\n"); - return false; - } - void checkBuffer() { - for (int i=0; i Listened Station"); + return true; + } + } + Serial.println(" ---> Station not Heard for last 30 min (Not Tx)\n"); + return false; } - packetBuffer.clear(); - for (int j=0; j") == -1) && (packet.indexOf(":`") == -1)) { - String sender = packet.substring(3,packet.indexOf(">")); - String tempAddressee = packet.substring(packet.indexOf("::") + 2); - String addressee = tempAddressee.substring(0,tempAddressee.indexOf(":")); - addressee.trim(); - String message = tempAddressee.substring(tempAddressee.indexOf(":")+1); - //Serial.println(String(millis()) + "," + sender + "," + addressee + "," + message); - packetBuffer.push_back(String(millis()) + "," + sender + "," + addressee + "," + message); - checkBuffer(); + // BORRAR ESTO !! + for (int i=0; i") == -1) && (packet.indexOf(":`") == -1)) { + String sender = packet.substring(3,packet.indexOf(">")); + String tempAddressee = packet.substring(packet.indexOf("::") + 2); + String addressee = tempAddressee.substring(0,tempAddressee.indexOf(":")); + addressee.trim(); + String message = tempAddressee.substring(tempAddressee.indexOf(":")+1); + //Serial.println(String(millis()) + "," + sender + "," + addressee + "," + message); + packetBuffer.push_back(String(millis()) + "," + sender + "," + addressee + "," + message); + checkBuffer(); + } } - } } \ No newline at end of file diff --git a/src/utils.cpp b/src/utils.cpp index fa8a444..233e544 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,7 +1,3 @@ -#include -#include -#include -#include #include #include "configuration.h" #include "station_utils.h" @@ -16,8 +12,6 @@ #include "display.h" #include "utils.h" -AsyncWebServer server(80); - extern WiFiClient espClient; extern Configuration Config; extern String versionDate; @@ -40,21 +34,13 @@ extern int rssi; extern float snr; extern int freqError; extern String distance; -extern String versionDate; extern uint32_t lastWiFiCheck; extern bool WiFiConnect; +extern bool WiFiConnected; -String name; -String email; - -unsigned long ota_progress_millis = 0; namespace Utils { - void notFound(AsyncWebServerRequest *request) { - request->send(404, "text/plain", "Not found"); - } - void processStatus() { String status = Config.callsign + ">APLRG1,WIDE1-1"; if (stationMode==1 || stationMode==2 || (stationMode==5 && WiFi.status() == WL_CONNECTED)) { @@ -77,7 +63,11 @@ namespace Utils { } String getLocalIP() { - return "IP : " + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]); + if (!WiFiConnected) { + return "IP : 192.168.4.1"; + } else { + return "IP : " + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]); + } } void setupDisplay() { @@ -85,8 +75,8 @@ namespace Utils { #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) digitalWrite(internalLedPin,HIGH); #endif - Serial.println("\nStarting iGate: " + Config.callsign + " Version: " + versionDate); - show_display(" LoRa APRS", "", " ( iGATE )", "", "", "Richonguzman / CA2RXU", " " + versionDate, 4000); + Serial.println("\nStarting Station: " + Config.callsign + " Version: " + versionDate); + show_display(" LoRa APRS", "", " ( iGATE & Digi )", "", "", "Richonguzman / CA2RXU", " " + versionDate, 4000); #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) digitalWrite(internalLedPin,LOW); #endif @@ -254,9 +244,11 @@ namespace Utils { void validateDigiFreqs() { if (stationMode==4) { if (abs(Config.loramodule.digirepeaterTxFreq - Config.loramodule.digirepeaterRxFreq) < 125000) { - Serial.println("Tx Freq less than 125kHz from Rx Freq ---> NOT VALID, check 'data/igate_conf.json'"); - show_display("Tx Freq is less than ", "125kHz from Rx Freq", "change it on : /data/", "igate_conf.json", 0); - while (1); + Serial.println("Tx Freq less than 125kHz from Rx Freq ---> NOT VALID"); + show_display("Tx Freq is less than ", "125kHz from Rx Freq", "device will autofix", "and then reboot", 1000); + Config.loramodule.digirepeaterTxFreq = Config.loramodule.digirepeaterRxFreq; // Inform about that but then change the digirepeaterTxFreq to digirepeaterRxFreq and reset the device + Config.writeFile(); + ESP.restart(); } } } @@ -318,83 +310,4 @@ namespace Utils { } } - void onOTAStart() { - Serial.println("OTA update started!"); - display_toggle(true); - lastScreenOn = millis(); - show_display("", "", "", " OTA update started!", "", "", "", 1000); - } - - void onOTAProgress(size_t current, size_t final) { - if (millis() - ota_progress_millis > 1000) { - display_toggle(true); - lastScreenOn = millis(); - ota_progress_millis = millis(); - Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final); - show_display("", "", " OTA Progress : " + String((current*100)/final) + "%", "", "", "", "", 100); - } - } - - void onOTAEnd(bool success) { - display_toggle(true); - lastScreenOn = millis(); - if (success) { - Serial.println("OTA update finished successfully!"); - show_display("", "", " OTA update success!", "", " Rebooting ...", "", "", 4000); - } else { - Serial.println("There was an error during OTA update!"); - show_display("", "", " OTA update fail!", "", "", "", "", 4000); - } - } - - void startServer() { - if (stationMode==1 || stationMode==2 || (stationMode==5 && WiFi.status()==WL_CONNECTED)) { - server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "text/plain", "Hi " + Config.callsign + ", \n\nthis is your (Richonguzman/CA2RXU) LoRa APRS iGate , version " + versionDate + "\n\nTo update your firmware or filesystem go to: http://" + getLocalIP().substring(getLocalIP().indexOf(":")+3) + "/update\n\n\n73!"); - }); - - server.on("/test", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(SPIFFS, "/test_info_1.html", "text/html");//"application/json"); - }); - - server.on("/test2", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(SPIFFS, "/test1.html", "text/html"); - }); - - if (Config.ota.username != "" && Config.ota.password != "") { - ElegantOTA.begin(&server, Config.ota.username.c_str(), Config.ota.password.c_str()); - } else { - ElegantOTA.begin(&server); - } - ElegantOTA.setAutoReboot(true); - ElegantOTA.onStart(onOTAStart); - ElegantOTA.onProgress(onOTAProgress); - ElegantOTA.onEnd(onOTAEnd); - - server.on("/process_form.php", HTTP_POST, [](AsyncWebServerRequest *request){ - String message; - - if (request->hasParam("email", true) && request->hasParam("name", true)) { - email = request->getParam("email", true)->value(); - name = request->getParam("name", true)->value(); - - String responseMessage = "Received EMAIL: " + email + ", NAME: " + name; - - // Assuming you're sending an HTTP response, for example, in an HTTP server context - request->send(200, "text/plain", responseMessage); - } else { - // Handle the case where one or both parameters are missing - request->send(400, "text/plain", "Both EMAIL and NAME parameters are required."); - } - }); - - server.onNotFound(notFound); - - server.serveStatic("/", SPIFFS, "/"); - - server.begin(); - Serial.println("init : OTA Server ... done!"); - } - } - } \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index 701ea1d..4cefb9c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -17,7 +17,6 @@ namespace Utils { void onOTAStart(); void onOTAProgress(size_t current, size_t final); void onOTAEnd(bool success); - void startServer(); } diff --git a/src/web_utils.cpp b/src/web_utils.cpp new file mode 100644 index 0000000..e9f0647 --- /dev/null +++ b/src/web_utils.cpp @@ -0,0 +1,192 @@ +#include "ota_utils.h" +#include "web_utils.h" +#include "configuration.h" + +extern Configuration Config; + +extern const char web_index_html[] asm("_binary_data_embed_index_html_gz_start"); +extern const char web_index_html_end[] asm("_binary_data_embed_index_html_gz_end"); +extern const size_t web_index_html_len = web_index_html_end - web_index_html; + +extern const char web_style_css[] asm("_binary_data_embed_style_css_gz_start"); +extern const char web_style_css_end[] asm("_binary_data_embed_style_css_gz_end"); +extern const size_t web_style_css_len = web_style_css_end - web_style_css; + +extern const char web_script_js[] asm("_binary_data_embed_script_js_gz_start"); +extern const char web_script_js_end[] asm("_binary_data_embed_script_js_gz_end"); +extern const size_t web_script_js_len = web_script_js_end - web_script_js; + +extern const char web_bootstrap_css[] asm("_binary_data_embed_bootstrap_css_gz_start"); +extern const char web_bootstrap_css_end[] asm("_binary_data_embed_bootstrap_css_gz_end"); +extern const size_t web_bootstrap_css_len = web_bootstrap_css_end - web_bootstrap_css; + +extern const char web_bootstrap_js[] asm("_binary_data_embed_bootstrap_js_gz_start"); +extern const char web_bootstrap_js_end[] asm("_binary_data_embed_bootstrap_js_gz_end"); +extern const size_t web_bootstrap_js_len = web_bootstrap_js_end - web_bootstrap_js; + +namespace WEB_Utils { + + AsyncWebServer server(80); + + void loop() { + + } + + void handleNotFound(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse(404, "text/plain", "Not found"); + response->addHeader("Cache-Control", "max-age=3600"); + request->send(response); + } + + void handleStatus(AsyncWebServerRequest *request) { + request->send(200, "text/plain", "OK"); + } + + void handleHome(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", (const uint8_t*)web_index_html, web_index_html_len); + response->addHeader("Content-Encoding", "gzip"); + request->send(response); + } + + void handleReadConfiguration(AsyncWebServerRequest *request) { + File file = SPIFFS.open("/igate_conf.json"); + + String fileContent; + while(file.available()){ + fileContent += String((char)file.read()); + } + + request->send(200, "application/json", fileContent); + } + + void handleWriteConfiguration(AsyncWebServerRequest *request) { + Serial.println("Got new config from www"); + + int networks = request->getParam("wifi.APs", true)->value().toInt(); + + Config.wifiAPs = {}; + + for (int i=0; igetParam("wifi.AP." + String(i) + ".ssid", true)->value(); + wifiap.password = request->getParam("wifi.AP." + String(i) + ".password", true)->value(); + wifiap.latitude = request->getParam("wifi.AP." + String(i) + ".latitude", true)->value().toDouble(); + wifiap.longitude = request->getParam("wifi.AP." + String(i) + ".longitude", true)->value().toDouble(); + + Config.wifiAPs.push_back(wifiap); + } + + Config.callsign = request->getParam("callsign", true)->value(); + Config.stationMode = request->getParam("stationMode", true)->value().toInt(); + Config.iGateComment = request->getParam("iGateComment", true)->value(); + + Config.wifiAutoAP.password = request->getParam("wifi.autoAP.password", true)->value(); + Config.wifiAutoAP.powerOff = request->getParam("wifi.autoAP.powerOff", true)->value().toInt(); + + Config.digi.comment = request->getParam("digi.comment", true)->value(); + Config.digi.latitude = request->getParam("digi.latitude", true)->value().toDouble(); + Config.digi.longitude = request->getParam("digi.longitude", true)->value().toDouble(); + + Config.aprs_is.passcode = request->getParam("aprs_is.passcode", true)->value(); + Config.aprs_is.server = request->getParam("aprs_is.server", true)->value(); + Config.aprs_is.port = request->getParam("aprs_is.port", true)->value().toInt(); + Config.aprs_is.reportingDistance = request->getParam("aprs_is.reportingDistance", true)->value().toInt(); + + Config.loramodule.iGateFreq = request->getParam("lora.iGateFreq", true)->value().toInt(); + + if (request->hasParam("lora.digirepeaterTxFreq", true)) { + Config.loramodule.digirepeaterTxFreq = request->getParam("lora.digirepeaterTxFreq", true)->value().toInt(); + } + + if (request->hasParam("lora.digirepeaterRxFreq", true)) { + Config.loramodule.digirepeaterRxFreq = request->getParam("lora.digirepeaterRxFreq", true)->value().toInt(); + } + + Config.loramodule.spreadingFactor = request->getParam("lora.spreadingFactor", true)->value().toInt(); + Config.loramodule.signalBandwidth = request->getParam("lora.signalBandwidth", true)->value().toInt(); + Config.loramodule.codingRate4 = request->getParam("lora.codingRate4", true)->value().toInt(); + Config.loramodule.power = request->getParam("lora.power", true)->value().toInt(); + + Config.display.alwaysOn = request->hasParam("display.alwaysOn", true); + + if (!Config.display.alwaysOn) { + Config.display.timeout = request->getParam("display.timeout", true)->value().toInt(); + } + + Config.display.turn180 = request->hasParam("display.turn180", true); + + Config.syslog.active = request->hasParam("syslog.active", true); + + if (Config.syslog.active) { + Config.syslog.server = request->getParam("syslog.server", true)->value(); + Config.syslog.port = request->getParam("syslog.port", true)->value().toInt(); + } + + Config.bme.active = request->hasParam("bme.active", true); + + Config.ota.username = request->getParam("ota.username", true)->value(); + Config.ota.password = request->getParam("ota.password", true)->value(); + + Config.beaconInterval = request->getParam("other.beaconInterval", true)->value().toInt(); + Config.igateSendsLoRaBeacons = request->hasParam("other.igateSendsLoRaBeacons", true); + Config.igateRepeatsLoRaPackets = request->hasParam("other.igateRepeatsLoRaPackets", true); + Config.rememberStationTime = request->getParam("other.rememberStationTime", true)->value().toInt(); + Config.sendBatteryVoltage = request->hasParam("other.sendBatteryVoltage", true); + Config.externalVoltageMeasurement = request->hasParam("other.externalVoltageMeasurement", true); + + if (Config.externalVoltageMeasurement) { + Config.externalVoltagePin = request->getParam("other.externalVoltagePin", true)->value().toInt(); + } + + Config.writeFile(); + + AsyncWebServerResponse *response = request->beginResponse(302, "text/html", ""); + response->addHeader("Location", "/"); + request->send(response); + + ESP.restart(); + } + + void handleStyle(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", (const uint8_t*)web_style_css, web_style_css_len); + response->addHeader("Content-Encoding", "gzip"); + request->send(response); + } + + void handleScript(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", (const uint8_t*)web_script_js, web_script_js_len); + response->addHeader("Content-Encoding", "gzip"); + request->send(response); + } + + void handleBootstrapStyle(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", (const uint8_t*)web_bootstrap_css, web_bootstrap_css_len); + response->addHeader("Content-Encoding", "gzip"); + response->addHeader("Cache-Control", "max-age=3600"); + request->send(response); + } + + void handleBootstrapScript(AsyncWebServerRequest *request) { + AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", (const uint8_t*)web_bootstrap_js, web_bootstrap_js_len); + response->addHeader("Content-Encoding", "gzip"); + response->addHeader("Cache-Control", "max-age=3600"); + request->send(response); + } + + void setup() { + server.on("/", HTTP_GET, handleHome); + server.on("/status", HTTP_GET, handleStatus); + server.on("/configuration.json", HTTP_GET, handleReadConfiguration); + server.on("/configuration.json", HTTP_POST, handleWriteConfiguration); + server.on("/style.css", HTTP_GET, handleStyle); + server.on("/script.js", HTTP_GET, handleScript); + server.on("/bootstrap.css", HTTP_GET, handleBootstrapStyle); + server.on("/bootstrap.js", HTTP_GET, handleBootstrapScript); + + OTA_Utils::setup(&server); // Include OTA Updater for WebServer + + server.onNotFound(handleNotFound); + + server.begin(); + } +} diff --git a/src/web_utils.h b/src/web_utils.h new file mode 100644 index 0000000..c9dd7b4 --- /dev/null +++ b/src/web_utils.h @@ -0,0 +1,31 @@ +#ifndef WEB_UTILS_H_ +#define WEB_UTILS_H_ + +#include +#include +#include +#include +#include + + +namespace WEB_Utils { + + void loop(); + + void handleNotFound(AsyncWebServerRequest *request); + void handleStatus(AsyncWebServerRequest *request); + void handleHome(AsyncWebServerRequest *request); + + //void handleReadConfiguration(AsyncWebServerRequest *request); + //void handleWriteConfiguration(AsyncWebServerRequest *request); + + void handleStyle(AsyncWebServerRequest *request); + void handleScript(AsyncWebServerRequest *request); + void handleBootstrapStyle(AsyncWebServerRequest *request); + void handleBootstrapScript(AsyncWebServerRequest *request); + + void setup(); + +} + +#endif \ No newline at end of file diff --git a/src/wifi_utils.cpp b/src/wifi_utils.cpp index 777d952..e3a3284 100644 --- a/src/wifi_utils.cpp +++ b/src/wifi_utils.cpp @@ -10,93 +10,141 @@ extern int myWiFiAPIndex; extern int myWiFiAPSize; extern int stationMode; extern uint32_t previousWiFiMillis; +extern bool WiFiConnected; +extern long WiFiAutoAPTime; +extern bool WiFiAutoAPStarted; namespace WIFI_Utils { - void checkWiFi() { - if ((WiFi.status() != WL_CONNECTED) && ((millis() - previousWiFiMillis) >= 30*1000)) { - Serial.print(millis()); - Serial.println("Reconnecting to WiFi..."); - WiFi.disconnect(); - WiFi.reconnect(); - previousWiFiMillis = millis(); - } - } - - void startWiFi() { - int wifiCounter = 0; - WiFi.mode(WIFI_STA); - WiFi.disconnect(); - delay(500); - unsigned long start = millis(); - show_display("", "", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0); - Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ..."); - WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str()); - while (WiFi.status() != WL_CONNECTED && wifiCounter<2) { - delay(500); - #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) - digitalWrite(internalLedPin,HIGH); - #endif - Serial.print('.'); - delay(500); - #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) - digitalWrite(internalLedPin,LOW); - #endif - if ((millis() - start) > 10000){ - delay(1000); - if(myWiFiAPIndex >= (myWiFiAPSize-1)) { - myWiFiAPIndex = 0; - if (stationMode==5) { - wifiCounter++; - } - } else { - myWiFiAPIndex++; + void checkWiFi() { + if ((WiFi.status() != WL_CONNECTED) && ((millis() - previousWiFiMillis) >= 30*1000) && !WiFiAutoAPStarted) { + Serial.print(millis()); + Serial.println("Reconnecting to WiFi..."); + WiFi.disconnect(); + WiFi.reconnect(); + previousWiFiMillis = millis(); } - currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; - start = millis(); - Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ..."); - show_display("", "", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0); - WiFi.disconnect(); - WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str()); - } } - #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) - digitalWrite(internalLedPin,LOW); - #endif - if (WiFi.status() == WL_CONNECTED) { - Serial.print("Connected as "); - Serial.println(WiFi.localIP()); - show_display("", "", " Connected!!", "" , " loading ...", 1000); - } else if (WiFi.status() != WL_CONNECTED && stationMode==5) { - Serial.println("\nNot connected to WiFi! (DigiRepeater Mode)"); - show_display("", "", " WiFi Not Connected!", " DigiRepeater MODE" , " loading ...", 2000); - } - } - void setup() { - if (stationMode==1 || stationMode==2) { - if (stationMode==1) { - Serial.println("stationMode ---> iGate (only Rx)"); - } else { - Serial.println("stationMode ---> iGate (Rx + Tx)"); - } - startWiFi(); - btStop(); - } else if (stationMode==3 || stationMode==4) { - if (stationMode==3) { - Serial.println("stationMode ---> DigiRepeater (Rx freq == Tx freq)"); - } else { - Serial.println("stationMode ---> DigiRepeater (Rx freq != Tx freq)"); - } - WiFi.mode(WIFI_OFF); - btStop(); - } else if (stationMode==5) { - Serial.println("stationMode ---> iGate when Wifi/APRS available (DigiRepeater when not)"); - } else { - Serial.println("stationMode ---> NOT VALID, check '/data/igate_conf.json'"); - show_display("------- ERROR -------", "stationMode Not Valid", "change it on : /data/", "igate_conf.json", 0); - while (1); + void startWiFi() { + bool startAP = false; + if (currentWiFi->ssid == "") { + startAP = true; + } else { + int wifiCounter = 0; + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + delay(500); + unsigned long start = millis(); + show_display("", "", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0); + Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ..."); + WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str()); + while (WiFi.status() != WL_CONNECTED && wifiCounter 10000){ + delay(1000); + if(myWiFiAPIndex >= (myWiFiAPSize-1)) { + myWiFiAPIndex = 0; + if (stationMode==5) { + wifiCounter++; + } + } else { + myWiFiAPIndex++; + } + wifiCounter++; + currentWiFi = &Config.wifiAPs[myWiFiAPIndex]; + start = millis(); + Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ..."); + show_display("", "", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0); + WiFi.disconnect(); + WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str()); + } + } + } + #if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) + digitalWrite(internalLedPin,LOW); + #endif + if (WiFi.status() == WL_CONNECTED) { + Serial.print("Connected as "); + Serial.println(WiFi.localIP()); + show_display("", "", " Connected!!", "" , " loading ...", 1000); + } else if (WiFi.status() != WL_CONNECTED) { + startAP = true; + + Serial.println("\nNot connected to WiFi! Starting Auto AP"); + show_display("", "", " WiFi Not Connected!", "" , " loading ...", 1000); + } + WiFiConnected = !startAP; + if (startAP) { + Serial.println("\nNot connected to WiFi! Starting Auto AP"); + show_display("", "", " Starting Auto AP", " Please connect to it " , " loading ...", 1000); + + WiFi.mode(WIFI_MODE_NULL); + + WiFi.mode(WIFI_AP); + WiFi.softAP(Config.callsign + " AP", "1234567890"); + + WiFiAutoAPTime = millis(); + WiFiAutoAPStarted = true; + } + } + + void checkIfAutoAPShouldPowerOff() { + if (WiFiAutoAPStarted && Config.wifiAutoAP.powerOff > 0) { + if (WiFi.softAPgetStationNum() > 0) { + WiFiAutoAPTime = 0; + } else { + if (WiFiAutoAPTime == 0) { + WiFiAutoAPTime = millis(); + } else if ((millis() - WiFiAutoAPTime) > Config.wifiAutoAP.powerOff * 60 * 1000) { + Serial.println("Stopping auto AP"); + + WiFiAutoAPStarted = false; + WiFi.softAPdisconnect(true); + + Serial.println("Auto AP stopped (timeout)"); + } + } + } + } + + void setup() { + if (stationMode==1 || stationMode==2) { + if (stationMode==1) { + Serial.println("stationMode ---> iGate (only Rx)"); + } else { + Serial.println("stationMode ---> iGate (Rx + Tx)"); + } + startWiFi(); + btStop(); + } else if (stationMode==3 || stationMode==4) { + if (stationMode==3) { + Serial.println("stationMode ---> DigiRepeater (Rx freq == Tx freq)"); + } else { + Serial.println("stationMode ---> DigiRepeater (Rx freq != Tx freq)"); + } + WiFi.mode(WIFI_OFF); + btStop(); + } else if (stationMode==5) { + Serial.println("stationMode ---> iGate when Wifi/APRS available (DigiRepeater when not)"); + } else { + Serial.println("stationMode ---> NOT VALID"); + show_display("------- ERROR -------", "stationMode Not Valid", "device will autofix", "and then reboot", 1000); + + Config.stationMode = 1; // Inform about that but then change the station mode to 1 and reset the device + Config.writeFile(); + + ESP.restart(); + } + } - } } \ No newline at end of file diff --git a/src/wifi_utils.h b/src/wifi_utils.h index fc4c5e9..d74eedf 100644 --- a/src/wifi_utils.h +++ b/src/wifi_utils.h @@ -7,7 +7,9 @@ namespace WIFI_Utils { void checkWiFi(); void startWiFi(); + void checkIfAutoAPShouldPowerOff(); void setup(); + }