mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-01 07:30:33 +00:00
Compare commits
98 Commits
v1.3.13.71
...
v1.3.19.3c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c6a2f7bb6 | ||
|
|
1996a2a193 | ||
|
|
b40abbf3ad | ||
|
|
8684fd1c49 | ||
|
|
2a6633a666 | ||
|
|
0943e5f500 | ||
|
|
a1dc350231 | ||
|
|
d5a258cebd | ||
|
|
125f76d984 | ||
|
|
b127479961 | ||
|
|
d18aa2e7cb | ||
|
|
d301144efe | ||
|
|
058b5ceddd | ||
|
|
e85baf00c4 | ||
|
|
4a6cad6e46 | ||
|
|
bc05f98685 | ||
|
|
6e671d808a | ||
|
|
1df3dd5f78 | ||
|
|
c9822dee93 | ||
|
|
e1783df49f | ||
|
|
6b8afdadc2 | ||
|
|
f918548e44 | ||
|
|
a1b07ed6aa | ||
|
|
b059fb9e8e | ||
|
|
553b35d0ad | ||
|
|
04478081c6 | ||
|
|
7bd07db2a8 | ||
|
|
5c44c4f772 | ||
|
|
7ff940409e | ||
|
|
cb5c32490c | ||
|
|
e0b63c6692 | ||
|
|
dc8d1d9a84 | ||
|
|
710e2694ef | ||
|
|
7594140afc | ||
|
|
e793d933c6 | ||
|
|
61427528b6 | ||
|
|
47ad27f9f6 | ||
|
|
77f096e56c | ||
|
|
5106433572 | ||
|
|
4458b470aa | ||
|
|
90957e6994 | ||
|
|
b73fd32f71 | ||
|
|
2a3272b7d0 | ||
|
|
3fd756900a | ||
|
|
beb8bc9e72 | ||
|
|
1ad5cdc93c | ||
|
|
e8e72d2e08 | ||
|
|
1d0badd468 | ||
|
|
9e87be4f22 | ||
|
|
97899aed26 | ||
|
|
0ee4ba4975 | ||
|
|
bbcccde787 | ||
|
|
42c285bc31 | ||
|
|
c831242f25 | ||
|
|
3c6f36c8f7 | ||
|
|
dfde6cc9c1 | ||
|
|
7816800012 | ||
|
|
ebf132ad21 | ||
|
|
67cf3018b5 | ||
|
|
eafbef0c2f | ||
|
|
4ab831c103 | ||
|
|
3df5ec0b11 | ||
|
|
c5c2765fb4 | ||
|
|
df9e9bc223 | ||
|
|
1ff0032c20 | ||
|
|
18024f1d25 | ||
|
|
313c50d6cf | ||
|
|
80e08f6de9 | ||
|
|
5a256323e2 | ||
|
|
45495c51e6 | ||
|
|
40ded630d0 | ||
|
|
432d06741e | ||
|
|
03b7f2f837 | ||
|
|
2e1b895791 | ||
|
|
9821a0535b | ||
|
|
0b666b827d | ||
|
|
235cacf9b9 | ||
|
|
db28a1562e | ||
|
|
f61d2d9eb4 | ||
|
|
5aef58e87f | ||
|
|
77a2054254 | ||
|
|
48ee995e0d | ||
|
|
c7dfd245e3 | ||
|
|
4e813b098a | ||
|
|
e57dbdd26c | ||
|
|
9512ea45de | ||
|
|
0d09767efd | ||
|
|
5828e6f423 | ||
|
|
c7a9ce7f49 | ||
|
|
95f091041b | ||
|
|
f33e6a0e66 | ||
|
|
fe8bfdb762 | ||
|
|
e8afd4fb4b | ||
|
|
b34b26518b | ||
|
|
b9f25eb85c | ||
|
|
a7fbe024e4 | ||
|
|
1f7fee8e2a | ||
|
|
b8e7c6ee7a |
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -51,7 +51,8 @@
|
||||
"iterator": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"iostream": "cpp",
|
||||
"esp_nimble_hci.h": "c"
|
||||
"esp_nimble_hci.h": "c",
|
||||
"map": "cpp"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"Blox",
|
||||
|
||||
@@ -28,12 +28,12 @@ IF "__%FILENAME%__" == "____" (
|
||||
)
|
||||
IF EXIST %FILENAME% (
|
||||
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
|
||||
%PYTHON% -m esptool --baud 921600 erase_flash
|
||||
%PYTHON% -m esptool --baud 921600 write_flash 0x1000 system-info.bin
|
||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x1000 system-info.bin
|
||||
for %%f in (littlefs-*.bin) do (
|
||||
%PYTHON% -m esptool --baud 921600 write_flash 0x00390000 %%f
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00390000 %%f
|
||||
)
|
||||
%PYTHON% -m esptool --baud 921600 write_flash 0x10000 %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
|
||||
@@ -28,9 +28,9 @@ IF "__%FILENAME%__" == "____" (
|
||||
)
|
||||
IF EXIST %FILENAME% (
|
||||
echo Trying to flash update %FILENAME%
|
||||
%PYTHON% -m esptool --baud 921600 write_flash 0x10000 %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
||||
echo Erasing the otadata partition, which will turn off flash flippy-flop and force the first image to be used
|
||||
%PYTHON% -m esptool --baud 921600 erase_region 0xe000 0x2000
|
||||
%PYTHON% -m esptool --baud 115200 erase_region 0xe000 0x2000
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
|
||||
@@ -44,9 +44,9 @@ shift "$((OPTIND-1))"
|
||||
|
||||
if [ -f "${FILENAME}" ]; then
|
||||
echo "Trying to flash update ${FILENAME}."
|
||||
$PYTHON -m esptool --baud 921600 write_flash 0x10000 ${FILENAME}
|
||||
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
|
||||
echo "Erasing the otadata partition, which will turn off flash flippy-flop and force the first image to be used"
|
||||
$PYTHON -m esptool --baud 921600 erase_region 0xe000 0x2000
|
||||
$PYTHON -m esptool --baud 115200 erase_region 0xe000 0x2000
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
|
||||
@@ -17,7 +17,7 @@ Import("projenv")
|
||||
|
||||
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
||||
verObj = readProps(prefsLoc)
|
||||
print("Using meshtastic platform-custom.py, firmare version " + verObj['long'])
|
||||
print("Using meshtastic platformio-custom.py, firmare version " + verObj['long'])
|
||||
# print("path is" + ','.join(sys.path))
|
||||
|
||||
# General options that are passed to the C and C++ compilers
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
esptool.py --baud 921600 read_flash 0x1000 0xf000 system-info.img
|
||||
esptool.py --baud 115200 read_flash 0x1000 0xf000 system-info.img
|
||||
|
||||
@@ -20,6 +20,7 @@ default_envs = tbeam
|
||||
;default_envs = pca10059_diy_eink
|
||||
;default_envs = meshtastic-diy-v1
|
||||
;default_envs = meshtastic-diy-v1.1
|
||||
;default_envs = m5stack-coreink
|
||||
|
||||
extra_configs = variants/*/platformio.ini
|
||||
|
||||
@@ -37,7 +38,7 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
-DPB_ENABLE_MALLOC=1
|
||||
|
||||
monitor_speed = 921600
|
||||
monitor_speed = 115200
|
||||
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#53580644255b48ebb7a737343c6b4e71c7e11cf2 ; ESP8266_SSD1306
|
||||
@@ -60,7 +61,8 @@ framework = arduino
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
; Portduino is using meshtastic fork for now
|
||||
https://github.com/jgromes/RadioLib.git#3df3b092ebf412bd0b26524e7b296733bd6a62f7
|
||||
https://github.com/jgromes/RadioLib.git
|
||||
|
||||
build_flags = ${env.build_flags} -Os
|
||||
# -DRADIOLIB_GODMODE
|
||||
build_src_filter = ${env.build_src_filter} -<portduino/>
|
||||
@@ -83,15 +85,17 @@ lib_deps =
|
||||
adafruit/Adafruit BME280 Library@^2.2.2
|
||||
adafruit/Adafruit BME680 Library@^2.0.1
|
||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||
|
||||
adafruit/Adafruit INA260 Library@^1.5.0
|
||||
adafruit/Adafruit INA219@^1.2.0
|
||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
platform = espressif32@3.5.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<nrf52/>
|
||||
upload_speed = 921600
|
||||
upload_speed = 115200
|
||||
debug_init_break = tbreak setup
|
||||
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
|
||||
Submodule protobufs updated: 695b242113...a7bbc35866
@@ -10,7 +10,7 @@
|
||||
#ifdef CONSOLE_MAX_BAUD
|
||||
#define SERIAL_BAUD CONSOLE_MAX_BAUD
|
||||
#else
|
||||
#define SERIAL_BAUD 921600 // Serial debug baud rate
|
||||
#define SERIAL_BAUD 115200 // Serial debug baud rate
|
||||
#endif
|
||||
|
||||
#include "SerialConsole.h"
|
||||
|
||||
@@ -28,6 +28,34 @@ void listDir(const char * dirname, uint8_t levels)
|
||||
#endif
|
||||
}
|
||||
|
||||
void rmDir(const char * dirname)
|
||||
#ifdef FSCom
|
||||
{
|
||||
File root = FSCom.open(dirname);
|
||||
if(!root){
|
||||
return;
|
||||
}
|
||||
if(!root.isDirectory()){
|
||||
return;
|
||||
}
|
||||
|
||||
File file = root.openNextFile();
|
||||
while(file){
|
||||
if(file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||
file.close();
|
||||
rmDir(file.name());
|
||||
FSCom.rmdir(file.name());
|
||||
} else {
|
||||
file.close();
|
||||
FSCom.remove(file.name());
|
||||
}
|
||||
file.close();
|
||||
file = root.openNextFile();
|
||||
}
|
||||
file.close();
|
||||
#endif
|
||||
}
|
||||
|
||||
void fsInit()
|
||||
{
|
||||
#ifdef FSCom
|
||||
|
||||
@@ -26,4 +26,6 @@
|
||||
using namespace Adafruit_LittleFS_Namespace;
|
||||
#endif
|
||||
|
||||
void fsInit();
|
||||
void fsInit();
|
||||
void listDir(const char * dirname, uint8_t levels);
|
||||
void rmDir(const char * dirname);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "main.h"
|
||||
#include "sleep.h"
|
||||
#include "utils.h"
|
||||
#include "buzz/buzz.h"
|
||||
|
||||
#ifdef TBEAM_V10
|
||||
// FIXME. nasty hack cleanup how we load axp192
|
||||
@@ -211,8 +212,12 @@ void Power::shutdown()
|
||||
{
|
||||
#ifdef TBEAM_V10
|
||||
DEBUG_MSG("Shutting down\n");
|
||||
axp.setChgLEDMode(AXP20X_LED_OFF);
|
||||
axp.shutdown();
|
||||
#elif NRF52_SERIES
|
||||
playBeep();
|
||||
ledOff(PIN_LED1);
|
||||
ledOff(PIN_LED2);
|
||||
doDeepSleep(DELAY_FOREVER);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ static bool isPowered()
|
||||
|
||||
// If we are not a router and we already have AC power go to POWER state after init, otherwise go to ON
|
||||
// We assume routers might be powered all the time, but from a low current (solar) source
|
||||
bool isLowPower = config.power.is_low_power || isRouter;
|
||||
bool isPowerSavingMode = config.power.is_power_saving || isRouter;
|
||||
|
||||
/* To determine if we're externally powered, assumptions
|
||||
1) If we're powered up and there's no battery, we must be getting power externally. (because we'd be dead otherwise)
|
||||
|
||||
2) If we detect USB power from the power management chip, we must be getting power externally.
|
||||
*/
|
||||
return !isLowPower && powerStatus && (!powerStatus->getHasBattery() || powerStatus->getHasUSB());
|
||||
return !isPowerSavingMode && powerStatus && (!powerStatus->getHasBattery() || powerStatus->getHasUSB());
|
||||
}
|
||||
|
||||
static void sdsEnter()
|
||||
@@ -335,7 +335,7 @@ void PowerFSM_setup()
|
||||
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK,
|
||||
config.display.screen_on_secs ? config.display.screen_on_secs
|
||||
: 60 * 1000,
|
||||
: 60 * 1000 * 10,
|
||||
NULL, "Screen-on timeout");
|
||||
|
||||
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
||||
@@ -348,9 +348,6 @@ void PowerFSM_setup()
|
||||
|
||||
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
||||
if (isRouter || config.power.is_power_saving) {
|
||||
|
||||
// I don't think this transition is correct, turning off for now - @geeksville
|
||||
// powerFSM.add_timed_transition(&stateDARK, &stateNB, getPref_phone_timeout_secs() * 1000, NULL, "Phone timeout");
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS,
|
||||
config.power.min_wake_secs ? config.power.min_wake_secs
|
||||
: default_min_wake_secs * 1000,
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#define Port Serial
|
||||
// Defaulting to the formerly removed phone_timeout_secs value of 15 minutes
|
||||
#define SERIAL_CONNECTION_TIMEOUT (15 * 60) * 1000UL
|
||||
|
||||
SerialConsole *console;
|
||||
|
||||
@@ -41,13 +43,12 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
||||
emitRebooted();
|
||||
}
|
||||
|
||||
|
||||
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
|
||||
bool SerialConsole::checkIsConnected()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
return (now - lastContactMsec) < config.power.phone_timeout_secs
|
||||
? config.power.phone_timeout_secs
|
||||
: default_phone_timeout_secs * 1000UL;
|
||||
return (now - lastContactMsec) < SERIAL_CONNECTION_TIMEOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef RV3028_RTC
|
||||
#include "Melopero_RV3028.h"
|
||||
#endif
|
||||
@@ -144,7 +145,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//#define DISABLE_NTP
|
||||
|
||||
// Disable the welcome screen and allow
|
||||
//#define DISABLE_WELCOME_UNSET
|
||||
#define DISABLE_WELCOME_UNSET
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// OLED & Input
|
||||
@@ -170,6 +171,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// The older M5 Faces I2C Keyboard
|
||||
#define FACESKB_ADDR 0x88
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SENSOR
|
||||
// -----------------------------------------------------------------------------
|
||||
#define BME_ADDR 0x76
|
||||
#define BME_ADDR_ALTERNATE 0x77
|
||||
#define MCP9808_ADDR 0x18
|
||||
#define INA_ADDR 0x40
|
||||
#define INA_ADDR_ALTERNATE 0x41
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// GPS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
#include "../configuration.h"
|
||||
#include "../main.h"
|
||||
#include <Wire.h>
|
||||
#include "mesh/generated/telemetry.pb.h"
|
||||
|
||||
#ifndef NO_WIRE
|
||||
uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) {
|
||||
uint16_t value = 0x00;
|
||||
Wire.beginTransmission(address);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission();
|
||||
delay(20);
|
||||
Wire.requestFrom(address, length);
|
||||
DEBUG_MSG("Wire.available() = %d\n", Wire.available());
|
||||
if (Wire.available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)Wire.read() << 8;
|
||||
value |= Wire.read();
|
||||
} else if (Wire.available()) {
|
||||
value = Wire.read();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t oled_probe(byte addr)
|
||||
{
|
||||
uint8_t r = 0;
|
||||
@@ -34,7 +53,7 @@ uint8_t oled_probe(byte addr)
|
||||
void scanI2Cdevice(void)
|
||||
{
|
||||
byte err, addr;
|
||||
uint8_t r = 0x00;
|
||||
uint16_t registerValue = 0x00;
|
||||
int nDevices = 0;
|
||||
for (addr = 1; addr < 127; addr++) {
|
||||
Wire.beginTransmission(addr);
|
||||
@@ -74,15 +93,8 @@ void scanI2Cdevice(void)
|
||||
if (addr == CARDKB_ADDR) {
|
||||
cardkb_found = addr;
|
||||
// Do we have the RAK14006 instead?
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(0x04); // SENSOR_GET_VERSION
|
||||
Wire.endTransmission();
|
||||
delay(20);
|
||||
Wire.requestFrom((int)addr, 1);
|
||||
if (Wire.available()) {
|
||||
r = Wire.read();
|
||||
}
|
||||
if (r == 0x02) { // KEYPAD_VERSION
|
||||
registerValue = getRegisterValue(addr, 0x04, 1);
|
||||
if (registerValue == 0x02) { // KEYPAD_VERSION
|
||||
DEBUG_MSG("RAK14004 found\n");
|
||||
kb_model = 0x02;
|
||||
} else {
|
||||
@@ -104,6 +116,31 @@ void scanI2Cdevice(void)
|
||||
DEBUG_MSG("axp192 PMU found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
|
||||
if (registerValue == 0x61) {
|
||||
DEBUG_MSG("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BME680] = addr;
|
||||
} else if (registerValue == 0x60) {
|
||||
DEBUG_MSG("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xFE, 2);
|
||||
DEBUG_MSG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
DEBUG_MSG("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_INA260] = addr;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
DEBUG_MSG("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_INA219] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == MCP9808_ADDR) {
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
|
||||
DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
}
|
||||
} else if (err == 4) {
|
||||
DEBUG_MSG("Unknow error at address 0x%x\n", addr);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class ESP32CryptoEngine : public CryptoEngine
|
||||
static uint8_t scratch[MAX_BLOCKSIZE];
|
||||
size_t nc_off = 0;
|
||||
|
||||
// DEBUG_MSG("ESP32 crypt fr=%x, num=%x, numBytes=%d!\n", fromNode, (uint32_t) packetId, numBytes);
|
||||
DEBUG_MSG("ESP32 crypt fr=%x, num=%x, numBytes=%d!\n", fromNode, (uint32_t) packetId, numBytes);
|
||||
initNonce(fromNode, packetId);
|
||||
assert(numBytes <= MAX_BLOCKSIZE);
|
||||
memcpy(scratch, bytes, numBytes);
|
||||
@@ -68,8 +68,6 @@ class ESP32CryptoEngine : public CryptoEngine
|
||||
|
||||
virtual void decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes) override
|
||||
{
|
||||
// DEBUG_MSG("ESP32 decrypt!\n");
|
||||
|
||||
// For CTR, the implementation is the same
|
||||
encrypt(fromNode, packetId, numBytes, bytes);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
//4.2 inch 300x400 - GxEPD2_420_M01
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_420_M01
|
||||
|
||||
#elif defined(M5_COREINK)
|
||||
//M5Stack CoreInk
|
||||
//1.54 inch 200x200 - GxEPD2_154_M09
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_154_M09
|
||||
|
||||
#endif
|
||||
|
||||
GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT> *adafruitDisplay;
|
||||
@@ -58,6 +63,12 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl)
|
||||
//GxEPD2_420_M01
|
||||
setGeometry(GEOMETRY_RAWMODE, 300, 400);
|
||||
|
||||
#elif defined(M5_COREINK)
|
||||
|
||||
//M5Stack_CoreInk 200x200
|
||||
//1.54 inch 200x200 - GxEPD2_154_M09
|
||||
setGeometry(GEOMETRY_RAWMODE, EPD_HEIGHT, EPD_WIDTH);
|
||||
|
||||
#endif
|
||||
// setGeometry(GEOMETRY_RAWMODE, 128, 64); // old resolution
|
||||
// setGeometry(GEOMETRY_128_64); // We originally used this because I wasn't sure if rawmode worked - it does
|
||||
@@ -108,7 +119,7 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
// 4.2 inch 300x400 - GxEPD2_420_M01
|
||||
//adafruitDisplay->nextPage();
|
||||
|
||||
#elif defined(PCA10059)
|
||||
#elif defined(PCA10059) || defined(M5_COREINK)
|
||||
adafruitDisplay->nextPage();
|
||||
#endif
|
||||
|
||||
@@ -180,35 +191,10 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
adafruitDisplay->setRotation(3);
|
||||
//For 1.54, 2.9 and 4.2
|
||||
//adafruitDisplay->setRotation(1);
|
||||
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
//adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
} else {
|
||||
(void)adafruitDisplay;
|
||||
}
|
||||
@@ -221,6 +207,13 @@ bool EInkDisplay::connect()
|
||||
adafruitDisplay->setRotation(3);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
}
|
||||
#elif defined(M5_COREINK)
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
delay(100);
|
||||
adafruitDisplay->init(115200, true, 20, false, SPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
adafruitDisplay->setRotation(0);
|
||||
adafruitDisplay->setPartialWindow(0, 0, EPD_WIDTH, EPD_HEIGHT);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -90,6 +90,9 @@ uint32_t serialSinceMsec;
|
||||
|
||||
bool axp192_found;
|
||||
|
||||
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
|
||||
uint8_t nodeTelemetrySensorsMap[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
|
||||
|
||||
const char *getDeviceName()
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "GPSStatus.h"
|
||||
#include "NodeStatus.h"
|
||||
#include "PowerStatus.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "mesh/generated/telemetry.pb.h"
|
||||
|
||||
extern uint8_t screen_found;
|
||||
extern uint8_t screen_model;
|
||||
@@ -17,6 +19,8 @@ extern bool axp192_found;
|
||||
extern bool isCharging;
|
||||
extern bool isUSBPowered;
|
||||
|
||||
extern uint8_t nodeTelemetrySensorsMap[12];
|
||||
|
||||
// Global Screen singleton.
|
||||
extern graphics::Screen *screen;
|
||||
// extern Observable<meshtastic::PowerStatus> newPowerStatus; //TODO: move this to main-esp32.cpp somehow or a helper class
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
|
||||
void CryptoEngine::setKey(const CryptoKey &k)
|
||||
{
|
||||
DEBUG_MSG("Installing AES%d key!\n", k.length * 8);
|
||||
/* for(uint8_t i = 0; i < k.length; i++)
|
||||
DEBUG_MSG("%02x ", k.bytes[i]);
|
||||
DEBUG_MSG("\n"); */
|
||||
|
||||
DEBUG_MSG("Using AES%d key!\n", k.length * 8);
|
||||
key = k;
|
||||
}
|
||||
|
||||
@@ -36,6 +32,4 @@ void CryptoEngine::initNonce(uint32_t fromNode, uint64_t packetId)
|
||||
// use memcpy to avoid breaking strict-aliasing
|
||||
memcpy(nonce, &packetId, sizeof(uint64_t));
|
||||
memcpy(nonce + sizeof(uint64_t), &fromNode, sizeof(uint32_t));
|
||||
//*((uint64_t *)&nonce[0]) = packetId;
|
||||
//*((uint32_t *)&nonce[8]) = fromNode;
|
||||
}
|
||||
@@ -48,7 +48,7 @@ DeviceState versions used to be defined in the .proto file but really only this
|
||||
#define here.
|
||||
*/
|
||||
|
||||
#define DEVICESTATE_CUR_VER 11
|
||||
#define DEVICESTATE_CUR_VER 13
|
||||
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
||||
|
||||
// FIXME - move this somewhere else
|
||||
@@ -90,18 +90,17 @@ bool NodeDB::resetRadioConfig()
|
||||
// radioConfig.has_preferences = true;
|
||||
if (config.device.factory_reset) {
|
||||
DEBUG_MSG("Performing factory reset!\n");
|
||||
// first, remove the "/prefs" (this removes most prefs)
|
||||
rmDir("/prefs");
|
||||
// second, install default state (this will deal with the duplicate mac address issue)
|
||||
installDefaultDeviceState();
|
||||
// third, write to disk
|
||||
saveToDisk();
|
||||
#ifndef NO_ESP32
|
||||
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
|
||||
nvs_flash_erase();
|
||||
#endif
|
||||
#ifdef NRF52_SERIES
|
||||
// first, remove the "/prefs" (this removes most prefs)
|
||||
FSCom.rmdir_r("/prefs");
|
||||
// second, install default state (this will deal with the duplicate mac address issue)
|
||||
installDefaultDeviceState();
|
||||
// third, write to disk
|
||||
saveToDisk();
|
||||
Bluefruit.begin();
|
||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
@@ -146,6 +145,7 @@ bool NodeDB::resetRadioConfig()
|
||||
void NodeDB::installDefaultConfig()
|
||||
{
|
||||
memset(&config, 0, sizeof(LocalConfig));
|
||||
config.version = DEVICESTATE_CUR_VER;
|
||||
config.has_device = true;
|
||||
config.has_display = true;
|
||||
config.has_lora = true;
|
||||
@@ -165,6 +165,7 @@ void NodeDB::installDefaultConfig()
|
||||
void NodeDB::installDefaultModuleConfig()
|
||||
{
|
||||
memset(&moduleConfig, 0, sizeof(ModuleConfig));
|
||||
moduleConfig.version = DEVICESTATE_CUR_VER;
|
||||
moduleConfig.has_canned_message = true;
|
||||
moduleConfig.has_external_notification = true;
|
||||
moduleConfig.has_mqtt = true;
|
||||
@@ -174,21 +175,10 @@ void NodeDB::installDefaultModuleConfig()
|
||||
moduleConfig.has_telemetry = true;
|
||||
}
|
||||
|
||||
// void NodeDB::installDefaultRadioConfig()
|
||||
// {
|
||||
// memset(&radioConfig, 0, sizeof(radioConfig));
|
||||
// radioConfig.has_preferences = true;
|
||||
// resetRadioConfig();
|
||||
|
||||
// // for backward compat, default position flags are BAT+ALT+MSL (0x23 = 35)
|
||||
// config.position.position_flags =
|
||||
// (Config_PositionConfig_PositionFlags_POS_BATTERY | Config_PositionConfig_PositionFlags_POS_ALTITUDE |
|
||||
// Config_PositionConfig_PositionFlags_POS_ALT_MSL);
|
||||
// }
|
||||
|
||||
void NodeDB::installDefaultChannels()
|
||||
{
|
||||
memset(&channelFile, 0, sizeof(ChannelFile));
|
||||
channelFile.version = DEVICESTATE_CUR_VER;
|
||||
}
|
||||
|
||||
void NodeDB::installDefaultDeviceState()
|
||||
@@ -215,7 +205,7 @@ void NodeDB::installDefaultDeviceState()
|
||||
// Set default owner name
|
||||
pickNewNodeNum(); // based on macaddr now
|
||||
sprintf(owner.long_name, "Unknown %02x%02x", ourMacAddr[4], ourMacAddr[5]);
|
||||
sprintf(owner.short_name, "?%02X", (unsigned)(myNodeInfo.my_node_num & 0xff));
|
||||
sprintf(owner.short_name, "%02x%02x", ourMacAddr[4], ourMacAddr[5]);
|
||||
|
||||
sprintf(owner.id, "!%08x", getNodeNum()); // Default node ID now based on nodenum
|
||||
memcpy(owner.macaddr, ourMacAddr, sizeof(owner.macaddr));
|
||||
@@ -308,12 +298,12 @@ static const char *channelfile = "/prefs/channels.proto";
|
||||
/** Load a protobuf from a file, return true for success */
|
||||
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
|
||||
{
|
||||
bool okay = false;
|
||||
#ifdef FSCom
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
|
||||
auto f = FSCom.open(filename);
|
||||
|
||||
bool okay = false;
|
||||
if (f) {
|
||||
DEBUG_MSG("Loading %s\n", filename);
|
||||
pb_istream_t stream = {&readcb, &f, protoSize};
|
||||
@@ -346,33 +336,66 @@ void NodeDB::loadFromDisk()
|
||||
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: devicestate %d is old, discarding\n", devicestate.version);
|
||||
installDefaultDeviceState();
|
||||
#ifndef NO_ESP32
|
||||
// This will erase what's in NVS including ssl keys, persistant variables and ble pairing
|
||||
nvs_flash_erase();
|
||||
#endif
|
||||
#ifdef NRF52_SERIES
|
||||
Bluefruit.begin();
|
||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
||||
Bluefruit.Periph.clearBonds();
|
||||
Bluefruit.Central.clearBonds();
|
||||
#endif
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved preferences version %d\n", devicestate.version);
|
||||
DEBUG_MSG("Loaded saved devicestate version %d\n", devicestate.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(configfile, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config)) {
|
||||
installDefaultConfig(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (config.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: config %d is old, discarding\n", config.version);
|
||||
installDefaultConfig();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved config version %d\n", config.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(moduleConfigfile, LocalModuleConfig_size, sizeof(LocalModuleConfig), LocalModuleConfig_fields, &moduleConfig)) {
|
||||
installDefaultModuleConfig(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (moduleConfig.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: moduleConfig %d is old, discarding\n", moduleConfig.version);
|
||||
installDefaultModuleConfig();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved moduleConfig version %d\n", moduleConfig.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(channelfile, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile)) {
|
||||
installDefaultChannels(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (channelFile.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: channelFile %d is old, discarding\n", channelFile.version);
|
||||
installDefaultChannels();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved channelFile version %d\n", channelFile.version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Save a protobuf from a file, return true for success */
|
||||
bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, const void *dest_struct)
|
||||
{
|
||||
bool okay = false;
|
||||
#ifdef FSCom
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
String filenameTmp = filename;
|
||||
filenameTmp += ".tmp";
|
||||
auto f = FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
|
||||
bool okay = false;
|
||||
if (f) {
|
||||
DEBUG_MSG("Saving %s\n", filename);
|
||||
pb_ostream_t stream = {&writecb, &f, protoSize};
|
||||
|
||||
@@ -138,7 +138,7 @@ extern NodeDB nodeDB;
|
||||
/*
|
||||
If is_router is set, we use a number of different default values
|
||||
|
||||
# FIXME - after tuning, move these params into the on-device defaults based on is_router and is_low_power
|
||||
# FIXME - after tuning, move these params into the on-device defaults based on is_router and is_power_saving
|
||||
|
||||
# prefs.position_broadcast_secs = FIXME possibly broadcast only once an hr
|
||||
prefs.wait_bluetooth_secs = 1 # Don't stay in bluetooth mode
|
||||
@@ -152,7 +152,7 @@ extern NodeDB nodeDB;
|
||||
# get a new GPS position once per day
|
||||
prefs.gps_update_interval = oneday
|
||||
|
||||
prefs.is_low_power = True
|
||||
prefs.is_power_saving = True
|
||||
|
||||
# allow up to five minutes for each new GPS lock attempt
|
||||
prefs.gps_attempt_time = 300
|
||||
@@ -168,7 +168,6 @@ extern NodeDB nodeDB;
|
||||
#define default_mesh_sds_timeout_secs IF_ROUTER(NODE_DELAY_FOREVER, 2 * 60 * 60)
|
||||
#define default_sds_secs 365 * 24 * 60 * 60
|
||||
#define default_ls_secs IF_ROUTER(24 * 60 * 60, 5 * 60)
|
||||
#define default_phone_timeout_secs 15 * 60
|
||||
#define default_min_wake_secs 10
|
||||
|
||||
|
||||
|
||||
@@ -77,10 +77,13 @@ template <class T> class ProtobufModule : protected SinglePortModule
|
||||
T *decoded = NULL;
|
||||
if (mp.which_payloadVariant == MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
|
||||
memset(&scratch, 0, sizeof(scratch));
|
||||
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch))
|
||||
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
|
||||
decoded = &scratch;
|
||||
else
|
||||
} else {
|
||||
DEBUG_MSG("Error decoding protobuf module!\n");
|
||||
// if we can't decode it, nobody can process it!
|
||||
return ProcessMessage::STOP;
|
||||
}
|
||||
}
|
||||
|
||||
return handleReceivedProtobuf(mp, decoded) ? ProcessMessage::STOP : ProcessMessage::CONTINUE;
|
||||
|
||||
@@ -159,61 +159,50 @@ uint32_t RadioInterface::getPacketTime(MeshPacket *p)
|
||||
/** The delay to use for retransmitting dropped packets */
|
||||
uint32_t RadioInterface::getRetransmissionMsec(const MeshPacket *p)
|
||||
{
|
||||
assert(shortPacketMsec); // Better be non zero
|
||||
assert(slotTimeMsec); // Better be non zero
|
||||
static uint8_t bytes[MAX_RHPACKETLEN];
|
||||
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), Data_fields, &p->decoded);
|
||||
uint32_t packetAirtime = getPacketTime(numbytes + sizeof(PacketHeader));
|
||||
uint32_t tCADmsec = 2 * (1 << sf) / bw; // duration of CAD is roughly 2 symbols according to SX127x datasheet
|
||||
/* Make sure enough time has elapsed for this packet to be sent and an ACK is received.
|
||||
* Right now we have to wait until another node floods the same packet, as that is our implicit ACK.
|
||||
* TODO: Revise when want_ack will be used (right now it is always set to 0 afterwards).
|
||||
*/
|
||||
return 2*packetAirtime + 2*MIN_TX_WAIT_MSEC + shortPacketMsec + shortPacketMsec*2 + PROCESSING_TIME_MSEC + 2*tCADmsec;
|
||||
// Make sure enough time has elapsed for this packet to be sent and an ACK is received.
|
||||
// DEBUG_MSG("Waiting for flooding message with airtime %d and slotTime is %d\n", packetAirtime, slotTimeMsec);
|
||||
float channelUtil = airTime->channelUtilizationPercent();
|
||||
uint8_t CWsize = map(channelUtil, 0, 100, CWmin, CWmax);
|
||||
// Assuming we pick max. of CWsize and there will be a receiver with SNR at half the range
|
||||
return 2*packetAirtime + (pow(2, CWsize) + pow(2, int((CWmax+CWmin)/2))) * slotTimeMsec + PROCESSING_TIME_MSEC;
|
||||
}
|
||||
|
||||
/** The delay to use when we want to send something but the ether is busy */
|
||||
/** The delay to use when we want to send something */
|
||||
uint32_t RadioInterface::getTxDelayMsec()
|
||||
{
|
||||
/** At the low end we want to pick a delay large enough that anyone who just completed sending (some other node)
|
||||
* has had enough time to switch their radio back into receive mode.
|
||||
*/
|
||||
const uint32_t MIN_TX_WAIT_MSEC = 100;
|
||||
|
||||
/**
|
||||
* At the high end, this value is used to spread node attempts across time so when they are replying to a packet
|
||||
* they don't both check that the airwaves are clear at the same moment. As long as they are off by some amount
|
||||
* one of the two will be first to start transmitting and the other will see that. I bet 500ms is more than enough
|
||||
* to guarantee this.
|
||||
*/
|
||||
// const uint32_t MAX_TX_WAIT_MSEC = 2000; // stress test would still fail occasionally with 1000
|
||||
|
||||
return random((MIN_TX_WAIT_MSEC), (MIN_TX_WAIT_MSEC + shortPacketMsec));
|
||||
/** We wait a random multiple of 'slotTimes' (see definition in header file) in order to avoid collisions.
|
||||
The pool to take a random multiple from is the contention window (CW), which size depends on the
|
||||
current channel utilization. */
|
||||
float channelUtil = airTime->channelUtilizationPercent();
|
||||
uint8_t CWsize = map(channelUtil, 0, 100, CWmin, CWmax);
|
||||
// DEBUG_MSG("Current channel utilization is %f so setting CWsize to %d\n", channelUtil, CWsize);
|
||||
return random(0, pow(2, CWsize)) * slotTimeMsec;
|
||||
}
|
||||
|
||||
/** The delay to use when we want to send something but the ether is busy */
|
||||
/** The delay to use when we want to flood a message */
|
||||
uint32_t RadioInterface::getTxDelayMsecWeighted(float snr)
|
||||
{
|
||||
/** At the low end we want to pick a delay large enough that anyone who just completed sending (some other node)
|
||||
* has had enough time to switch their radio back into receive mode.
|
||||
*/
|
||||
const uint32_t MIN_TX_WAIT_MSEC = 100;
|
||||
|
||||
// The minimum value for a LoRa SNR
|
||||
const uint32_t SNR_MIN = -20;
|
||||
|
||||
// The maximum value for a LoRa SNR
|
||||
const uint32_t SNR_MAX = 15;
|
||||
|
||||
// high SNR = Long Delay
|
||||
// low SNR = Short Delay
|
||||
// high SNR = large CW size (Long Delay)
|
||||
// low SNR = small CW size (Short Delay)
|
||||
uint32_t delay = 0;
|
||||
|
||||
uint8_t CWsize = map(snr, SNR_MIN, SNR_MAX, CWmin, CWmax);
|
||||
// DEBUG_MSG("rx_snr of %f so setting CWsize to:%d\n", snr, CWsize);
|
||||
if (config.device.role == Config_DeviceConfig_Role_Router ||
|
||||
config.device.role == Config_DeviceConfig_Role_RouterClient) {
|
||||
delay = map(snr, SNR_MIN, SNR_MAX, MIN_TX_WAIT_MSEC, (MIN_TX_WAIT_MSEC + (shortPacketMsec / 2)));
|
||||
delay = random(0, 2*CWsize) * slotTimeMsec;
|
||||
DEBUG_MSG("rx_snr found in packet. As a router, setting tx delay:%d\n", delay);
|
||||
} else {
|
||||
delay = map(snr, SNR_MIN, SNR_MAX, MIN_TX_WAIT_MSEC + (shortPacketMsec / 2), (MIN_TX_WAIT_MSEC + shortPacketMsec * 2));
|
||||
delay = random(0, pow(2, CWsize)) * slotTimeMsec;
|
||||
DEBUG_MSG("rx_snr found in packet. Setting tx delay:%d\n", delay);
|
||||
}
|
||||
|
||||
@@ -411,9 +400,14 @@ void RadioInterface::applyModemConfig()
|
||||
}
|
||||
|
||||
power = loraConfig.tx_power;
|
||||
shortPacketMsec = getPacketTime(sizeof(PacketHeader));
|
||||
assert(myRegion); // Should have been found in init
|
||||
|
||||
if ((power == 0) || (power > myRegion->powerLimit))
|
||||
power = myRegion->powerLimit;
|
||||
|
||||
if (power == 0)
|
||||
power = 17; // Default to default power if we don't have a valid power
|
||||
|
||||
// Calculate the number of channels
|
||||
uint32_t numChannels = floor((myRegion->freqEnd - myRegion->freqStart) / (myRegion->spacing + (bw / 1000)));
|
||||
|
||||
@@ -431,7 +425,7 @@ void RadioInterface::applyModemConfig()
|
||||
DEBUG_MSG("Radio myRegion->numChannels: %d\n", numChannels);
|
||||
DEBUG_MSG("Radio channel_num: %d\n", channel_num);
|
||||
DEBUG_MSG("Radio frequency: %f\n", getFreq());
|
||||
DEBUG_MSG("Short packet time: %u msec\n", shortPacketMsec);
|
||||
DEBUG_MSG("Slot time: %u msec\n", slotTimeMsec);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,8 +52,6 @@ class RadioInterface
|
||||
CallbackObserver<RadioInterface, void *> notifyDeepSleepObserver =
|
||||
CallbackObserver<RadioInterface, void *>(this, &RadioInterface::notifyDeepSleepCb);
|
||||
|
||||
/// Number of msecs we expect our shortest actual packet to be over the wire (used in retry timeout calcs)
|
||||
uint32_t shortPacketMsec;
|
||||
|
||||
protected:
|
||||
bool disabled = false;
|
||||
@@ -61,10 +59,16 @@ class RadioInterface
|
||||
float bw = 125;
|
||||
uint8_t sf = 9;
|
||||
uint8_t cr = 7;
|
||||
|
||||
/** Slottime is the minimum time to wait, consisting of:
|
||||
- CAD duration (maximum of SX126x and SX127x);
|
||||
- roundtrip air propagation time (assuming max. 30km between nodes);
|
||||
- Tx/Rx turnaround time (maximum of SX126x and SX127x);
|
||||
- MAC processing time (measured on T-beam) */
|
||||
uint32_t slotTimeMsec = 8.5 * pow(2, sf)/bw + 0.2 + 0.4 + 7;
|
||||
uint16_t preambleLength = 32; // 8 is default, but we use longer to increase the amount of sleep time when receiving
|
||||
const uint32_t MIN_TX_WAIT_MSEC = 100; // minimum time to wait before transmitting after sensing the channel in ms
|
||||
const uint32_t PROCESSING_TIME_MSEC = 4500; // time to construct, process and construct a packet again (empirically determined)
|
||||
const uint8_t CWmin = 2; // minimum CWsize
|
||||
const uint8_t CWmax = 8; // maximum CWsize
|
||||
|
||||
MeshPacket *sendingPacket = NULL; // The packet we are currently sending
|
||||
uint32_t lastTxStart = 0L;
|
||||
@@ -128,10 +132,10 @@ class RadioInterface
|
||||
/** The delay to use for retransmitting dropped packets */
|
||||
uint32_t getRetransmissionMsec(const MeshPacket *p);
|
||||
|
||||
/** The delay to use when we want to send something but the ether is busy */
|
||||
/** The delay to use when we want to send something */
|
||||
uint32_t getTxDelayMsec();
|
||||
|
||||
/** The delay to use when we want to send something but the ether is busy. Use a weighted scale based on SNR */
|
||||
/** The delay to use when we want to flood a message. Use a weighted scale based on SNR */
|
||||
uint32_t getTxDelayMsecWeighted(float snr);
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
// FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that
|
||||
static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
|
||||
|
||||
#ifdef PORTDUINO
|
||||
|
||||
void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes)
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
@@ -18,6 +20,24 @@ void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint
|
||||
Module::SPItransfer(cmd, reg, dataOut, dataIn, numBytes);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void LockingModule::SPIbeginTransaction()
|
||||
{
|
||||
spiLock->lock();
|
||||
|
||||
Module::SPIbeginTransaction();
|
||||
}
|
||||
|
||||
void LockingModule::SPIendTransaction()
|
||||
{
|
||||
spiLock->unlock();
|
||||
|
||||
Module::SPIendTransaction();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy,
|
||||
SPIClass &spi, PhysicalLayer *_iface)
|
||||
: NotifiedWorkerThread("RadioIf"), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface)
|
||||
@@ -170,17 +190,11 @@ ErrorCode RadioLibInterface::send(MeshPacket *p)
|
||||
}
|
||||
|
||||
/** radio helper thread callback.
|
||||
|
||||
We never immediately transmit after any operation (either rx or tx). Instead we should start receiving and
|
||||
wait a random delay of 100ms to 100ms+shortPacketMsec to make sure we are not stomping on someone else. The 100ms delay
|
||||
at the beginning ensures all possible listeners have had time to finish processing the previous packet and now have their
|
||||
radio in RX state. The up to 100ms+shortPacketMsec random delay gives a chance for all possible senders to have high odds
|
||||
of detecting that someone else started transmitting first and then they will wait until that packet finishes.
|
||||
|
||||
NOTE: the large flood rebroadcast delay might still be needed even with this approach. Because we might not be able to
|
||||
hear other transmitters that we are potentially stomping on. Requires further thought.
|
||||
|
||||
FIXME, the MIN_TX_WAIT_MSEC and MAX_TX_WAIT_MSEC values should be tuned via logic analyzer later.
|
||||
We never immediately transmit after any operation (either Rx or Tx). Instead we should wait a random multiple of
|
||||
'slotTimes' (see definition in RadioInterface.h) taken from a contention window (CW) to lower the chance of collision.
|
||||
The CW size is determined by setTransmitDelay() and depends either on the current channel utilization or SNR in case
|
||||
of a flooding message. After this, we perform channel activity detection (CAD) and reset the transmit delay if it is
|
||||
currently active.
|
||||
*/
|
||||
void RadioLibInterface::onNotify(uint32_t notification)
|
||||
{
|
||||
|
||||
@@ -40,21 +40,13 @@ class LockingModule : public Module
|
||||
: Module(cs, irq, rst, gpio, spi, spiSettings)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief SPI single transfer method.
|
||||
|
||||
\param cmd SPI access command (read/write/burst/...).
|
||||
|
||||
\param reg Address of SPI register to transfer to/from.
|
||||
|
||||
\param dataOut Data that will be transfered from master to slave.
|
||||
|
||||
\param dataIn Data that was transfered from slave to master.
|
||||
|
||||
\param numBytes Number of bytes to transfer.
|
||||
*/
|
||||
virtual void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes);
|
||||
|
||||
#ifdef PORTDUINO
|
||||
void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes) override;
|
||||
#else
|
||||
void SPIbeginTransaction() override;
|
||||
void SPIendTransaction() override;
|
||||
#endif
|
||||
};
|
||||
|
||||
class RadioLibInterface : public RadioInterface, protected concurrency::NotifiedWorkerThread
|
||||
|
||||
@@ -120,20 +120,16 @@ typedef struct _Config_PositionConfig {
|
||||
bool gps_disabled;
|
||||
uint32_t gps_update_interval;
|
||||
uint32_t gps_attempt_time;
|
||||
bool gps_accept_2d;
|
||||
uint32_t gps_max_dop;
|
||||
uint32_t position_flags;
|
||||
} Config_PositionConfig;
|
||||
|
||||
typedef struct _Config_PowerConfig {
|
||||
Config_PowerConfig_ChargeCurrent charge_current;
|
||||
bool is_low_power;
|
||||
bool is_power_saving;
|
||||
bool is_always_powered;
|
||||
uint32_t on_battery_shutdown_after_secs;
|
||||
bool is_power_saving;
|
||||
float adc_multiplier_override;
|
||||
uint32_t wait_bluetooth_secs;
|
||||
uint32_t phone_timeout_secs;
|
||||
uint32_t mesh_sds_timeout_secs;
|
||||
uint32_t sds_secs;
|
||||
uint32_t ls_secs;
|
||||
@@ -194,15 +190,15 @@ extern "C" {
|
||||
/* Initializer values for message structs */
|
||||
#define Config_init_default {0, {Config_DeviceConfig_init_default}}
|
||||
#define Config_DeviceConfig_init_default {_Config_DeviceConfig_Role_MIN, 0, 0, 0, ""}
|
||||
#define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PowerConfig_init_default {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PowerConfig_init_default {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_WiFiConfig_init_default {"", "", 0, 0}
|
||||
#define Config_DisplayConfig_init_default {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0}
|
||||
#define Config_LoRaConfig_init_default {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, {0, 0, 0}}
|
||||
#define Config_init_zero {0, {Config_DeviceConfig_init_zero}}
|
||||
#define Config_DeviceConfig_init_zero {_Config_DeviceConfig_Role_MIN, 0, 0, 0, ""}
|
||||
#define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PowerConfig_init_zero {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_PowerConfig_init_zero {_Config_PowerConfig_ChargeCurrent_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define Config_WiFiConfig_init_zero {"", "", 0, 0}
|
||||
#define Config_DisplayConfig_init_zero {0, _Config_DisplayConfig_GpsCoordinateFormat_MIN, 0}
|
||||
#define Config_LoRaConfig_init_zero {0, _Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, {0, 0, 0}}
|
||||
@@ -232,17 +228,13 @@ extern "C" {
|
||||
#define Config_PositionConfig_gps_disabled_tag 5
|
||||
#define Config_PositionConfig_gps_update_interval_tag 6
|
||||
#define Config_PositionConfig_gps_attempt_time_tag 7
|
||||
#define Config_PositionConfig_gps_accept_2d_tag 8
|
||||
#define Config_PositionConfig_gps_max_dop_tag 9
|
||||
#define Config_PositionConfig_position_flags_tag 10
|
||||
#define Config_PowerConfig_charge_current_tag 1
|
||||
#define Config_PowerConfig_is_low_power_tag 2
|
||||
#define Config_PowerConfig_is_power_saving_tag 2
|
||||
#define Config_PowerConfig_is_always_powered_tag 3
|
||||
#define Config_PowerConfig_on_battery_shutdown_after_secs_tag 4
|
||||
#define Config_PowerConfig_is_power_saving_tag 5
|
||||
#define Config_PowerConfig_adc_multiplier_override_tag 6
|
||||
#define Config_PowerConfig_wait_bluetooth_secs_tag 7
|
||||
#define Config_PowerConfig_phone_timeout_secs_tag 8
|
||||
#define Config_PowerConfig_mesh_sds_timeout_secs_tag 9
|
||||
#define Config_PowerConfig_sds_secs_tag 10
|
||||
#define Config_PowerConfig_ls_secs_tag 11
|
||||
@@ -291,21 +283,17 @@ X(a, STATIC, SINGULAR, BOOL, fixed_position, 3) \
|
||||
X(a, STATIC, SINGULAR, BOOL, gps_disabled, 5) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_update_interval, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_attempt_time, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, gps_accept_2d, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_max_dop, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_flags, 10)
|
||||
#define Config_PositionConfig_CALLBACK NULL
|
||||
#define Config_PositionConfig_DEFAULT NULL
|
||||
|
||||
#define Config_PowerConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UENUM, charge_current, 1) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_low_power, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_power_saving, 2) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_always_powered, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, on_battery_shutdown_after_secs, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, is_power_saving, 5) \
|
||||
X(a, STATIC, SINGULAR, FLOAT, adc_multiplier_override, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, wait_bluetooth_secs, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, phone_timeout_secs, 8) \
|
||||
X(a, STATIC, SINGULAR, UINT32, mesh_sds_timeout_secs, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, sds_secs, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, ls_secs, 11) \
|
||||
@@ -363,8 +351,8 @@ extern const pb_msgdesc_t Config_LoRaConfig_msg;
|
||||
#define Config_DeviceConfig_size 42
|
||||
#define Config_DisplayConfig_size 14
|
||||
#define Config_LoRaConfig_size 67
|
||||
#define Config_PositionConfig_size 38
|
||||
#define Config_PowerConfig_size 55
|
||||
#define Config_PositionConfig_size 30
|
||||
#define Config_PowerConfig_size 47
|
||||
#define Config_WiFiConfig_size 103
|
||||
#define Config_size 105
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ typedef struct _ChannelFile {
|
||||
/* The channels our node knows about */
|
||||
pb_size_t channels_count;
|
||||
Channel channels[8];
|
||||
/* A version integer used to invalidate old save files when we make
|
||||
incompatible changes This integer is set at build time and is private to
|
||||
NodeDB.cpp in the device code. */
|
||||
uint32_t version;
|
||||
} ChannelFile;
|
||||
|
||||
/* This message is never sent over the wire, but it is used for serializing DB
|
||||
@@ -44,7 +48,7 @@ typedef struct _DeviceState {
|
||||
User owner;
|
||||
/* TODO: REPLACE */
|
||||
pb_size_t node_db_count;
|
||||
NodeInfo node_db[64];
|
||||
NodeInfo node_db[80];
|
||||
/* Received packets saved for delivery to the phone */
|
||||
pb_size_t receive_queue_count;
|
||||
MeshPacket receive_queue[1];
|
||||
@@ -92,15 +96,16 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
|
||||
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}}
|
||||
#define DeviceState_init_default {false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0}
|
||||
#define ChannelFile_init_default {0, {Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default, Channel_init_default}, 0}
|
||||
#define OEMStore_init_default {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
|
||||
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
|
||||
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}}
|
||||
#define DeviceState_init_zero {false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0}
|
||||
#define ChannelFile_init_zero {0, {Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero, Channel_init_zero}, 0}
|
||||
#define OEMStore_init_zero {0, 0, {0, {0}}, _ScreenFonts_MIN, ""}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define ChannelFile_channels_tag 1
|
||||
#define ChannelFile_version_tag 2
|
||||
#define DeviceState_my_node_tag 2
|
||||
#define DeviceState_owner_tag 3
|
||||
#define DeviceState_node_db_tag 4
|
||||
@@ -134,7 +139,8 @@ X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 11)
|
||||
#define DeviceState_rx_text_message_MSGTYPE MeshPacket
|
||||
|
||||
#define ChannelFile_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REPEATED, MESSAGE, channels, 1)
|
||||
X(a, STATIC, REPEATED, MESSAGE, channels, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 2)
|
||||
#define ChannelFile_CALLBACK NULL
|
||||
#define ChannelFile_DEFAULT NULL
|
||||
#define ChannelFile_channels_MSGTYPE Channel
|
||||
@@ -158,8 +164,8 @@ extern const pb_msgdesc_t OEMStore_msg;
|
||||
#define OEMStore_fields &OEMStore_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define ChannelFile_size 624
|
||||
#define DeviceState_size 19184
|
||||
#define ChannelFile_size 630
|
||||
#define DeviceState_size 23728
|
||||
#define OEMStore_size 2106
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -13,48 +13,56 @@
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _LocalConfig {
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Device */
|
||||
bool has_device;
|
||||
Config_DeviceConfig device;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the GPS Position */
|
||||
bool has_position;
|
||||
Config_PositionConfig position;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Power settings */
|
||||
bool has_power;
|
||||
Config_PowerConfig power;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Wifi Settings */
|
||||
bool has_wifi;
|
||||
Config_WiFiConfig wifi;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Display */
|
||||
bool has_display;
|
||||
Config_DisplayConfig display;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Lora Radio */
|
||||
bool has_lora;
|
||||
Config_LoRaConfig lora;
|
||||
/* A version integer used to invalidate old save files when we make
|
||||
incompatible changes This integer is set at build time and is private to
|
||||
NodeDB.cpp in the device code. */
|
||||
uint32_t version;
|
||||
} LocalConfig;
|
||||
|
||||
typedef struct _LocalModuleConfig {
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the MQTT module */
|
||||
bool has_mqtt;
|
||||
ModuleConfig_MQTTConfig mqtt;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Serial module */
|
||||
bool has_serial;
|
||||
ModuleConfig_SerialConfig serial;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the ExternalNotification module */
|
||||
bool has_external_notification;
|
||||
ModuleConfig_ExternalNotificationConfig external_notification;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Store & Forward module */
|
||||
bool has_store_forward;
|
||||
ModuleConfig_StoreForwardConfig store_forward;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the RangeTest module */
|
||||
bool has_range_test;
|
||||
ModuleConfig_RangeTestConfig range_test;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Telemetry module */
|
||||
bool has_telemetry;
|
||||
ModuleConfig_TelemetryConfig telemetry;
|
||||
/* TODO: REPLACE */
|
||||
/* The part of the config that is specific to the Canned Message module */
|
||||
bool has_canned_message;
|
||||
ModuleConfig_CannedMessageConfig canned_message;
|
||||
/* A version integer used to invalidate old save files when we make
|
||||
incompatible changes This integer is set at build time and is private to
|
||||
NodeDB.cpp in the device code. */
|
||||
uint32_t version;
|
||||
} LocalModuleConfig;
|
||||
|
||||
|
||||
@@ -63,10 +71,10 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define LocalConfig_init_default {false, Config_DeviceConfig_init_default, false, Config_PositionConfig_init_default, false, Config_PowerConfig_init_default, false, Config_WiFiConfig_init_default, false, Config_DisplayConfig_init_default, false, Config_LoRaConfig_init_default}
|
||||
#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default}
|
||||
#define LocalConfig_init_zero {false, Config_DeviceConfig_init_zero, false, Config_PositionConfig_init_zero, false, Config_PowerConfig_init_zero, false, Config_WiFiConfig_init_zero, false, Config_DisplayConfig_init_zero, false, Config_LoRaConfig_init_zero}
|
||||
#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero}
|
||||
#define LocalConfig_init_default {false, Config_DeviceConfig_init_default, false, Config_PositionConfig_init_default, false, Config_PowerConfig_init_default, false, Config_WiFiConfig_init_default, false, Config_DisplayConfig_init_default, false, Config_LoRaConfig_init_default, 0}
|
||||
#define LocalModuleConfig_init_default {false, ModuleConfig_MQTTConfig_init_default, false, ModuleConfig_SerialConfig_init_default, false, ModuleConfig_ExternalNotificationConfig_init_default, false, ModuleConfig_StoreForwardConfig_init_default, false, ModuleConfig_RangeTestConfig_init_default, false, ModuleConfig_TelemetryConfig_init_default, false, ModuleConfig_CannedMessageConfig_init_default, 0}
|
||||
#define LocalConfig_init_zero {false, Config_DeviceConfig_init_zero, false, Config_PositionConfig_init_zero, false, Config_PowerConfig_init_zero, false, Config_WiFiConfig_init_zero, false, Config_DisplayConfig_init_zero, false, Config_LoRaConfig_init_zero, 0}
|
||||
#define LocalModuleConfig_init_zero {false, ModuleConfig_MQTTConfig_init_zero, false, ModuleConfig_SerialConfig_init_zero, false, ModuleConfig_ExternalNotificationConfig_init_zero, false, ModuleConfig_StoreForwardConfig_init_zero, false, ModuleConfig_RangeTestConfig_init_zero, false, ModuleConfig_TelemetryConfig_init_zero, false, ModuleConfig_CannedMessageConfig_init_zero, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define LocalConfig_device_tag 1
|
||||
@@ -75,6 +83,7 @@ extern "C" {
|
||||
#define LocalConfig_wifi_tag 4
|
||||
#define LocalConfig_display_tag 5
|
||||
#define LocalConfig_lora_tag 6
|
||||
#define LocalConfig_version_tag 7
|
||||
#define LocalModuleConfig_mqtt_tag 1
|
||||
#define LocalModuleConfig_serial_tag 2
|
||||
#define LocalModuleConfig_external_notification_tag 3
|
||||
@@ -82,6 +91,7 @@ extern "C" {
|
||||
#define LocalModuleConfig_range_test_tag 5
|
||||
#define LocalModuleConfig_telemetry_tag 6
|
||||
#define LocalModuleConfig_canned_message_tag 7
|
||||
#define LocalModuleConfig_version_tag 8
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define LocalConfig_FIELDLIST(X, a) \
|
||||
@@ -90,7 +100,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, position, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, power, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, wifi, 4) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, display, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, lora, 6)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, lora, 6) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 7)
|
||||
#define LocalConfig_CALLBACK NULL
|
||||
#define LocalConfig_DEFAULT NULL
|
||||
#define LocalConfig_device_MSGTYPE Config_DeviceConfig
|
||||
@@ -107,7 +118,8 @@ X(a, STATIC, OPTIONAL, MESSAGE, external_notification, 3) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, store_forward, 4) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, range_test, 5) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, telemetry, 6) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7)
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, canned_message, 7) \
|
||||
X(a, STATIC, SINGULAR, UINT32, version, 8)
|
||||
#define LocalModuleConfig_CALLBACK NULL
|
||||
#define LocalModuleConfig_DEFAULT NULL
|
||||
#define LocalModuleConfig_mqtt_MSGTYPE ModuleConfig_MQTTConfig
|
||||
@@ -126,8 +138,8 @@ extern const pb_msgdesc_t LocalModuleConfig_msg;
|
||||
#define LocalModuleConfig_fields &LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define LocalConfig_size 331
|
||||
#define LocalModuleConfig_size 282
|
||||
#define LocalConfig_size 321
|
||||
#define LocalModuleConfig_size 288
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#ifndef PB_MESH_PB_H_INCLUDED
|
||||
#define PB_MESH_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "localonly.pb.h"
|
||||
#include "portnums.pb.h"
|
||||
#include "telemetry.pb.h"
|
||||
|
||||
@@ -630,6 +631,7 @@ typedef struct _FromRadio {
|
||||
union {
|
||||
MyNodeInfo my_info;
|
||||
NodeInfo node_info;
|
||||
LocalConfig config;
|
||||
LogRecord log_record;
|
||||
uint32_t config_complete_id;
|
||||
bool rebooted;
|
||||
@@ -819,6 +821,7 @@ extern "C" {
|
||||
#define FromRadio_id_tag 1
|
||||
#define FromRadio_my_info_tag 3
|
||||
#define FromRadio_node_info_tag 4
|
||||
#define FromRadio_config_tag 6
|
||||
#define FromRadio_log_record_tag 7
|
||||
#define FromRadio_config_complete_id_tag 8
|
||||
#define FromRadio_rebooted_tag 9
|
||||
@@ -968,6 +971,7 @@ X(a, STATIC, SINGULAR, UENUM, level, 4)
|
||||
X(a, STATIC, SINGULAR, UINT32, id, 1) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,my_info,my_info), 3) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,node_info,node_info), 4) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,config,config), 6) \
|
||||
X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,log_record,log_record), 7) \
|
||||
X(a, STATIC, ONEOF, UINT32, (payloadVariant,config_complete_id,config_complete_id), 8) \
|
||||
X(a, STATIC, ONEOF, BOOL, (payloadVariant,rebooted,rebooted), 9) \
|
||||
@@ -976,6 +980,7 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 11)
|
||||
#define FromRadio_DEFAULT NULL
|
||||
#define FromRadio_payloadVariant_my_info_MSGTYPE MyNodeInfo
|
||||
#define FromRadio_payloadVariant_node_info_MSGTYPE NodeInfo
|
||||
#define FromRadio_payloadVariant_config_MSGTYPE LocalConfig
|
||||
#define FromRadio_payloadVariant_log_record_MSGTYPE LogRecord
|
||||
#define FromRadio_payloadVariant_packet_MSGTYPE MeshPacket
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ typedef struct _ModuleConfig_TelemetryConfig {
|
||||
uint32_t environment_sensor_pin;
|
||||
} ModuleConfig_TelemetryConfig;
|
||||
|
||||
/* TODO: REPLACE */
|
||||
/* Module Config */
|
||||
typedef struct _ModuleConfig {
|
||||
/* TODO: REPLACE */
|
||||
pb_size_t which_payloadVariant;
|
||||
|
||||
@@ -48,6 +48,8 @@ typedef enum _PortNum {
|
||||
PortNum_ADMIN_APP = 6,
|
||||
/* Compressed TEXT_MESSAGE payloads. */
|
||||
PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
|
||||
/* Waypoint payloads. */
|
||||
PortNum_WAYPOINT_APP = 8,
|
||||
/* Provides a 'ping' service that replies to any packet it receives.
|
||||
Also serves as a small example module. */
|
||||
PortNum_REPLY_APP = 32,
|
||||
|
||||
@@ -12,26 +12,30 @@
|
||||
/* Enum definitions */
|
||||
/* TODO: REPLACE */
|
||||
typedef enum _TelemetrySensorType {
|
||||
/* No external telemetry sensor */
|
||||
/* No external telemetry sensor explicitly set */
|
||||
TelemetrySensorType_NotSet = 0,
|
||||
/* TODO: REPLACE */
|
||||
/* Moderate accuracy temperature */
|
||||
TelemetrySensorType_DHT11 = 1,
|
||||
/* TODO: REPLACE */
|
||||
/* High accuracy temperature */
|
||||
TelemetrySensorType_DS18B20 = 2,
|
||||
/* TODO: REPLACE */
|
||||
/* Moderate accuracy temperature and humidity */
|
||||
TelemetrySensorType_DHT12 = 3,
|
||||
/* TODO: REPLACE */
|
||||
/* Moderate accuracy temperature and humidity */
|
||||
TelemetrySensorType_DHT21 = 4,
|
||||
/* TODO: REPLACE */
|
||||
/* Moderate accuracy temperature and humidity */
|
||||
TelemetrySensorType_DHT22 = 5,
|
||||
/* TODO: REPLACE */
|
||||
/* High accuracy temperature, pressure, humidity */
|
||||
TelemetrySensorType_BME280 = 6,
|
||||
/* TODO: REPLACE */
|
||||
/* High accuracy temperature, pressure, humidity, and air resistance */
|
||||
TelemetrySensorType_BME680 = 7,
|
||||
/* TODO: REPLACE */
|
||||
/* Very high accuracy temperature */
|
||||
TelemetrySensorType_MCP9808 = 8,
|
||||
/* TODO: REPLACE */
|
||||
TelemetrySensorType_SHTC3 = 9
|
||||
/* Moderate accuracy temperature and humidity */
|
||||
TelemetrySensorType_SHTC3 = 9,
|
||||
/* Moderate accuracy current and voltage */
|
||||
TelemetrySensorType_INA260 = 10,
|
||||
/* Moderate accuracy current and voltage */
|
||||
TelemetrySensorType_INA219 = 11
|
||||
} TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
@@ -82,8 +86,8 @@ typedef struct _Telemetry {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _TelemetrySensorType_MIN TelemetrySensorType_NotSet
|
||||
#define _TelemetrySensorType_MAX TelemetrySensorType_SHTC3
|
||||
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_SHTC3+1))
|
||||
#define _TelemetrySensorType_MAX TelemetrySensorType_INA219
|
||||
#define _TelemetrySensorType_ARRAYSIZE ((TelemetrySensorType)(TelemetrySensorType_INA219+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -17,14 +17,6 @@ AdminModule *adminModule;
|
||||
/// a change.
|
||||
static const char *secretReserved = "sekrit";
|
||||
|
||||
/// If buf is !empty, change it to secret
|
||||
static void hideSecret(char *buf)
|
||||
{
|
||||
if (*buf) {
|
||||
strcpy(buf, secretReserved);
|
||||
}
|
||||
}
|
||||
|
||||
/// If buf is the reserved secret word, replace the buffer with currentVal
|
||||
static void writeSecret(char *buf, const char *currentVal)
|
||||
{
|
||||
@@ -314,11 +306,10 @@ void AdminModule::handleGetConfig(const MeshPacket &req, const uint32_t configTy
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secs & phone_timeout value so it can properly expect sleep behavior.
|
||||
// NOTE: The phone app needs to know the ls_secs value so it can properly expect sleep behavior.
|
||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||
// r.get_radio_response.preferences.phone_timeout_secs = getPref_phone_timeout_secs();
|
||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private
|
||||
// and useful for users to know current provisioning) hideSecret(r.get_radio_response.preferences.wifi_password);
|
||||
// r.get_config_response.which_payloadVariant = Config_ModuleConfig_telemetry_tag;
|
||||
@@ -371,11 +362,10 @@ void AdminModule::handleGetModuleConfig(const MeshPacket &req, const uint32_t co
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secs & phone_timeout value so it can properly expect sleep behavior.
|
||||
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
||||
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
|
||||
// using to the app (so that even old phone apps work with new device loads).
|
||||
// r.get_radio_response.preferences.ls_secs = getPref_ls_secs();
|
||||
// r.get_radio_response.preferences.phone_timeout_secs = getPref_phone_timeout_secs();
|
||||
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private
|
||||
// and useful for users to know current provisioning) hideSecret(r.get_radio_response.preferences.wifi_password);
|
||||
// r.get_config_response.which_payloadVariant = Config_ModuleConfig_telemetry_tag;
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
#include "Sensor/DHTSensor.h"
|
||||
#include "Sensor/DallasSensor.h"
|
||||
#include "Sensor/MCP9808Sensor.h"
|
||||
#include "Sensor/INA260Sensor.h"
|
||||
#include "Sensor/INA219Sensor.h"
|
||||
|
||||
|
||||
BME280Sensor bme280Sensor;
|
||||
BME680Sensor bme680Sensor;
|
||||
DHTSensor dhtSensor;
|
||||
DallasSensor dallasSensor;
|
||||
MCP9808Sensor mcp9808Sensor;
|
||||
INA260Sensor ina260Sensor;
|
||||
INA219Sensor ina219Sensor;
|
||||
|
||||
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
|
||||
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
|
||||
@@ -45,10 +50,12 @@ MCP9808Sensor mcp9808Sensor;
|
||||
int32_t EnvironmentTelemetryModule::runOnce()
|
||||
{
|
||||
#ifndef PORTDUINO
|
||||
int32_t result = INT32_MAX;
|
||||
/*
|
||||
Uncomment the preferences below if you want to use the module
|
||||
without having to configure it from the PythonAPI or WebUI.
|
||||
*/
|
||||
|
||||
/*
|
||||
moduleConfig.telemetry.environment_measurement_enabled = 1;
|
||||
moduleConfig.telemetry.environment_screen_enabled = 1;
|
||||
@@ -62,7 +69,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
if (!(moduleConfig.telemetry.environment_measurement_enabled ||
|
||||
moduleConfig.telemetry.environment_screen_enabled)) {
|
||||
// If this module is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
|
||||
return (INT32_MAX);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (firstTime) {
|
||||
@@ -73,32 +80,37 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
DEBUG_MSG("Environment Telemetry: Initializing\n");
|
||||
// it's possible to have this module enabled, only for displaying values on the screen.
|
||||
// therefore, we should only enable the sensor loop if measurement is also enabled
|
||||
|
||||
switch (moduleConfig.telemetry.environment_sensor_type) {
|
||||
|
||||
case TelemetrySensorType_DHT11:
|
||||
case TelemetrySensorType_DHT12:
|
||||
case TelemetrySensorType_DHT21:
|
||||
case TelemetrySensorType_DHT22:
|
||||
return dhtSensor.runOnce();
|
||||
case TelemetrySensorType_DS18B20:
|
||||
return dallasSensor.runOnce();
|
||||
case TelemetrySensorType_BME280:
|
||||
return bme280Sensor.runOnce();
|
||||
case TelemetrySensorType_BME680:
|
||||
return bme680Sensor.runOnce();
|
||||
case TelemetrySensorType_MCP9808:
|
||||
return mcp9808Sensor.runOnce();
|
||||
default:
|
||||
DEBUG_MSG("Environment Telemetry: Invalid sensor type selected; Disabling module");
|
||||
return (INT32_MAX);
|
||||
case TelemetrySensorType_DHT11:
|
||||
case TelemetrySensorType_DHT12:
|
||||
case TelemetrySensorType_DHT21:
|
||||
case TelemetrySensorType_DHT22:
|
||||
result = dhtSensor.runOnce();
|
||||
break;
|
||||
case TelemetrySensorType_DS18B20:
|
||||
result = dallasSensor.runOnce();
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("Environment Telemetry: No sensor type specified; Checking for detected i2c sensors\n");
|
||||
break;
|
||||
}
|
||||
if (bme680Sensor.hasSensor())
|
||||
result = bme680Sensor.runOnce();
|
||||
if (bme280Sensor.hasSensor())
|
||||
result = bme280Sensor.runOnce();
|
||||
if (mcp9808Sensor.hasSensor())
|
||||
result = mcp9808Sensor.runOnce();
|
||||
if (ina260Sensor.hasSensor())
|
||||
result = ina260Sensor.runOnce();
|
||||
if (ina219Sensor.hasSensor())
|
||||
result = ina219Sensor.runOnce();
|
||||
}
|
||||
return (INT32_MAX);
|
||||
return result;
|
||||
} else {
|
||||
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
|
||||
if (!moduleConfig.telemetry.environment_measurement_enabled)
|
||||
return (INT32_MAX);
|
||||
return result;
|
||||
// this is not the first time OSThread library has called this function
|
||||
// so just do what we intend to do on the interval
|
||||
if (sensor_read_error_count > moduleConfig.telemetry.environment_read_error_count_threshold) {
|
||||
@@ -114,7 +126,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
DEBUG_MSG("Environment Telemetry: DISABLED; The telemetry_module_environment_read_error_count_threshold has "
|
||||
"been exceed: %d. Reads will not be retried until after device reset\n",
|
||||
moduleConfig.telemetry.environment_read_error_count_threshold);
|
||||
return (INT32_MAX);
|
||||
return result;
|
||||
|
||||
} else if (sensor_read_error_count > 0) {
|
||||
DEBUG_MSG("Environment Telemetry: There have been %d sensor read failures. Will retry %d more times\n",
|
||||
@@ -124,23 +136,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
||||
if (!sendOurTelemetry()) {
|
||||
// if we failed to read the sensor, then try again
|
||||
// as soon as we can according to the maximum polling frequency
|
||||
|
||||
switch (moduleConfig.telemetry.environment_sensor_type) {
|
||||
case TelemetrySensorType_DHT11:
|
||||
case TelemetrySensorType_DHT12:
|
||||
case TelemetrySensorType_DHT21:
|
||||
case TelemetrySensorType_DHT22:
|
||||
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
case TelemetrySensorType_DS18B20:
|
||||
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
case TelemetrySensorType_BME280:
|
||||
case TelemetrySensorType_BME680:
|
||||
return (BME_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
case TelemetrySensorType_MCP9808:
|
||||
return (MCP_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
default:
|
||||
return (DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
}
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
}
|
||||
return getIntervalOrDefaultMs(moduleConfig.telemetry.environment_update_interval);
|
||||
@@ -245,29 +241,30 @@ bool EnvironmentTelemetryModule::sendOurTelemetry(NodeNum dest, bool wantReplies
|
||||
DEBUG_MSG("Environment Telemetry: Read data\n");
|
||||
|
||||
switch (moduleConfig.telemetry.environment_sensor_type) {
|
||||
case TelemetrySensorType_DS18B20:
|
||||
if (!dallasSensor.getMeasurement(&m))
|
||||
sensor_read_error_count++;
|
||||
break;
|
||||
case TelemetrySensorType_DHT11:
|
||||
case TelemetrySensorType_DHT12:
|
||||
case TelemetrySensorType_DHT21:
|
||||
case TelemetrySensorType_DHT22:
|
||||
if (!dhtSensor.getMeasurement(&m))
|
||||
sensor_read_error_count++;
|
||||
break;
|
||||
case TelemetrySensorType_BME280:
|
||||
bme280Sensor.getMeasurement(&m);
|
||||
break;
|
||||
case TelemetrySensorType_BME680:
|
||||
bme680Sensor.getMeasurement(&m);
|
||||
break;
|
||||
case TelemetrySensorType_MCP9808:
|
||||
mcp9808Sensor.getMeasurement(&m);
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("Environment Telemetry: No external sensor type selected; Only sending internal metrics\n");
|
||||
case TelemetrySensorType_DS18B20:
|
||||
if (!dallasSensor.getMetrics(&m))
|
||||
sensor_read_error_count++;
|
||||
break;
|
||||
case TelemetrySensorType_DHT11:
|
||||
case TelemetrySensorType_DHT12:
|
||||
case TelemetrySensorType_DHT21:
|
||||
case TelemetrySensorType_DHT22:
|
||||
if (!dhtSensor.getMetrics(&m))
|
||||
sensor_read_error_count++;
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("Environment Telemetry: No specified sensor type; Trying any detected i2c sensors\n");
|
||||
}
|
||||
if (bme280Sensor.hasSensor())
|
||||
bme280Sensor.getMetrics(&m);
|
||||
if (bme680Sensor.hasSensor())
|
||||
bme680Sensor.getMetrics(&m);
|
||||
if (mcp9808Sensor.hasSensor())
|
||||
mcp9808Sensor.getMetrics(&m);
|
||||
if (ina219Sensor.hasSensor())
|
||||
ina219Sensor.getMetrics(&m);
|
||||
if (ina260Sensor.hasSensor())
|
||||
ina260Sensor.getMetrics(&m);
|
||||
|
||||
DEBUG_MSG("Telemetry->time: %i\n", m.time);
|
||||
DEBUG_MSG("Telemetry->barometric_pressure: %f\n", m.variant.environment_metrics.barometric_pressure);
|
||||
|
||||
@@ -3,24 +3,26 @@
|
||||
#include "TelemetrySensor.h"
|
||||
#include "BME280Sensor.h"
|
||||
#include <Adafruit_BME280.h>
|
||||
#include <typeinfo>
|
||||
|
||||
BME280Sensor::BME280Sensor() : TelemetrySensor {} {
|
||||
BME280Sensor::BME280Sensor() :
|
||||
TelemetrySensor(TelemetrySensorType_BME280, "BME280")
|
||||
{
|
||||
}
|
||||
|
||||
int32_t BME280Sensor::runOnce() {
|
||||
unsigned bme280Status;
|
||||
// Default i2c address for BME280
|
||||
bme280Status = bme280.begin(0x76);
|
||||
if (!bme280Status) {
|
||||
DEBUG_MSG("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
|
||||
// TODO more verbose diagnostics
|
||||
} else {
|
||||
DEBUG_MSG("Telemetry: Opened BME280 on default i2c bus");
|
||||
DEBUG_MSG("Init sensor: %s\n", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
return BME_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
status = bme280.begin(nodeTelemetrySensorsMap[sensorType]);
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
bool BME280Sensor::getMeasurement(Telemetry *measurement) {
|
||||
void BME280Sensor::setup() { }
|
||||
|
||||
bool BME280Sensor::getMetrics(Telemetry *measurement) {
|
||||
DEBUG_MSG("BME280Sensor::getMetrics\n");
|
||||
measurement->variant.environment_metrics.temperature = bme280.readTemperature();
|
||||
measurement->variant.environment_metrics.relative_humidity = bme280.readHumidity();
|
||||
measurement->variant.environment_metrics.barometric_pressure = bme280.readPressure() / 100.0F;
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Adafruit_BME280.h>
|
||||
|
||||
#define BME_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||
|
||||
class BME280Sensor : virtual public TelemetrySensor {
|
||||
private:
|
||||
Adafruit_BME280 bme280;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
BME280Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMeasurement(Telemetry *measurement) override;
|
||||
virtual bool getMetrics(Telemetry *measurement) override;
|
||||
};
|
||||
@@ -4,29 +4,31 @@
|
||||
#include "BME680Sensor.h"
|
||||
#include <Adafruit_BME680.h>
|
||||
|
||||
BME680Sensor::BME680Sensor() : TelemetrySensor {} {
|
||||
BME680Sensor::BME680Sensor() :
|
||||
TelemetrySensor(TelemetrySensorType_BME680, "BME680")
|
||||
{
|
||||
}
|
||||
|
||||
int32_t BME680Sensor::runOnce() {
|
||||
unsigned bme680Status;
|
||||
// Default i2c address for BME680
|
||||
bme680Status = bme680.begin(0x76);
|
||||
if (!bme680Status) {
|
||||
DEBUG_MSG("Could not find a valid BME680 sensor, check wiring, address, sensor ID!");
|
||||
// TODO more verbose TelemetrySensor
|
||||
} else {
|
||||
DEBUG_MSG("Telemetry: Opened BME680 on default i2c bus");
|
||||
// Set up oversampling and filter initialization
|
||||
bme680.setTemperatureOversampling(BME680_OS_8X);
|
||||
bme680.setHumidityOversampling(BME680_OS_2X);
|
||||
bme680.setPressureOversampling(BME680_OS_4X);
|
||||
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3);
|
||||
bme680.setGasHeater(320, 150); // 320*C for 150 ms
|
||||
DEBUG_MSG("Init sensor: %s\n", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
return (BME_680_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
status = bme680.begin(nodeTelemetrySensorsMap[sensorType]);
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
bool BME680Sensor::getMeasurement(Telemetry *measurement) {
|
||||
void BME680Sensor::setup()
|
||||
{
|
||||
// Set up oversampling and filter initialization
|
||||
bme680.setTemperatureOversampling(BME680_OS_8X);
|
||||
bme680.setHumidityOversampling(BME680_OS_2X);
|
||||
bme680.setPressureOversampling(BME680_OS_4X);
|
||||
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3);
|
||||
bme680.setGasHeater(320, 150); // 320*C for 150 ms
|
||||
}
|
||||
|
||||
bool BME680Sensor::getMetrics(Telemetry *measurement) {
|
||||
measurement->variant.environment_metrics.temperature = bme680.readTemperature();
|
||||
measurement->variant.environment_metrics.relative_humidity = bme680.readHumidity();
|
||||
measurement->variant.environment_metrics.barometric_pressure = bme680.readPressure() / 100.0F;
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Adafruit_BME680.h>
|
||||
|
||||
#define BME_680_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||
|
||||
class BME680Sensor : virtual public TelemetrySensor {
|
||||
private:
|
||||
Adafruit_BME680 bme680;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
BME680Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMeasurement(Telemetry *measurement) override;
|
||||
virtual bool getMetrics(Telemetry *measurement) override;
|
||||
};
|
||||
@@ -5,11 +5,14 @@
|
||||
#include "configuration.h"
|
||||
#include <DHT.h>
|
||||
|
||||
DHTSensor::DHTSensor() : TelemetrySensor{} {}
|
||||
|
||||
int32_t DHTSensor::runOnce()
|
||||
DHTSensor::DHTSensor() :
|
||||
TelemetrySensor(TelemetrySensorType_NotSet, "DHT")
|
||||
{
|
||||
if (TelemetrySensorType_DHT11 || TelemetrySensorType_DHT12) {
|
||||
}
|
||||
|
||||
int32_t DHTSensor::runOnce() {
|
||||
if (moduleConfig.telemetry.environment_sensor_type == TelemetrySensorType_DHT11 ||
|
||||
moduleConfig.telemetry.environment_sensor_type == TelemetrySensorType_DHT12) {
|
||||
dht = new DHT(moduleConfig.telemetry.environment_sensor_pin, DHT11);
|
||||
} else {
|
||||
dht = new DHT(moduleConfig.telemetry.environment_sensor_pin, DHT22);
|
||||
@@ -17,13 +20,15 @@ int32_t DHTSensor::runOnce()
|
||||
|
||||
dht->begin();
|
||||
dht->read();
|
||||
DEBUG_MSG("Telemetry: Opened DHT11/DHT12 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
|
||||
DEBUG_MSG("Opened DHT11/DHT12 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
|
||||
|
||||
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
bool DHTSensor::getMeasurement(Telemetry *measurement)
|
||||
{
|
||||
void DHTSensor::setup() { }
|
||||
|
||||
bool DHTSensor::getMetrics(Telemetry *measurement) {
|
||||
DEBUG_MSG("DHTSensor::getMetrics\n");
|
||||
if (!dht->read(true)) {
|
||||
DEBUG_MSG("Telemetry: FAILED TO READ DATA\n");
|
||||
return false;
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
#include "TelemetrySensor.h"
|
||||
#include <DHT.h>
|
||||
|
||||
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||
|
||||
class DHTSensor : virtual public TelemetrySensor {
|
||||
private:
|
||||
DHT *dht = NULL;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
DHTSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMeasurement(Telemetry *measurement) override;
|
||||
virtual bool getMetrics(Telemetry *measurement) override;
|
||||
};
|
||||
@@ -6,21 +6,25 @@
|
||||
#include <DS18B20.h>
|
||||
#include <OneWire.h>
|
||||
|
||||
DallasSensor::DallasSensor() : TelemetrySensor{} {}
|
||||
|
||||
int32_t DallasSensor::runOnce()
|
||||
DallasSensor::DallasSensor() :
|
||||
TelemetrySensor(TelemetrySensorType_DS18B20, "DS18B20")
|
||||
{
|
||||
}
|
||||
|
||||
int32_t DallasSensor::runOnce() {
|
||||
oneWire = new OneWire(moduleConfig.telemetry.environment_sensor_pin);
|
||||
ds18b20 = new DS18B20(oneWire);
|
||||
ds18b20->begin();
|
||||
ds18b20->setResolution(12);
|
||||
ds18b20->requestTemperatures();
|
||||
DEBUG_MSG("Telemetry: Opened DS18B20 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
|
||||
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
DEBUG_MSG("Opened DS18B20 on pin: %d\n", moduleConfig.telemetry.environment_sensor_pin);
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
|
||||
bool DallasSensor::getMeasurement(Telemetry *measurement)
|
||||
{
|
||||
void DallasSensor::setup() {}
|
||||
|
||||
bool DallasSensor::getMetrics(Telemetry *measurement){
|
||||
DEBUG_MSG("DallasSensor::getMetrics\n");
|
||||
if (ds18b20->isConversionComplete()) {
|
||||
measurement->variant.environment_metrics.temperature = ds18b20->getTempC();
|
||||
measurement->variant.environment_metrics.relative_humidity = 0;
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
#include <DS18B20.h>
|
||||
#include <OneWire.h>
|
||||
|
||||
#define DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||
|
||||
class DallasSensor : virtual public TelemetrySensor {
|
||||
private:
|
||||
OneWire *oneWire = NULL;
|
||||
DS18B20 *ds18b20 = NULL;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
DallasSensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMeasurement(Telemetry *measurement) override;
|
||||
virtual bool getMetrics(Telemetry *measurement) override;
|
||||
};
|
||||
30
src/modules/Telemetry/Sensor/INA219Sensor.cpp
Normal file
30
src/modules/Telemetry/Sensor/INA219Sensor.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "../mesh/generated/telemetry.pb.h"
|
||||
#include "configuration.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include "INA219Sensor.h"
|
||||
#include <Adafruit_INA219.h>
|
||||
|
||||
INA219Sensor::INA219Sensor() :
|
||||
TelemetrySensor(TelemetrySensorType_INA219, "INA219")
|
||||
{
|
||||
}
|
||||
|
||||
int32_t INA219Sensor::runOnce() {
|
||||
DEBUG_MSG("Init sensor: %s\n", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
ina219 = Adafruit_INA219(nodeTelemetrySensorsMap[sensorType]);
|
||||
status = ina219.begin();
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void INA219Sensor::setup()
|
||||
{
|
||||
}
|
||||
|
||||
bool INA219Sensor::getMetrics(Telemetry *measurement) {
|
||||
measurement->variant.environment_metrics.voltage = ina219.getBusVoltage_V();
|
||||
measurement->variant.environment_metrics.current = ina219.getCurrent_mA();
|
||||
return true;
|
||||
}
|
||||
17
src/modules/Telemetry/Sensor/INA219Sensor.h
Normal file
17
src/modules/Telemetry/Sensor/INA219Sensor.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "../mesh/generated/telemetry.pb.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Adafruit_INA219.h>
|
||||
|
||||
|
||||
class INA219Sensor : virtual public TelemetrySensor {
|
||||
private:
|
||||
Adafruit_INA219 ina219;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
INA219Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(Telemetry *measurement) override;
|
||||
};
|
||||
30
src/modules/Telemetry/Sensor/INA260Sensor.cpp
Normal file
30
src/modules/Telemetry/Sensor/INA260Sensor.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "../mesh/generated/telemetry.pb.h"
|
||||
#include "configuration.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include "INA260Sensor.h"
|
||||
#include <Adafruit_INA260.h>
|
||||
|
||||
INA260Sensor::INA260Sensor() :
|
||||
TelemetrySensor(TelemetrySensorType_INA260, "INA260")
|
||||
{
|
||||
}
|
||||
|
||||
int32_t INA260Sensor::runOnce() {
|
||||
DEBUG_MSG("Init sensor: %s\n", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
status = ina260.begin(nodeTelemetrySensorsMap[sensorType]);
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
void INA260Sensor::setup()
|
||||
{
|
||||
}
|
||||
|
||||
bool INA260Sensor::getMetrics(Telemetry *measurement) {
|
||||
// mV conversion to V
|
||||
measurement->variant.environment_metrics.voltage = ina260.readBusVoltage() / 1000;
|
||||
measurement->variant.environment_metrics.current = ina260.readCurrent();
|
||||
return true;
|
||||
}
|
||||
17
src/modules/Telemetry/Sensor/INA260Sensor.h
Normal file
17
src/modules/Telemetry/Sensor/INA260Sensor.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "../mesh/generated/telemetry.pb.h"
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Adafruit_INA260.h>
|
||||
|
||||
|
||||
class INA260Sensor : virtual public TelemetrySensor {
|
||||
private:
|
||||
Adafruit_INA260 ina260 = Adafruit_INA260();
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
INA260Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMetrics(Telemetry *measurement) override;
|
||||
};
|
||||
@@ -4,25 +4,26 @@
|
||||
#include "MCP9808Sensor.h"
|
||||
#include <Adafruit_MCP9808.h>
|
||||
|
||||
MCP9808Sensor::MCP9808Sensor() : TelemetrySensor {} {
|
||||
MCP9808Sensor::MCP9808Sensor() :
|
||||
TelemetrySensor(TelemetrySensorType_MCP9808, "MCP9808")
|
||||
{
|
||||
}
|
||||
|
||||
int32_t MCP9808Sensor::runOnce() {
|
||||
unsigned mcp9808Status;
|
||||
// Default i2c address for MCP9808
|
||||
mcp9808Status = mcp9808.begin(0x18);
|
||||
if (!mcp9808Status) {
|
||||
DEBUG_MSG("Could not find a valid MCP9808 sensor, check wiring, address, sensor ID!");
|
||||
} else {
|
||||
DEBUG_MSG("TelemetrySensor: Opened MCP9808 on default i2c bus");
|
||||
// Reduce resolution from 0.0625 degrees (precision) to 0.125 degrees (high).
|
||||
mcp9808.setResolution(2);
|
||||
DEBUG_MSG("Init sensor: %s\n", sensorName);
|
||||
if (!hasSensor()) {
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
return (MCP_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
|
||||
status = mcp9808.begin(nodeTelemetrySensorsMap[sensorType]);
|
||||
return initI2CSensor();
|
||||
}
|
||||
|
||||
bool MCP9808Sensor::getMeasurement(Telemetry *measurement) {
|
||||
measurement->variant.environment_metrics.temperature = mcp9808.readTempC();
|
||||
void MCP9808Sensor::setup() {
|
||||
mcp9808.setResolution(2);
|
||||
}
|
||||
|
||||
bool MCP9808Sensor::getMetrics(Telemetry *measurement) {
|
||||
DEBUG_MSG("MCP9808Sensor::getMetrics\n");
|
||||
measurement->variant.environment_metrics.temperature = mcp9808.readTempC();
|
||||
return true;
|
||||
}
|
||||
@@ -2,14 +2,15 @@
|
||||
#include "TelemetrySensor.h"
|
||||
#include <Adafruit_MCP9808.h>
|
||||
|
||||
#define MCP_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||
|
||||
class MCP9808Sensor : virtual public TelemetrySensor {
|
||||
private:
|
||||
Adafruit_MCP9808 mcp9808;
|
||||
|
||||
protected:
|
||||
virtual void setup() override;
|
||||
|
||||
public:
|
||||
MCP9808Sensor();
|
||||
virtual int32_t runOnce() override;
|
||||
virtual bool getMeasurement(Telemetry *measurement) override;
|
||||
virtual bool getMetrics(Telemetry *measurement) override;
|
||||
};
|
||||
4
src/modules/Telemetry/Sensor/TelemetrySensor.cpp
Normal file
4
src/modules/Telemetry/Sensor/TelemetrySensor.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "TelemetrySensor.h"
|
||||
#include "../mesh/generated/telemetry.pb.h"
|
||||
#include "NodeDB.h"
|
||||
#include "main.h"
|
||||
@@ -1,14 +1,41 @@
|
||||
#pragma once
|
||||
#include "../mesh/generated/telemetry.pb.h"
|
||||
#include "NodeDB.h"
|
||||
#include "main.h"
|
||||
|
||||
#define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
|
||||
|
||||
class TelemetrySensor
|
||||
{
|
||||
protected:
|
||||
TelemetrySensor() {}
|
||||
TelemetrySensor(TelemetrySensorType sensorType, const char *sensorName)
|
||||
{
|
||||
this->sensorName = sensorName;
|
||||
this->sensorType = sensorType;
|
||||
this->status = 0;
|
||||
}
|
||||
|
||||
const char *sensorName;
|
||||
TelemetrySensorType sensorType;
|
||||
unsigned status;
|
||||
|
||||
int32_t initI2CSensor() {
|
||||
if (!status) {
|
||||
DEBUG_MSG("Could not connect to detected %s sensor.\n Removing from nodeTelemetrySensorsMap.\n", sensorName);
|
||||
nodeTelemetrySensorsMap[sensorType] = 0;
|
||||
} else {
|
||||
DEBUG_MSG("Opened %s sensor on default i2c bus\n", sensorName);
|
||||
setup();
|
||||
}
|
||||
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
|
||||
}
|
||||
virtual void setup();
|
||||
|
||||
public:
|
||||
bool hasSensor() {
|
||||
return sensorType < sizeof(nodeTelemetrySensorsMap) && nodeTelemetrySensorsMap[sensorType] > 0;
|
||||
}
|
||||
|
||||
virtual int32_t runOnce() = 0;
|
||||
virtual bool getMeasurement(Telemetry *measurement) = 0;
|
||||
virtual bool getMetrics(Telemetry *measurement) = 0;
|
||||
};
|
||||
|
||||
@@ -16,48 +16,31 @@ class NRF52CryptoEngine : public CryptoEngine
|
||||
*/
|
||||
virtual void encrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes) override
|
||||
{
|
||||
// DEBUG_MSG("NRF52 encrypt!\n");
|
||||
|
||||
if (key.length > 16) {
|
||||
DEBUG_MSG("Software encrypt fr=%x, num=%x, numBytes=%d!\n", fromNode, (uint32_t) packetId, numBytes);
|
||||
AES_ctx ctx;
|
||||
initNonce(fromNode, packetId);
|
||||
AES_init_ctx_iv(&ctx, key.bytes, nonce);
|
||||
AES_CTR_xcrypt_buffer(&ctx, bytes, numBytes);
|
||||
} else if (key.length > 0) {
|
||||
DEBUG_MSG("nRF52 encrypt fr=%x, num=%x, numBytes=%d!\n", fromNode, (uint32_t) packetId, numBytes);
|
||||
nRFCrypto.begin();
|
||||
nRFCrypto_AES ctx;
|
||||
uint8_t myLen = ctx.blockLen(numBytes);
|
||||
char encBuf[myLen] = {0};
|
||||
memcpy(encBuf, bytes, numBytes);
|
||||
initNonce(fromNode, packetId);
|
||||
ctx.begin();
|
||||
ctx.Process(encBuf, numBytes, nonce, key.bytes, key.length, (char*)bytes, ctx.encryptFlag, ctx.ctrMode);
|
||||
ctx.Process((char*)bytes, numBytes, nonce, key.bytes, key.length, encBuf, ctx.encryptFlag, ctx.ctrMode);
|
||||
ctx.end();
|
||||
nRFCrypto.end();
|
||||
memcpy(bytes, encBuf, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes) override
|
||||
{
|
||||
// DEBUG_MSG("NRF52 decrypt!\n");
|
||||
|
||||
if (key.length > 16) {
|
||||
AES_ctx ctx;
|
||||
initNonce(fromNode, packetId);
|
||||
AES_init_ctx_iv(&ctx, key.bytes, nonce);
|
||||
AES_CTR_xcrypt_buffer(&ctx, bytes, numBytes);
|
||||
} else if (key.length > 0) {
|
||||
nRFCrypto.begin();
|
||||
nRFCrypto_AES ctx;
|
||||
uint8_t myLen = ctx.blockLen(numBytes);
|
||||
char decBuf[myLen] = {0};
|
||||
memcpy(decBuf, bytes, numBytes);
|
||||
initNonce(fromNode, packetId);
|
||||
ctx.begin();
|
||||
ctx.Process(decBuf, numBytes, nonce, key.bytes, key.length, (char*)bytes, ctx.decryptFlag, ctx.ctrMode);
|
||||
ctx.end();
|
||||
nRFCrypto.end();
|
||||
}
|
||||
// For CTR, the implementation is the same
|
||||
encrypt(fromNode, packetId, numBytes, bytes);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -30,7 +30,7 @@ void powerCommandsCheck()
|
||||
DEBUG_MSG("Shutting down from admin command\n");
|
||||
#ifdef TBEAM_V10
|
||||
if (axp192_found == true) {
|
||||
// setLed(false); //TODO: FIXME: this is not working
|
||||
playShutdownMelody();
|
||||
power->shutdown();
|
||||
}
|
||||
#elif NRF52_SERIES
|
||||
|
||||
18
variants/m5stack_coreink/platformio.ini
Normal file
18
variants/m5stack_coreink/platformio.ini
Normal file
@@ -0,0 +1,18 @@
|
||||
[env:m5stack-coreink]
|
||||
extends = esp32_base
|
||||
board = m5stack-coreink
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D M5_COREINK -I variants/m5stack_coreink
|
||||
;-D RADIOLIB_VERBOSE
|
||||
-Ofast
|
||||
-D__MCUXPRESSO
|
||||
-DEPD_HEIGHT=200
|
||||
-DEPD_WIDTH=200
|
||||
-DM5STACK
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
zinggjm/GxEPD2@^1.4.5
|
||||
lewisxhe/PCF8563_Library@^0.0.1
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
upload_port = /dev/ttyACM*
|
||||
49
variants/m5stack_coreink/variant.h
Normal file
49
variants/m5stack_coreink/variant.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#define I2C_SDA 21 //-1
|
||||
#define I2C_SCL 22 //-1
|
||||
|
||||
//#define LED_PIN 10
|
||||
|
||||
#include "pcf8563.h"
|
||||
// PCF8563 RTC Module
|
||||
#define PCF8563_RTC 0x51
|
||||
|
||||
#define BUTTON_NEED_PULLUP
|
||||
#define BUTTON_PIN 5
|
||||
|
||||
//Wheel
|
||||
// Down 37
|
||||
// Push 38
|
||||
// Up 39
|
||||
|
||||
// Top Physical Button 5
|
||||
|
||||
#undef RF95_SCK
|
||||
#undef RF95_MISO
|
||||
#undef RF95_MOSI
|
||||
#undef RF95_NSS
|
||||
#define USE_RF95
|
||||
|
||||
#define RF95_SCK 18 //13
|
||||
#define RF95_MISO 34 //26
|
||||
#define RF95_MOSI 23 //25
|
||||
#define RF95_NSS 14
|
||||
#define LORA_DIO0 25 //32 now moved from ext port
|
||||
#define LORA_RESET 26 //33 now moved from ext port
|
||||
#define LORA_DIO1 RADIOLIB_NC
|
||||
#define LORA_DIO2 RADIOLIB_NC
|
||||
|
||||
#define NO_GPS
|
||||
// This board has no GPS for now
|
||||
#undef GPS_RX_PIN
|
||||
#undef GPS_TX_PIN
|
||||
|
||||
#define HAS_EINK
|
||||
//https://docs.m5stack.com/en/core/coreink
|
||||
//https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/schematic/Core/coreink/coreink_sch.pdf
|
||||
#define PIN_EINK_EN -1
|
||||
#define PIN_EINK_CS 9 // EPD_CS
|
||||
#define PIN_EINK_BUSY 4 // EPD_BUSY
|
||||
#define PIN_EINK_DC 15 // EPD_D/C
|
||||
#define PIN_EINK_RES -1 // Connected to GPIO0 but no needed !!!! maybe causing issue ?
|
||||
#define PIN_EINK_SCLK 18 // EPD_SCLK
|
||||
#define PIN_EINK_MOSI 23 // EPD_MOSI
|
||||
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 1
|
||||
minor = 3
|
||||
build = 13
|
||||
build = 19
|
||||
|
||||
Reference in New Issue
Block a user