feat: web configurator

This commit is contained in:
SQ2CPA 2024-02-24 14:09:05 +01:00
parent d069c201d9
commit 3361b6d8e4
20 changed files with 1798 additions and 1378 deletions

View file

@ -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<String> lastHeardStation;
@ -46,55 +51,63 @@ std::vector<String> 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();
}
}
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}
}
}

View file

@ -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<String>();
wifiap.password = WiFiArray[i]["password"].as<String>();
wifiap.latitude = WiFiArray[i]["latitude"].as<double>();
wifiap.longitude = WiFiArray[i]["longitude"].as<double>();
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<String>();
stationMode = data["stationMode"].as<int>();
iGateComment = data["iGateComment"].as<String>();
beaconInterval = data["other"]["beaconInterval"].as<int>();
igateSendsLoRaBeacons = data["other"]["igateSendsLoRaBeacons"].as<bool>();
igateRepeatsLoRaPackets = data["other"]["igateRepeatsLoRaPackets"].as<bool>();
rememberStationTime = data["other"]["rememberStationTime"].as<int>();
sendBatteryVoltage = data["other"]["sendBatteryVoltage"].as<bool>();
externalVoltageMeasurement = data["other"]["externalVoltageMeasurement"].as<bool>();
externalVoltagePin = data["other"]["externalVoltagePin"].as<int>();
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<String>();
digi.latitude = data["digi"]["latitude"].as<double>();
digi.longitude = data["digi"]["longitude"].as<double>();
data["digi"]["comment"] = digi.comment;
data["digi"]["latitude"] = digi.latitude;
data["digi"]["longitude"] = digi.longitude;
aprs_is.passcode = data["aprs_is"]["passcode"].as<String>();
aprs_is.server = data["aprs_is"]["server"].as<String>();
aprs_is.port = data["aprs_is"]["port"].as<int>();
aprs_is.reportingDistance = data["aprs_is"]["reportingDistance"].as<int>();
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<long>();
loramodule.digirepeaterTxFreq = data["lora"]["digirepeaterTxFreq"].as<long>();
loramodule.digirepeaterRxFreq = data["lora"]["digirepeaterRxFreq"].as<long>();
loramodule.spreadingFactor = data["lora"]["spreadingFactor"].as<int>();
loramodule.signalBandwidth = data["lora"]["signalBandwidth"].as<long>();
loramodule.codingRate4 = data["lora"]["codingRate4"].as<int>();
loramodule.power = data["lora"]["power"].as<int>();
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<bool>();
display.timeout = data["display"]["timeout"].as<int>();
display.turn180 = data["display"]["turn180"].as<bool>();
data["display"]["alwaysOn"] = display.alwaysOn;
data["display"]["timeout"] = display.timeout;
data["display"]["turn180"] = display.turn180;
syslog.active = data["syslog"]["active"].as<bool>();
syslog.server = data["syslog"]["server"].as<String>();
syslog.port = data["syslog"]["port"].as<int>();
data["syslog"]["active"] = syslog.active;
data["syslog"]["server"] = syslog.server;
data["syslog"]["port"] = syslog.port;
bme.active = data["bme"]["active"].as<bool>();
data["bme"]["active"] = bme.active;
ota.username = data["ota"]["username"].as<String>();
ota.password = data["ota"]["password"].as<String>();
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<String>();
wifiap.password = WiFiArray[i]["password"].as<String>();
wifiap.latitude = WiFiArray[i]["latitude"].as<double>();
wifiap.longitude = WiFiArray[i]["longitude"].as<double>();
wifiAPs.push_back(wifiap);
}
wifiAutoAP.password = data["wifi"]["autoAP"]["password"].as<String>();
wifiAutoAP.powerOff = data["wifi"]["autoAP"]["powerOff"].as<int>();
callsign = data["callsign"].as<String>();
stationMode = data["stationMode"].as<int>();
iGateComment = data["iGateComment"].as<String>();
beaconInterval = data["other"]["beaconInterval"].as<int>();
igateSendsLoRaBeacons = data["other"]["igateSendsLoRaBeacons"].as<bool>();
igateRepeatsLoRaPackets = data["other"]["igateRepeatsLoRaPackets"].as<bool>();
rememberStationTime = data["other"]["rememberStationTime"].as<int>();
sendBatteryVoltage = data["other"]["sendBatteryVoltage"].as<bool>();
externalVoltageMeasurement = data["other"]["externalVoltageMeasurement"].as<bool>();
externalVoltagePin = data["other"]["externalVoltagePin"].as<int>();
digi.comment = data["digi"]["comment"].as<String>();
digi.latitude = data["digi"]["latitude"].as<double>();
digi.longitude = data["digi"]["longitude"].as<double>();
aprs_is.passcode = data["aprs_is"]["passcode"].as<String>();
aprs_is.server = data["aprs_is"]["server"].as<String>();
aprs_is.port = data["aprs_is"]["port"].as<int>();
aprs_is.reportingDistance = data["aprs_is"]["reportingDistance"].as<int>();
loramodule.iGateFreq = data["lora"]["iGateFreq"].as<long>();
loramodule.digirepeaterTxFreq = data["lora"]["digirepeaterTxFreq"].as<long>();
loramodule.digirepeaterRxFreq = data["lora"]["digirepeaterRxFreq"].as<long>();
loramodule.spreadingFactor = data["lora"]["spreadingFactor"].as<int>();
loramodule.signalBandwidth = data["lora"]["signalBandwidth"].as<long>();
loramodule.codingRate4 = data["lora"]["codingRate4"].as<int>();
loramodule.power = data["lora"]["power"].as<int>();
display.alwaysOn = data["display"]["alwaysOn"].as<bool>();
display.timeout = data["display"]["timeout"].as<int>();
display.turn180 = data["display"]["turn180"].as<bool>();
syslog.active = data["syslog"]["active"].as<bool>();
syslog.server = data["syslog"]["server"].as<String>();
syslog.port = data["syslog"]["port"].as<int>();
bme.active = data["bme"]["active"].as<bool>();
ota.username = data["ota"]["username"].as<String>();
ota.password = data["ota"]["password"].as<String>();
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();
}

View file

@ -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<WiFi_AP> 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<WiFi_AP> 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

View file

@ -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);
}

View file

@ -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<ndec;i++) {
n -= v;
n = 10 * abs(n);
v = n;
r += v;
}
return r;
}
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<ndec;i++) {
n -= v;
n = 10 * abs(n);
v = n;
r += v;
}
return r;
}
String processLatitudeAPRS(double lat) {
String degrees = double2string(lat,6);
String north_south, latitude, convDeg3;
float convDeg, convDeg2;
String processLatitudeAPRS(double lat) {
String degrees = double2string(lat,6);
String north_south, latitude, convDeg3;
float convDeg, convDeg2;
if (abs(degrees.toFloat()) < 10) {
latitude += "0";
if (abs(degrees.toFloat()) < 10) {
latitude += "0";
}
Serial.println(latitude);
if (degrees.indexOf("-") == 0) {
north_south = "S";
latitude += degrees.substring(1,degrees.indexOf("."));
} else {
north_south = "N";
latitude += degrees.substring(0,degrees.indexOf("."));
}
convDeg = abs(degrees.toFloat()) - abs(int(degrees.toFloat()));
convDeg2 = (convDeg * 60)/100;
convDeg3 = String(convDeg2,6);
latitude += convDeg3.substring(convDeg3.indexOf(".")+1,convDeg3.indexOf(".")+3) + "." + convDeg3.substring(convDeg3.indexOf(".")+3,convDeg3.indexOf(".")+5);
latitude += north_south;
return latitude;
}
Serial.println(latitude);
if (degrees.indexOf("-") == 0) {
north_south = "S";
latitude += degrees.substring(1,degrees.indexOf("."));
} else {
north_south = "N";
latitude += degrees.substring(0,degrees.indexOf("."));
}
convDeg = abs(degrees.toFloat()) - abs(int(degrees.toFloat()));
convDeg2 = (convDeg * 60)/100;
convDeg3 = String(convDeg2,6);
latitude += convDeg3.substring(convDeg3.indexOf(".")+1,convDeg3.indexOf(".")+3) + "." + convDeg3.substring(convDeg3.indexOf(".")+3,convDeg3.indexOf(".")+5);
latitude += north_south;
return latitude;
}
String processLongitudeAPRS(double lon) {
String degrees = double2string(lon,6);
String east_west, longitude, convDeg3;
float convDeg, convDeg2;
if (abs(degrees.toFloat()) < 100) {
longitude += "0";
String processLongitudeAPRS(double lon) {
String degrees = double2string(lon,6);
String east_west, longitude, convDeg3;
float convDeg, convDeg2;
if (abs(degrees.toFloat()) < 100) {
longitude += "0";
}
if (abs(degrees.toFloat()) < 10) {
longitude += "0";
}
if (degrees.indexOf("-") == 0) {
east_west = "W";
longitude += degrees.substring(1,degrees.indexOf("."));
} else {
east_west = "E";
longitude += degrees.substring(0,degrees.indexOf("."));
}
convDeg = abs(degrees.toFloat()) - abs(int(degrees.toFloat()));
convDeg2 = (convDeg * 60)/100;
convDeg3 = String(convDeg2,6);
longitude += convDeg3.substring(convDeg3.indexOf(".")+1,convDeg3.indexOf(".")+3) + "." + convDeg3.substring(convDeg3.indexOf(".")+3,convDeg3.indexOf(".")+5);
longitude += east_west;
return longitude;
}
if (abs(degrees.toFloat()) < 10) {
longitude += "0";
}
if (degrees.indexOf("-") == 0) {
east_west = "W";
longitude += degrees.substring(1,degrees.indexOf("."));
} else {
east_west = "E";
longitude += degrees.substring(0,degrees.indexOf("."));
}
convDeg = abs(degrees.toFloat()) - abs(int(degrees.toFloat()));
convDeg2 = (convDeg * 60)/100;
convDeg3 = String(convDeg2,6);
longitude += convDeg3.substring(convDeg3.indexOf(".")+1,convDeg3.indexOf(".")+3) + "." + convDeg3.substring(convDeg3.indexOf(".")+3,convDeg3.indexOf(".")+5);
longitude += east_west;
return longitude;
}
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) {
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 " _ / _ / _ ";
}
}
}

View file

@ -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
}
}

56
src/ota_utils.cpp Normal file
View file

@ -0,0 +1,56 @@
#include <ESPAsyncWebServer.h>
#include <ElegantOTA.h>
#include <AsyncTCP.h>
#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);
}
}
}

16
src/ota_utils.h Normal file
View file

@ -0,0 +1,16 @@
#ifndef OTA_UTILS_H_
#define OTA_UTILS_H_
#include <Arduino.h>
#include <ESPAsyncWebServer.h>
namespace OTA_Utils {
void setup(AsyncWebServer *server);
void onOTAStart();
void onOTAProgress(size_t current, size_t final);
void onOTAEnd(bool success);
}
#endif

View file

@ -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
}*/
}

View file

@ -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

View file

@ -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; i<lastHeardStation.size(); i++) {
answer += lastHeardStation[i].substring(0,lastHeardStation[i].indexOf(",")) + " ";
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.3 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; i<lastHeardStation.size(); i++) {
answer += lastHeardStation[i].substring(0,lastHeardStation[i].indexOf(",")) + " ";
}
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;
}
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;
}
}
}

View file

@ -12,93 +12,93 @@ extern String fourthLine;
namespace STATION_Utils {
void deleteNotHeard() {
for (int i=0; i<lastHeardStation.size(); i++) {
String deltaTimeString = lastHeardStation[i].substring(lastHeardStation[i].indexOf(",")+1);
uint32_t deltaTime = deltaTimeString.toInt();
if ((millis() - deltaTime) < Config.rememberStationTime*60*1000) {
lastHeardStation_temp.push_back(lastHeardStation[i]);
}
}
lastHeardStation.clear();
for (int j=0; j<lastHeardStation_temp.size(); j++) {
lastHeardStation.push_back(lastHeardStation_temp[j]);
}
lastHeardStation_temp.clear();
}
void updateLastHeard(String station) {
deleteNotHeard();
bool stationHeard = false;
for (int i=0; i<lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0,lastHeardStation[i].indexOf(",")) == station) {
lastHeardStation[i] = station + "," + String(millis());
stationHeard = true;
}
}
if (!stationHeard) {
lastHeardStation.push_back(station + "," + String(millis()));
void deleteNotHeard() {
for (int i=0; i<lastHeardStation.size(); i++) {
String deltaTimeString = lastHeardStation[i].substring(lastHeardStation[i].indexOf(",")+1);
uint32_t deltaTime = deltaTimeString.toInt();
if ((millis() - deltaTime) < Config.rememberStationTime*60*1000) {
lastHeardStation_temp.push_back(lastHeardStation[i]);
}
}
lastHeardStation.clear();
for (int j=0; j<lastHeardStation_temp.size(); j++) {
lastHeardStation.push_back(lastHeardStation_temp[j]);
}
lastHeardStation_temp.clear();
}
fourthLine = "Stations (" + String(Config.rememberStationTime) + "min) = ";
if (lastHeardStation.size() < 10) {
fourthLine += " ";
}
fourthLine += String(lastHeardStation.size());
void updateLastHeard(String station) {
deleteNotHeard();
bool stationHeard = false;
for (int i=0; i<lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0,lastHeardStation[i].indexOf(",")) == station) {
lastHeardStation[i] = station + "," + String(millis());
stationHeard = true;
}
}
if (!stationHeard) {
lastHeardStation.push_back(station + "," + String(millis()));
}
#ifndef TextSerialOutputForApp ////// This is just for debugging
Serial.print("Stations Near (last " + String(Config.rememberStationTime) + " minutes): ");
for (int k=0; k<lastHeardStation.size(); k++) {
Serial.print(lastHeardStation[k].substring(0,lastHeardStation[k].indexOf(","))); Serial.print(" ");
}
Serial.println("");
#endif
}
fourthLine = "Stations (" + String(Config.rememberStationTime) + "min) = ";
if (lastHeardStation.size() < 10) {
fourthLine += " ";
}
fourthLine += String(lastHeardStation.size());
bool wasHeard(String station) {
deleteNotHeard();
for (int i=0; i<lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0,lastHeardStation[i].indexOf(",")) == station) {
Serial.println(" ---> 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<lastHeardStation.size(); k++) {
Serial.print(lastHeardStation[k].substring(0,lastHeardStation[k].indexOf(","))); Serial.print(" ");
}
Serial.println("");
#endif
}
Serial.println(" ---> Station not Heard for last 30 min (Not Tx)\n");
return false;
}
void checkBuffer() {
for (int i=0; i<packetBuffer.size(); i++) {
String deltaTimeString = packetBuffer[i].substring(0,packetBuffer[i].indexOf(","));
uint32_t deltaTime = deltaTimeString.toInt();
if ((millis() - deltaTime) < 60*1000) { // cambiar a 15 segundos?
packetBuffer_temp.push_back(packetBuffer[i]);
}
bool wasHeard(String station) {
deleteNotHeard();
for (int i=0; i<lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0,lastHeardStation[i].indexOf(",")) == station) {
Serial.println(" ---> 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<packetBuffer_temp.size(); j++) {
packetBuffer.push_back(packetBuffer_temp[j]);
}
packetBuffer_temp.clear();
// BORRAR ESTO !!
for (int i=0; i<packetBuffer.size(); i++) {
Serial.println(packetBuffer[i]);
}
//
}
void checkBuffer() {
for (int i=0; i<packetBuffer.size(); i++) {
String deltaTimeString = packetBuffer[i].substring(0,packetBuffer[i].indexOf(","));
uint32_t deltaTime = deltaTimeString.toInt();
if ((millis() - deltaTime) < 60*1000) { // cambiar a 15 segundos?
packetBuffer_temp.push_back(packetBuffer[i]);
}
}
packetBuffer.clear();
for (int j=0; j<packetBuffer_temp.size(); j++) {
packetBuffer.push_back(packetBuffer_temp[j]);
}
packetBuffer_temp.clear();
void updatePacketBuffer(String packet) {
if ((packet.indexOf(":!") == -1) && (packet.indexOf(":=") == -1) && (packet.indexOf(":>") == -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<packetBuffer.size(); i++) {
Serial.println(packetBuffer[i]);
}
//
}
void updatePacketBuffer(String packet) {
if ((packet.indexOf(":!") == -1) && (packet.indexOf(":=") == -1) && (packet.indexOf(":>") == -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();
}
}
}
}

View file

@ -1,7 +1,3 @@
#include <ESPAsyncWebServer.h>
#include <ElegantOTA.h>
#include <AsyncTCP.h>
#include <SPIFFS.h>
#include <WiFi.h>
#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!");
}
}
}

View file

@ -17,7 +17,6 @@ namespace Utils {
void onOTAStart();
void onOTAProgress(size_t current, size_t final);
void onOTAEnd(bool success);
void startServer();
}

192
src/web_utils.cpp Normal file
View file

@ -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; i<networks; i++) {
WiFi_AP wifiap;
wifiap.ssid = request->getParam("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();
}
}

31
src/web_utils.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef WEB_UTILS_H_
#define WEB_UTILS_H_
#include <ESPAsyncWebServer.h>
#include <ESPmDNS.h>
#include <Arduino.h>
#include <SPIFFS.h>
#include <WiFi.h>
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

View file

@ -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<myWiFiAPSize) {
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++;
}
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();
}
}
}
}

View file

@ -7,7 +7,9 @@ namespace WIFI_Utils {
void checkWiFi();
void startWiFi();
void checkIfAutoAPShouldPowerOff();
void setup();
}