Merge branch 'master' into fkp-Gualtherius-LoRaHam

pull/189/head
Peter Buchegger 2022-11-16 21:54:13 +01:00 zatwierdzone przez GitHub
commit 90b0274a78
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
26 zmienionych plików z 379 dodań i 1015 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

@ -38,8 +38,6 @@ jobs:
- 'lib/BoardFinder'
- 'lib/ConfigurationManagement'
#- 'lib/Display'
#- 'lib/LoRa'
- 'lib/LoRa_APRS'
#- 'lib/NTPClient'
- 'lib/PowerManagement'
- 'lib/System'

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,7 +63,7 @@ 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
@ -106,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

@ -76,7 +76,7 @@
"topic": "LoraAPRS/Data"
},
"syslog": {
"active": true,
"active": false,
"server": "syslog.lora-aprs.info",
"port": 514
},

Wyświetl plik

@ -35,7 +35,7 @@ void ConfigurationManagement::readConfiguration(logging::Logger &logger, Configu
readProjectConfiguration(data, conf);
// update config in memory to get the new fields:
writeConfiguration(logger, conf);
// writeConfiguration(logger, conf);
}
void ConfigurationManagement::writeConfiguration(logging::Logger &logger, Configuration &conf) {

Wyświetl plik

@ -1,636 +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_MODEM_STAT 0x18
#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) | 0x01);
// 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;
}
bool LoRaClass::rxSignalDetected() {
return (readRegister(REG_MODEM_STAT) & 0x01) == 0x01;
}
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, 0x01);
// 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,120 +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();
bool rxSignalDetected();
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,69 +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);
}
void LoRa_APRS::setRxGain(uint8_t gain) {
setGain(gain);
}
// 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,33 +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 setRxGain(uint8_t gain);
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,12 +31,16 @@ 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() {

Wyświetl plik

@ -21,8 +21,9 @@ 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:
@ -30,7 +31,8 @@ private:
Configuration const *_userConfig;
TaskManager _taskManager;
Display _display;
bool _isWifiEthConnected;
bool _isEthConnected;
bool _isWifiConnected;
logging::Logger _logger;
};

Wyświetl plik

@ -6,7 +6,7 @@ platform = espressif32 @ 3.1.1
framework = arduino
lib_ldf_mode = deep+
monitor_speed = 115200
monitor_flags = --raw
monitor_raw = yes
lib_deps =
bblanchon/ArduinoJson @ 6.17.0
lewisxhe/AXP202X_Library @ 1.1.2
@ -16,6 +16,7 @@ lib_deps =
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

@ -4,6 +4,7 @@
#include <BoardFinder.h>
#include <System.h>
#include <TaskManager.h>
#include <esp_task_wdt.h>
#include <logger.h>
#include <power_management.h>
@ -13,14 +14,14 @@
#include "TaskEth.h"
#include "TaskFTP.h"
#include "TaskMQTT.h"
#include "TaskModem.h"
#include "TaskNTP.h"
#include "TaskOTA.h"
#include "TaskRadiolib.h"
#include "TaskRouter.h"
#include "TaskWifi.h"
#include "project_configuration.h"
#define VERSION "22.14.0"
#define VERSION "22.20.0"
#define MODULE_NAME "Main"
String create_lat_aprs(double lat);
@ -35,18 +36,21 @@ System LoRaSystem;
Configuration userConfig;
DisplayTask displayTask;
ModemTask 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);
// 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() {
esp_task_wdt_init(10, true);
esp_task_wdt_add(NULL);
Serial.begin(115200);
LoRaSystem.getLogger().setSerial(&Serial);
setWiFiLogger(&LoRaSystem.getLogger());
@ -138,6 +142,7 @@ void setup() {
}
}
esp_task_wdt_reset();
LoRaSystem.getTaskManager().setup(LoRaSystem);
LoRaSystem.getDisplay().showSpashScreen("LoRa APRS iGate", VERSION);
@ -167,8 +172,9 @@ void setup() {
volatile bool syslogSet = false;
void loop() {
esp_task_wdt_reset();
LoRaSystem.getTaskManager().loop(LoRaSystem);
if (LoRaSystem.isWifiEthConnected() && LoRaSystem.getUserConfig()->syslog.active && !syslogSet) {
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;

Wyświetl plik

@ -7,6 +7,7 @@ enum TaskNames
TaskEth,
TaskFtp,
TaskModem,
TaskRadiolib,
TaskNtp,
TaskOta,
TaskWifi,
@ -16,15 +17,16 @@ enum TaskNames
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_MQTT "MQTTTask"
#define TASK_BEACON "BeaconTask"
#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()) {

Wyświetl plik

@ -25,10 +25,11 @@ void WiFiEvent(WiFiEvent_t event) {
break;
case SYSTEM_EVENT_STA_GOT_IP:
_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, "IPv4: %s", WiFi.localIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "Gateway: %s", WiFi.gatewayIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "DNS1: %s", WiFi.dnsIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "DNS2: %s", WiFi.dnsIP(1).toString().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:
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Disconnected");
@ -37,23 +38,22 @@ void WiFiEvent(WiFiEvent_t event) {
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Stopped");
break;
case SYSTEM_EVENT_ETH_START:
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "WiFi Started");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Started");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "Hostname: %s", ETH.getHostname());
_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, "IPv4: %s", ETH.localIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "Gateway: %s", ETH.gatewayIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "DNS1: %s", ETH.dnsIP().toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "DNS2: %s", ETH.dnsIP(1).toString().c_str());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "Hostname: %s", ETH.getHostname());
_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()) {
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "FULL_DUPLEX");
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH FULL_DUPLEX");
}
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "%dMbps", ETH.linkSpeed());
_logger->log(logging::LoggerLevel::LOGGER_LEVEL_INFO, WIFI_EVENT, "ETH Speed: %dMbps", ETH.linkSpeed());
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
@ -106,17 +106,18 @@ bool EthTask::setup(System &system) {
} else {
ETH.setHostname(system.getUserConfig()->callsign.c_str());
}
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

@ -18,7 +18,7 @@ bool MQTTTask::setup(System &system) {
}
bool MQTTTask::loop(System &system) {
if (!system.isWifiEthConnected()) {
if (!system.isWifiOrEthConnected()) {
return false;
}

Wyświetl plik

@ -1,64 +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)) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "Starting LoRa failed!");
_stateInfo = "LoRa-Modem failed";
_state = Error;
while (true)
;
}
_lora_aprs.setRxFrequency(system.getUserConfig()->lora.frequencyRx);
_lora_aprs.setRxGain(system.getUserConfig()->lora.gainRx);
_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();
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Received packet '%s' with RSSI %ddBm, SNR %.2fdB and FreqErr %dHz", timeString().c_str(), msg->toString().c_str(), _lora_aprs.packetRssi(), _lora_aprs.packetSnr(), -_lora_aprs.packetFrequencyError());
_fromModem.addElement(msg);
system.getDisplay().addFrame(std::shared_ptr<DisplayFrame>(new TextFrame("LoRa", msg->toString().c_str())));
}
if (!_toModem.empty()) {
if (_lora_aprs.rxSignalDetected()) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] RX signal detected. Waiting TX", timeString().c_str());
delay(1000);
} else {
std::shared_ptr<APRSMessage> msg = _toModem.getElement();
if (system.getUserConfig()->lora.tx_enable) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] Transmitting packet '%s'", timeString().c_str(), msg->toString().c_str());
_lora_aprs.sendMessage(msg);
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] TX done", timeString().c_str());
} else {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "[%s] NOT transmitting packet as TX is not enabled '%s'", timeString().c_str(), msg->toString().c_str());
}
}
}
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) {

Wyświetl plik

@ -1,3 +1,4 @@
#include <esp_task_wdt.h>
#include <logger.h>
#include "Task.h"
@ -18,14 +19,11 @@ bool OTATask::setup(System &system) {
} else { // U_SPIFFS
type = "filesystem";
}
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Start updating %s", type.c_str());
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Start updating %s. please wait, this prozess is taking some time!", type.c_str());
})
.onEnd([&]() {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "OTA End");
})
.onProgress([&](unsigned int progress, unsigned int total) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_INFO, getName(), "Progress: %f", (progress / (total / 100)));
})
.onError([&](ota_error_t error) {
String error_str;
if (error == OTA_AUTH_ERROR) {
@ -40,6 +38,9 @@ bool OTATask::setup(System &system) {
error_str = "End Failed";
}
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, getName(), "Error[%d]: %s", error, error_str.c_str());
})
.onProgress([&](unsigned int received, unsigned int total_size) {
esp_task_wdt_reset();
});
if (system.getUserConfig()->network.hostname.overwrite) {
_ota.setHostname(system.getUserConfig()->network.hostname.name.c_str());

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", 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

@ -40,19 +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);
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) {
system.getLogger().log(logging::LoggerLevel::LOGGER_LEVEL_DEBUG, getName(), "IP address: %s", WiFi.localIP().toString().c_str());
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;
}