diff --git a/.github/workflows/build_check.yml b/.github/workflows/build_check.yml index 3694829..a5655db 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/build_check.yml @@ -1,19 +1,15 @@ name: Integreation Tests -on: [push, pull_request] +on: + push: + branches: + - '*' + - '!master' + pull_request: + branches: + - master jobs: - version_check: - name: Version Check - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - - name: check version - run: ./scripts/check_version.py - build: name: Compile Firmware runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ccc28a..71a9939 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,46 +1,39 @@ -on: - push: - tags: - - 'v*' +name: Create new release -name: Upload Release Assets +on: + workflow_dispatch: jobs: - build: - name: Upload Release Assets + version_check: + name: Version Check runs-on: ubuntu-latest steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up Python + uses: actions/setup-python@v2 + - run: pip install GitPython + - name: check version + run: ./scripts/check_version.py + + create_release: + needs: version_check + name: Create new release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 - run: sudo apt-get install python3-setuptools python3-wheel - run: pip3 install platformio - run: echo "$HOME/.local/bin" >> $GITHUB_PATH - - uses: actions/checkout@v2 - with: - submodules: 'recursive' - run: platformio run - - id: create_release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - run: echo "VERSION=$(./scripts/create_version_tag.py)" >> $GITHUB_ENV + - uses: ncipollo/release-action@v1 with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: false - prerelease: false - # upload firmware bin - - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: .pio/build/lora_board/firmware.bin - asset_name: lora_board.bin - asset_content_type: application/bin - # upload json file - - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: data/is-cfg.json - asset_name: is-cfg.json - asset_content_type: application/json \ No newline at end of file + tag: ${{ env.VERSION }} + commit: master + generateReleaseNotes: true + artifacts: ".pio/build/lora_board/firmware.bin,data/is-cfg.json" + owner: ${{ secrets.OWNER }} + token: ${{ secrets.PAT }} diff --git a/.github/workflows/tweet_release.yml b/.github/workflows/tweet_release.yml new file mode 100644 index 0000000..462b2bc --- /dev/null +++ b/.github/workflows/tweet_release.yml @@ -0,0 +1,19 @@ +name: tweet-release + +on: + release: + types: [published] + +jobs: + tweet: + runs-on: ubuntu-latest + steps: + - uses: Eomm/why-don-t-you-tweet@v1 + if: ${{ !github.event.repository.private }} + with: + tweet-message: "New ${{ github.event.repository.name }} release ${{ github.event.release.tag_name }}! ${{ github.event.release.html_url }} #LoRa #APRS #HAM #hamradio #iGate" + env: + TWITTER_CONSUMER_API_KEY: ${{ secrets.TWITTER_CONSUMER_API_KEY }} + TWITTER_CONSUMER_API_SECRET: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} + TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }} + TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} diff --git a/data/is-cfg.json b/data/is-cfg.json index 942f750..47d6f65 100644 --- a/data/is-cfg.json +++ b/data/is-cfg.json @@ -29,6 +29,7 @@ "latitude": 0.000000, "longitude": 0.000000 }, + "use_gps": false, "timeout": 15 }, "aprs_is": { diff --git a/lib/BoardFinder/BoardFinder.cpp b/lib/BoardFinder/BoardFinder.cpp index 318e343..797d229 100644 --- a/lib/BoardFinder/BoardFinder.cpp +++ b/lib/BoardFinder/BoardFinder.cpp @@ -4,8 +4,8 @@ #define MODULE_NAME "BoardFinder" -BoardConfig::BoardConfig(String name, BoardType type, uint8_t oledsda, uint8_t oledscl, uint8_t oledaddr, uint8_t oledreset, uint8_t lorasck, uint8_t loramiso, uint8_t loramosi, uint8_t loracs, uint8_t lorareset, uint8_t lorairq, bool needcheckpowerchip, bool powercheckstatus) - : Name(name), Type(type), OledSda(oledsda), OledScl(oledscl), OledAddr(oledaddr), OledReset(oledreset), LoraSck(lorasck), LoraMiso(loramiso), LoraMosi(loramosi), LoraCS(loracs), LoraReset(lorareset), LoraIRQ(lorairq), needCheckPowerChip(needcheckpowerchip), powerCheckStatus(powercheckstatus) { +BoardConfig::BoardConfig(String name, BoardType type, uint8_t oledsda, uint8_t oledscl, uint8_t oledaddr, uint8_t oledreset, uint8_t lorasck, uint8_t loramiso, uint8_t loramosi, uint8_t loracs, uint8_t lorareset, uint8_t lorairq, uint8_t gpsrx, uint8_t gpstx, uint8_t button, bool needcheckpowerchip, bool powercheckstatus) + : Name(name), Type(type), OledSda(oledsda), OledScl(oledscl), OledAddr(oledaddr), OledReset(oledreset), LoraSck(lorasck), LoraMiso(loramiso), LoraMosi(loramosi), LoraCS(loracs), LoraReset(lorareset), LoraIRQ(lorairq), GpsRx(gpsrx), GpsTx(gpstx), Button(button), needCheckPowerChip(needcheckpowerchip), powerCheckStatus(powercheckstatus) { } BoardFinder::BoardFinder(const std::list &boardConfigs) : _boardConfigs(boardConfigs) { @@ -130,14 +130,14 @@ bool BoardFinder::checkPowerConfig(BoardConfig const *boardConfig, logging::Logg } // clang-format off -BoardConfig TTGO_LORA32_V1 ("TTGO_LORA32_V1", eTTGO_LORA32_V1, 4, 15, 0x3C, 0, 5, 19, 27, 18, 14, 26); -BoardConfig TTGO_LORA32_V2 ("TTGO_LORA32_V2", eTTGO_LORA32_V2, 21, 22, 0x3C, 0, 5, 19, 27, 18, 14, 26, true); -BoardConfig TTGO_T_Beam_V0_7 ("TTGO_T_Beam_V0_7", eTTGO_T_Beam_V0_7, 21, 22, 0x3C, 0, 5, 19, 27, 18, 14, 26, true); -BoardConfig TTGO_T_Beam_V1_0 ("TTGO_T_Beam_V1_0", eTTGO_T_Beam_V1_0, 21, 22, 0x3C, 0, 5, 19, 27, 18, 14, 26, true, true); -BoardConfig ETH_BOARD ("ETH_BOARD", eETH_BOARD, 33, 32, 0x3C, 0, 14, 2, 15, 12, 4, 36); -BoardConfig TRACKERD ("TRACKERD", eTRACKERD, 5, 4, 0x3C, 0, 18, 19, 23, 16, 14, 26); -BoardConfig HELTEC_WIFI_LORA_32_V1("HELTEC_WIFI_LORA_32_V1", eHELTEC_WIFI_LORA_32_V1, 4, 15, 0x3C, 16, 5, 19, 27, 18, 14, 26); -BoardConfig HELTEC_WIFI_LORA_32_V2("HELTEC_WIFI_LORA_32_V2", eHELTEC_WIFI_LORA_32_V2, 4, 15, 0x3C, 16, 5, 19, 27, 18, 14, 26); -BoardConfig GUALTHERIUS_LORAHAM_v100("GUALTHERIUS_LORAHAM_v100", eGUALTHERIUS_LORAHAM_v100, 17, 16, 0x3C, 0, 18, 19, 23, 5, 13, 35); -BoardConfig GUALTHERIUS_LORAHAM_v106("GUALTHERIUS_LORAHAM_v106", eGUALTHERIUS_LORAHAM_v100, 17, 16, 0x3C, 0, 18, 19, 23, 2, 13, 35); +BoardConfig TTGO_LORA32_V1 ("TTGO_LORA32_V1", eTTGO_LORA32_V1, 4, 15, 0x3C, 0, 5, 19, 27, 18, 14, 26, 0, 0, 0); +BoardConfig TTGO_LORA32_V2 ("TTGO_LORA32_V2", eTTGO_LORA32_V2, 21, 22, 0x3C, 0, 5, 19, 27, 18, 14, 26, 0, 0, 0, true); +BoardConfig TTGO_T_Beam_V0_7 ("TTGO_T_Beam_V0_7", eTTGO_T_Beam_V0_7, 21, 22, 0x3C, 0, 5, 19, 27, 18, 14, 26, 15, 12, 38, true); +BoardConfig TTGO_T_Beam_V1_0 ("TTGO_T_Beam_V1_0", eTTGO_T_Beam_V1_0, 21, 22, 0x3C, 0, 5, 19, 27, 18, 14, 26, 12, 34, 38, true, true); +BoardConfig ETH_BOARD ("ETH_BOARD", eETH_BOARD, 33, 32, 0x3C, 0, 14, 2, 15, 12, 4, 36, 0, 0, 0); +BoardConfig TRACKERD ("TRACKERD", eTRACKERD, 5, 4, 0x3C, 0, 18, 19, 23, 16, 14, 26, 0, 0, 0); +BoardConfig HELTEC_WIFI_LORA_32_V1("HELTEC_WIFI_LORA_32_V1", eHELTEC_WIFI_LORA_32_V1, 4, 15, 0x3C, 16, 5, 19, 27, 18, 14, 26, 0, 0, 0); +BoardConfig HELTEC_WIFI_LORA_32_V2("HELTEC_WIFI_LORA_32_V2", eHELTEC_WIFI_LORA_32_V2, 4, 15, 0x3C, 16, 5, 19, 27, 18, 14, 26, 0, 0, 0); +BoardConfig GUALTHERIUS_LORAHAM_v100("GUALTHERIUS_LORAHAM_v100", eGUALTHERIUS_LORAHAM_v100, 17, 16, 0x3C, 0, 18, 19, 23, 5, 13, 35, 0, 0, 0); +BoardConfig GUALTHERIUS_LORAHAM_v106("GUALTHERIUS_LORAHAM_v106", eGUALTHERIUS_LORAHAM_v106, 17, 16, 0x3C, 0, 18, 19, 23, 2, 13, 35, 0, 0, 0); // clang-format on diff --git a/lib/BoardFinder/BoardFinder.h b/lib/BoardFinder/BoardFinder.h index c0bf6e5..8df5a5a 100644 --- a/lib/BoardFinder/BoardFinder.h +++ b/lib/BoardFinder/BoardFinder.h @@ -26,7 +26,7 @@ enum BoardType class BoardConfig { public: - explicit BoardConfig(String name, BoardType type, uint8_t oledsda, uint8_t oledscl, uint8_t oledaddr, uint8_t oledreset, uint8_t lorasck, uint8_t loramiso, uint8_t loramosi, uint8_t loracs, uint8_t lorareset, uint8_t lorairq, bool needcheckpowerchip = false, bool powercheckstatus = false); + explicit BoardConfig(String name, BoardType type, uint8_t oledsda, uint8_t oledscl, uint8_t oledaddr, uint8_t oledreset, uint8_t lorasck, uint8_t loramiso, uint8_t loramosi, uint8_t loracs, uint8_t lorareset, uint8_t lorairq, uint8_t gpsrx, uint8_t gpstx, uint8_t button, bool needcheckpowerchip = false, bool powercheckstatus = false); String Name; BoardType Type; @@ -42,6 +42,9 @@ public: uint8_t LoraCS; uint8_t LoraReset; uint8_t LoraIRQ; + uint8_t GpsRx; + uint8_t GpsTx; + uint8_t Button; bool needCheckPowerChip; bool powerCheckStatus; diff --git a/lib/LoRa/LoRa.cpp b/lib/LoRa/LoRa.cpp index 35dfacd..2422ca8 100644 --- a/lib/LoRa/LoRa.cpp +++ b/lib/LoRa/LoRa.cpp @@ -18,6 +18,7 @@ #define REG_FIFO_RX_CURRENT_ADDR 0x10 #define REG_IRQ_FLAGS 0x12 #define REG_RX_NB_BYTES 0x13 +#define REG_MODEM_STAT 0x18 #define REG_PKT_SNR_VALUE 0x19 #define REG_PKT_RSSI_VALUE 0x1a #define REG_RSSI_VALUE 0x1b @@ -251,6 +252,10 @@ float LoRaClass::packetSnr() { return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25; } +bool LoRaClass::rxSignalDetected() { + return (readRegister(REG_MODEM_STAT) & 0x01) == 0x01; +} + long LoRaClass::packetFrequencyError() { int32_t freqError = 0; freqError = static_cast(readRegister(REG_FREQ_ERROR_MSB) & B111); diff --git a/lib/LoRa/LoRa.h b/lib/LoRa/LoRa.h index 51e089a..45c92bd 100644 --- a/lib/LoRa/LoRa.h +++ b/lib/LoRa/LoRa.h @@ -44,6 +44,7 @@ public: int packetRssi(); float packetSnr(); long packetFrequencyError(); + bool rxSignalDetected(); int rssi(); diff --git a/platformio.ini b/platformio.ini index e9d1555..a2f5cb3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,6 +14,8 @@ lib_deps = peterus/esp-logger @ 1.0.0 peterus/ESP-FTP-Server-Lib @ 0.9.5 knolleary/PubSubClient@^2.8 + mikalhart/TinyGPSPlus @ 1.0.2 + shaggydog/OneButton @ 1.5.0 check_tool = cppcheck check_flags = cppcheck: --suppress=*:*.pio\* --inline-suppr -DCPPCHECK --force lib -ilib/TimeLib -ilib/LoRa -ilib/NTPClient diff --git a/scripts/check_version.py b/scripts/check_version.py index df9914f..57f87ea 100755 --- a/scripts/check_version.py +++ b/scripts/check_version.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +import git from datetime import date today = date.today() @@ -16,20 +17,33 @@ with open("src/LoRa_APRS_iGate.cpp") as f: version_split = version.split(".") version_year = int(version_split[0]) version_week = int(version_split[1]) +version_vers = int(version_split[2]) -print(f"firmware version year: {version_year}") -print(f"firmware version week: {version_week}") +print(f"[INFO] firmware version year: {version_year}") +print(f"[INFO] firmware version week: {version_week}") +print(f"[INFO] firmware version version: {version_vers}") +print(f"[INFO] -> {version}") -print(f"current year: {current_year}") -print(f"current week: {current_week}") +print(f"[INFO] current year: {current_year}") +print(f"[INFO] current week: {current_week}") +print(f"[INFO] -> {current_year}.{current_week}.x") error = False if version_year != current_year: - print("firmware version is not current year!") + print("[ERROR] firmware version is not current year!") error = True if version_week != current_week: - print("firmware version is not current week!") + print("[ERROR] firmware version is not current week!") error = True +repo = git.Repo('.') +print(f"[INFO] found {len(repo.tags)} tags in repo") +if f"v{version}" in repo.tags: + print("[ERROR] tag with this version is already existing") + error = True + +if error: + print("[ERROR] check/update VERSION define in src/LoRa_APRS_iGate.cpp to fix this issue") + exit(error) diff --git a/scripts/create_version_tag.py b/scripts/create_version_tag.py new file mode 100755 index 0000000..5b37c82 --- /dev/null +++ b/scripts/create_version_tag.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +from datetime import date + +today = date.today() + +current_year = int(str(today.isocalendar()[0])[2:]) +current_week = int(today.isocalendar()[1]) + +version = None +with open("src/LoRa_APRS_iGate.cpp") as f: + for line in f: + if line.startswith("#define VERSION"): + version = line.strip().split(" ")[-1].replace('"', "") + +version_split = version.split(".") +version_year = int(version_split[0]) +version_week = int(version_split[1]) +version_vers = int(version_split[2]) + +print(f"v{version_year}.{version_week}.{version_vers}") diff --git a/src/LoRa_APRS_iGate.cpp b/src/LoRa_APRS_iGate.cpp index 465692d..4b8cf97 100644 --- a/src/LoRa_APRS_iGate.cpp +++ b/src/LoRa_APRS_iGate.cpp @@ -8,6 +8,7 @@ #include #include "TaskAprsIs.h" +#include "TaskBeacon.h" #include "TaskDisplay.h" #include "TaskEth.h" #include "TaskFTP.h" @@ -19,7 +20,7 @@ #include "TaskWifi.h" #include "project_configuration.h" -#define VERSION "22.11.2" +#define VERSION "22.14.0" #define MODULE_NAME "Main" String create_lat_aprs(double lat); @@ -43,6 +44,7 @@ FTPTask ftpTask; MQTTTask mqttTask(toMQTT); AprsIsTask aprsIsTask(toAprsIs); RouterTask routerTask(fromModem, toModem, toAprsIs, toMQTT); +BeaconTask beaconTask(toModem, toAprsIs); void setup() { Serial.begin(115200); @@ -95,7 +97,11 @@ void setup() { } powerManagement.activateLoRa(); powerManagement.activateOLED(); - powerManagement.deactivateGPS(); + if (userConfig.beacon.use_gps) { + powerManagement.activateGPS(); + } else { + powerManagement.deactivateGPS(); + } } LoRaSystem.setBoardConfig(boardConfig); @@ -112,24 +118,33 @@ void setup() { LoRaSystem.getTaskManager().addTask(&displayTask); LoRaSystem.getTaskManager().addTask(&modemTask); LoRaSystem.getTaskManager().addTask(&routerTask); + LoRaSystem.getTaskManager().addTask(&beaconTask); - if (userConfig.aprs_is.active) { - if (boardConfig->Type == eETH_BOARD && !userConfig.wifi.active) { - LoRaSystem.getTaskManager().addAlwaysRunTask(ðTask); - } - if (userConfig.wifi.active) { - LoRaSystem.getTaskManager().addAlwaysRunTask(&wifiTask); - } + bool tcpip = false; + + if (userConfig.wifi.active) { + LoRaSystem.getTaskManager().addAlwaysRunTask(&wifiTask); + tcpip = true; + } + if (boardConfig->Type == eETH_BOARD) { + LoRaSystem.getTaskManager().addAlwaysRunTask(ðTask); + tcpip = true; + } + + if (tcpip) { LoRaSystem.getTaskManager().addTask(&otaTask); LoRaSystem.getTaskManager().addTask(&ntpTask); if (userConfig.ftp.active) { LoRaSystem.getTaskManager().addTask(&ftpTask); } - LoRaSystem.getTaskManager().addTask(&aprsIsTask); - } - if (userConfig.mqtt.active) { - LoRaSystem.getTaskManager().addTask(&mqttTask); + if (userConfig.aprs_is.active) { + LoRaSystem.getTaskManager().addTask(&aprsIsTask); + } + + if (userConfig.mqtt.active) { + LoRaSystem.getTaskManager().addTask(&mqttTask); + } } LoRaSystem.getTaskManager().setup(LoRaSystem); @@ -176,27 +191,3 @@ void loop() { syslogSet = true; } } - -String create_lat_aprs(double lat) { - char str[20]; - char n_s = 'N'; - if (lat < 0) { - n_s = 'S'; - } - lat = std::abs(lat); - sprintf(str, "%02d%05.2f%c", (int)lat, (lat - (double)((int)lat)) * 60.0, n_s); - String lat_str(str); - return lat_str; -} - -String create_long_aprs(double lng) { - char str[20]; - char e_w = 'E'; - if (lng < 0) { - e_w = 'W'; - } - lng = std::abs(lng); - sprintf(str, "%03d%05.2f%c", (int)lng, (lng - (double)((int)lng)) * 60.0, e_w); - String lng_str(str); - return lng_str; -} diff --git a/src/Task.h b/src/Task.h index 7dd4e6d..cd4b3da 100644 --- a/src/Task.h +++ b/src/Task.h @@ -12,6 +12,7 @@ enum TaskNames TaskWifi, TaskRouter, TaskMQTT, + TaskBeacon, TaskSize }; @@ -24,5 +25,6 @@ enum TaskNames #define TASK_WIFI "WifiTask" #define TASK_ROUTER "RouterTask" #define TASK_MQTT "MQTTTask" +#define TASK_BEACON "BeaconTask" #endif diff --git a/src/TaskBeacon.cpp b/src/TaskBeacon.cpp new file mode 100644 index 0000000..e356920 --- /dev/null +++ b/src/TaskBeacon.cpp @@ -0,0 +1,126 @@ +#include + +#include +#include + +#include "Task.h" +#include "TaskBeacon.h" +#include "project_configuration.h" + +BeaconTask::BeaconTask(TaskQueue> &toModem, TaskQueue> &toAprsIs) : Task(TASK_BEACON, TaskBeacon), _toModem(toModem), _toAprsIs(toAprsIs), _ss(1), _useGps(false) { +} + +BeaconTask::~BeaconTask() { +} + +OneButton BeaconTask::_userButton; +bool BeaconTask::_send_update; +uint BeaconTask::_instances; + +void BeaconTask::pushButton() { + _send_update = true; +} + +bool BeaconTask::setup(System &system) { + if (_instances++ == 0 && system.getBoardConfig()->Button > 0) { + _userButton = OneButton(system.getBoardConfig()->Button, true, true); + _userButton.attachClick(pushButton); + _send_update = false; + } + + _useGps = system.getUserConfig()->beacon.use_gps; + + if (_useGps) { + if (system.getBoardConfig()->GpsRx != 0) { + _ss.begin(9600, SERIAL_8N1, system.getBoardConfig()->GpsTx, system.getBoardConfig()->GpsRx); + } else { + system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "NO GPS found."); + _useGps = false; + } + } + // setup beacon + _beacon_timer.setTimeout(system.getUserConfig()->beacon.timeout * 60 * 1000); + + _beaconMsg = std::shared_ptr(new APRSMessage()); + _beaconMsg->setSource(system.getUserConfig()->callsign); + _beaconMsg->setDestination("APLG01"); + + return true; +} + +bool BeaconTask::loop(System &system) { + if (_useGps) { + while (_ss.available() > 0) { + char c = _ss.read(); + _gps.encode(c); + } + } + + _userButton.tick(); + + // check for beacon + if (_beacon_timer.check() || _send_update) { + if (sendBeacon(system)) { + _send_update = false; + _beacon_timer.start(); + } + } + + uint32_t diff = _beacon_timer.getTriggerTimeInSec(); + _stateInfo = "beacon " + String(uint32_t(diff / 600)) + String(uint32_t(diff / 60) % 10) + ":" + String(uint32_t(diff / 10) % 6) + String(uint32_t(diff % 10)); + + return true; +} + +String create_lat_aprs(double lat) { + char str[20]; + char n_s = 'N'; + if (lat < 0) { + n_s = 'S'; + } + lat = std::abs(lat); + sprintf(str, "%02d%05.2f%c", (int)lat, (lat - (double)((int)lat)) * 60.0, n_s); + String lat_str(str); + return lat_str; +} + +String create_long_aprs(double lng) { + char str[20]; + char e_w = 'E'; + if (lng < 0) { + e_w = 'W'; + } + lng = std::abs(lng); + sprintf(str, "%03d%05.2f%c", (int)lng, (lng - (double)((int)lng)) * 60.0, e_w); + String lng_str(str); + return lng_str; +} + +bool BeaconTask::sendBeacon(System &system) { + double lat = system.getUserConfig()->beacon.positionLatitude; + double lng = system.getUserConfig()->beacon.positionLongitude; + + if (_useGps) { + if (_gps.location.isUpdated()) { + lat = _gps.location.lat(); + lng = _gps.location.lng(); + } else { + return false; + } + } + _beaconMsg->getBody()->setData(String("=") + create_lat_aprs(lat) + "L" + create_long_aprs(lng) + "&" + system.getUserConfig()->beacon.message); + + system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "[%s] %s", timeString().c_str(), _beaconMsg->encode().c_str()); + + if (system.getUserConfig()->aprs_is.active) { + _toAprsIs.addElement(_beaconMsg); + } + + if (system.getUserConfig()->digi.beacon) { + _toModem.addElement(_beaconMsg); + } + + system.getDisplay().addFrame(std::shared_ptr(new TextFrame("BEACON", _beaconMsg->toString()))); + + return true; +} diff --git a/src/TaskBeacon.h b/src/TaskBeacon.h new file mode 100644 index 0000000..ba0ff22 --- /dev/null +++ b/src/TaskBeacon.h @@ -0,0 +1,37 @@ +#ifndef TASK_BEACON_H_ +#define TASK_BEACON_H_ + +#include +#include + +#include +#include +#include + +class BeaconTask : public Task { +public: + BeaconTask(TaskQueue> &toModem, TaskQueue> &toAprsIs); + virtual ~BeaconTask(); + + virtual bool setup(System &system) override; + virtual bool loop(System &system) override; + bool sendBeacon(System &system); + +private: + TaskQueue> &_toModem; + TaskQueue> &_toAprsIs; + + std::shared_ptr _beaconMsg; + Timer _beacon_timer; + + HardwareSerial _ss; + TinyGPSPlus _gps; + bool _useGps; + + static uint _instances; + static OneButton _userButton; + static bool _send_update; + static void pushButton(); +}; + +#endif diff --git a/src/TaskModem.cpp b/src/TaskModem.cpp index ca0784d..05e4fcd 100644 --- a/src/TaskModem.cpp +++ b/src/TaskModem.cpp @@ -39,19 +39,24 @@ bool ModemTask::setup(System &system) { bool ModemTask::loop(System &system) { if (_lora_aprs.checkMessage()) { std::shared_ptr msg = _lora_aprs.getMessage(); - system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Received packet '%s' with RSSI %d and SNR %f", timeString().c_str(), msg->toString().c_str(), _lora_aprs.packetRssi(), _lora_aprs.packetSnr()); + system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Received packet '%s' with RSSI %ddBm, SNR %.2fdB and FreqErr %dHz", timeString().c_str(), msg->toString().c_str(), _lora_aprs.packetRssi(), _lora_aprs.packetSnr(), -_lora_aprs.packetFrequencyError()); _fromModem.addElement(msg); system.getDisplay().addFrame(std::shared_ptr(new TextFrame("LoRa", msg->toString().c_str()))); } if (!_toModem.empty()) { - std::shared_ptr msg = _toModem.getElement(); - if (system.getUserConfig()->lora.tx_enable) { - system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Transmitting packet '%s'", timeString().c_str(), msg->toString().c_str()); - _lora_aprs.sendMessage(msg); - system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX done", timeString().c_str()); + if (_lora_aprs.rxSignalDetected()) { + system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] RX signal detected. Waiting TX", timeString().c_str()); + delay(1000); } else { - system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] NOT transmitting packet as TX is not enabled '%s'", timeString().c_str(), msg->toString().c_str()); + std::shared_ptr msg = _toModem.getElement(); + if (system.getUserConfig()->lora.tx_enable) { + system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Transmitting packet '%s'", timeString().c_str(), msg->toString().c_str()); + _lora_aprs.sendMessage(msg); + system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX done", timeString().c_str()); + } else { + system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] NOT transmitting packet as TX is not enabled '%s'", timeString().c_str(), msg->toString().c_str()); + } } } diff --git a/src/TaskRouter.cpp b/src/TaskRouter.cpp index 96b13dc..dc9da8a 100644 --- a/src/TaskRouter.cpp +++ b/src/TaskRouter.cpp @@ -6,9 +6,6 @@ #include "TaskRouter.h" #include "project_configuration.h" -String create_lat_aprs(double lat); -String create_long_aprs(double lng); - RouterTask::RouterTask(TaskQueue> &fromModem, TaskQueue> &toModem, TaskQueue> &toAprsIs, TaskQueue> &toMQTT) : Task(TASK_ROUTER, TaskRouter), _fromModem(fromModem), _toModem(toModem), _toAprsIs(toAprsIs), _toMQTT(toMQTT) { } @@ -16,15 +13,6 @@ RouterTask::~RouterTask() { } bool RouterTask::setup(System &system) { - _beacon_timer.setTimeout(system.getUserConfig()->beacon.timeout * 60 * 1000); - - _beaconMsg = std::shared_ptr(new APRSMessage()); - _beaconMsg->setSource(system.getUserConfig()->callsign); - _beaconMsg->setDestination("APLG01"); - String lat = create_lat_aprs(system.getUserConfig()->beacon.positionLatitude); - String lng = create_long_aprs(system.getUserConfig()->beacon.positionLongitude); - _beaconMsg->getBody()->setData(String("=") + lat + "L" + lng + "&" + system.getUserConfig()->beacon.message); - return true; } @@ -78,23 +66,7 @@ bool RouterTask::loop(System &system) { } } - // check for beacon - if (_beacon_timer.check()) { - system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "[%s] %s", timeString().c_str(), _beaconMsg->encode().c_str()); - - if (system.getUserConfig()->aprs_is.active) - _toAprsIs.addElement(_beaconMsg); - - if (system.getUserConfig()->digi.beacon) { - _toModem.addElement(_beaconMsg); - } - - system.getDisplay().addFrame(std::shared_ptr(new TextFrame("BEACON", _beaconMsg->toString()))); - _beacon_timer.start(); - } - - uint32_t diff = _beacon_timer.getTriggerTimeInSec(); - _stateInfo = "beacon " + String(uint32_t(diff / 600)) + String(uint32_t(diff / 60) % 10) + ":" + String(uint32_t(diff / 10) % 6) + String(uint32_t(diff % 10)); + _stateInfo = "Router done "; return true; } diff --git a/src/TaskRouter.h b/src/TaskRouter.h index 348cdff..a2e1bbe 100644 --- a/src/TaskRouter.h +++ b/src/TaskRouter.h @@ -18,9 +18,6 @@ private: TaskQueue> &_toModem; TaskQueue> &_toAprsIs; TaskQueue> &_toMQTT; - - std::shared_ptr _beaconMsg; - Timer _beacon_timer; }; #endif diff --git a/src/project_configuration.cpp b/src/project_configuration.cpp index 92e6d43..3dc30e1 100644 --- a/src/project_configuration.cpp +++ b/src/project_configuration.cpp @@ -33,24 +33,29 @@ void ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocumen JsonArray aps = data["wifi"]["AP"].as(); for (JsonVariant v : aps) { Configuration::Wifi::AP ap; - ap.SSID = v["SSID"].as(); - ap.password = v["password"].as(); + if (v.containsKey("SSID")) + ap.SSID = v["SSID"].as(); + if (v.containsKey("password")) + 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.beacon.use_gps = data["beacon"]["use_gps"] | false; conf.beacon.timeout = data["beacon"]["timeout"] | 15; conf.aprs_is.active = data["aprs_is"]["active"] | true; + if (data.containsKey("aprs_is") && data["aprs_is"].containsKey("passcode")) conf.aprs_is.passcode = data["aprs_is"]["passcode"].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.digi.active = data["digi"]["active"] | false; - conf.digi.beacon = data["digi"]["beacon"] | false; + conf.digi.active = data["digi"]["active"] | false; + conf.digi.beacon = data["digi"]["beacon"] | false; + conf.lora.frequencyRx = data["lora"]["frequency_rx"] | 433775000; conf.lora.gainRx = data["lora"]["gain_rx"] | 0; conf.lora.frequencyTx = data["lora"]["frequency_tx"] | 433775000; @@ -59,6 +64,7 @@ void ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocumen conf.lora.signalBandwidth = data["lora"]["signal_bandwidth"] | 125000; conf.lora.codingRate4 = data["lora"]["coding_rate4"] | 5; conf.lora.tx_enable = data["lora"]["tx_enable"] | true; + conf.display.alwaysOn = data["display"]["always_on"] | true; conf.display.timeout = data["display"]["timeout"] | 10; conf.display.overwritePin = data["display"]["overwrite_pin"] | 0; @@ -70,8 +76,10 @@ void ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocumen JsonArray users = data["ftp"]["user"].as(); for (JsonVariant u : users) { Configuration::Ftp::User us; - us.name = u["name"].as(); - us.password = u["password"].as(); + if (u.containsKey("name")) + us.name = u["name"].as(); + if (u.containsKey("password")) + us.password = u["password"].as(); conf.ftp.users.push_back(us); } if (conf.ftp.users.empty()) { @@ -80,19 +88,23 @@ void ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocumen us.password = "ftp"; conf.ftp.users.push_back(us); } - if (data.containsKey("mqtt")) { - conf.mqtt.active = data["mqtt"]["active"] | false; - conf.mqtt.server = data["mqtt"]["server"].as(); - conf.mqtt.port = data["mqtt"]["port"].as(); - conf.mqtt.name = data["mqtt"]["name"].as(); + + conf.mqtt.active = data["mqtt"]["active"] | false; + if (data["mqtt"].containsKey("server")) + conf.mqtt.server = data["mqtt"]["server"].as(); + conf.mqtt.port = data["mqtt"]["port"] | 1883; + if (data["mqtt"].containsKey("name")) + conf.mqtt.name = data["mqtt"]["name"].as(); + if (data["mqtt"].containsKey("password")) conf.mqtt.password = data["mqtt"]["password"].as(); - conf.mqtt.topic = data["mqtt"]["topic"].as(); - } - if (data.containsKey("syslog")) { - conf.syslog.active = data["syslog"]["active"] | true; + if (data["mqtt"].containsKey("topic")) + conf.mqtt.topic = data["mqtt"]["topic"].as(); + + conf.syslog.active = data["syslog"]["active"] | true; + if (data["syslog"].containsKey("server")) conf.syslog.server = data["syslog"]["server"].as(); - conf.syslog.port = data["syslog"]["port"] | 514; - } + conf.syslog.port = data["syslog"]["port"] | 514; + if (data.containsKey("ntp_server")) conf.ntpServer = data["ntp_server"].as(); @@ -124,6 +136,7 @@ void ProjectConfigurationManagement::writeProjectConfiguration(Configuration &co data["beacon"]["message"] = conf.beacon.message; data["beacon"]["position"]["latitude"] = conf.beacon.positionLatitude; data["beacon"]["position"]["longitude"] = conf.beacon.positionLongitude; + data["beacon"]["use_gps"] = conf.beacon.use_gps; data["beacon"]["timeout"] = conf.beacon.timeout; data["aprs_is"]["active"] = conf.aprs_is.active; data["aprs_is"]["passcode"] = conf.aprs_is.passcode; diff --git a/src/project_configuration.h b/src/project_configuration.h index de64c60..c5ca4fd 100644 --- a/src/project_configuration.h +++ b/src/project_configuration.h @@ -48,12 +48,13 @@ public: class Beacon { public: - Beacon() : message("LoRa iGATE & Digi, Info: github.com/peterus/LoRa_APRS_iGate"), positionLatitude(0.0), positionLongitude(0.0), timeout(15) { + Beacon() : message("LoRa iGATE & Digi, Info: github.com/peterus/LoRa_APRS_iGate"), positionLatitude(0.0), positionLongitude(0.0), use_gps(false), timeout(15) { } String message; double positionLatitude; double positionLongitude; + bool use_gps; int timeout; }; @@ -125,12 +126,12 @@ public: MQTT() : active(false), server(""), port(1883), name(""), password(""), topic("LoraAPRS/Data") { } - bool active; - String server; - uint16_t port; - String name; - String password; - String topic; + bool active; + String server; + int port; + String name; + String password; + String topic; }; class Syslog {