Merge branch 'master' into python_test_framework

python_test_framework
Peter Buchegger 2022-11-06 20:59:51 +01:00
commit 99be71263a
46 zmienionych plików z 1147 dodań i 1359 usunięć

Wyświetl plik

@ -0,0 +1,6 @@
ARG VARIANT="3.10-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}
RUN apt-get update && apt-get install -y clang-format-11
RUN pip3 --disable-pip-version-check --no-cache-dir install platformio

Wyświetl plik

@ -0,0 +1,33 @@
{
"name": "Python 3",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"VARIANT": "3.10-bullseye"
}
},
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
"clang-format.executable": "clang-format-11"
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"platformio.platformio-ide",
"xaver.clang-format"
],
"postCreateCommand": "pip3 install --user platformio",
//"remoteUser": "vscode"
}

Wyświetl plik

@ -1,6 +1,13 @@
name: Integreation Tests
on: [push, pull_request]
on:
push:
branches:
- '*'
- '!master'
pull_request:
branches:
- master
jobs:
build:
@ -31,8 +38,6 @@ jobs:
- 'lib/BoardFinder'
- 'lib/ConfigurationManagement'
#- 'lib/Display'
#- 'lib/LoRa'
- 'lib/LoRa_APRS'
#- 'lib/NTPClient'
- 'lib/PowerManagement'
- 'lib/System'
@ -41,7 +46,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@v2
- name: Run clang-format style check for C/C++ programs.
uses: jidicula/clang-format-action@v3.2.0
uses: jidicula/clang-format-action@v4.5.0
with:
clang-format-version: '11'
check-path: ${{ matrix.path }}

Wyświetl plik

@ -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
tag: ${{ env.VERSION }}
commit: master
generateReleaseNotes: true
artifacts: ".pio/build/lora_board/firmware.bin,data/is-cfg.json"
owner: ${{ secrets.OWNER }}
token: ${{ secrets.PAT }}

Wyświetl plik

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

Wyświetl plik

@ -18,11 +18,11 @@ Try it out and be part of the APRS network.
* [Manuel Lausmann - Tracker](https://www.youtube.com/watch?v=clIlTEFbWLk) (youtube - german - OLD) 02.11.2020
* [OE1ROT](https://www.aronaut.at/2019/12/lora-aprs-tracker-mit-ttgo-t-beam-433mhz/) (blog post - german) 09.12.2019
feel free to add yours or create a ticket if you want to be added.
Feel free to add yours or create a ticket if you want to be added.
## Supported boards
You can use one of the Lora32 boards without changings:
You can use one of the Lora32 boards without changes:
* Heltec WiFi LoRa 32 V1 (433MHz SX1278)
* Heltec WiFi LoRa 32 V2 (433MHz SX1278)
@ -42,7 +42,7 @@ Here are some amazon-de links for some example boards:
* [T-Beam V1.0](https://www.amazon.de/dp/B07RT9FKPL)
This boards cost around 20 Euros, they are very cheap and perfect for an LoRa iGate.
Keep in minde: you need a 433MHz version!
Keep in mind: you need a 433MHz version!
## Compiling and configuration
@ -63,22 +63,12 @@ The best success is to use PlatformIO (and it is the only platform where I can s
* You can find all nessesary settings to change for your configuration in **data/is-cfg.json**.
* To upload it to your board you have to do this via **Upload File System image** in PlatformIO!
* To find the 'Upload File System image' click the PlatformIO symbol (the little alien) on the left side, choos your configuration, click on 'Platform' and search for 'Upload File System image'.
* To find the 'Upload File System image' click the PlatformIO symbol (the little alien) on the left side, choose your configuration, click on 'Platform' and search for 'Upload File System image'.
## Branches in this repository and version system
This firmware is developed in a rolling release system: everyday a new release could be created. But there are still rules where new pull requests has to go and and how the version system looks like.
### Branches
There are 2 main branches:
* *master* and
* *develop*
The *master* branch has all releases and is the most stable one. With the different tags you can jump to different versions or if you take the most current *master* branch you will just get the latest, stable version. There will be no side releases which are branched of from *master*. If there is a bugfix version it will be done directly on the *master* branch and a tag will be generated with a new version.
The *develop* branch is used for new feature development. It will be also used to stabilize the current development to create a new stable version (pull request to *master* branch). **Again:** all new development (pull requests) has to go directly into the *develop* branch!
### Version system
If the *develop* branch is stable enough for a new release it will be merged with a pull request to the *master* branch and a new version will be generated.
@ -116,13 +106,15 @@ Look at my other project: a [LoRa Tracker](https://github.com/peterus/LoRa_APRS_
### Here are some peculiarities of the different boards
* TTGO T-Beam V1
* TTGO T-Beam V1.0 and V1.1 and SSD1306 OLED display
When adding a 0,96" OLED display direct to the board you have to be careful, there are two different pinout
When adding an SSD1306 0,96" OLED display direct to the board you have to be careful, there are two different pinout
versions on the market.
For direct mount you need a display with this Pinout -> [VCC - GND - SCL - SDA](pics/display-right.jpg).
A direct mount of the [other display](pics/display-wrong.jpg) is not possible without damage the display!
The 'wrong' display works too but you have to change VCC and GND by wire !
feel free to add hints!
The [LoRa APRS WiKi Displays](https://github.com/lora-aprs/LoRa_APRS_Tracker/wiki/Displays) page has more details.
Feel free to add hints!

Wyświetl plik

@ -2,13 +2,20 @@
"callsign": "NOCALL-10",
"network": {
"DHCP": true,
"staticIP": "192.0.2.100",
"subnet": "255.255.255.0",
"gateway": "192.0.2.1",
"dns1": "192.0.2.1",
"dns2": "192.0.2.2"
"static": {
"ip": "192.168.0.100",
"subnet": "255.255.255.0",
"gateway": "192.168.0.1",
"dns1": "192.168.0.1",
"dns2": "192.168.0.2"
},
"hostname": {
"overwrite": false,
"name": "NOCALL-10"
}
},
"wifi": {
"active": true,
"AP": [
{
"SSID": "YOURSSID",
@ -22,6 +29,7 @@
"latitude": 0.000000,
"longitude": 0.000000
},
"use_gps": false,
"timeout": 15
},
"aprs_is": {
@ -36,11 +44,13 @@
},
"lora": {
"frequency_rx": 433775000,
"gain_rx": 0,
"frequency_tx": 433775000,
"power": 20,
"spreading_factor": 12,
"signal_bandwidth": 125000,
"coding_rate4": 5
"coding_rate4": 5,
"tx_enable": false
},
"display": {
"always_on": true,
@ -57,5 +67,18 @@
}
]
},
"mqtt": {
"active": false,
"server": "",
"port": 1883,
"name": "",
"password": "",
"topic": "LoraAPRS/Data"
},
"syslog": {
"active": true,
"server": "syslog.lora-aprs.info",
"port": 514
},
"ntp_server": "pool.ntp.org"
}

Wyświetl plik

@ -8,34 +8,32 @@ void APRS_IS::setup(const String &user, const String &passcode, const String &to
_version = version;
}
bool APRS_IS::connect(const String &server, const int port) {
APRS_IS::ConnectionStatus APRS_IS::connect(const String &server, const int port) {
const String login = "user " + _user + " pass " + _passcode + " vers " + _tool_name + " " + _version + "\n\r";
return _connect(server, port, login);
}
bool APRS_IS::connect(const String &server, const int port, const String &filter) {
APRS_IS::ConnectionStatus APRS_IS::connect(const String &server, const int port, const String &filter) {
const String login = "user " + _user + " pass " + _passcode + " vers " + _tool_name + " " + _version + " filter " + filter + "\n\r";
return _connect(server, port, login);
}
bool APRS_IS::_connect(const String &server, const int port, const String &login_line) {
APRS_IS::ConnectionStatus APRS_IS::_connect(const String &server, const int port, const String &login_line) {
if (!_client.connect(server.c_str(), port)) {
logPrintlnE("Something went wrong on connecting! Is the server reachable?");
return false;
return ERROR_CONNECTION;
}
sendMessage(login_line);
while (true) {
String line = _client.readStringUntil('\n');
if (line.indexOf("logresp") != -1) {
if (line.indexOf("unverified") == -1) {
return true;
return SUCCESS;
} else {
logPrintlnE("User can not be verified with passcode!");
return false;
return ERROR_PASSCODE;
}
}
}
return true;
return SUCCESS;
}
bool APRS_IS::connected() {
@ -76,7 +74,6 @@ std::shared_ptr<APRSMessage> APRS_IS::getAPRSMessage() {
line = _client.readStringUntil('\n');
}
if (line.startsWith("#")) {
logPrintlnD(line);
return 0;
}
if (line.length() == 0) {

Wyświetl plik

@ -9,9 +9,16 @@ class APRS_IS {
public:
void setup(const String &user, const String &passcode, const String &tool_name, const String &version);
bool connect(const String &server, const int port);
bool connect(const String &server, const int port, const String &filter);
bool connected();
enum ConnectionStatus
{
SUCCESS,
ERROR_CONNECTION,
ERROR_PASSCODE,
};
ConnectionStatus connect(const String &server, const int port);
ConnectionStatus connect(const String &server, const int port, const String &filter);
bool connected();
bool sendMessage(const String &message);
bool sendMessage(const std::shared_ptr<APRSMessage> message);
@ -28,7 +35,7 @@ private:
String _version;
WiFiClient _client;
bool _connect(const String &server, const int port, const String &login_line);
ConnectionStatus _connect(const String &server, const int port, const String &login_line);
};
#endif

Wyświetl plik

@ -2,19 +2,21 @@
#include <logger.h>
#include <power_management.h>
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) {
#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, 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<BoardConfig const *> &boardConfigs) : _boardConfigs(boardConfigs) {
}
BoardConfig const *BoardFinder::searchBoardConfig() {
logPrintlnI("looking for a board config.");
logPrintlnI("searching for OLED...");
BoardConfig const *BoardFinder::searchBoardConfig(logging::Logger &logger) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "looking for a board config.");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "searching for OLED...");
for (BoardConfig const *boardconf : _boardConfigs) {
if (boardconf->needCheckPowerChip && checkPowerConfig(boardconf) == boardconf->powerCheckStatus) {
if (boardconf->needCheckPowerChip && checkPowerConfig(boardconf, logger) == boardconf->powerCheckStatus) {
PowerManagement powerManagement;
Wire.begin(boardconf->OledSda, boardconf->OledScl);
powerManagement.begin(Wire);
@ -22,30 +24,28 @@ BoardConfig const *BoardFinder::searchBoardConfig() {
} else if (boardconf->needCheckPowerChip) {
continue;
}
if (checkOledConfig(boardconf)) {
logPrintI("found a board config: ");
logPrintlnI(boardconf->Name);
if (checkOledConfig(boardconf, logger)) {
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "found a board config: %s", boardconf->Name.c_str());
return boardconf;
}
}
logPrintlnI("could not find OLED, will search for the modem now...");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "could not find OLED, will search for the modem now...");
for (BoardConfig const *boardconf : _boardConfigs) {
if (boardconf->needCheckPowerChip && checkPowerConfig(boardconf) == boardconf->powerCheckStatus) {
if (boardconf->needCheckPowerChip && checkPowerConfig(boardconf, logger) == boardconf->powerCheckStatus) {
PowerManagement powerManagement;
Wire.begin(boardconf->OledSda, boardconf->OledScl);
powerManagement.begin(Wire);
powerManagement.activateLoRa();
}
if (checkModemConfig(boardconf)) {
logPrintI("found a board config: ");
logPrintlnI(boardconf->Name);
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "found a board config: %s", boardconf->Name.c_str());
return boardconf;
}
}
logPrintlnE("could not find a board config!");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "could not find a board config!");
return 0;
}
@ -60,7 +60,7 @@ BoardConfig const *BoardFinder::getBoardConfig(String name) {
return *elem;
}
bool BoardFinder::checkOledConfig(BoardConfig const *boardConfig) {
bool BoardFinder::checkOledConfig(BoardConfig const *boardConfig, logging::Logger &logger) {
if (boardConfig->OledReset > 0) {
pinMode(boardConfig->OledReset, OUTPUT);
digitalWrite(boardConfig->OledReset, HIGH);
@ -70,7 +70,7 @@ bool BoardFinder::checkOledConfig(BoardConfig const *boardConfig) {
digitalWrite(boardConfig->OledReset, HIGH);
}
if (!Wire.begin(boardConfig->OledSda, boardConfig->OledScl)) {
logPrintlnW("issue with wire");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, MODULE_NAME, "issue with wire");
return false;
}
Wire.beginTransmission(boardConfig->OledAddr);
@ -107,9 +107,9 @@ bool BoardFinder::checkModemConfig(BoardConfig const *boardConfig) {
return false;
}
bool BoardFinder::checkPowerConfig(BoardConfig const *boardConfig) {
bool BoardFinder::checkPowerConfig(BoardConfig const *boardConfig, logging::Logger &logger) {
if (!Wire.begin(boardConfig->OledSda, boardConfig->OledScl)) {
logPrintlnW("issue with wire");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, MODULE_NAME, "issue with wire");
return false;
}
Wire.beginTransmission(0x34);
@ -120,22 +120,22 @@ bool BoardFinder::checkPowerConfig(BoardConfig const *boardConfig) {
int response = Wire.read();
Wire.endTransmission();
logPrintlnD(String(response));
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, MODULE_NAME, "wire response: %d", response);
if (response == 0x03) {
logPrintlnD("power chip found!");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, MODULE_NAME, "power chip found!");
return true;
}
logPrintlnD("power chip NOT found");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, MODULE_NAME, "power chip NOT found");
return false;
}
// 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 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);
// clang-format on

Wyświetl plik

@ -8,6 +8,8 @@
#include <SPI.h>
#include <Wire.h>
#include <logger.h>
enum BoardType
{
eHELTEC_WIFI_LORA_32_V1,
@ -22,7 +24,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;
@ -38,6 +40,9 @@ public:
uint8_t LoraCS;
uint8_t LoraReset;
uint8_t LoraIRQ;
uint8_t GpsRx;
uint8_t GpsTx;
uint8_t Button;
bool needCheckPowerChip;
bool powerCheckStatus;
@ -47,16 +52,16 @@ class BoardFinder {
public:
explicit BoardFinder(const std::list<BoardConfig const *> &boardConfigs);
BoardConfig const *searchBoardConfig();
BoardConfig const *searchBoardConfig(logging::Logger &logger);
BoardConfig const *getBoardConfig(String name);
private:
const std::list<BoardConfig const *> &_boardConfigs;
bool checkOledConfig(BoardConfig const *boardConfig);
bool checkOledConfig(BoardConfig const *boardConfig, logging::Logger &logger);
bool checkModemConfig(BoardConfig const *boardConfig);
bool checkPowerConfig(BoardConfig const *boardConfig);
bool checkPowerConfig(BoardConfig const *boardConfig, logging::Logger &logger);
};
extern BoardConfig TTGO_LORA32_V1;

Wyświetl plik

@ -2,12 +2,14 @@
#include <SPIFFS.h>
#include <logger.h>
ConfigurationManagement::ConfigurationManagement(String FilePath) : mFilePath(FilePath) {
#define MODULE_NAME "ConfigurationManagement"
ConfigurationManagement::ConfigurationManagement(logging::Logger &logger, String FilePath) : mFilePath(FilePath) {
if (!SPIFFS.begin(true)) {
logPrintlnI("Mounting SPIFFS was not possible. Trying to format SPIFFS...");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "Mounting SPIFFS was not possible. Trying to format SPIFFS...");
SPIFFS.format();
if (!SPIFFS.begin()) {
logPrintlnE("Formating SPIFFS was not okay!");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "Formating SPIFFS was not okay!");
}
}
}
@ -15,16 +17,16 @@ ConfigurationManagement::ConfigurationManagement(String FilePath) : mFilePath(Fi
ConfigurationManagement::~ConfigurationManagement() {
}
void ConfigurationManagement::readConfiguration(Configuration &conf) {
void ConfigurationManagement::readConfiguration(logging::Logger &logger, Configuration &conf) {
File file = SPIFFS.open(mFilePath);
if (!file) {
logPrintlnE("Failed to open file for reading, using default configuration.");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "Failed to open file for reading, using default configuration.");
return;
}
DynamicJsonDocument data(2048);
DeserializationError error = deserializeJson(data, file);
if (error) {
logPrintlnW("Failed to read file, using default configuration.");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, MODULE_NAME, "Failed to read file, using default configuration.");
}
// serializeJson(data, Serial);
// Serial.println();
@ -33,13 +35,13 @@ void ConfigurationManagement::readConfiguration(Configuration &conf) {
readProjectConfiguration(data, conf);
// update config in memory to get the new fields:
writeConfiguration(conf);
// writeConfiguration(logger, conf);
}
void ConfigurationManagement::writeConfiguration(Configuration &conf) {
void ConfigurationManagement::writeConfiguration(logging::Logger &logger, Configuration &conf) {
File file = SPIFFS.open(mFilePath, "w");
if (!file) {
logPrintlnE("Failed to open file for writing...");
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "Failed to open file for writing...");
return;
}
DynamicJsonDocument data(2048);

Wyświetl plik

@ -9,15 +9,17 @@
#include <ArduinoJson.h>
#endif
#include <logger.h>
class Configuration;
class ConfigurationManagement {
public:
explicit ConfigurationManagement(String FilePath);
explicit ConfigurationManagement(logging::Logger &logger, String FilePath);
virtual ~ConfigurationManagement();
void readConfiguration(Configuration &conf);
void writeConfiguration(Configuration &conf);
void readConfiguration(logging::Logger &logger, Configuration &conf);
void writeConfiguration(logging::Logger &logger, Configuration &conf);
private:
virtual void readProjectConfiguration(DynamicJsonDocument &data, Configuration &conf) = 0;

Wyświetl plik

@ -1,673 +0,0 @@
// Copyright (c) Sandeep Mistry. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include <LoRa.h>
// registers
#define REG_FIFO 0x00
#define REG_OP_MODE 0x01
#define REG_FRF_MSB 0x06
#define REG_FRF_MID 0x07
#define REG_FRF_LSB 0x08
#define REG_PA_CONFIG 0x09
#define REG_OCP 0x0b
#define REG_LNA 0x0c
#define REG_FIFO_ADDR_PTR 0x0d
#define REG_FIFO_TX_BASE_ADDR 0x0e
#define REG_FIFO_RX_BASE_ADDR 0x0f
#define REG_FIFO_RX_CURRENT_ADDR 0x10
#define REG_IRQ_FLAGS 0x12
#define REG_RX_NB_BYTES 0x13
#define REG_PKT_SNR_VALUE 0x19
#define REG_PKT_RSSI_VALUE 0x1a
#define REG_RSSI_VALUE 0x1b
#define REG_MODEM_CONFIG_1 0x1d
#define REG_MODEM_CONFIG_2 0x1e
#define REG_PREAMBLE_MSB 0x20
#define REG_PREAMBLE_LSB 0x21
#define REG_PAYLOAD_LENGTH 0x22
#define REG_MODEM_CONFIG_3 0x26
#define REG_FREQ_ERROR_MSB 0x28
#define REG_FREQ_ERROR_MID 0x29
#define REG_FREQ_ERROR_LSB 0x2a
#define REG_RSSI_WIDEBAND 0x2c
#define REG_DETECTION_OPTIMIZE 0x31
#define REG_INVERTIQ 0x33
#define REG_DETECTION_THRESHOLD 0x37
#define REG_SYNC_WORD 0x39
#define REG_INVERTIQ2 0x3b
#define REG_DIO_MAPPING_1 0x40
#define REG_VERSION 0x42
#define REG_PA_DAC 0x4d
// modes
#define MODE_LONG_RANGE_MODE 0x80
#define MODE_SLEEP 0x00
#define MODE_STDBY 0x01
#define MODE_TX 0x03
#define MODE_RX_CONTINUOUS 0x05
#define MODE_RX_SINGLE 0x06
// PA config
#define PA_BOOST 0x80
// IRQ masks
#define IRQ_TX_DONE_MASK 0x08
#define IRQ_PAYLOAD_CRC_ERROR_MASK 0x20
#define IRQ_RX_DONE_MASK 0x40
#define RF_MID_BAND_THRESHOLD 525E6
#define RSSI_OFFSET_HF_PORT 157
#define RSSI_OFFSET_LF_PORT 164
#define MAX_PKT_LENGTH 255
#if (ESP8266 || ESP32)
#define ISR_PREFIX ICACHE_RAM_ATTR
#else
#define ISR_PREFIX
#endif
LoRaClass::LoRaClass() :
_spiSettings(LORA_DEFAULT_SPI_FREQUENCY, MSBFIRST, SPI_MODE0),
_spi(&LORA_DEFAULT_SPI),
_ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN),
_frequency(0),
_packetIndex(0),
_implicitHeaderMode(0)
{
// overide Stream timeout value
setTimeout(0);
}
int LoRaClass::begin(long frequency)
{
#if defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310)
pinMode(LORA_IRQ_DUMB, OUTPUT);
digitalWrite(LORA_IRQ_DUMB, LOW);
// Hardware reset
pinMode(LORA_BOOT0, OUTPUT);
digitalWrite(LORA_BOOT0, LOW);
pinMode(LORA_RESET, OUTPUT);
digitalWrite(LORA_RESET, HIGH);
delay(200);
digitalWrite(LORA_RESET, LOW);
delay(200);
digitalWrite(LORA_RESET, HIGH);
delay(50);
#endif
// setup pins
pinMode(_ss, OUTPUT);
// set SS high
digitalWrite(_ss, HIGH);
if (_reset != -1) {
pinMode(_reset, OUTPUT);
// perform reset
digitalWrite(_reset, LOW);
delay(10);
digitalWrite(_reset, HIGH);
delay(10);
}
// start SPI
_spi->begin();
// check version
uint8_t version = readRegister(REG_VERSION);
if (version != 0x12) {
return 0;
}
// put in sleep mode
sleep();
// set frequency
setFrequency(frequency);
// set base addresses
writeRegister(REG_FIFO_TX_BASE_ADDR, 0);
writeRegister(REG_FIFO_RX_BASE_ADDR, 0);
// set LNA boost
writeRegister(REG_LNA, readRegister(REG_LNA) | 0x03);
// set auto AGC
writeRegister(REG_MODEM_CONFIG_3, 0x04);
// set output power to 17 dBm
setTxPower(17);
// put in standby mode
idle();
return 1;
}
void LoRaClass::end()
{
// put in sleep mode
sleep();
// stop SPI
_spi->end();
}
int LoRaClass::beginPacket(int implicitHeader)
{
if (isTransmitting()) {
return 0;
}
// put in standby mode
idle();
if (implicitHeader) {
implicitHeaderMode();
} else {
explicitHeaderMode();
}
// reset FIFO address and paload length
writeRegister(REG_FIFO_ADDR_PTR, 0);
writeRegister(REG_PAYLOAD_LENGTH, 0);
return 1;
}
int LoRaClass::endPacket(bool async)
{
// put in TX mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_TX);
if (!async) {
// wait for TX done
while ((readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == 0) {
yield();
}
// clear IRQ's
writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
}
return 1;
}
bool LoRaClass::isTransmitting()
{
if ((readRegister(REG_OP_MODE) & MODE_TX) == MODE_TX) {
return true;
}
if (readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) {
// clear IRQ's
writeRegister(REG_IRQ_FLAGS, IRQ_TX_DONE_MASK);
}
return false;
}
int LoRaClass::parsePacket(int size)
{
int packetLength = 0;
int irqFlags = readRegister(REG_IRQ_FLAGS);
if (size > 0) {
implicitHeaderMode();
writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
} else {
explicitHeaderMode();
}
// clear IRQ's
writeRegister(REG_IRQ_FLAGS, irqFlags);
if ((irqFlags & IRQ_RX_DONE_MASK) && (irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) {
// received a packet
_packetIndex = 0;
// read packet length
if (_implicitHeaderMode) {
packetLength = readRegister(REG_PAYLOAD_LENGTH);
} else {
packetLength = readRegister(REG_RX_NB_BYTES);
}
// set FIFO address to current RX address
writeRegister(REG_FIFO_ADDR_PTR, readRegister(REG_FIFO_RX_CURRENT_ADDR));
// put in standby mode
idle();
} else if (readRegister(REG_OP_MODE) != (MODE_LONG_RANGE_MODE | MODE_RX_SINGLE)) {
// not currently in RX mode
// reset FIFO address
writeRegister(REG_FIFO_ADDR_PTR, 0);
// put in single RX mode
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_SINGLE);
}
return packetLength;
}
int LoRaClass::packetRssi()
{
return (readRegister(REG_PKT_RSSI_VALUE) - (_frequency < RF_MID_BAND_THRESHOLD ? RSSI_OFFSET_LF_PORT : RSSI_OFFSET_HF_PORT));
}
float LoRaClass::packetSnr()
{
return ((int8_t)readRegister(REG_PKT_SNR_VALUE)) * 0.25;
}
long LoRaClass::packetFrequencyError()
{
int32_t freqError = 0;
freqError = static_cast<int32_t>(readRegister(REG_FREQ_ERROR_MSB) & B111);
freqError <<= 8L;
freqError += static_cast<int32_t>(readRegister(REG_FREQ_ERROR_MID));
freqError <<= 8L;
freqError += static_cast<int32_t>(readRegister(REG_FREQ_ERROR_LSB));
if (readRegister(REG_FREQ_ERROR_MSB) & B1000) { // Sign bit is on
freqError -= 524288; // B1000'0000'0000'0000'0000
}
const float fXtal = 32E6; // FXOSC: crystal oscillator (XTAL) frequency (2.5. Chip Specification, p. 14)
const float fError = ((static_cast<float>(freqError) * (1L << 24)) / fXtal) * (getSignalBandwidth() / 500000.0f); // p. 37
return static_cast<long>(fError);
}
int LoRaClass::rssi()
{
return (readRegister(REG_RSSI_VALUE) - (_frequency < RF_MID_BAND_THRESHOLD ? RSSI_OFFSET_LF_PORT : RSSI_OFFSET_HF_PORT));
}
size_t LoRaClass::write(uint8_t byte)
{
return write(&byte, sizeof(byte));
}
size_t LoRaClass::write(const uint8_t *buffer, size_t size)
{
int currentLength = readRegister(REG_PAYLOAD_LENGTH);
// check size
if ((currentLength + size) > MAX_PKT_LENGTH) {
size = MAX_PKT_LENGTH - currentLength;
}
// write data
for (size_t i = 0; i < size; i++) {
writeRegister(REG_FIFO, buffer[i]);
}
// update length
writeRegister(REG_PAYLOAD_LENGTH, currentLength + size);
return size;
}
int LoRaClass::available()
{
return (readRegister(REG_RX_NB_BYTES) - _packetIndex);
}
int LoRaClass::read()
{
if (!available()) {
return -1;
}
_packetIndex++;
return readRegister(REG_FIFO);
}
int LoRaClass::peek()
{
if (!available()) {
return -1;
}
// store current FIFO address
int currentAddress = readRegister(REG_FIFO_ADDR_PTR);
// read
uint8_t b = readRegister(REG_FIFO);
// restore FIFO address
writeRegister(REG_FIFO_ADDR_PTR, currentAddress);
return b;
}
void LoRaClass::flush()
{
}
void LoRaClass::receive(int size)
{
writeRegister(REG_DIO_MAPPING_1, 0x00); // DIO0 => RXDONE
if (size > 0) {
implicitHeaderMode();
writeRegister(REG_PAYLOAD_LENGTH, size & 0xff);
} else {
explicitHeaderMode();
}
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_RX_CONTINUOUS);
}
void LoRaClass::idle()
{
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_STDBY);
}
void LoRaClass::sleep()
{
writeRegister(REG_OP_MODE, MODE_LONG_RANGE_MODE | MODE_SLEEP);
}
void LoRaClass::setTxPower(int level, int outputPin)
{
if (PA_OUTPUT_RFO_PIN == outputPin) {
// RFO
if (level < 0) {
level = 0;
} else if (level > 14) {
level = 14;
}
writeRegister(REG_PA_CONFIG, 0x70 | level);
} else {
// PA BOOST
if (level > 17) {
if (level > 20) {
level = 20;
}
// subtract 3 from level, so 18 - 20 maps to 15 - 17
level -= 3;
// High Power +20 dBm Operation (Semtech SX1276/77/78/79 5.4.3.)
writeRegister(REG_PA_DAC, 0x87);
setOCP(140);
} else {
if (level < 2) {
level = 2;
}
//Default value PA_HF/LF or +17dBm
writeRegister(REG_PA_DAC, 0x84);
setOCP(100);
}
writeRegister(REG_PA_CONFIG, PA_BOOST | (level - 2));
}
}
void LoRaClass::setFrequency(long frequency)
{
_frequency = frequency;
uint64_t frf = ((uint64_t)frequency << 19) / 32000000;
writeRegister(REG_FRF_MSB, (uint8_t)(frf >> 16));
writeRegister(REG_FRF_MID, (uint8_t)(frf >> 8));
writeRegister(REG_FRF_LSB, (uint8_t)(frf >> 0));
}
int LoRaClass::getSpreadingFactor()
{
return readRegister(REG_MODEM_CONFIG_2) >> 4;
}
void LoRaClass::setSpreadingFactor(int sf)
{
if (sf < 6) {
sf = 6;
} else if (sf > 12) {
sf = 12;
}
if (sf == 6) {
writeRegister(REG_DETECTION_OPTIMIZE, 0xc5);
writeRegister(REG_DETECTION_THRESHOLD, 0x0c);
} else {
writeRegister(REG_DETECTION_OPTIMIZE, 0xc3);
writeRegister(REG_DETECTION_THRESHOLD, 0x0a);
}
writeRegister(REG_MODEM_CONFIG_2, (readRegister(REG_MODEM_CONFIG_2) & 0x0f) | ((sf << 4) & 0xf0));
setLdoFlag();
}
long LoRaClass::getSignalBandwidth()
{
byte bw = (readRegister(REG_MODEM_CONFIG_1) >> 4);
switch (bw) {
case 0: return 7.8E3;
case 1: return 10.4E3;
case 2: return 15.6E3;
case 3: return 20.8E3;
case 4: return 31.25E3;
case 5: return 41.7E3;
case 6: return 62.5E3;
case 7: return 125E3;
case 8: return 250E3;
case 9: return 500E3;
}
return -1;
}
void LoRaClass::setSignalBandwidth(long sbw)
{
int bw;
if (sbw <= 7.8E3) {
bw = 0;
} else if (sbw <= 10.4E3) {
bw = 1;
} else if (sbw <= 15.6E3) {
bw = 2;
} else if (sbw <= 20.8E3) {
bw = 3;
} else if (sbw <= 31.25E3) {
bw = 4;
} else if (sbw <= 41.7E3) {
bw = 5;
} else if (sbw <= 62.5E3) {
bw = 6;
} else if (sbw <= 125E3) {
bw = 7;
} else if (sbw <= 250E3) {
bw = 8;
} else /*if (sbw <= 250E3)*/ {
bw = 9;
}
writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0x0f) | (bw << 4));
setLdoFlag();
}
void LoRaClass::setLdoFlag()
{
// Section 4.1.1.5
long symbolDuration = 1000 / ( getSignalBandwidth() / (1L << getSpreadingFactor()) ) ;
// Section 4.1.1.6
boolean ldoOn = symbolDuration > 16;
uint8_t config3 = readRegister(REG_MODEM_CONFIG_3);
bitWrite(config3, 3, ldoOn);
writeRegister(REG_MODEM_CONFIG_3, config3);
}
void LoRaClass::setCodingRate4(int denominator)
{
if (denominator < 5) {
denominator = 5;
} else if (denominator > 8) {
denominator = 8;
}
int cr = denominator - 4;
writeRegister(REG_MODEM_CONFIG_1, (readRegister(REG_MODEM_CONFIG_1) & 0xf1) | (cr << 1));
}
void LoRaClass::setPreambleLength(long length)
{
writeRegister(REG_PREAMBLE_MSB, (uint8_t)(length >> 8));
writeRegister(REG_PREAMBLE_LSB, (uint8_t)(length >> 0));
}
void LoRaClass::setSyncWord(int sw)
{
writeRegister(REG_SYNC_WORD, sw);
}
void LoRaClass::enableCrc()
{
writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) | 0x04);
}
void LoRaClass::disableCrc()
{
writeRegister(REG_MODEM_CONFIG_2, readRegister(REG_MODEM_CONFIG_2) & 0xfb);
}
void LoRaClass::enableInvertIQ()
{
writeRegister(REG_INVERTIQ, 0x66);
writeRegister(REG_INVERTIQ2, 0x19);
}
void LoRaClass::disableInvertIQ()
{
writeRegister(REG_INVERTIQ, 0x27);
writeRegister(REG_INVERTIQ2, 0x1d);
}
void LoRaClass::setOCP(uint8_t mA)
{
uint8_t ocpTrim = 27;
if (mA <= 120) {
ocpTrim = (mA - 45) / 5;
} else if (mA <=240) {
ocpTrim = (mA + 30) / 10;
}
writeRegister(REG_OCP, 0x20 | (0x1F & ocpTrim));
}
void LoRaClass::setGain(uint8_t gain)
{
// check allowed range
if (gain > 6) {
gain = 6;
}
// set to standby
idle();
// set gain
if (gain == 0) {
// if gain = 0, enable AGC
writeRegister(REG_MODEM_CONFIG_3, 0x04);
} else {
// disable AGC
writeRegister(REG_MODEM_CONFIG_3, 0x00);
// clear Gain and set LNA boost
writeRegister(REG_LNA, 0x03);
// set gain
writeRegister(REG_LNA, readRegister(REG_LNA) | (gain << 5));
}
}
byte LoRaClass::random()
{
return readRegister(REG_RSSI_WIDEBAND);
}
void LoRaClass::setPins(int ss, int reset, int dio0)
{
_ss = ss;
_reset = reset;
_dio0 = dio0;
}
void LoRaClass::setSPI(SPIClass& spi)
{
_spi = &spi;
}
void LoRaClass::setSPIFrequency(uint32_t frequency)
{
_spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0);
}
void LoRaClass::dumpRegisters(Stream& out)
{
for (int i = 0; i < 128; i++) {
out.print("0x");
out.print(i, HEX);
out.print(": 0x");
out.println(readRegister(i), HEX);
}
}
void LoRaClass::explicitHeaderMode()
{
_implicitHeaderMode = 0;
writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) & 0xfe);
}
void LoRaClass::implicitHeaderMode()
{
_implicitHeaderMode = 1;
writeRegister(REG_MODEM_CONFIG_1, readRegister(REG_MODEM_CONFIG_1) | 0x01);
}
uint8_t LoRaClass::readRegister(uint8_t address)
{
return singleTransfer(address & 0x7f, 0x00);
}
void LoRaClass::writeRegister(uint8_t address, uint8_t value)
{
singleTransfer(address | 0x80, value);
}
uint8_t LoRaClass::singleTransfer(uint8_t address, uint8_t value)
{
uint8_t response;
digitalWrite(_ss, LOW);
_spi->beginTransaction(_spiSettings);
_spi->transfer(address);
response = _spi->transfer(value);
_spi->endTransaction();
digitalWrite(_ss, HIGH);
return response;
}

Wyświetl plik

@ -1,119 +0,0 @@
// Copyright (c) Sandeep Mistry. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#ifndef LORA_H
#define LORA_H
#include <Arduino.h>
#include <SPI.h>
#if defined(ARDUINO_SAMD_MKRWAN1300)
#define LORA_DEFAULT_SPI SPI1
#define LORA_DEFAULT_SPI_FREQUENCY 200000
#define LORA_DEFAULT_SS_PIN LORA_IRQ_DUMB
#define LORA_DEFAULT_RESET_PIN -1
#define LORA_DEFAULT_DIO0_PIN -1
#elif defined(ARDUINO_SAMD_MKRWAN1310)
#define LORA_DEFAULT_SPI SPI1
#define LORA_DEFAULT_SPI_FREQUENCY 200000
#define LORA_DEFAULT_SS_PIN LORA_IRQ_DUMB
#define LORA_DEFAULT_RESET_PIN -1
#define LORA_DEFAULT_DIO0_PIN LORA_IRQ
#else
#define LORA_DEFAULT_SPI SPI
#define LORA_DEFAULT_SPI_FREQUENCY 8E6
#define LORA_DEFAULT_SS_PIN 10
#define LORA_DEFAULT_RESET_PIN 9
#define LORA_DEFAULT_DIO0_PIN 2
#endif
#define PA_OUTPUT_RFO_PIN 0
#define PA_OUTPUT_PA_BOOST_PIN 1
class LoRaClass : public Stream {
public:
LoRaClass();
int begin(long frequency);
void end();
int beginPacket(int implicitHeader = false);
int endPacket(bool async = false);
int parsePacket(int size = 0);
int packetRssi();
float packetSnr();
long packetFrequencyError();
int rssi();
// from Print
virtual size_t write(uint8_t byte);
virtual size_t write(const uint8_t *buffer, size_t size);
// from Stream
virtual int available();
virtual int read();
virtual int peek();
virtual void flush();
void receive(int size = 0);
void idle();
void sleep();
void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
void setFrequency(long frequency);
void setSpreadingFactor(int sf);
void setSignalBandwidth(long sbw);
void setCodingRate4(int denominator);
void setPreambleLength(long length);
void setSyncWord(int sw);
void enableCrc();
void disableCrc();
void enableInvertIQ();
void disableInvertIQ();
void setOCP(uint8_t mA); // Over Current Protection control
void setGain(uint8_t gain); // Set LNA gain
// deprecated
void crc() { enableCrc(); }
void noCrc() { disableCrc(); }
byte random();
void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN);
void setSPI(SPIClass& spi);
void setSPIFrequency(uint32_t frequency);
void dumpRegisters(Stream& out);
private:
void explicitHeaderMode();
void implicitHeaderMode();
bool isTransmitting();
int getSpreadingFactor();
long getSignalBandwidth();
void setLdoFlag();
uint8_t readRegister(uint8_t address);
void writeRegister(uint8_t address, uint8_t value);
uint8_t singleTransfer(uint8_t address, uint8_t value);
private:
SPISettings _spiSettings;
SPIClass* _spi;
int _ss;
int _reset;
int _dio0;
long _frequency;
int _packetIndex;
int _implicitHeaderMode;
};
#endif

Wyświetl plik

@ -1,65 +0,0 @@
#include "LoRa_APRS.h"
LoRa_APRS::LoRa_APRS() : _RxFrequency(433775000), _TxFrequency(433775000) {
}
bool LoRa_APRS::checkMessage() {
if (!parsePacket()) {
return false;
}
// read header:
char dummy[4];
readBytes(dummy, 3);
if (dummy[0] != '<') {
// is no APRS message, ignore message
while (available()) {
read();
}
return false;
}
// read APRS data:
String str;
while (available()) {
str += (char)read();
}
_LastReceivedMsg = std::shared_ptr<APRSMessage>(new APRSMessage());
_LastReceivedMsg->decode(str);
return true;
}
std::shared_ptr<APRSMessage> LoRa_APRS::getMessage() {
return _LastReceivedMsg;
}
void LoRa_APRS::sendMessage(const std::shared_ptr<APRSMessage> msg) {
setFrequency(_TxFrequency);
String data = msg->encode();
beginPacket();
// Header:
write('<');
write(0xFF);
write(0x01);
// APRS Data:
write((const uint8_t *)data.c_str(), data.length());
endPacket();
setFrequency(_RxFrequency);
}
void LoRa_APRS::setRxFrequency(long frequency) {
_RxFrequency = frequency;
setFrequency(_RxFrequency);
}
// cppcheck-suppress unusedFunction
long LoRa_APRS::getRxFrequency() const {
return _RxFrequency;
}
void LoRa_APRS::setTxFrequency(long frequency) {
_TxFrequency = frequency;
}
// cppcheck-suppress unusedFunction
long LoRa_APRS::getTxFrequency() const {
return _TxFrequency;
}

Wyświetl plik

@ -1,31 +0,0 @@
#ifndef LORA_H_
#define LORA_H_
#include <Arduino.h>
#include <APRS-Decoder.h>
#include <LoRa.h>
#include <memory>
class LoRa_APRS : public LoRaClass {
public:
LoRa_APRS();
bool checkMessage();
std::shared_ptr<APRSMessage> getMessage();
void sendMessage(const std::shared_ptr<APRSMessage> msg);
void setRxFrequency(long frequency);
long getRxFrequency() const;
void setTxFrequency(long frequency);
long getTxFrequency() const;
private:
std::shared_ptr<APRSMessage> _LastReceivedMsg;
long _RxFrequency;
long _TxFrequency;
};
#endif

Wyświetl plik

@ -17,7 +17,7 @@ class NTPClient {
unsigned int _port = NTP_DEFAULT_LOCAL_PORT;
long _timeOffset = 0;
unsigned long _updateInterval = 60000; // In ms
unsigned long _updateInterval = 3600000; // In ms
unsigned long _currentEpoc = 0; // In s
unsigned long _lastUpdate = 0; // In ms

Wyświetl plik

@ -1,7 +1,7 @@
#include "System.h"
System::System() : _boardConfig(0), _userConfig(0), _isWifiEthConnected(false) {
System::System() : _boardConfig(0), _userConfig(0), _isEthConnected(false), _isWifiConnected(false) {
}
System::~System() {
@ -31,10 +31,18 @@ Display &System::getDisplay() {
return _display;
}
bool System::isWifiEthConnected() const {
return _isWifiEthConnected;
bool System::isWifiOrEthConnected() const {
return _isEthConnected || _isWifiConnected;
}
void System::connectedViaWifiEth(bool status) {
_isWifiEthConnected = status;
void System::connectedViaEth(bool status) {
_isEthConnected = status;
}
void System::connectedViaWifi(bool status) {
_isWifiConnected = status;
}
logging::Logger &System::getLogger() {
return _logger;
}

Wyświetl plik

@ -1,6 +1,7 @@
#ifndef SYSTEM_H_
#define SYSTEM_H_
#include <logger.h>
#include <memory>
#include "TaskManager.h"
@ -20,15 +21,19 @@ public:
Configuration const *const getUserConfig() const;
TaskManager & getTaskManager();
Display & getDisplay();
bool isWifiEthConnected() const;
void connectedViaWifiEth(bool status);
bool isWifiOrEthConnected() const;
void connectedViaEth(bool status);
void connectedViaWifi(bool status);
logging::Logger & getLogger();
private:
BoardConfig const * _boardConfig;
Configuration const *_userConfig;
TaskManager _taskManager;
Display _display;
bool _isWifiEthConnected;
bool _isEthConnected;
bool _isWifiConnected;
logging::Logger _logger;
};
#endif

Wyświetl plik

@ -2,6 +2,8 @@
#include <FontConfig.h>
#include <logger.h>
#define MODULE_NAME "TaskManager"
TaskManager::TaskManager() {
}
@ -20,15 +22,13 @@ std::list<Task *> TaskManager::getTasks() {
}
bool TaskManager::setup(System &system) {
logPrintlnV("will setup all tasks...");
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "will setup all tasks...");
for (Task *elem : _alwaysRunTasks) {
logPrintD("call setup from ");
logPrintlnD(elem->getName());
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, MODULE_NAME, "call setup for %s", elem->getName().c_str());
elem->setup(system);
}
for (Task *elem : _tasks) {
logPrintD("call setup from ");
logPrintlnD(elem->getName());
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, MODULE_NAME, "call setup for %s", elem->getName().c_str());
elem->setup(system);
}
_nextTask = _tasks.begin();
@ -36,10 +36,7 @@ bool TaskManager::setup(System &system) {
}
bool TaskManager::loop(System &system) {
// logPrintlnD("will loop all tasks...");
for (Task *elem : _alwaysRunTasks) {
// logPrintD("call loop from ");
// logPrintlnD(elem->getName());
elem->loop(system);
}

Wyświetl plik

@ -11,8 +11,12 @@ lib_deps =
bblanchon/ArduinoJson @ 6.17.0
lewisxhe/AXP202X_Library @ 1.1.2
peterus/APRS-Decoder-Lib @ 0.0.6
peterus/esp-logger @ 0.0.1
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
jgromes/RadioLib @ 5.1.2
check_tool = cppcheck
check_flags =
cppcheck: --suppress=*:*.pio\* --inline-suppr -DCPPCHECK --force lib -ilib/TimeLib -ilib/LoRa -ilib/NTPClient

Wyświetl plik

@ -0,0 +1,49 @@
#!/usr/bin/env python3
import git
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"[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"[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("[ERROR] firmware version is not current year!")
error = True
if version_week != 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)

Wyświetl plik

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

Wyświetl plik

@ -8,17 +8,20 @@
#include <power_management.h>
#include "TaskAprsIs.h"
#include "TaskBeacon.h"
#include "TaskDisplay.h"
#include "TaskEth.h"
#include "TaskFTP.h"
#include "TaskModem.h"
#include "TaskMQTT.h"
#include "TaskNTP.h"
#include "TaskOTA.h"
#include "TaskRadiolib.h"
#include "TaskRouter.h"
#include "TaskWifi.h"
#include "project_configuration.h"
#define VERSION "21.35.0-dev"
#define VERSION "22.20.0"
#define MODULE_NAME "Main"
String create_lat_aprs(double lat);
String create_long_aprs(double lng);
@ -26,26 +29,31 @@ String create_long_aprs(double lng);
TaskQueue<std::shared_ptr<APRSMessage>> toAprsIs;
TaskQueue<std::shared_ptr<APRSMessage>> fromModem;
TaskQueue<std::shared_ptr<APRSMessage>> toModem;
TaskQueue<std::shared_ptr<APRSMessage>> toMQTT;
System LoRaSystem;
Configuration userConfig;
DisplayTask displayTask;
ModemTask modemTask(fromModem, toModem);
EthTask ethTask;
WifiTask wifiTask;
OTATask otaTask;
NTPTask ntpTask;
FTPTask ftpTask;
AprsIsTask aprsIsTask(toAprsIs);
RouterTask routerTask(fromModem, toModem, toAprsIs);
// ModemTask modemTask(fromModem, toModem);
RadiolibTask modemTask(fromModem, toModem);
EthTask ethTask;
WifiTask wifiTask;
OTATask otaTask;
NTPTask ntpTask;
FTPTask ftpTask;
MQTTTask mqttTask(toMQTT);
AprsIsTask aprsIsTask(toAprsIs);
RouterTask routerTask(fromModem, toModem, toAprsIs, toMQTT);
BeaconTask beaconTask(toModem, toAprsIs);
void setup() {
Serial.begin(115200);
Logger::instance().setSerial(&Serial);
LoRaSystem.getLogger().setSerial(&Serial);
setWiFiLogger(&LoRaSystem.getLogger());
delay(500);
logPrintlnI("LoRa APRS iGate by OE5BPA (Peter Buchegger)");
logPrintlnI("Version: " VERSION);
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "LoRa APRS iGate by OE5BPA (Peter Buchegger)");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "Version: %s", VERSION);
std::list<BoardConfig const *> boardConfigs;
boardConfigs.push_back(&TTGO_LORA32_V1);
@ -57,40 +65,42 @@ void setup() {
boardConfigs.push_back(&HELTEC_WIFI_LORA_32_V1);
boardConfigs.push_back(&HELTEC_WIFI_LORA_32_V2);
ProjectConfigurationManagement confmg;
confmg.readConfiguration(userConfig);
ProjectConfigurationManagement confmg(LoRaSystem.getLogger());
confmg.readConfiguration(LoRaSystem.getLogger(), userConfig);
BoardFinder finder(boardConfigs);
BoardConfig const *boardConfig = finder.getBoardConfig(userConfig.board);
if (!boardConfig) {
boardConfig = finder.searchBoardConfig();
boardConfig = finder.searchBoardConfig(LoRaSystem.getLogger());
if (!boardConfig) {
logPrintlnE("Board config not set and search failed!");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "Board config not set and search failed!");
while (true)
;
} else {
userConfig.board = boardConfig->Name;
confmg.writeConfiguration(userConfig);
logPrintlnI("will restart board now!");
confmg.writeConfiguration(LoRaSystem.getLogger(), userConfig);
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "will restart board now!");
ESP.restart();
}
}
logPrintI("Board ");
logPrintI(boardConfig->Name);
logPrintlnI(" loaded.");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "Board %s loaded.", boardConfig->Name.c_str());
if (boardConfig->Type == eTTGO_T_Beam_V1_0) {
Wire.begin(boardConfig->OledSda, boardConfig->OledScl);
PowerManagement powerManagement;
if (!powerManagement.begin(Wire)) {
logPrintlnI("AXP192 init done!");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "AXP192 init done!");
} else {
logPrintlnE("AXP192 init failed!");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "AXP192 init failed!");
}
powerManagement.activateLoRa();
powerManagement.activateOLED();
powerManagement.deactivateGPS();
if (userConfig.beacon.use_gps) {
powerManagement.activateGPS();
} else {
powerManagement.deactivateGPS();
}
}
LoRaSystem.setBoardConfig(boardConfig);
@ -98,19 +108,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) {
LoRaSystem.getTaskManager().addAlwaysRunTask(&ethTask);
} else {
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(&ethTask);
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.aprs_is.active) {
LoRaSystem.getTaskManager().addTask(&aprsIsTask);
}
if (userConfig.mqtt.active) {
LoRaSystem.getTaskManager().addTask(&mqttTask);
}
}
LoRaSystem.getTaskManager().setup(LoRaSystem);
@ -118,13 +142,13 @@ void setup() {
LoRaSystem.getDisplay().showSpashScreen("LoRa APRS iGate", VERSION);
if (userConfig.callsign == "NOCALL-10") {
logPrintlnE("You have to change your settings in 'data/is-cfg.json' and upload it via \"Upload File System image\"!");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "You have to change your settings in 'data/is-cfg.json' and upload it via 'Upload File System image'!");
LoRaSystem.getDisplay().showStatusScreen("ERROR", "You have to change your settings in 'data/is-cfg.json' and upload it via \"Upload File System image\"!");
while (true)
;
}
if ((!userConfig.aprs_is.active) && !(userConfig.digi.active)) {
logPrintlnE("No mode selected (iGate or Digi)! You have to activate one of iGate or Digi.");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, MODULE_NAME, "No mode selected (iGate or Digi)! You have to activate one of iGate or Digi.");
LoRaSystem.getDisplay().showStatusScreen("ERROR", "No mode selected (iGate or Digi)! You have to activate one of iGate or Digi.");
while (true)
;
@ -136,33 +160,16 @@ void setup() {
}
delay(5000);
logPrintlnI("setup done...");
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "setup done...");
}
volatile bool syslogSet = false;
void loop() {
LoRaSystem.getTaskManager().loop(LoRaSystem);
}
String create_lat_aprs(double lat) {
char str[20];
char n_s = 'N';
if (lat < 0) {
n_s = 'S';
if (LoRaSystem.isWifiOrEthConnected() && LoRaSystem.getUserConfig()->syslog.active && !syslogSet) {
LoRaSystem.getLogger().setSyslogServer(LoRaSystem.getUserConfig()->syslog.server, LoRaSystem.getUserConfig()->syslog.port, LoRaSystem.getUserConfig()->callsign);
LoRaSystem.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, MODULE_NAME, "System connected after a restart to the network, syslog server set");
syslogSet = true;
}
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;
}

Wyświetl plik

@ -7,20 +7,26 @@ enum TaskNames
TaskEth,
TaskFtp,
TaskModem,
TaskRadiolib,
TaskNtp,
TaskOta,
TaskWifi,
TaskRouter,
TaskSize,
TaskMQTT,
TaskBeacon,
TaskSize
};
#define TASK_APRS_IS "AprsIsTask"
#define TASK_ETH "EthTask"
#define TASK_FTP "FTPTask"
#define TASK_MODEM "ModemTask"
#define TASK_NTP "NTPTask"
#define TASK_OTA "OTATask"
#define TASK_WIFI "WifiTask"
#define TASK_ROUTER "RouterTask"
#define TASK_APRS_IS "AprsIsTask"
#define TASK_ETH "EthTask"
#define TASK_FTP "FTPTask"
#define TASK_MODEM "ModemTask"
#define TASK_RADIOLIB "RadiolibTask"
#define TASK_NTP "NTPTask"
#define TASK_OTA "OTATask"
#define TASK_WIFI "WifiTask"
#define TASK_ROUTER "RouterTask"
#define TASK_MQTT "MQTTTask"
#define TASK_BEACON "BeaconTask"
#endif

Wyświetl plik

@ -16,7 +16,7 @@ bool AprsIsTask::setup(System &system) {
}
bool AprsIsTask::loop(System &system) {
if (!system.isWifiEthConnected()) {
if (!system.isWifiOrEthConnected()) {
return false;
}
if (!_aprs_is.connected()) {
@ -40,15 +40,18 @@ bool AprsIsTask::loop(System &system) {
return true;
}
bool AprsIsTask::connect(const System &system) {
logPrintI("connecting to APRS-IS server: ");
logPrintI(system.getUserConfig()->aprs_is.server);
logPrintI(" on port: ");
logPrintlnI(String(system.getUserConfig()->aprs_is.port));
if (!_aprs_is.connect(system.getUserConfig()->aprs_is.server, system.getUserConfig()->aprs_is.port)) {
logPrintlnE("Connection failed.");
bool AprsIsTask::connect(System &system) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "connecting to APRS-IS server: %s on port: %d", system.getUserConfig()->aprs_is.server.c_str(), system.getUserConfig()->aprs_is.port);
APRS_IS::ConnectionStatus status = _aprs_is.connect(system.getUserConfig()->aprs_is.server, system.getUserConfig()->aprs_is.port);
if (status == APRS_IS::ERROR_CONNECTION) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "Something went wrong on connecting! Is the server reachable?");
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "Connection failed.");
return false;
} else if (status == APRS_IS::ERROR_PASSCODE) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "User can not be verified with passcode!");
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "Connection failed.");
return false;
}
logPrintlnI("Connected to APRS-IS server!");
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Connected to APRS-IS server!");
return true;
}

Wyświetl plik

@ -19,7 +19,7 @@ private:
TaskQueue<std::shared_ptr<APRSMessage>> &_toAprsIs;
bool connect(const System &system);
bool connect(System &system);
};
#endif

126
src/TaskBeacon.cpp 100644
Wyświetl plik

@ -0,0 +1,126 @@
#include <logger.h>
#include <OneButton.h>
#include <TimeLib.h>
#include "Task.h"
#include "TaskBeacon.h"
#include "project_configuration.h"
BeaconTask::BeaconTask(TaskQueue<std::shared_ptr<APRSMessage>> &toModem, TaskQueue<std::shared_ptr<APRSMessage>> &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<APRSMessage>(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<DisplayFrame>(new TextFrame("BEACON", _beaconMsg->toString())));
return true;
}

37
src/TaskBeacon.h 100644
Wyświetl plik

@ -0,0 +1,37 @@
#ifndef TASK_BEACON_H_
#define TASK_BEACON_H_
#include <OneButton.h>
#include <TinyGPS++.h>
#include <APRSMessage.h>
#include <TaskMQTT.h>
#include <TaskManager.h>
class BeaconTask : public Task {
public:
BeaconTask(TaskQueue<std::shared_ptr<APRSMessage>> &toModem, TaskQueue<std::shared_ptr<APRSMessage>> &toAprsIs);
virtual ~BeaconTask();
virtual bool setup(System &system) override;
virtual bool loop(System &system) override;
bool sendBeacon(System &system);
private:
TaskQueue<std::shared_ptr<APRSMessage>> &_toModem;
TaskQueue<std::shared_ptr<APRSMessage>> &_toAprsIs;
std::shared_ptr<APRSMessage> _beaconMsg;
Timer _beacon_timer;
HardwareSerial _ss;
TinyGPSPlus _gps;
bool _useGps;
static uint _instances;
static OneButton _userButton;
static bool _send_update;
static void pushButton();
};
#endif

Wyświetl plik

@ -6,66 +6,62 @@
#include "TaskEth.h"
#include "project_configuration.h"
volatile bool eth_connected = false;
#define WIFI_EVENT "WiFiEvent"
volatile bool eth_connected = false;
logging::Logger *_logger;
void setWiFiLogger(logging::Logger *logger) {
_logger = logger;
}
void WiFiEvent(WiFiEvent_t event) {
switch (event) {
case SYSTEM_EVENT_STA_START:
logPrintlnI("WiFi Started");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Started");
break;
case SYSTEM_EVENT_STA_CONNECTED:
logPrintlnI("WiFi Connected");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Connected");
break;
case SYSTEM_EVENT_STA_GOT_IP:
logPrintI("WiFi MAC: ");
logPrintI(WiFi.macAddress());
logPrintI(", IPv4: ");
logPrintI(WiFi.localIP().toString());
logPrintI(", Gateway: ");
logPrintI(WiFi.gatewayIP().toString());
logPrintI(", DNS1: ");
logPrintI(WiFi.dnsIP().toString());
logPrintI(", DNS2: ");
logPrintlnI(WiFi.dnsIP(1).toString());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi MAC: %s", WiFi.macAddress().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi IPv4: %s", WiFi.localIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Gateway: %s", WiFi.gatewayIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi DNS1: %s", WiFi.dnsIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi DNS2: %s", WiFi.dnsIP(1).toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Hostname: %s", WiFi.getHostname());
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
logPrintlnW("WiFi Disconnected");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Disconnected");
break;
case SYSTEM_EVENT_STA_STOP:
logPrintlnW("WiFi Stopped");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Stopped");
break;
case SYSTEM_EVENT_ETH_START:
logPrintlnI("ETH Started");
ETH.setHostname("esp32-ethernet");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Started");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
logPrintlnI("ETH Connected");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
logPrintI("ETH MAC: ");
logPrintI(ETH.macAddress());
logPrintI(", IPv4: ");
logPrintI(ETH.localIP().toString());
logPrintI(", Gateway: ");
logPrintI(ETH.gatewayIP().toString());
logPrintI(", DNS1: ");
logPrintI(ETH.dnsIP().toString());
logPrintI(", DNS2: ");
logPrintI(ETH.dnsIP(1).toString());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH MAC: %s", ETH.macAddress().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH IPv4: %s", ETH.localIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Gateway: %s", ETH.gatewayIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH DNS1: %s", ETH.dnsIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH DNS2: %s", ETH.dnsIP(1).toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Hostname: %s", ETH.getHostname());
if (ETH.fullDuplex()) {
logPrintI(", FULL_DUPLEX");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH FULL_DUPLEX");
}
logPrintI(", ");
logPrintI(String(ETH.linkSpeed()));
logPrintlnI("Mbps");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Speed: %dMbps", ETH.linkSpeed());
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
logPrintlnW("ETH Disconnected");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_WARN, WIFI_EVENT, "ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
logPrintlnW("ETH Stopped");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_WARN, WIFI_EVENT, "ETH Stopped");
eth_connected = false;
break;
default:
@ -100,22 +96,28 @@ bool EthTask::setup(System &system) {
delay(200);
digitalWrite(ETH_NRST, 1);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK);
if (!system.getUserConfig()->network.DHCP) {
ETH.config(system.getUserConfig()->network.staticIP, system.getUserConfig()->network.gateway, system.getUserConfig()->network.subnet, system.getUserConfig()->network.dns1, system.getUserConfig()->network.dns2);
ETH.config(system.getUserConfig()->network.static_.ip, system.getUserConfig()->network.static_.gateway, system.getUserConfig()->network.static_.subnet, system.getUserConfig()->network.static_.dns1, system.getUserConfig()->network.static_.dns2);
}
if (system.getUserConfig()->network.hostname.overwrite) {
ETH.setHostname(system.getUserConfig()->network.hostname.name.c_str());
} else {
ETH.setHostname(system.getUserConfig()->callsign.c_str());
}
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK);
return true;
}
bool EthTask::loop(System &system) {
if (!eth_connected) {
system.connectedViaWifiEth(false);
system.connectedViaEth(false);
_stateInfo = "Ethernet not connected";
_state = Error;
return false;
}
system.connectedViaWifiEth(true);
system.connectedViaEth(true);
_stateInfo = ETH.localIP().toString();
_state = Okay;
return true;

Wyświetl plik

@ -3,6 +3,7 @@
#include <TaskManager.h>
void setWiFiLogger(logging::Logger *logger);
void WiFiEvent(WiFiEvent_t event);
class EthTask : public Task {

Wyświetl plik

@ -14,8 +14,7 @@ FTPTask::~FTPTask() {
bool FTPTask::setup(System &system) {
for (Configuration::Ftp::User user : system.getUserConfig()->ftp.users) {
logPrintD("Adding user to FTP Server: ");
logPrintlnD(user.name);
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "Adding user to FTP Server: %s", user.name.c_str());
_ftpServer.addUser(user.name, user.password);
}
_ftpServer.addFilesystem("SPIFFS", &SPIFFS);
@ -31,8 +30,7 @@ bool FTPTask::loop(System &system) {
_ftpServer.handle();
static bool configWasOpen = false;
if (configWasOpen && _ftpServer.countConnections() == 0) {
logPrintlnW("Maybe the config has been changed via FTP, lets restart now to get the new config...");
logPrintlnW("");
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_WARN, getName(), "Maybe the config has been changed via FTP, lets restart now to get the new config...");
ESP.restart();
}
if (_ftpServer.countConnections() > 0) {

64
src/TaskMQTT.cpp 100644
Wyświetl plik

@ -0,0 +1,64 @@
#include <logger.h>
#include "Task.h"
#include "TaskMQTT.h"
#include "project_configuration.h"
#include <ArduinoJson.h>
MQTTTask::MQTTTask(TaskQueue<std::shared_ptr<APRSMessage>> &toMQTT) : Task(TASK_MQTT, TaskMQTT), _toMQTT(toMQTT), _MQTT(_client) {
}
MQTTTask::~MQTTTask() {
}
bool MQTTTask::setup(System &system) {
_MQTT.setServer(system.getUserConfig()->mqtt.server.c_str(), system.getUserConfig()->mqtt.port);
return true;
}
bool MQTTTask::loop(System &system) {
if (!system.isWifiOrEthConnected()) {
return false;
}
if (!_MQTT.connected()) {
connect(system);
}
if (!_toMQTT.empty()) {
std::shared_ptr<APRSMessage> msg = _toMQTT.getElement();
DynamicJsonDocument data(1024);
data["source"] = msg->getSource();
data["destination"] = msg->getDestination();
data["path"] = msg->getPath();
data["type"] = msg->getType().toString();
String body = msg->getBody()->encode();
body.replace("\n", "");
data["data"] = body;
String r;
serializeJson(data, r);
String topic = String(system.getUserConfig()->mqtt.topic);
if (!topic.endsWith("/")) {
topic = topic + "/";
}
topic = topic + system.getUserConfig()->callsign;
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "Send MQTT with topic: '%s', data: %s", topic.c_str(), r.c_str());
_MQTT.publish(topic.c_str(), r.c_str());
}
_MQTT.loop();
return true;
}
bool MQTTTask::connect(System &system) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Connecting to MQTT broker: %s on port %d", system.getUserConfig()->mqtt.server.c_str(), system.getUserConfig()->mqtt.port);
if (_MQTT.connect(system.getUserConfig()->callsign.c_str(), system.getUserConfig()->mqtt.name.c_str(), system.getUserConfig()->mqtt.password.c_str())) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Connected to MQTT broker as: %s", system.getUserConfig()->callsign.c_str());
return true;
}
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Connecting to MQTT broker failed. Try again later.");
return false;
}

26
src/TaskMQTT.h 100644
Wyświetl plik

@ -0,0 +1,26 @@
#ifndef TASK_MQTT_H_
#define TASK_MQTT_H_
#include <APRSMessage.h>
#include <PubSubClient.h>
#include <TaskManager.h>
#include <WiFi.h>
class MQTTTask : public Task {
public:
MQTTTask(TaskQueue<std::shared_ptr<APRSMessage>> &toMQTT);
virtual ~MQTTTask();
virtual bool setup(System &system) override;
virtual bool loop(System &system) override;
private:
TaskQueue<std::shared_ptr<APRSMessage>> &_toMQTT;
WiFiClient _client;
PubSubClient _MQTT;
bool connect(System &system);
};
#endif

Wyświetl plik

@ -1,60 +0,0 @@
#include <logger.h>
#include <TimeLib.h>
#include "Task.h"
#include "TaskAprsIs.h"
#include "TaskModem.h"
#include "project_configuration.h"
ModemTask::ModemTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &toModem) : Task(TASK_MODEM, TaskModem), _lora_aprs(), _fromModem(fromModem), _toModem(toModem) {
}
ModemTask::~ModemTask() {
}
bool ModemTask::setup(System &system) {
SPI.begin(system.getBoardConfig()->LoraSck, system.getBoardConfig()->LoraMiso, system.getBoardConfig()->LoraMosi, system.getBoardConfig()->LoraCS);
_lora_aprs.setPins(system.getBoardConfig()->LoraCS, system.getBoardConfig()->LoraReset, system.getBoardConfig()->LoraIRQ);
if (!_lora_aprs.begin(system.getUserConfig()->lora.frequencyRx)) {
logPrintlnE("Starting LoRa failed!");
_stateInfo = "LoRa-Modem failed";
_state = Error;
while (true)
;
}
_lora_aprs.setRxFrequency(system.getUserConfig()->lora.frequencyRx);
_lora_aprs.setTxFrequency(system.getUserConfig()->lora.frequencyTx);
_lora_aprs.setTxPower(system.getUserConfig()->lora.power);
_lora_aprs.setSpreadingFactor(system.getUserConfig()->lora.spreadingFactor);
_lora_aprs.setSignalBandwidth(system.getUserConfig()->lora.signalBandwidth);
_lora_aprs.setCodingRate4(system.getUserConfig()->lora.codingRate4);
_lora_aprs.enableCrc();
_stateInfo = "";
return true;
}
bool ModemTask::loop(System &system) {
if (_lora_aprs.checkMessage()) {
std::shared_ptr<APRSMessage> msg = _lora_aprs.getMessage();
// msg->getAPRSBody()->setData(msg->getAPRSBody()->getData() + " 123");
logPrintD("[" + timeString() + "] ");
logPrintD("Received packet '");
logPrintD(msg->toString());
logPrintD("' with RSSI ");
logPrintD(String(_lora_aprs.packetRssi()));
logPrintD(" and SNR ");
logPrintlnD(String(_lora_aprs.packetSnr()));
_fromModem.addElement(msg);
system.getDisplay().addFrame(std::shared_ptr<DisplayFrame>(new TextFrame("LoRa", msg->toString())));
}
if (!_toModem.empty()) {
std::shared_ptr<APRSMessage> msg = _toModem.getElement();
_lora_aprs.sendMessage(msg);
}
return true;
}

Wyświetl plik

@ -1,23 +0,0 @@
#ifndef TASK_LORA_H_
#define TASK_LORA_H_
#include <BoardFinder.h>
#include <LoRa_APRS.h>
#include <TaskManager.h>
class ModemTask : public Task {
public:
explicit ModemTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &_toModem);
virtual ~ModemTask();
virtual bool setup(System &system) override;
virtual bool loop(System &system) override;
private:
LoRa_APRS _lora_aprs;
TaskQueue<std::shared_ptr<APRSMessage>> &_fromModem;
TaskQueue<std::shared_ptr<APRSMessage>> &_toModem;
};
#endif

Wyświetl plik

@ -18,7 +18,7 @@ bool NTPTask::setup(System &system) {
}
bool NTPTask::loop(System &system) {
if (!system.isWifiEthConnected()) {
if (!system.isWifiOrEthConnected()) {
return false;
}
if (!_beginCalled) {
@ -27,8 +27,7 @@ bool NTPTask::loop(System &system) {
}
if (_ntpClient.update()) {
setTime(_ntpClient.getEpochTime());
logPrintI("Current time: ");
logPrintlnI(_ntpClient.getFormattedTime());
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Current time: %s", _ntpClient.getFormattedTime().c_str());
}
_stateInfo = _ntpClient.getFormattedTime();
_state = Okay;

Wyświetl plik

@ -13,37 +13,36 @@ OTATask::~OTATask() {
bool OTATask::setup(System &system) {
_ota.onStart([&]() {
String type;
if (_ota.getCommand() == U_FLASH)
if (_ota.getCommand() == U_FLASH) {
type = "sketch";
else // U_SPIFFS
} else { // U_SPIFFS
type = "filesystem";
logPrintlnI("Start updating " + type);
}
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Start updating %s. please wait, this prozess is taking some time!", type.c_str());
})
.onEnd([]() {
logPrintlnI("");
logPrintlnI("OTA End");
.onEnd([&]() {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "OTA End");
})
.onProgress([](unsigned int progress, unsigned int total) {
logPrintI("Progress: ");
logPrintI(String(progress / (total / 100)));
logPrintlnI("%");
})
.onError([](ota_error_t error) {
logPrintE("Error[");
logPrintE(String(error));
logPrintE("]: ");
if (error == OTA_AUTH_ERROR)
logPrintlnE("Auth Failed");
else if (error == OTA_BEGIN_ERROR)
logPrintlnE("Begin Failed");
else if (error == OTA_CONNECT_ERROR)
logPrintlnE("Connect Failed");
else if (error == OTA_RECEIVE_ERROR)
logPrintlnE("Receive Failed");
else if (error == OTA_END_ERROR)
logPrintlnE("End Failed");
.onError([&](ota_error_t error) {
String error_str;
if (error == OTA_AUTH_ERROR) {
error_str = "Auth Failed";
} else if (error == OTA_BEGIN_ERROR) {
error_str = "Begin Failed";
} else if (error == OTA_CONNECT_ERROR) {
error_str = "Connect Failed";
} else if (error == OTA_RECEIVE_ERROR) {
error_str = "Receive Failed";
} else if (error == OTA_END_ERROR) {
error_str = "End Failed";
}
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "Error[%d]: %s", error, error_str.c_str());
});
_ota.setHostname(system.getUserConfig()->callsign.c_str());
if (system.getUserConfig()->network.hostname.overwrite) {
_ota.setHostname(system.getUserConfig()->network.hostname.name.c_str());
} else {
_ota.setHostname(system.getUserConfig()->callsign.c_str());
}
_stateInfo = "";
return true;
}

Wyświetl plik

@ -0,0 +1,212 @@
#include <Task.h>
#include <TimeLib.h>
#include <logger.h>
#include "TaskRadiolib.h"
RadiolibTask::RadiolibTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &toModem) : Task(TASK_RADIOLIB, TaskRadiolib), _fromModem(fromModem), _toModem(toModem) {
}
RadiolibTask::~RadiolibTask() {
radio->clearDio0Action();
}
volatile bool RadiolibTask::enableInterrupt = true; // Need to catch interrupt or not.
volatile bool RadiolibTask::operationDone = false; // Caught IRQ or not.
void RadiolibTask::setFlag(void) {
if (!enableInterrupt) {
return;
}
operationDone = true;
}
bool RadiolibTask::setup(System &system) {
SPI.begin(system.getBoardConfig()->LoraSck, system.getBoardConfig()->LoraMiso, system.getBoardConfig()->LoraMosi, system.getBoardConfig()->LoraCS);
module = new Module(system.getBoardConfig()->LoraCS, system.getBoardConfig()->LoraIRQ, system.getBoardConfig()->LoraReset);
radio = new SX1278(module);
config = system.getUserConfig()->lora;
rxEnable = true;
txEnable = config.tx_enable;
float freqMHz = (float)config.frequencyRx / 1000000;
float BWkHz = (float)config.signalBandwidth / 1000;
const uint16_t preambleLength = 8;
int16_t state = radio->begin(freqMHz, BWkHz, config.spreadingFactor, config.codingRate4, RADIOLIB_SX127X_SYNC_WORD, config.power, preambleLength, config.gainRx);
if (state != RADIOLIB_ERR_NONE) {
switch (state) {
case RADIOLIB_ERR_INVALID_FREQUENCY:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, The supplied frequency value (%fMHz) is invalid for this module.", timeString().c_str(), freqMHz);
rxEnable = false;
txEnable = false;
break;
case RADIOLIB_ERR_INVALID_BANDWIDTH:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, The supplied bandwidth value (%fkHz) is invalid for this module. Should be 7800, 10400, 15600, 20800, 31250, 41700 ,62500, 125000, 250000, 500000.", timeString().c_str(), BWkHz);
rxEnable = false;
txEnable = false;
break;
case RADIOLIB_ERR_INVALID_SPREADING_FACTOR:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, The supplied spreading factor value (%d) is invalid for this module.", timeString().c_str(), config.spreadingFactor);
rxEnable = false;
txEnable = false;
break;
case RADIOLIB_ERR_INVALID_CODING_RATE:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, The supplied coding rate value (%d) is invalid for this module.", timeString().c_str(), config.codingRate4);
rxEnable = false;
txEnable = false;
break;
case RADIOLIB_ERR_INVALID_OUTPUT_POWER:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, The supplied output power value (%d) is invalid for this module.", timeString().c_str(), config.power);
txEnable = false;
break;
case RADIOLIB_ERR_INVALID_PREAMBLE_LENGTH:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, The supplied preamble length is invalid.", timeString().c_str());
txEnable = false;
break;
case RADIOLIB_ERR_INVALID_GAIN:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, The supplied gain value (%d) is invalid.", timeString().c_str(), config.gainRx);
rxEnable = false;
break;
default:
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] SX1278 init failed, code %d", timeString().c_str(), state);
rxEnable = false;
txEnable = false;
}
_stateInfo = "LoRa-Modem failed";
_state = Error;
}
state = radio->setCRC(true);
if (state != RADIOLIB_ERR_NONE) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] setCRC failed, code %d", timeString().c_str(), state);
_stateInfo = "LoRa-Modem failed";
_state = Error;
}
radio->setDio0Action(setFlag);
if (rxEnable) {
int state = startRX(RADIOLIB_SX127X_RXCONTINUOUS);
if (state != RADIOLIB_ERR_NONE) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] startRX failed, code %d", timeString().c_str(), state);
rxEnable = false;
_stateInfo = "LoRa-Modem failed";
_state = Error;
}
}
preambleDurationMilliSec = ((uint64_t)(preambleLength + 4) << (config.spreadingFactor + 10 /* to milli-sec */)) / config.signalBandwidth;
_stateInfo = "";
return true;
}
int transmissionState = RADIOLIB_ERR_NONE;
bool transmitFlag = false; // Transmitting or not.
bool RadiolibTask::loop(System &system) {
if (operationDone) { // occurs interrupt.
enableInterrupt = false;
if (transmitFlag) { // transmitted.
if (transmissionState == RADIOLIB_ERR_NONE) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX done", timeString().c_str());
} else {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] transmitFlag failed, code %d", timeString().c_str(), transmissionState);
}
operationDone = false;
transmitFlag = false;
txWaitTimer.setTimeout(preambleDurationMilliSec * 2);
txWaitTimer.start();
} else { // received.
String str;
int state = radio->readData(str);
if (state != RADIOLIB_ERR_NONE) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] readData failed, code %d", timeString().c_str(), state);
} else {
if (str.substring(0, 3) != "<\xff\x01") {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Unknown packet '%s' with RSSI %.0fdBm, SNR %.2fdB and FreqErr %fHz%s", timeString().c_str(), str.c_str(), radio->getRSSI(), radio->getSNR(), -radio->getFrequencyError());
} else {
std::shared_ptr<APRSMessage> msg = std::shared_ptr<APRSMessage>(new APRSMessage());
msg->decode(str.substring(3));
_fromModem.addElement(msg);
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Received packet '%s' with RSSI %.0fdBm, SNR %.2fdB and FreqErr %fHz", timeString().c_str(), msg->toString().c_str(), radio->getRSSI(), radio->getSNR(), -radio->getFrequencyError());
system.getDisplay().addFrame(std::shared_ptr<DisplayFrame>(new TextFrame("LoRa", msg->toString().c_str())));
}
}
operationDone = false;
}
if (rxEnable) {
int state = startRX(RADIOLIB_SX127X_RXCONTINUOUS);
if (state != RADIOLIB_ERR_NONE) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] startRX failed, code %d", timeString().c_str(), state);
rxEnable = false;
}
}
enableInterrupt = true;
} else { // not interrupt.
if (!txWaitTimer.check()) {
} else {
if (!txEnable) {
// system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX is not enabled", timeString().c_str());
} else {
if (transmitFlag) {
// system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX signal detected. Waiting TX", timeString().c_str());
} else {
if (!_toModem.empty()) {
if (config.frequencyRx == config.frequencyTx && (radio->getModemStatus() & 0x01) == 0x01) {
// system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] RX signal detected. Waiting TX", timeString().c_str());
} else {
std::shared_ptr<APRSMessage> msg = _toModem.getElement();
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Transmitting packet '%s'", timeString().c_str(), msg->toString().c_str());
int16_t state = startTX("<\xff\x01" + msg->encode());
if (state != RADIOLIB_ERR_NONE) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "[%s] startTX failed, code %d", timeString().c_str(), state);
txEnable = false;
return true;
}
}
}
}
}
}
}
return true;
}
int16_t RadiolibTask::startRX(uint8_t mode) {
if (config.frequencyTx != config.frequencyRx) {
int16_t state = radio->setFrequency((float)config.frequencyRx / 1000000);
if (state != RADIOLIB_ERR_NONE) {
return state;
}
}
return radio->startReceive(0, mode);
}
int16_t RadiolibTask::startTX(String &str) {
if (config.frequencyTx != config.frequencyRx) {
int16_t state = radio->setFrequency((float)config.frequencyTx / 1000000);
if (state != RADIOLIB_ERR_NONE) {
return state;
}
}
transmissionState = radio->startTransmit(str);
transmitFlag = true;
return RADIOLIB_ERR_NONE;
}

41
src/TaskRadiolib.h 100644
Wyświetl plik

@ -0,0 +1,41 @@
#ifndef TASK_LORA_H_
#define TASK_LORA_H_
#include "project_configuration.h"
#include <APRS-Decoder.h>
#include <BoardFinder.h>
#include <RadioLib.h>
#include <TaskManager.h>
class RadiolibTask : public Task {
public:
explicit RadiolibTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &_toModem);
virtual ~RadiolibTask();
virtual bool setup(System &system) override;
virtual bool loop(System &system) override;
private:
Module *module;
SX1278 *radio;
Configuration::LoRa config;
bool rxEnable, txEnable;
TaskQueue<std::shared_ptr<APRSMessage>> &_fromModem;
TaskQueue<std::shared_ptr<APRSMessage>> &_toModem;
static volatile bool enableInterrupt; // Need to catch interrupt or not.
static volatile bool operationDone; // Caught IRQ or not.
static void setFlag(void);
int16_t startRX(uint8_t mode);
int16_t startTX(String &str);
uint32_t preambleDurationMilliSec;
Timer txWaitTimer;
};
#endif

Wyświetl plik

@ -6,34 +6,24 @@
#include "TaskRouter.h"
#include "project_configuration.h"
String create_lat_aprs(double lat);
String create_long_aprs(double lng);
RouterTask::RouterTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &toModem, TaskQueue<std::shared_ptr<APRSMessage>> &toAprsIs) : Task(TASK_ROUTER, TaskRouter), _fromModem(fromModem), _toModem(toModem), _toAprsIs(toAprsIs) {
RouterTask::RouterTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &toModem, TaskQueue<std::shared_ptr<APRSMessage>> &toAprsIs, TaskQueue<std::shared_ptr<APRSMessage>> &toMQTT) : Task(TASK_ROUTER, TaskRouter), _fromModem(fromModem), _toModem(toModem), _toAprsIs(toAprsIs), _toMQTT(toMQTT) {
}
RouterTask::~RouterTask() {
}
bool RouterTask::setup(System &system) {
// setup beacon
_beacon_timer.setTimeout(system.getUserConfig()->beacon.timeout * 60 * 1000);
_beaconMsg = std::shared_ptr<APRSMessage>(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;
}
bool RouterTask::loop(System &system) {
// do routing
if (!_fromModem.empty()) {
std::shared_ptr<APRSMessage> modemMsg = _fromModem.getElement();
if (system.getUserConfig()->mqtt.active) {
_toMQTT.addElement(modemMsg);
}
if (system.getUserConfig()->aprs_is.active && modemMsg->getSource() != system.getUserConfig()->callsign) {
std::shared_ptr<APRSMessage> aprsIsMsg = std::make_shared<APRSMessage>(*modemMsg);
String path = aprsIsMsg->getPath();
@ -43,20 +33,21 @@ bool RouterTask::loop(System &system) {
path += ",";
}
aprsIsMsg->setPath(path + "qAR," + system.getUserConfig()->callsign);
aprsIsMsg->setPath(path + "qAO," + system.getUserConfig()->callsign);
logPrintD("APRS-IS: ");
logPrintlnD(aprsIsMsg->toString());
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "APRS-IS: %s", aprsIsMsg->toString().c_str());
_toAprsIs.addElement(aprsIsMsg);
} else {
logPrintlnD("APRS-IS: no forward => RFonly");
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "APRS-IS: no forward => RFonly");
}
} else {
if (!system.getUserConfig()->aprs_is.active)
logPrintlnD("APRS-IS: disabled");
if (!system.getUserConfig()->aprs_is.active) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "APRS-IS: disabled");
}
if (modemMsg->getSource() == system.getUserConfig()->callsign)
logPrintlnD("APRS-IS: no forward => own packet received");
if (modemMsg->getSource() == system.getUserConfig()->callsign) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "APRS-IS: no forward => own packet received");
}
}
if (system.getUserConfig()->digi.active && modemMsg->getSource() != system.getUserConfig()->callsign) {
@ -68,33 +59,14 @@ bool RouterTask::loop(System &system) {
// fixme
digiMsg->setPath(system.getUserConfig()->callsign + "*");
logPrintD("DIGI: ");
logPrintlnD(digiMsg->toString());
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "DIGI: %s", digiMsg->toString().c_str());
_toModem.addElement(digiMsg);
}
}
}
// check for beacon
if (_beacon_timer.check()) {
logPrintD("[" + timeString() + "] ");
logPrintlnD(_beaconMsg->encode());
if (system.getUserConfig()->aprs_is.active)
_toAprsIs.addElement(_beaconMsg);
if (system.getUserConfig()->digi.beacon) {
_toModem.addElement(_beaconMsg);
}
system.getDisplay().addFrame(std::shared_ptr<DisplayFrame>(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;
}

Wyświetl plik

@ -2,11 +2,12 @@
#define TASK_ROUTER_H_
#include <APRSMessage.h>
#include <TaskMQTT.h>
#include <TaskManager.h>
class RouterTask : public Task {
public:
RouterTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &toModem, TaskQueue<std::shared_ptr<APRSMessage>> &toAprsIs);
RouterTask(TaskQueue<std::shared_ptr<APRSMessage>> &fromModem, TaskQueue<std::shared_ptr<APRSMessage>> &toModem, TaskQueue<std::shared_ptr<APRSMessage>> &toAprsIs, TaskQueue<std::shared_ptr<APRSMessage>> &toMQTT);
virtual ~RouterTask();
virtual bool setup(System &system) override;
@ -16,9 +17,7 @@ private:
TaskQueue<std::shared_ptr<APRSMessage>> &_fromModem;
TaskQueue<std::shared_ptr<APRSMessage>> &_toModem;
TaskQueue<std::shared_ptr<APRSMessage>> &_toAprsIs;
std::shared_ptr<APRSMessage> _beaconMsg;
Timer _beacon_timer;
TaskQueue<std::shared_ptr<APRSMessage>> &_toMQTT;
};
#endif

Wyświetl plik

@ -20,15 +20,18 @@ bool WifiTask::setup(System &system) {
WiFi.mode(WIFI_STA);
WiFi.onEvent(WiFiEvent);
WiFi.setHostname(system.getUserConfig()->callsign.c_str());
if (system.getUserConfig()->network.hostname.overwrite) {
WiFi.setHostname(system.getUserConfig()->network.hostname.name.c_str());
} else {
WiFi.setHostname(system.getUserConfig()->callsign.c_str());
}
if (!system.getUserConfig()->network.DHCP) {
WiFi.config(system.getUserConfig()->network.staticIP, system.getUserConfig()->network.gateway, system.getUserConfig()->network.subnet, system.getUserConfig()->network.dns1, system.getUserConfig()->network.dns2);
WiFi.config(system.getUserConfig()->network.static_.ip, system.getUserConfig()->network.static_.gateway, system.getUserConfig()->network.static_.subnet, system.getUserConfig()->network.static_.dns1, system.getUserConfig()->network.static_.dns2);
}
for (Configuration::Wifi::AP ap : system.getUserConfig()->wifi.APs) {
logPrintD("Looking for AP: ");
logPrintlnD(ap.SSID);
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "Looking for AP: %s", ap.SSID.c_str());
_wiFiMulti.addAP(ap.SSID.c_str(), ap.password.c_str());
}
return true;
@ -37,20 +40,19 @@ bool WifiTask::setup(System &system) {
bool WifiTask::loop(System &system) {
const uint8_t wifi_status = _wiFiMulti.run();
if (wifi_status != WL_CONNECTED) {
system.connectedViaWifiEth(false);
logPrintlnE("WiFi not connected!");
system.connectedViaWifi(false);
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "WiFi not connected!");
_oldWifiStatus = wifi_status;
_stateInfo = "WiFi not connected";
_state = Error;
return false;
} else if (wifi_status != _oldWifiStatus) {
logPrintD("IP address: ");
logPrintlnD(WiFi.localIP().toString());
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "WiFi IP address: %s", WiFi.localIP().toString().c_str());
_oldWifiStatus = wifi_status;
return false;
}
system.connectedViaWifiEth(true);
_stateInfo = WiFi.localIP().toString();
system.connectedViaWifi(true);
_stateInfo = String("IP .") + String(WiFi.localIP()[3]) + String(" @ ") + String(WiFi.RSSI()) + String("dBm");
_state = Okay;
return true;
}

Wyświetl plik

@ -8,42 +8,63 @@ void ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocumen
if (data.containsKey("callsign"))
conf.callsign = data["callsign"].as<String>();
if (data.containsKey("network") && data["network"].containsKey("DHCP")) {
conf.network.DHCP = data["network"]["DHCP"];
conf.network.staticIP.fromString(data["network"]["staticIP"].as<String>());
conf.network.subnet.fromString(data["network"]["subnet"].as<String>());
conf.network.gateway.fromString(data["network"]["gateway"].as<String>());
conf.network.dns1.fromString(data["network"]["dns1"].as<String>());
conf.network.dns2.fromString(data["network"]["dns2"].as<String>());
if (data.containsKey("network")) {
conf.network.DHCP = data["network"]["DHCP"] | false;
if (data["network"].containsKey("static")) {
if (data["network"]["static"].containsKey("ip"))
conf.network.static_.ip.fromString(data["network"]["static"]["ip"].as<String>());
if (data["network"]["static"].containsKey("subnet"))
conf.network.static_.subnet.fromString(data["network"]["static"]["subnet"].as<String>());
if (data["network"]["static"].containsKey("gateway"))
conf.network.static_.gateway.fromString(data["network"]["static"]["gateway"].as<String>());
if (data["network"]["static"].containsKey("dns1"))
conf.network.static_.dns1.fromString(data["network"]["static"]["dns1"].as<String>());
if (data["network"]["static"].containsKey("dns2"))
conf.network.static_.dns2.fromString(data["network"]["static"]["dns2"].as<String>());
}
if (data["network"].containsKey("hostname")) {
conf.network.hostname.overwrite = data["network"]["hostname"]["overwrite"] | false;
if (data["network"]["hostname"].containsKey("name"))
conf.network.hostname.name = data["network"]["hostname"]["name"].as<String>();
}
}
JsonArray aps = data["wifi"]["AP"].as<JsonArray>();
conf.wifi.active = data["wifi"]["active"];
JsonArray aps = data["wifi"]["AP"].as<JsonArray>();
for (JsonVariant v : aps) {
Configuration::Wifi::AP ap;
ap.SSID = v["SSID"].as<String>();
ap.password = v["password"].as<String>();
if (v.containsKey("SSID"))
ap.SSID = v["SSID"].as<String>();
if (v.containsKey("password"))
ap.password = v["password"].as<String>();
conf.wifi.APs.push_back(ap);
}
if (data.containsKey("beacon") && data["beacon"].containsKey("message"))
conf.beacon.message = data["beacon"]["message"].as<String>();
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<String>();
if (data.containsKey("aprs_is") && data["aprs_is"].containsKey("server"))
conf.aprs_is.server = data["aprs_is"]["server"].as<String>();
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;
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.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;
@ -53,8 +74,10 @@ void ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocumen
JsonArray users = data["ftp"]["user"].as<JsonArray>();
for (JsonVariant u : users) {
Configuration::Ftp::User us;
us.name = u["name"].as<String>();
us.password = u["password"].as<String>();
if (u.containsKey("name"))
us.name = u["name"].as<String>();
if (u.containsKey("password"))
us.password = u["password"].as<String>();
conf.ftp.users.push_back(us);
}
if (conf.ftp.users.empty()) {
@ -63,6 +86,23 @@ void ProjectConfigurationManagement::readProjectConfiguration(DynamicJsonDocumen
us.password = "ftp";
conf.ftp.users.push_back(us);
}
conf.mqtt.active = data["mqtt"]["active"] | false;
if (data["mqtt"].containsKey("server"))
conf.mqtt.server = data["mqtt"]["server"].as<String>();
conf.mqtt.port = data["mqtt"]["port"] | 1883;
if (data["mqtt"].containsKey("name"))
conf.mqtt.name = data["mqtt"]["name"].as<String>();
if (data["mqtt"].containsKey("password"))
conf.mqtt.password = data["mqtt"]["password"].as<String>();
if (data["mqtt"].containsKey("topic"))
conf.mqtt.topic = data["mqtt"]["topic"].as<String>();
conf.syslog.active = data["syslog"]["active"] | true;
if (data["syslog"].containsKey("server"))
conf.syslog.server = data["syslog"]["server"].as<String>();
conf.syslog.port = data["syslog"]["port"] | 514;
if (data.containsKey("ntp_server"))
conf.ntpServer = data["ntp_server"].as<String>();
@ -74,15 +114,18 @@ void ProjectConfigurationManagement::writeProjectConfiguration(Configuration &co
data["callsign"] = conf.callsign;
if (!conf.network.DHCP) {
data["network"]["DHCP"] = conf.network.DHCP;
data["network"]["staticIP"] = conf.network.staticIP.toString();
data["network"]["subnet"] = conf.network.subnet.toString();
data["network"]["gateway"] = conf.network.gateway.toString();
data["network"]["dns1"] = conf.network.dns1.toString();
data["network"]["dns2"] = conf.network.dns2.toString();
data["network"]["DHCP"] = conf.network.DHCP;
data["network"]["static"]["ip"] = conf.network.static_.ip.toString();
data["network"]["static"]["subnet"] = conf.network.static_.subnet.toString();
data["network"]["static"]["gateway"] = conf.network.static_.gateway.toString();
data["network"]["static"]["dns1"] = conf.network.static_.dns1.toString();
data["network"]["static"]["dns2"] = conf.network.static_.dns2.toString();
data["network"]["hostname"]["overwrite"] = conf.network.hostname.overwrite;
data["network"]["hostname"]["name"] = conf.network.hostname.name;
}
JsonArray aps = data["wifi"].createNestedArray("AP");
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;
@ -91,6 +134,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;
@ -99,11 +143,13 @@ void ProjectConfigurationManagement::writeProjectConfiguration(Configuration &co
data["digi"]["active"] = conf.digi.active;
data["digi"]["beacon"] = conf.digi.beacon;
data["lora"]["frequency_rx"] = conf.lora.frequencyRx;
data["lora"]["gain_rx"] = conf.lora.gainRx;
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["lora"]["tx_enable"] = conf.lora.tx_enable;
data["display"]["always_on"] = conf.display.alwaysOn;
data["display"]["timeout"] = conf.display.timeout;
data["display"]["overwrite_pin"] = conf.display.overwritePin;
@ -115,7 +161,16 @@ void ProjectConfigurationManagement::writeProjectConfiguration(Configuration &co
v["name"] = u.name;
v["password"] = u.password;
}
data["ntp_server"] = conf.ntpServer;
data["mqtt"]["active"] = conf.mqtt.active;
data["mqtt"]["server"] = conf.mqtt.server;
data["mqtt"]["port"] = conf.mqtt.port;
data["mqtt"]["name"] = conf.mqtt.name;
data["mqtt"]["password"] = conf.mqtt.password;
data["mqtt"]["topic"] = conf.mqtt.topic;
data["syslog"]["active"] = conf.syslog.active;
data["syslog"]["server"] = conf.syslog.server;
data["syslog"]["port"] = conf.syslog.port;
data["ntp_server"] = conf.ntpServer;
data["board"] = conf.board;
}

Wyświetl plik

@ -6,41 +6,55 @@
class Configuration {
public:
class Network {
class Static {
public:
Network() : DHCP(true) {
}
bool DHCP;
IPAddress staticIP;
IPAddress ip;
IPAddress subnet;
IPAddress gateway;
IPAddress dns1;
IPAddress dns2;
};
class Hostname {
public:
bool overwrite;
String name;
};
class Network {
public:
Network() : DHCP(true) {
}
bool DHCP;
Static static_;
Hostname hostname;
};
class Wifi {
public:
Wifi() : active(true) {
}
bool active;
class AP {
public:
String SSID;
String password;
};
Wifi() {
}
std::list<AP> APs;
};
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;
};
@ -66,15 +80,17 @@ public:
class LoRa {
public:
LoRa() : frequencyRx(433775000), frequencyTx(433775000), power(20), spreadingFactor(12), signalBandwidth(125000), codingRate4(5) {
LoRa() : frequencyRx(433775000), frequencyTx(433775000), power(20), spreadingFactor(12), signalBandwidth(125000), codingRate4(5), tx_enable(true) {
}
long frequencyRx;
long frequencyTx;
int power;
int spreadingFactor;
long signalBandwidth;
int codingRate4;
long frequencyRx;
uint8_t gainRx;
long frequencyTx;
int power;
int spreadingFactor;
long signalBandwidth;
int codingRate4;
bool tx_enable;
};
class Display {
@ -103,7 +119,31 @@ public:
std::list<User> users;
};
Configuration() : callsign("NOCALL-10"), board(""), ntpServer("pool.ntp.org"){};
class MQTT {
public:
MQTT() : active(false), server(""), port(1883), name(""), password(""), topic("LoraAPRS/Data") {
}
bool active;
String server;
int port;
String name;
String password;
String topic;
};
class Syslog {
public:
Syslog() : active(true), server("syslog.lora-aprs.info"), port(514) {
}
bool active;
String server;
int port;
};
Configuration() : callsign("NOCALL-10"), ntpServer("pool.ntp.org"), board("") {
}
String callsign;
Network network;
@ -114,13 +154,15 @@ public:
LoRa lora;
Display display;
Ftp ftp;
String board;
MQTT mqtt;
Syslog syslog;
String ntpServer;
String board;
};
class ProjectConfigurationManagement : public ConfigurationManagement {
public:
explicit ProjectConfigurationManagement() : ConfigurationManagement("/is-cfg.json") {
explicit ProjectConfigurationManagement(logging::Logger &logger) : ConfigurationManagement(logger, "/is-cfg.json") {
}
virtual ~ProjectConfigurationManagement() {
}