Compare commits

...

98 Commits

Author SHA1 Message Date
Jm Casler
3c6a2f7bb6 Bump to 1.3.19 2022-06-16 05:24:08 -07:00
Thomas Göttgens
1996a2a193 Merge pull request #1520 from meshtastic/radiolib-fix
Tryfix Portduino Radiolib
2022-06-16 12:30:23 +02:00
Thomas Göttgens
b40abbf3ad Tryfix Portduino Radiolib 2022-06-16 12:22:01 +02:00
Jm Casler
8684fd1c49 Bump to .18 2022-06-15 19:00:40 -07:00
Thomas Göttgens
2a6633a666 Merge pull request #1518 from meshtastic/create-pull-request/patch
TEST: Push out LocalConfig Object on app Handshake
2022-06-15 19:43:05 +02:00
caveman99
0943e5f500 [create-pull-request] automated change 2022-06-15 17:40:08 +00:00
Ben Meadors
a1dc350231 Changed default baud to 115200 (#1517)
Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
2022-06-15 11:44:37 -05:00
Thomas Göttgens
d5a258cebd Merge pull request #1516 from meshtastic/LocalConfig
add file version to local savefiles
2022-06-15 18:05:52 +02:00
Thomas Göttgens
125f76d984 Don't use rmdir_r but roll our own version. 2022-06-15 17:52:37 +02:00
Thomas Göttgens
b127479961 - Refactored factory reset a bit to not installDefaultDeviceState twice on ESP32
- clear BLE bonds on settings version increase
2022-06-15 17:09:42 +02:00
Thomas Göttgens
d18aa2e7cb add file version to local savefiles 2022-06-15 16:52:04 +02:00
Thomas Göttgens
d301144efe Merge pull request #1515 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-06-15 16:45:11 +02:00
caveman99
058b5ceddd [create-pull-request] automated change 2022-06-15 14:44:33 +00:00
Thomas Göttgens
e85baf00c4 Merge pull request #1511 from meshtastic/radiolib-fix
Set TX Power to some meaningful value
2022-06-13 23:24:37 +02:00
Thomas Göttgens
4a6cad6e46 Set TX Power to some meaningful value 2022-06-13 23:00:50 +02:00
Thomas Göttgens
bc05f98685 Merge pull request #1499 from meshtastic/radiolib-fix
new radiolib version (use upstream)
2022-06-13 21:33:51 +02:00
Thomas Göttgens
6e671d808a Our mod was accepted by RadioLib 2022-06-13 21:25:27 +02:00
Thomas Göttgens
1df3dd5f78 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-13 21:21:46 +02:00
Jm Casler
c9822dee93 Update to 1.13.17 2022-06-13 09:38:33 -07:00
Thomas Göttgens
e1783df49f Merge branch 'radiolib-fix' of github.com:meshtastic/Meshtastic-device
# Conflicts:
#	src/mesh/RadioLibInterface.h
2022-06-13 16:13:13 +02:00
Thomas Göttgens
6b8afdadc2 New variant of Radiolib patch 2022-06-13 16:10:16 +02:00
Thomas Göttgens
f918548e44 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-13 16:08:50 +02:00
GUVWAF
a1b07ed6aa Introduce contention window (CW) (#1500)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2022-06-13 08:21:18 -05:00
Thomas Göttgens
b059fb9e8e Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-13 12:23:51 +02:00
Ben Meadors
553b35d0ad Consolidate power saving prefs (#1507)
* Fixed conversion linter warning

* Power saving consolidation

* Whoops
2022-06-12 19:56:32 -05:00
Thomas Göttgens
04478081c6 Merge pull request #1508 from meshtastic/crpytfix
Remove nRF Crypt Debug
2022-06-12 23:52:16 +02:00
Thomas Göttgens
7bd07db2a8 Remove nRF Crypt Debug 2022-06-12 23:35:59 +02:00
Thomas Göttgens
5c44c4f772 Remove Debug Code for Encryption 2022-06-12 23:29:27 +02:00
Thomas Göttgens
7ff940409e Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-12 23:28:04 +02:00
Ben Meadors
cb5c32490c Merge branch 'master' into radiolib-fix 2022-06-12 15:27:58 -05:00
Thomas Göttgens
e0b63c6692 Merge pull request #1506 from meshtastic/1504-proposal-default-short-name-to-mac-last-4
implement #1504
2022-06-12 22:05:04 +02:00
Thomas Göttgens
dc8d1d9a84 implement #1504 2022-06-12 21:52:46 +02:00
Thomas Göttgens
710e2694ef Merge branch 'master' into radiolib-fix 2022-06-12 20:32:00 +02:00
Thomas Göttgens
7594140afc actual change to our interface 2022-06-12 20:31:23 +02:00
Thomas Göttgens
e793d933c6 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-12 20:28:39 +02:00
Thomas Göttgens
61427528b6 Merge pull request #1505 from meshtastic/caveman99-patch-1
fix C++ warnings
2022-06-12 18:39:46 +02:00
Thomas Göttgens
47ad27f9f6 fix C++ warnings
The cast throws errors about ambiguous conversions. There's a prototype of requestFrom(uint8_t address, uint8_t length) so just use that one.
2022-06-12 17:59:16 +02:00
Thomas Göttgens
77f096e56c Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-12 17:37:43 +02:00
Ben Meadors
5106433572 Removed phone_timeout_secs pref references (#1503) 2022-06-12 09:44:23 -05:00
Ben Meadors
4458b470aa Don't enable environmental telemetry by default (#1502)
* INA219 + INA260 support in telemetry

* Protobuf update

* Fixes + debug statement

* Fix size

* Fix conversion from mv

* Added getRegisterValue for i2cscan

* Accidentally left this in

* Removed line
2022-06-12 07:14:33 -05:00
Ben Meadors
90957e6994 INA260 + INA219 sensor support (#1501)
* INA219 + INA260 support in telemetry

* Protobuf update

* Fixes + debug statement

* Fix size

* Fix conversion from mv

* Added getRegisterValue for i2cscan
2022-06-11 16:44:56 -05:00
Thomas Göttgens
b73fd32f71 Merge branch 'master' into radiolib-fix 2022-06-10 20:39:50 +02:00
Thomas Göttgens
2a3272b7d0 patch radiolib on-the-fly while building. 2022-06-10 20:38:56 +02:00
Ben Meadors
3fd756900a Refactoring some of the i2c boilerplate (#1498)
* Refactoring some of the i2c boilerplate

* Default value

* Debug statement
2022-06-10 12:04:04 -05:00
Thomas Göttgens
beb8bc9e72 Merge pull request #1496 from benner/fix/NodeDB_without_FSCom
Compile when FSCom is not defined (NodeDB.cpp)
2022-06-07 22:22:20 +02:00
Thomas Göttgens
1ad5cdc93c Merge branch 'master' into fix/NodeDB_without_FSCom 2022-06-07 21:57:26 +02:00
Nerijus Bendžiūnas
e8e72d2e08 Compile when FSCom is not defined (NodeDB.cpp) 2022-06-07 20:55:05 +03:00
Thomas Göttgens
1d0badd468 Merge pull request #1495 from benner/fix/typo
Correctly print script name in platformio-custom.py
2022-06-07 11:39:47 +02:00
Nerijus Bendžiūnas
9e87be4f22 Correctly print script name in platformio-custom.py 2022-06-07 12:26:01 +03:00
Jm Casler
97899aed26 1.3.16 2022-06-06 22:10:18 -07:00
Thomas Göttgens
0ee4ba4975 Merge pull request #1494 from meshtastic/fix-1493
fixes power LED on T-Echo and T-Beam
2022-06-06 19:23:23 +02:00
Thomas Göttgens
bbcccde787 Merge branch 'fix-1493' of github.com:meshtastic/Meshtastic-device 2022-06-06 19:15:14 +02:00
Thomas Göttgens
42c285bc31 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-06 19:14:43 +02:00
Thomas Göttgens
c831242f25 fix nrf build 2022-06-06 19:14:30 +02:00
Thomas Göttgens
3c6f36c8f7 Merge branch 'master' into fix-1493 2022-06-06 18:57:51 +02:00
Thomas Göttgens
dfde6cc9c1 Merge pull request #1490 from meshtastic/CryptFix
Crypt fix. Please leave branch open
2022-06-06 18:57:27 +02:00
Thomas Göttgens
7816800012 Merge branch 'master' into CryptFix 2022-06-06 18:49:38 +02:00
Thomas Göttgens
ebf132ad21 Bug-1493 2022-06-06 18:48:22 +02:00
Thomas Göttgens
67cf3018b5 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-06 18:27:28 +02:00
Ben Meadors
eafbef0c2f Scan for i2c sensors in environmental telemetry if enabled (#1492)
* Scan for i2c sensors in environmental telemetry if enabled

* Update TelemetrySensor.h

* Added surpression.

* Remove suppression and fix real bug

* Interrogate BME sensor id registers
2022-06-05 09:50:06 -05:00
Ben Meadors
4ab831c103 Fix nagging bool linter warnings (#1491) 2022-06-04 07:28:58 -05:00
Thomas Göttgens
3df5ec0b11 Merge pull request #1479 from meshtastic/ProtoFix
If we get an unreadable buffer, don't try to process it.
2022-06-04 11:07:00 +02:00
Thomas Göttgens
c5c2765fb4 Merge branch 'master' into ProtoFix 2022-06-04 10:49:36 +02:00
Thomas Göttgens
df9e9bc223 Bugfix for nRF Crypto 90% done, includes heavy debug code, do not merge for now. 2022-06-04 10:37:24 +02:00
Thomas Göttgens
1ff0032c20 Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-04 10:35:42 +02:00
Jm Casler
18024f1d25 Merge pull request #1489 from mc-hamster/master
Disabled the unset welcome screen
2022-06-04 01:19:44 -07:00
Jm Casler
313c50d6cf Merge branch 'master' into master 2022-06-03 21:55:27 -07:00
Jm Casler
80e08f6de9 Disabled the unset welcome screen 2022-06-03 21:51:47 -07:00
Jm Casler
5a256323e2 Merge pull request #1488 from mc-hamster/master
Change default screen on to 10 minutes
2022-06-03 20:57:23 -07:00
Jm Casler
45495c51e6 Merge branch 'meshtastic:master' into master 2022-06-03 20:38:28 -07:00
Jm Casler
40ded630d0 Change default screen on to 10 minutes 2022-06-03 20:38:13 -07:00
Jm Casler
432d06741e Update version.properties 2022-06-03 18:49:18 -07:00
Jm Casler
03b7f2f837 Merge pull request #1487 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-06-03 18:47:52 -07:00
mc-hamster
2e1b895791 [create-pull-request] automated change 2022-06-04 01:47:29 +00:00
Jm Casler
9821a0535b Bump to 1.3.14 2022-06-03 14:32:32 -07:00
Thomas Göttgens
0b666b827d Merge branch 'master' of github.com:meshtastic/Meshtastic-device 2022-06-03 15:38:50 +02:00
Thomas Göttgens
235cacf9b9 Merge pull request #1485 from markbirss/master
Update EInkDisplay2.cpp
2022-06-03 15:09:56 +02:00
Mark Trevor Birss
db28a1562e Update EInkDisplay2.cpp
Fix E-Ink not powering up bug at startup
2022-06-03 14:21:27 +02:00
Jm Casler
f61d2d9eb4 Merge pull request #1484 from meshtastic/create-pull-request/patch
Changes by create-pull-request action
2022-06-02 18:12:35 -07:00
mc-hamster
5aef58e87f [create-pull-request] automated change 2022-06-03 01:07:08 +00:00
Thomas Göttgens
77a2054254 Merge pull request #1480 from markbirss/master
Add M5Stack CoreInk 1.54 inch e-Ink - HopeRF95 Support
2022-06-01 20:56:05 +02:00
Mark Trevor Birss
48ee995e0d Update EInkDisplay2.cpp 2022-06-01 20:33:51 +02:00
Mark Trevor Birss
c7dfd245e3 Update EInkDisplay2.cpp 2022-06-01 20:31:39 +02:00
Mark Trevor Birss
4e813b098a Update platformio.ini 2022-06-01 20:30:21 +02:00
Thomas Göttgens
e57dbdd26c Merge branch 'master' into master 2022-06-01 20:28:12 +02:00
Mark Trevor Birss
9512ea45de Update EInkDisplay2.cpp 2022-06-01 19:27:38 +02:00
Mark Trevor Birss
0d09767efd Update variant.h 2022-06-01 18:11:06 +02:00
Mark Trevor Birss
5828e6f423 Update variant.h 2022-06-01 18:08:40 +02:00
Mark Trevor Birss
c7a9ce7f49 Update variant.h 2022-06-01 18:08:13 +02:00
Mark Trevor Birss
95f091041b Update variant.h 2022-06-01 17:53:19 +02:00
Mark Trevor Birss
f33e6a0e66 Update platformio.ini 2022-06-01 17:49:10 +02:00
Mark Trevor Birss
fe8bfdb762 Update variant.h 2022-06-01 17:48:31 +02:00
Thomas Göttgens
e8afd4fb4b If we get an unreadable buffer, don't try to process it. 2022-06-01 17:09:57 +02:00
Mark Trevor Birss
b34b26518b Update EInkDisplay2.cpp 2022-06-01 11:28:18 +02:00
Mark Trevor Birss
b9f25eb85c Update EInkDisplay2.cpp 2022-06-01 11:21:09 +02:00
Mark Trevor Birss
a7fbe024e4 Create variant.h 2022-06-01 11:12:45 +02:00
Mark Trevor Birss
1f7fee8e2a Create platformio.ini 2022-06-01 11:10:49 +02:00
Mark Trevor Birss
b8e7c6ee7a Update platformio.ini 2022-06-01 11:09:21 +02:00
58 changed files with 708 additions and 404 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);

View File

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

View File

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

View File

@@ -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;
}
/**

View File

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

View File

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

View File

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

View File

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

View File

@@ -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()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);
}
/**

View File

@@ -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);

View File

@@ -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)
{

View File

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

View File

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

View File

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

View File

@@ -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" */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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;
}

View 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;
};

View 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;
}

View 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;
};

View File

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

View File

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

View File

@@ -0,0 +1,4 @@
#include "TelemetrySensor.h"
#include "../mesh/generated/telemetry.pb.h"
#include "NodeDB.h"
#include "main.h"

View File

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

View File

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

View File

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

View 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*

View 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

View File

@@ -1,4 +1,4 @@
[VERSION]
major = 1
minor = 3
build = 13
build = 19