From d0cfe7f580f7d5f5a5644a8d56f1e49b82b6ccba Mon Sep 17 00:00:00 2001 From: Peter Buchegger Date: Sun, 6 Dec 2020 23:51:59 +0100 Subject: [PATCH] update config handling on project level --- .gitmodules | 2 +- lib | 1 - lib/Common | 1 + src/LoRa_APRS_iGate.cpp | 112 +++++++++++++++---------------- src/project_configuration.cpp | 109 ++++++++++++++++++++++++++++++ src/project_configuration.h | 121 ++++++++++++++++++++++++++++++++++ 6 files changed, 288 insertions(+), 58 deletions(-) delete mode 160000 lib create mode 160000 lib/Common create mode 100644 src/project_configuration.cpp create mode 100644 src/project_configuration.h diff --git a/.gitmodules b/.gitmodules index 37a6bca..2a34780 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "lib"] - path = lib + path = lib/Common url = ../LoRa_APRS_Common diff --git a/lib b/lib deleted file mode 160000 index 757733b..0000000 --- a/lib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 757733be04730095a27be008363b4f51dd68bacb diff --git a/lib/Common b/lib/Common new file mode 160000 index 0000000..ae8be81 --- /dev/null +++ b/lib/Common @@ -0,0 +1 @@ +Subproject commit ae8be81399487ba62ea04bc771d2c628c41135c4 diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 51c1c17..bde09dc 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -17,7 +17,7 @@ #include "pins.h" #include "display.h" -#include "configuration.h" +#include "project_configuration.h" #if defined(ARDUINO_T_Beam) && !defined(ARDUINO_T_Beam_V0_7) #include "power_management.h" @@ -35,7 +35,7 @@ WiFiMulti WiFiMulti; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, 60*60); FTPServer ftpServer; -Configuration Config; +Configuration * Config; APRS_IS * aprs_is = 0; LoRa_APRS lora_aprs; std::shared_ptr BeaconMsg; @@ -97,7 +97,7 @@ void setup() setup_ftp(); setup_aprs_is(); #else - if(Config.wifi.active) + if(Config->wifi.active) { setup_wifi(); setup_ota(); @@ -110,14 +110,14 @@ void setup() WiFi.mode(WIFI_OFF); btStop(); } - if(Config.aprs_is.active) setup_aprs_is(); + if(Config->aprs_is.active) setup_aprs_is(); #endif setup_timer(); - if(Config.display.overwritePin != 0) + if(Config->display.overwritePin != 0) { - pinMode(Config.display.overwritePin, INPUT); - pinMode(Config.display.overwritePin, INPUT_PULLUP); + pinMode(Config->display.overwritePin, INPUT); + pinMode(Config->display.overwritePin, INPUT_PULLUP); } delay(500); @@ -129,37 +129,37 @@ void setup() void loop() { static bool display_is_on = true; - if(Config.display.overwritePin != 0 && !digitalRead(Config.display.overwritePin)) + if(Config->display.overwritePin != 0 && !digitalRead(Config->display.overwritePin)) { secondsSinceDisplay = 0; display_is_on = true; setup_display(); } else - if(!Config.display.alwaysOn && secondsSinceDisplay > Config.display.timeout && display_is_on) + if(!Config->display.alwaysOn && secondsSinceDisplay > Config->display.timeout && display_is_on) { turn_off_display(); display_is_on = false; } - static bool beacon_aprs_is = Config.aprs_is.active && Config.aprs_is.beacon; - static bool beacon_digi = Config.digi.active && Config.digi.beacon; + static bool beacon_aprs_is = Config->aprs_is.active && Config->aprs_is.beacon; + static bool beacon_digi = Config->digi.active && Config->digi.beacon; - if(Config.aprs_is.active && Config.aprs_is.beacon && secondsSinceLastAPRSISBeacon >= (Config.aprs_is.beaconTimeout*60)) + if(Config->aprs_is.active && Config->aprs_is.beacon && secondsSinceLastAPRSISBeacon >= (Config->aprs_is.beaconTimeout*60)) { portENTER_CRITICAL(&timerMux); - secondsSinceLastAPRSISBeacon -= (Config.aprs_is.beaconTimeout*60); + secondsSinceLastAPRSISBeacon -= (Config->aprs_is.beaconTimeout*60); portEXIT_CRITICAL(&timerMux); beacon_aprs_is = true; } - if(Config.digi.active && Config.digi.beacon && secondsSinceLastDigiBeacon >= (Config.digi.beaconTimeout*60)) + if(Config->digi.active && Config->digi.beacon && secondsSinceLastDigiBeacon >= (Config->digi.beaconTimeout*60)) { portENTER_CRITICAL(&timerMux); - secondsSinceLastDigiBeacon -= (Config.digi.beaconTimeout*60); + secondsSinceLastDigiBeacon -= (Config->digi.beaconTimeout*60); portEXIT_CRITICAL(&timerMux); beacon_digi = true; } - if(Config.ftp.active) + if(Config->ftp.active) { ftpServer.handle(); static bool configWasOpen = false; @@ -175,8 +175,8 @@ void loop() } } - if(Config.wifi.active || eth_connected) ArduinoOTA.handle(); - if(Config.wifi.active && WiFiMulti.run() != WL_CONNECTED) + if(Config->wifi.active || eth_connected) ArduinoOTA.handle(); + if(Config->wifi.active && WiFiMulti.run() != WL_CONNECTED) { setup_display(); secondsSinceDisplay = 0; display_is_on = true; logPrintlnE("WiFi not connected!"); @@ -184,15 +184,15 @@ void loop() delay(1000); return; } - if((eth_connected && !aprs_is->connected()) || (Config.aprs_is.active && !aprs_is->connected())) + if((eth_connected && !aprs_is->connected()) || (Config->aprs_is.active && !aprs_is->connected())) { setup_display(); secondsSinceDisplay = 0; display_is_on = true; logPrintI("connecting to APRS-IS server: "); - logPrintI(Config.aprs_is.server); + logPrintI(Config->aprs_is.server); logPrintI(" on port: "); - logPrintlnI(String(Config.aprs_is.port)); + logPrintlnI(String(Config->aprs_is.port)); show_display("INFO", "Connecting to APRS-IS server"); - if(!aprs_is->connect(Config.aprs_is.server, Config.aprs_is.port)) + if(!aprs_is->connect(Config->aprs_is.server, Config->aprs_is.port)) { logPrintlnE("Connection failed."); logPrintlnI("Waiting 5 seconds before retrying..."); @@ -202,7 +202,7 @@ void loop() } logPrintlnI("Connected to APRS-IS server!"); } - if(Config.aprs_is.active && aprs_is->available() > 0) + if(Config->aprs_is.active && aprs_is->available() > 0) { String str = aprs_is->getMessage(); logPrintD("[" + timeClient.getFormattedTime() + "] "); @@ -213,7 +213,7 @@ void loop() std::shared_ptr msg = lora_aprs.getMessage(); setup_display(); secondsSinceDisplay = 0; display_is_on = true; - show_display(Config.callsign, timeClient.getFormattedTime() + " LoRa", "RSSI: " + String(lora_aprs.packetRssi()) + ", SNR: " + String(lora_aprs.packetSnr()), msg->toString()); + show_display(Config->callsign, timeClient.getFormattedTime() + " LoRa", "RSSI: " + String(lora_aprs.packetRssi()) + ", SNR: " + String(lora_aprs.packetSnr()), msg->toString()); logPrintD("[" + timeClient.getFormattedTime() + "] "); logPrintD(" Received packet '"); logPrintD(msg->toString()); @@ -222,13 +222,13 @@ void loop() logPrintD(" and SNR "); logPrintlnD(String(lora_aprs.packetSnr())); - if(Config.aprs_is.active) + if(Config->aprs_is.active) { aprs_is->sendMessage(msg->encode()); } - if(Config.digi.active) + if(Config->digi.active) { - if(msg->getSource().indexOf(Config.callsign) != -1) + if(msg->getSource().indexOf(Config->callsign) != -1) { logPrintD("Message already received as repeater: '"); logPrintD(msg->toString()); @@ -254,14 +254,14 @@ void loop() if(foundMsg == lastMessages.end()) { setup_display(); secondsSinceDisplay = 0; display_is_on = true; - show_display(Config.callsign, "RSSI: " + String(lora_aprs.packetRssi()) + ", SNR: " + String(lora_aprs.packetSnr()), msg->toString(), 0); + show_display(Config->callsign, "RSSI: " + String(lora_aprs.packetRssi()) + ", SNR: " + String(lora_aprs.packetSnr()), msg->toString(), 0); logPrintD("Received packet '"); logPrintD(msg->toString()); logPrintD("' with RSSI "); logPrintD(String(lora_aprs.packetRssi())); logPrintD(" and SNR "); logPrintlnD(String(lora_aprs.packetSnr())); - msg->setPath(String(Config.callsign) + "*"); + msg->setPath(String(Config->callsign) + "*"); lora_aprs.sendMessage(msg); lastMessages.insert({secondsSinceStartup, msg}); } @@ -277,11 +277,11 @@ void loop() return; } } - if(Config.digi.active) + if(Config->digi.active) { for(std::map>::iterator iter = lastMessages.begin(); iter != lastMessages.end(); ) { - if(secondsSinceStartup >= iter->first + Config.digi.forwardTimeout*60) + if(secondsSinceStartup >= iter->first + Config->digi.forwardTimeout*60) { iter = lastMessages.erase(iter); } @@ -295,30 +295,30 @@ void loop() { beacon_digi = false; setup_display(); secondsSinceDisplay = 0; display_is_on = true; - show_display(Config.callsign, "Beacon to HF..."); + show_display(Config->callsign, "Beacon to HF..."); logPrintD("[" + timeClient.getFormattedTime() + "] "); logPrintlnD(BeaconMsg->encode()); lora_aprs.sendMessage(BeaconMsg); logPrintlnD("finished TXing..."); - show_display(Config.callsign, "Standby..."); + show_display(Config->callsign, "Standby..."); } if(beacon_aprs_is) { beacon_aprs_is = false; setup_display(); secondsSinceDisplay = 0; display_is_on = true; - show_display(Config.callsign, "Beacon to APRS-IS Server..."); + show_display(Config->callsign, "Beacon to APRS-IS Server..."); logPrintD("[" + timeClient.getFormattedTime() + "] "); logPrintlnD(BeaconMsg->encode()); aprs_is->sendMessage(BeaconMsg); - show_display(Config.callsign, "Standby..."); + show_display(Config->callsign, "Standby..."); } } void load_config() { - ConfigurationManagement confmg("/is-cfg.json"); + ProjectConfigurationManagement confmg; Config = confmg.readConfiguration(); - if(Config.callsign == "NOCALL-10") + if(Config->callsign == "NOCALL-10") { logPrintlnE("You have to change your settings in 'data/is-cfg.json' and upload it via \"Upload File System image\"!"); show_display("ERROR", "You have to change your settings in 'data/is-cfg.json' and upload it via \"Upload File System image\"!"); @@ -327,7 +327,7 @@ void load_config() } #ifndef ETH_BOARD - if(Config.aprs_is.active && !Config.wifi.active) + if(Config->aprs_is.active && !Config->wifi.active) { logPrintlnE("You have to activate Wifi for APRS IS to work, please check your settings!"); show_display("ERROR", "You have to activate Wifi for APRS IS to work, please check your settings!"); @@ -336,9 +336,9 @@ void load_config() } #endif - if(KEY_BUILTIN != 0 && Config.display.overwritePin == 0) + if(KEY_BUILTIN != 0 && Config->display.overwritePin == 0) { - Config.display.overwritePin = KEY_BUILTIN; + Config->display.overwritePin = KEY_BUILTIN; } logPrintlnI("Configuration loaded!"); } @@ -403,8 +403,8 @@ void setup_eth() void setup_wifi() { WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE); - WiFi.setHostname(Config.callsign.c_str()); - for(Configuration::Wifi::AP ap : Config.wifi.APs) + WiFi.setHostname(Config->callsign.c_str()); + for(Configuration::Wifi::AP ap : Config->wifi.APs) { logPrintD("Looking for AP: "); logPrintlnD(ap.SSID); @@ -459,34 +459,34 @@ void setup_ota() else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); - ArduinoOTA.setHostname(Config.callsign.c_str()); + ArduinoOTA.setHostname(Config->callsign.c_str()); ArduinoOTA.begin(); logPrintlnI("OTA init done!"); } void setup_lora() { - lora_aprs.setRxFrequency(Config.lora.frequencyRx); - lora_aprs.setTxFrequency(Config.lora.frequencyTx); + lora_aprs.setRxFrequency(Config->lora.frequencyRx); + lora_aprs.setTxFrequency(Config->lora.frequencyTx); if (!lora_aprs.begin(lora_aprs.getRxFrequency())) { logPrintlnE("Starting LoRa failed!"); show_display("ERROR", "Starting LoRa failed!"); while (1); } - lora_aprs.setTxPower(Config.lora.power); - lora_aprs.setSpreadingFactor(Config.lora.spreadingFactor); - lora_aprs.setSignalBandwidth(Config.lora.signalBandwidth); - lora_aprs.setCodingRate4(Config.lora.codingRate4); + lora_aprs.setTxPower(Config->lora.power); + lora_aprs.setSpreadingFactor(Config->lora.spreadingFactor); + lora_aprs.setSignalBandwidth(Config->lora.signalBandwidth); + lora_aprs.setCodingRate4(Config->lora.codingRate4); logPrintlnI("LoRa init done!"); show_display("INFO", "LoRa init done!", 2000); BeaconMsg = std::shared_ptr(new APRSMessage()); - BeaconMsg->setSource(Config.callsign); + BeaconMsg->setSource(Config->callsign); BeaconMsg->setDestination("APLG0"); - String lat = create_lat_aprs(Config.beacon.positionLatitude); - String lng = create_long_aprs(Config.beacon.positionLongitude); - BeaconMsg->getAPRSBody()->setData(String("=") + lat + "I" + lng + "&" + Config.beacon.message); + String lat = create_lat_aprs(Config->beacon.positionLatitude); + String lng = create_long_aprs(Config->beacon.positionLongitude); + BeaconMsg->getAPRSBody()->setData(String("=") + lat + "I" + lng + "&" + Config->beacon.message); } void setup_ntp() @@ -503,7 +503,7 @@ void setup_ntp() void setup_aprs_is() { - aprs_is = new APRS_IS(Config.callsign, Config.aprs_is.password , "ESP32-APRS-IS", "0.1"); + aprs_is = new APRS_IS(Config->callsign, Config->aprs_is.password , "ESP32-APRS-IS", "0.1"); } void IRAM_ATTR onTimer() @@ -526,11 +526,11 @@ void setup_timer() void setup_ftp() { - if(!Config.ftp.active) + if(!Config->ftp.active) { return; } - for(Configuration::Ftp::User user : Config.ftp.users) + for(Configuration::Ftp::User user : Config->ftp.users) { logPrintD("Adding user to FTP Server: "); logPrintlnD(user.name); diff --git a/src/project_configuration.cpp b/src/project_configuration.cpp new file mode 100644 index 0000000..6cfaec8 --- /dev/null +++ b/src/project_configuration.cpp @@ -0,0 +1,109 @@ +#include + +#include "project_configuration.h" +#include "logger.h" + +Configuration * ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocument & data) +{ + Configuration * conf = new Configuration; + if(data.containsKey("callsign")) + conf->callsign = data["callsign"].as(); + + conf->wifi.active = data["wifi"]["active"] | false; + JsonArray aps = data["wifi"]["AP"].as(); + for(JsonVariant v : aps) + { + Configuration::Wifi::AP ap; + ap.SSID = v["SSID"].as(); + ap.password = v["password"].as(); + conf->wifi.APs.push_back(ap); + } + if(data.containsKey("beacon") && data["beacon"].containsKey("message")) + conf->beacon.message = data["beacon"]["message"].as(); + conf->beacon.positionLatitude = data["beacon"]["position"]["latitude"] | 0.0; + conf->beacon.positionLongitude = data["beacon"]["position"]["longitude"] | 0.0; + conf->aprs_is.active = data["aprs_is"]["active"] | false; + if(data.containsKey("aprs_is") && data["aprs_is"].containsKey("password")) + conf->aprs_is.password = data["aprs_is"]["password"].as(); + if(data.containsKey("aprs_is") && data["aprs_is"].containsKey("server")) + conf->aprs_is.server = data["aprs_is"]["server"].as(); + conf->aprs_is.port = data["aprs_is"]["port"] | 14580; + conf->aprs_is.beacon = data["aprs_is"]["beacon"] | true; + conf->aprs_is.beaconTimeout = data["aprs_is"]["beacon_timeout"] | 15; + conf->digi.active = data["digi"]["active"] | false; + conf->digi.forwardTimeout = data["digi"]["forward_timeout"] | 5; + conf->digi.beacon = data["digi"]["beacon"] | true; + conf->digi.beaconTimeout = data["digi"]["beacon_timeout"] | 30; + + conf->lora.frequencyRx = data["lora"]["frequency_rx"] | 433775000; + conf->lora.frequencyTx = data["lora"]["frequency_tx"] | 433775000; + conf->lora.power = data["lora"]["power"] | 20; + conf->lora.spreadingFactor = data["lora"]["spreading_factor"] | 12; + conf->lora.signalBandwidth = data["lora"]["signal_bandwidth"] | 125000; + conf->lora.codingRate4 = data["lora"]["coding_rate4"] | 5; + conf->display.alwaysOn = data["display"]["always_on"] | true; + conf->display.timeout = data["display"]["timeout"] | 10; + conf->display.overwritePin = data["display"]["overwrite_pin"] | 0; + + conf->ftp.active = data["ftp"]["active"] | false; + JsonArray users = data["ftp"]["user"].as(); + for(JsonVariant u : users) + { + Configuration::Ftp::User us; + us.name = u["name"].as(); + us.password = u["password"].as(); + conf->ftp.users.push_back(us); + } + if(conf->ftp.users.empty()) + { + Configuration::Ftp::User us; + us.name = "ftp"; + us.password = "ftp"; + conf->ftp.users.push_back(us); + } + + return conf; +} + +void ProjectConfigurationManagement::writeProjectConfiguration(Configuration * conf, DynamicJsonDocument & data) +{ + data["callsign"] = conf->callsign; + data["wifi"]["active"] = conf->wifi.active; + JsonArray aps = data["wifi"].createNestedArray("AP"); + for(Configuration::Wifi::AP ap : conf->wifi.APs) + { + JsonObject v = aps.createNestedObject(); + v["SSID"] = ap.SSID; + v["password"] = ap.password; + } + data["beacon"]["message"] = conf->beacon.message; + data["beacon"]["position"]["latitude"] = conf->beacon.positionLatitude; + data["beacon"]["position"]["longitude"] = conf->beacon.positionLongitude; + data["aprs_is"]["active"] = conf->aprs_is.active; + data["aprs_is"]["password"] = conf->aprs_is.password; + data["aprs_is"]["server"] = conf->aprs_is.server; + data["aprs_is"]["port"] = conf->aprs_is.port; + data["aprs_is"]["beacon"] = conf->aprs_is.beacon; + data["aprs_is"]["beacon_timeout"] = conf->aprs_is.beaconTimeout; + data["digi"]["active"] = conf->digi.active; + data["digi"]["forward_timeout"] = conf->digi.forwardTimeout; + data["digi"]["beacon"] = conf->digi.beacon; + data["digi"]["beacon_timeout"] = conf->digi.beaconTimeout; + data["lora"]["frequency_rx"] = conf->lora.frequencyRx; + data["lora"]["frequency_tx"] = conf->lora.frequencyTx; + data["lora"]["power"] = conf->lora.power; + data["lora"]["spreading_factor"] = conf->lora.spreadingFactor; + data["lora"]["signal_bandwidth"] = conf->lora.signalBandwidth; + data["lora"]["coding_rate4"] = conf->lora.codingRate4; + data["display"]["always_on"] = conf->display.alwaysOn; + data["display"]["timeout"] = conf->display.timeout; + data["display"]["overwrite_pin"] = conf->display.overwritePin; + data["ftp"]["active"] = conf->ftp.active; + JsonArray users = data["ftp"].createNestedArray("user"); + for(Configuration::Ftp::User u : conf->ftp.users) + { + JsonObject v = users.createNestedObject(); + v["name"] = u.name; + v["password"] = u.password; + } +} diff --git a/src/project_configuration.h b/src/project_configuration.h new file mode 100644 index 0000000..5a65724 --- /dev/null +++ b/src/project_configuration.h @@ -0,0 +1,121 @@ +#ifndef PROJECT_CONFIGURATION_H_ +#define PROJECT_CONFIGURATION_H_ + +#include "configuration.h" + +class Configuration +{ +public: + class Wifi + { + public: + class AP + { + public: + String SSID; + String password; + }; + + Wifi() : active(false) {} + + bool active; + std::list APs; + }; + + class Beacon + { + public: + Beacon() : message("LoRa iGATE & Digi, Info: github.com/peterus/LoRa_APRS_iGate"), positionLatitude(0.0), positionLongitude(0.0) {} + + String message; + double positionLatitude; + double positionLongitude; + }; + + class APRS_IS + { + public: + APRS_IS() : active(false), server("euro.aprs2.net"), port(14580), beacon(true), beaconTimeout(15) {} + + bool active; + String password; + String server; + int port; + bool beacon; + int beaconTimeout; + }; + + class Digi + { + public: + Digi() : active(false), forwardTimeout(5), beacon(true), beaconTimeout(30) {} + + bool active; + int forwardTimeout; + bool beacon; + int beaconTimeout; + }; + + class LoRa + { + public: + LoRa() : frequencyRx(433775000), frequencyTx(433775000), power(20), spreadingFactor(12), signalBandwidth(125000), codingRate4(5) {} + + long frequencyRx; + long frequencyTx; + int power; + int spreadingFactor; + long signalBandwidth; + int codingRate4; + }; + + class Display + { + public: + Display() : alwaysOn(true), timeout(10), overwritePin(0) {} + + bool alwaysOn; + int timeout; + int overwritePin; + }; + + class Ftp + { + public: + class User + { + public: + String name; + String password; + }; + + Ftp() : active(false) {} + + bool active; + std::list users; + }; + + Configuration() : callsign("NOCALL-10") {}; + + String callsign; + Wifi wifi; + Beacon beacon; + APRS_IS aprs_is; + Digi digi; + LoRa lora; + Display display; + Ftp ftp; +}; + +class ProjectConfigurationManagement : public ConfigurationManagement +{ +public: + explicit ProjectConfigurationManagement() : ConfigurationManagement("/is-cfg.json") {} + virtual ~ProjectConfigurationManagement() {} + +private: + virtual Configuration * readProjectConfiguration(DynamicJsonDocument & data); + virtual void writeProjectConfiguration(Configuration * conf, DynamicJsonDocument & data); +}; + +#endif