diff --git a/data/tracker.json b/data/tracker.json index f439a10..ab35abe 100644 --- a/data/tracker.json +++ b/data/tracker.json @@ -1,41 +1,42 @@ { - "callsign":"NOCALL-7", "debug": false, "enhance_precision": true, - "beacon": - { - "message":"LoRa Tracker", - "timeout": 1, - "button_tx": false, - "symbol": "[", - "overlay": "/" + "beacons": [ + { + "callsign": "NOCALL-7", + "message": "LoRa Tracker", + "timeout": 1, + "symbol": "[", + "overlay": "/" + } + ], + "button": { + "tx": true, + "alt_message": true }, - "smart_beacon": - { - "active":true, - "turn_min":25, - "slow_rate":300, - "slow_speed":10, - "fast_rate":60, - "fast_speed":100, - "min_tx_dist":100, - "min_bcn":5 + "smart_beacon": { + "active": true, + "turn_min": 25, + "slow_rate": 300, + "slow_speed": 10, + "fast_rate": 60, + "fast_speed": 100, + "min_tx_dist": 100, + "min_bcn": 5, }, - "lora": - { - "frequency_rx":433775000, - "frequency_tx":433775000, - "power":20, - "spreading_factor":12, - "signal_bandwidth":125000, - "coding_rate4":5 + "lora": { + "frequency_rx": 433775000, + "frequency_tx": 433775000, + "power": 20, + "spreading_factor": 12, + "signal_bandwidth": 125000, + "coding_rate4": 5 }, - "ptt_output": - { - "active":false, + "ptt_output": { + "active": false, "io_pin": 4, "start_delay": 0, "end_delay": 0, - "reverse":false + "reverse": false } -} +} \ No newline at end of file diff --git a/src/LoRa_APRS_Tracker.cpp b/src/LoRa_APRS_Tracker.cpp index 05d3761..9a7bf42 100644 --- a/src/LoRa_APRS_Tracker.cpp +++ b/src/LoRa_APRS_Tracker.cpp @@ -40,6 +40,11 @@ static void handle_tx_click() { send_update = true; } +static void handle_next_beacon() { + Configuration::Beacon beacon = Config.SetNextBeacon(); + show_display(beacon.callsign, beacon.message, 2000); +} + // cppcheck-suppress unusedFunction void setup() { Serial.begin(115200); @@ -76,11 +81,15 @@ void setup() { WiFi.mode(WIFI_OFF); btStop(); - if (Config.beacon.button_tx) { + if (Config.button.tx) { // attach TX action to user button (defined by BUTTON_PIN) userButton.attachClick(handle_tx_click); } + if (Config.button.alt_message) { + userButton.attachLongPressStart(handle_next_beacon); + } + logPrintlnI("Smart Beacon is " + getSmartBeaconState()); show_display("INFO", "Smart Beacon is " + getSmartBeaconState(), 1000); logPrintlnI("setup done..."); @@ -124,7 +133,7 @@ void loop() { rate_limit_message_text = 0; } else { // enforce message text every n's Config.beacon.timeout frame - if (Config.beacon.timeout * rate_limit_message_text > 30) { + if (Config.GetCurrentBeacon().timeout * rate_limit_message_text > 30) { rate_limit_message_text = 0; } } @@ -178,14 +187,16 @@ void loop() { if (send_update && gps_loc_update) { send_update = false; - nextBeaconTimeStamp = now() + (Config.smart_beacon.active ? Config.smart_beacon.slow_rate : (Config.beacon.timeout * SECS_PER_MIN)); + nextBeaconTimeStamp = now() + (Config.smart_beacon.active ? Config.smart_beacon.slow_rate : (Config.GetCurrentBeacon().timeout * SECS_PER_MIN)); APRSMessage msg; String lat; String lng; String dao; - msg.setSource(Config.callsign); + Configuration::Beacon beacon = Config.GetCurrentBeacon(); + + msg.setSource(beacon.callsign); msg.setDestination("APLT00-1"); if (!Config.enhance_precision) { @@ -232,13 +243,13 @@ void loop() { } String aprsmsg; - aprsmsg = "!" + lat + Config.beacon.overlay + lng + Config.beacon.symbol + course_and_speed + alt; + aprsmsg = "!" + lat + beacon.overlay + lng + beacon.symbol + course_and_speed + alt; // message_text every 10's packet (i.e. if we have beacon rate 1min at high // speed -> every 10min). May be enforced above (at expirey of smart beacon // rate (i.e. every 30min), or every third packet on static rate (i.e. // static rate 10 -> every third packet) if (!(rate_limit_message_text++ % 10)) { - aprsmsg += Config.beacon.message; + aprsmsg += beacon.message; } if (BatteryIsConnected) { aprsmsg += " - _Bat.: " + batteryVoltage + "V - Cur.: " + batteryChargeCurrent + "mA"; @@ -282,7 +293,8 @@ void loop() { } if (gps_time_update) { - show_display(Config.callsign, createDateString(now()) + " " + createTimeString(now()), String("Sats: ") + gps.satellites.value() + " HDOP: " + gps.hdop.hdop(), String("Nxt Bcn: ") + (Config.smart_beacon.active ? "~" : "") + createTimeString(nextBeaconTimeStamp), BatteryIsConnected ? (String("Bat: ") + batteryVoltage + "V, " + batteryChargeCurrent + "mA") : "Powered via USB", String("Smart Beacon: " + getSmartBeaconState())); + + show_display(Config.GetCurrentBeacon().callsign, createDateString(now()) + " " + createTimeString(now()), String("Sats: ") + gps.satellites.value() + " HDOP: " + gps.hdop.hdop(), String("Nxt Bcn: ") + (Config.smart_beacon.active ? "~" : "") + createTimeString(nextBeaconTimeStamp), BatteryIsConnected ? (String("Bat: ") + batteryVoltage + "V, " + batteryChargeCurrent + "mA") : "Powered via USB", String("Smart Beacon: " + getSmartBeaconState())); if (Config.smart_beacon.active) { // Change the Tx internal based on the current speed @@ -316,7 +328,7 @@ void loop() { void load_config() { ConfigurationManagement confmg("/tracker.json"); Config = confmg.readConfiguration(); - if (Config.callsign == "NOCALL-10") { + if (Config.GetCurrentBeacon().callsign == "NOCALL-10") { logPrintlnE("You have to change your settings in 'data/tracker.json' and " "upload it via \"Upload File System image\"!"); show_display("ERROR", "You have to change your settings in 'data/tracker.json' and " diff --git a/src/configuration.cpp b/src/configuration.cpp index 3534698..52945a5 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -33,19 +33,26 @@ Configuration ConfigurationManagement::readConfiguration() { file.close(); Configuration conf; - if (data.containsKey("callsign")) - conf.callsign = data["callsign"].as(); + conf.debug = data["debug"] | false; conf.enhance_precision = data["enhance_precision"] | false; - if (data.containsKey("beacon") && data["beacon"].containsKey("message")) - conf.beacon.message = data["beacon"]["message"].as(); - conf.beacon.timeout = data["beacon"]["timeout"] | 1; - if (data.containsKey("beacon") && data["beacon"].containsKey("symbol")) - conf.beacon.symbol = data["beacon"]["symbol"].as(); - if (data.containsKey("beacon") && data["beacon"].containsKey("overlay")) - conf.beacon.overlay = data["beacon"]["overlay"].as(); - if (data.containsKey("beacon") && data["beacon"].containsKey("button_tx")) - conf.beacon.button_tx = data["beacon"]["button_tx"] | false; + + JsonArray beacons = data["beacons"].as(); + for (JsonVariant v : beacons) { + Configuration::Beacon beacon; + + if (v.containsKey("callsign")) + beacon.callsign = v["callsign"].as(); + if (v.containsKey("message")) + beacon.message = v["message"].as(); + beacon.timeout = v["timeout"] | 1; + if (v.containsKey("symbol")) + beacon.symbol = v["symbol"].as(); + if (v.containsKey("overlay")) + beacon.overlay = v["overlay"].as(); + + conf.beacons.push_back(beacon); + } conf.smart_beacon.active = data["smart_beacon"]["active"] | false; conf.smart_beacon.turn_min = data["smart_beacon"]["turn_min"] | 25; @@ -55,6 +62,9 @@ Configuration ConfigurationManagement::readConfiguration() { conf.smart_beacon.fast_speed = data["smart_beacon"]["fast_speed"] | 100; conf.smart_beacon.min_tx_dist = data["smart_beacon"]["min_tx_dist"] | 100; conf.smart_beacon.min_bcn = data["smart_beacon"]["min_bcn"] | 5; + + conf.button.tx = data["button"]["tx"] | false; + conf.button.alt_message = data["button"]["alt_message"] | false; conf.lora.frequencyRx = data["lora"]["frequency_rx"] | 433775000; conf.lora.frequencyTx = data["lora"]["frequency_tx"] | 433775000; @@ -81,14 +91,22 @@ void ConfigurationManagement::writeConfiguration(Configuration conf) { } DynamicJsonDocument data(2048); - data["callsign"] = conf.callsign; + JsonArray beacons = data.createNestedArray("beacons"); + for (Configuration::Beacon beacon : conf.beacons) { + JsonObject v = beacons.createNestedObject(); + v["callsign"] = beacon.callsign; + v["message"] = beacon.message; + v["timeout"] = beacon.timeout; + v["symbol"] = beacon.symbol; + v["overlay"] = beacon.overlay; + } + data["debug"] = conf.debug; data["enhance_precision"] = conf.enhance_precision; - data["beacon"]["message"] = conf.beacon.message; - data["beacon"]["timeout"] = conf.beacon.timeout; - data["beacon"]["symbol"] = conf.beacon.symbol; - data["beacon"]["overlay"] = conf.beacon.overlay; - data["beacon"]["button_tx"] = conf.beacon.button_tx; + + data["button"]["tx"] = conf.button.tx; + data["button"]["alt_message"] = conf.button.alt_message; + data["smart_beacon"]["active"] = conf.smart_beacon.active; data["smart_beacon"]["turn_min"] = conf.smart_beacon.turn_min; data["smart_beacon"]["slow_rate"] = conf.smart_beacon.slow_rate; @@ -114,3 +132,16 @@ void ConfigurationManagement::writeConfiguration(Configuration conf) { serializeJson(data, file); file.close(); } + +Configuration::Beacon Configuration::GetCurrentBeacon() { + auto iterator = this->beacons.begin(); + std::advance(iterator, this->current_beacon_index); + return *iterator; +} + +Configuration::Beacon Configuration::SetNextBeacon() { + this->current_beacon_index++; + if (this->current_beacon_index >= this->beacons.size()) + this->current_beacon_index = 0; + return this->GetCurrentBeacon(); +} \ No newline at end of file diff --git a/src/configuration.h b/src/configuration.h index affa0cd..2aca0fe 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -2,6 +2,7 @@ #define CONFIGURATION_H_ #include +#include #include @@ -9,14 +10,14 @@ class Configuration { public: class Beacon { public: - Beacon() : message("LoRa Tracker, Info: github.com/lora-aprs/LoRa_APRS_Tracker"), timeout(1), symbol("["), overlay("/"), button_tx(false) { + Beacon() : callsign("NOCALL-10"), message("LoRa Tracker, Info: github.com/lora-aprs/LoRa_APRS_Tracker"), timeout(1), symbol("["), overlay("/") { } + String callsign; String message; int timeout; String symbol; String overlay; - bool button_tx; }; class Smart_Beacon { @@ -59,15 +60,28 @@ public: bool reverse; }; - Configuration() : callsign("NOCALL-10"), debug(false), enhance_precision(true){}; + class Button { + public: + Button() : tx(false), alt_message(false) { + } - String callsign; - bool debug; - bool enhance_precision; - Beacon beacon; - Smart_Beacon smart_beacon; - LoRa lora; - PTT ptt; + bool tx; + int alt_message; + }; + + Configuration() : debug(false), enhance_precision(true), current_beacon_index(0) {}; + + bool debug; + bool enhance_precision; + std::list beacons; + int current_beacon_index; + Smart_Beacon smart_beacon; + LoRa lora; + PTT ptt; + Button button; + + Beacon GetCurrentBeacon(); + Beacon SetNextBeacon(); }; class ConfigurationManagement {