Merge branch 'master' into raspi-portduino

This commit is contained in:
Thomas Göttgens 2023-04-21 16:50:48 +02:00 committed by GitHub
commit 85818b8dfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 541 additions and 139 deletions

View File

@ -42,6 +42,7 @@ jobs:
uses: ./.github/actions/setup-base uses: ./.github/actions/setup-base
- name: Trunk Check - name: Trunk Check
if: ${{ github.event_name != 'workflow_dispatch' }}
uses: trunk-io/trunk-action@v1 uses: trunk-io/trunk-action@v1
- name: Check ${{ matrix.board }} - name: Check ${{ matrix.board }}

View File

@ -35,7 +35,7 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0 h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1 https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
lib_ignore = lib_ignore =
segger_rtt segger_rtt

View File

@ -34,8 +34,7 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0 h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1 https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
lib_ignore = lib_ignore =
segger_rtt segger_rtt
ESP32 BLE Arduino ESP32 BLE Arduino

View File

@ -35,7 +35,7 @@ lib_deps =
${environmental_base.lib_deps} ${environmental_base.lib_deps}
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1 https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
lib_ignore = lib_ignore =
segger_rtt segger_rtt

View File

@ -35,7 +35,7 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2 https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
h2zero/NimBLE-Arduino@^1.4.0 h2zero/NimBLE-Arduino@^1.4.0
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6 https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
caveman99/ESP32 Codec2@^1.0.1 https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
lib_ignore = lib_ignore =
segger_rtt segger_rtt

38
bin/generate_ci_matrix.py Executable file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env python
"""Generate the CI matrix"""
import configparser
import json
import os
import sys
rootdir = "variants/"
options = sys.argv[1:]
outlist = []
if len(options) < 1:
print(json.dumps(outlist))
exit()
for subdir, dirs, files in os.walk(rootdir):
for file in files:
if file == "platformio.ini":
config = configparser.ConfigParser()
config.read(subdir + "/" + file)
for c in config.sections():
if c.startswith("env:"):
section = config[c].name[4:]
if "extends" in config[config[c].name]:
if config[config[c].name]["extends"] == options[0] + "_base":
if "board_level" in config[config[c].name]:
if (
config[config[c].name]["board_level"] == "extra"
) & ("extra" in options):
outlist.append(section)
else:
outlist.append(section)
print(json.dumps(outlist))

View File

@ -1,5 +1 @@
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto
@REM cd ../src/mesh/generated/meshtastic
@REM sed -i 's/#include "meshtastic/#include "./g' *
@REM sed -i 's/meshtastic_//g' *

View File

@ -85,7 +85,7 @@ lib_deps =
${env.lib_deps} ${env.lib_deps}
mprograms/QMC5883LCompass@^1.1.1 mprograms/QMC5883LCompass@^1.1.1
end2endzone/NonBlockingRTTTL@^1.3.0 end2endzone/NonBlockingRTTTL@^1.3.0
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76 https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0 build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
build_src_filter = ${env.build_src_filter} -<platform/portduino/> build_src_filter = ${env.build_src_filter} -<platform/portduino/>
@ -105,7 +105,7 @@ lib_deps =
adafruit/Adafruit Unified Sensor@^1.1.9 adafruit/Adafruit Unified Sensor@^1.1.9
adafruit/Adafruit BMP280 Library@^2.6.6 adafruit/Adafruit BMP280 Library@^2.6.6
adafruit/Adafruit BME280 Library@^2.2.2 adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit BME680 Library@^2.0.1 https://github.com/meshtastic/BSEC-Arduino-library.git#452f9a7ffa8b53e1debe2c454fe375dfad98b507
adafruit/Adafruit MCP9808 Library@^2.0.0 adafruit/Adafruit MCP9808 Library@^2.0.0
adafruit/Adafruit INA260 Library@^1.5.0 adafruit/Adafruit INA260 Library@^1.5.0
adafruit/Adafruit INA219@^1.2.0 adafruit/Adafruit INA219@^1.2.0

@ -1 +1 @@
Subproject commit 641d7c3a460de9cc580bc2b8a0812e8b9d417b05 Subproject commit ef2bc66bba41e8ef98ea893e46eb36a2da40cb5e

View File

@ -45,10 +45,10 @@ class ButtonThread : public concurrency::OSThread
ButtonThread() : OSThread("Button") ButtonThread() : OSThread("Button")
{ {
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
userButton = OneButton(BUTTON_PIN, true, true); userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
#ifdef INPUT_PULLUP_SENSE #ifdef INPUT_PULLUP_SENSE
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did // Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE); pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
#endif #endif
userButton.attachClick(userButtonPressed); userButton.attachClick(userButtonPressed);
userButton.setClickTicks(300); userButton.setClickTicks(300);
@ -57,7 +57,7 @@ class ButtonThread : public concurrency::OSThread
userButton.attachMultiClick(userButtonMultiPressed); userButton.attachMultiClick(userButtonMultiPressed);
userButton.attachLongPressStart(userButtonPressedLongStart); userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop); userButton.attachLongPressStop(userButtonPressedLongStop);
wakeOnIrq(BUTTON_PIN, FALLING); wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
#endif #endif
#ifdef BUTTON_PIN_ALT #ifdef BUTTON_PIN_ALT
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true); userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
@ -115,7 +115,9 @@ class ButtonThread : public concurrency::OSThread
{ {
// LOG_DEBUG("press!\n"); // LOG_DEBUG("press!\n");
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) || !moduleConfig.canned_message.enabled) { if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
#endif #endif
@ -124,13 +126,8 @@ class ButtonThread : public concurrency::OSThread
{ {
// LOG_DEBUG("Long press!\n"); // LOG_DEBUG("Long press!\n");
// If user button is held down for 5 seconds, shutdown the device. // If user button is held down for 5 seconds, shutdown the device.
if ((millis() - longPressTime > 5 * 1000) && (longPressTime > 0)) { if ((millis() - longPressTime > 5000) && (longPressTime > 0)) {
#ifdef HAS_PMU #if defined(ARCH_NRF52) || defined(ARCH_ESP32)
if (pmu_found == true) {
setLed(false);
power->shutdown();
}
#elif defined(ARCH_NRF52) || defined(ARCH_ESP32)
// Do actual shutdown when button released, otherwise the button release // Do actual shutdown when button released, otherwise the button release
// may wake the board immediatedly. // may wake the board immediatedly.
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) { if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {

View File

@ -34,6 +34,7 @@ bool copyFile(const char *from, const char *to)
f2.write(cbuffer, i); f2.write(cbuffer, i);
} }
f2.flush();
f2.close(); f2.close();
f1.close(); f1.close();
return true; return true;

View File

@ -212,7 +212,7 @@ Power::Power() : OSThread("Power")
statusHandler = {}; statusHandler = {};
low_voltage_counter = 0; low_voltage_counter = 0;
#ifdef DEBUG_HEAP #ifdef DEBUG_HEAP
lastheap = ESP.getFreeHeap(); lastheap = memGet.getFreeHeap();
#endif #endif
} }
@ -277,12 +277,11 @@ void Power::shutdown()
LOG_INFO("Shutting down\n"); LOG_INFO("Shutting down\n");
#ifdef HAS_PMU #ifdef HAS_PMU
if (PMU) { if (pmu_found == true) {
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF); PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
PMU->shutdown();
} }
#endif #elif defined(ARCH_NRF52) || defined(ARCH_ESP32)
#if defined(ARCH_NRF52) || defined(ARCH_ESP32)
#ifdef PIN_LED1 #ifdef PIN_LED1
ledOff(PIN_LED1); ledOff(PIN_LED1);
#endif #endif
@ -328,7 +327,7 @@ void Power::readPowerStatus()
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent()); powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
newStatus.notifyObservers(&powerStatus2); newStatus.notifyObservers(&powerStatus2);
#ifdef DEBUG_HEAP #ifdef DEBUG_HEAP
if (lastheap != ESP.getFreeHeap()) { if (lastheap != memGet.getFreeHeap()) {
LOG_DEBUG("Threads running:"); LOG_DEBUG("Threads running:");
int running = 0; int running = 0;
for (int i = 0; i < MAX_THREADS; i++) { for (int i = 0; i < MAX_THREADS; i++) {
@ -339,9 +338,9 @@ void Power::readPowerStatus()
} }
} }
LOG_DEBUG("\n"); LOG_DEBUG("\n");
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", ESP.getFreeHeap(), ESP.getHeapSize(), LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", memGet.getFreeHeap(), memGet.getHeapSize(),
ESP.getFreeHeap() - lastheap, running, concurrency::mainController.size(false)); memGet.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
lastheap = ESP.getFreeHeap(); lastheap = memGet.getFreeHeap();
} }
#ifdef DEBUG_HEAP_MQTT #ifdef DEBUG_HEAP_MQTT
if (mqtt) { if (mqtt) {
@ -350,15 +349,17 @@ void Power::readPowerStatus()
getMacAddr(dmac); // Get our hardware ID getMacAddr(dmac); // Get our hardware ID
char mac[18]; char mac[18];
sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]); sprintf(mac, "!%02x%02x%02x%02x", dmac[2], dmac[3], dmac[4], dmac[5]);
auto newHeap = ESP.getFreeHeap();
std::string heapTopic = "msh/2/heap/" + std::string(mac); auto newHeap = memGet.getFreeHeap();
std::string heapTopic =
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/heap/") + std::string(mac);
std::string heapString = std::to_string(newHeap); std::string heapString = std::to_string(newHeap);
mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false); mqtt->pubSub.publish(heapTopic.c_str(), heapString.c_str(), false);
// auto fragHeap = ESP.getHeapFragmentation();
auto wifiRSSI = WiFi.RSSI(); auto wifiRSSI = WiFi.RSSI();
heapTopic = "msh/2/wifi/" + std::string(mac); std::string wifiTopic =
(*moduleConfig.mqtt.root ? moduleConfig.mqtt.root : "msh") + std::string("/2/wifi/") + std::string(mac);
std::string wifiString = std::to_string(wifiRSSI); std::string wifiString = std::to_string(wifiRSSI);
mqtt->pubSub.publish(heapTopic.c_str(), wifiString.c_str(), false); mqtt->pubSub.publish(wifiTopic.c_str(), wifiString.c_str(), false);
} }
#endif #endif

View File

@ -93,18 +93,23 @@ static void lsIdle()
powerFSM.trigger(EVENT_SERIAL_CONNECTED); powerFSM.trigger(EVENT_SERIAL_CONNECTED);
break; break;
case ESP_SLEEP_WAKEUP_GPIO:
// GPIO of BUTTON_PIN (if available) triggered the wakeup
powerFSM.trigger(EVENT_PRESS);
break;
default: default:
// We woke for some other reason (device interrupt) // We woke for some other reason (button press, device interrupt)
// uint64_t status = esp_sleep_get_ext1_wakeup_status(); // uint64_t status = esp_sleep_get_ext1_wakeup_status();
LOG_INFO("wakeCause2 %d\n", wakeCause2); LOG_INFO("wakeCause2 %d\n", wakeCause2);
// Let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
#ifdef BUTTON_PIN
bool pressed = !digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#else
bool pressed = false;
#endif
if (pressed) { // If we woke because of press, instead generate a PRESS event.
powerFSM.trigger(EVENT_PRESS);
} else {
// Otherwise let the NB state handle the IRQ (and that state will handle stuff like IRQs etc)
// we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code // we lie and say "wake timer" because the interrupt will be handled by the regular IRQ code
powerFSM.trigger(EVENT_WAKE_TIMER); powerFSM.trigger(EVENT_WAKE_TIMER);
}
break; break;
} }
} else { } else {

View File

@ -1,5 +1,6 @@
#include "OSThread.h" #include "OSThread.h"
#include "configuration.h" #include "configuration.h"
#include "memGet.h"
#include <assert.h> #include <assert.h>
namespace concurrency namespace concurrency
@ -75,12 +76,12 @@ bool OSThread::shouldRun(unsigned long time)
void OSThread::run() void OSThread::run()
{ {
#ifdef DEBUG_HEAP #ifdef DEBUG_HEAP
auto heap = ESP.getFreeHeap(); auto heap = memGet.getFreeHeap();
#endif #endif
currentThread = this; currentThread = this;
auto newDelay = runOnce(); auto newDelay = runOnce();
#ifdef DEBUG_HEAP #ifdef DEBUG_HEAP
auto newHeap = ESP.getFreeHeap(); auto newHeap = memGet.getFreeHeap();
if (newHeap < heap) if (newHeap < heap)
LOG_DEBUG("------ Thread %s leaked heap %d -> %d (%d) ------\n", ThreadName.c_str(), heap, newHeap, newHeap - heap); LOG_DEBUG("------ Thread %s leaked heap %d -> %d (%d) ------\n", ThreadName.c_str(), heap, newHeap, newHeap - heap);
if (heap < newHeap) if (heap < newHeap)

View File

@ -142,17 +142,6 @@ static int32_t ledBlinker()
setLed(ledOn); setLed(ledOn);
#ifdef ARCH_ESP32
auto newHeap = ESP.getFreeHeap();
if (newHeap < 11000) {
LOG_DEBUG("\n\n====== heap too low [11000] -> reboot in 1s ======\n\n");
#ifdef HAS_SCREEN
screen->startRebootScreen();
#endif
rebootAtMsec = millis() + 900;
}
#endif
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that // have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000); return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000);
} }
@ -229,10 +218,10 @@ void setup()
// If the button is connected to GPIO 12, don't enable the ability to use // If the button is connected to GPIO 12, don't enable the ability to use
// meshtasticAdmin on the device. // meshtasticAdmin on the device.
pinMode(BUTTON_PIN, INPUT); pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT);
#ifdef BUTTON_NEED_PULLUP #ifdef BUTTON_NEED_PULLUP
gpio_pullup_en((gpio_num_t)BUTTON_PIN); gpio_pullup_en((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
delay(10); delay(10);
#endif #endif
@ -400,10 +389,7 @@ void setup()
// scanEInkDevice(); // scanEInkDevice();
#endif #endif
#if HAS_BUTTON // LED init
// Buttons & LED
buttonThread = new ButtonThread();
#endif
#ifdef LED_PIN #ifdef LED_PIN
pinMode(LED_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT);
@ -428,6 +414,11 @@ void setup()
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
router = new FloodingRouter(); router = new FloodingRouter();
#if HAS_BUTTON
// Buttons. Moved here cause we need NodeDB to be initialized
buttonThread = new ButtonThread();
#endif
playStartMelody(); playStartMelody();
// fixed screen override? // fixed screen override?

View File

@ -5,6 +5,7 @@
#include "PowerStatus.h" #include "PowerStatus.h"
#include "detect/ScanI2C.h" #include "detect/ScanI2C.h"
#include "graphics/Screen.h" #include "graphics/Screen.h"
#include "memGet.h"
#include "mesh/generated/meshtastic/config.pb.h" #include "mesh/generated/meshtastic/config.pb.h"
#include "mesh/generated/meshtastic/telemetry.pb.h" #include "mesh/generated/meshtastic/telemetry.pb.h"
#include <map> #include <map>

46
src/memGet.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "memGet.h"
#include "configuration.h"
MemGet memGet;
uint32_t MemGet::getFreeHeap()
{
#ifdef ARCH_ESP32
return ESP.getFreeHeap();
#elif defined(ARCH_NRF52)
return dbgHeapFree();
#else
// this platform does not have heap management function implemented
return UINT32_MAX;
#endif
}
uint32_t MemGet::getHeapSize()
{
#ifdef ARCH_ESP32
return ESP.getHeapSize();
#elif defined(ARCH_NRF52)
return dbgHeapTotal();
#else
// this platform does not have heap management function implemented
return UINT32_MAX;
#endif
}
uint32_t MemGet::getFreePsram()
{
#ifdef ARCH_ESP32
return ESP.getFreePsram();
#else
return 0;
#endif
}
uint32_t MemGet::getPsramSize()
{
#ifdef ARCH_ESP32
return ESP.getPsramSize();
#else
return 0;
#endif
}

18
src/memGet.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#ifndef _MT_MEMGET_H
#define _MT_MEMGET_H
#include <Arduino.h>
class MemGet
{
public:
uint32_t getFreeHeap();
uint32_t getHeapSize();
uint32_t getFreePsram();
uint32_t getPsramSize();
};
extern MemGet memGet;
#endif

View File

@ -1,6 +1,8 @@
#include "CryptoEngine.h" #include "CryptoEngine.h"
#include "configuration.h" #include "configuration.h"
concurrency::Lock *cryptLock;
void CryptoEngine::setKey(const CryptoKey &k) void CryptoEngine::setKey(const CryptoKey &k)
{ {
LOG_DEBUG("Using AES%d key!\n", k.length * 8); LOG_DEBUG("Using AES%d key!\n", k.length * 8);

View File

@ -1,7 +1,10 @@
#pragma once #pragma once
#include "concurrency/LockGuard.h"
#include <Arduino.h> #include <Arduino.h>
extern concurrency::Lock *cryptLock;
struct CryptoKey { struct CryptoKey {
uint8_t bytes[32]; uint8_t bytes[32];

View File

@ -490,6 +490,7 @@ bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_
} else { } else {
okay = true; okay = true;
} }
f.flush();
f.close(); f.close();
// brief window of risk here ;-) // brief window of risk here ;-)
@ -689,11 +690,11 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
/** Update user info for this node based on received user data /** Update user info for this node based on received user data
*/ */
void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p) bool NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
{ {
meshtastic_NodeInfo *info = getOrCreateNode(nodeId); meshtastic_NodeInfo *info = getOrCreateNode(nodeId);
if (!info) { if (!info) {
return; return false;
} }
LOG_DEBUG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name); LOG_DEBUG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name);
@ -713,6 +714,8 @@ void NodeDB::updateUser(uint32_t nodeId, const meshtastic_User &p)
// We just changed something important about the user, store our DB // We just changed something important about the user, store our DB
saveToDisk(SEGMENT_DEVICESTATE); saveToDisk(SEGMENT_DEVICESTATE);
} }
return changed;
} }
/// given a subpacket sniffed from the network, update our DB state /// given a subpacket sniffed from the network, update our DB state
@ -765,7 +768,7 @@ meshtastic_NodeInfo *NodeDB::getOrCreateNode(NodeNum n)
meshtastic_NodeInfo *info = getNode(n); meshtastic_NodeInfo *info = getNode(n);
if (!info) { if (!info) {
if (*numNodes >= MAX_NUM_NODES) { if ((*numNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfo_size * 3)) {
screen->print("warning: node_db full! erasing oldest entry\n"); screen->print("warning: node_db full! erasing oldest entry\n");
// look for oldest node and erase it // look for oldest node and erase it
uint32_t oldest = UINT32_MAX; uint32_t oldest = UINT32_MAX;

View File

@ -86,7 +86,7 @@ class NodeDB
/** Update user info for this node based on received user data /** Update user info for this node based on received user data
*/ */
void updateUser(uint32_t nodeId, const meshtastic_User &p); bool updateUser(uint32_t nodeId, const meshtastic_User &p);
/// @return our node number /// @return our node number
NodeNum getNodeNum() { return myNodeInfo.my_node_num; } NodeNum getNodeNum() { return myNodeInfo.my_node_num; }

View File

@ -55,6 +55,10 @@ Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRA
LOG_DEBUG("Size of MeshPacket %d\n", sizeof(MeshPacket)); */ LOG_DEBUG("Size of MeshPacket %d\n", sizeof(MeshPacket)); */
fromRadioQueue.setReader(this); fromRadioQueue.setReader(this);
// init Lockguard for crypt operations
assert(!cryptLock);
cryptLock = new concurrency::Lock();
} }
/** /**
@ -305,6 +309,8 @@ void Router::sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Rout
bool perhapsDecode(meshtastic_MeshPacket *p) bool perhapsDecode(meshtastic_MeshPacket *p)
{ {
concurrency::LockGuard g(cryptLock);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER && if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER &&
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING) config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING)
return false; return false;
@ -371,6 +377,8 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
*/ */
meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p) meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
{ {
concurrency::LockGuard g(cryptLock);
// If the packet is not yet encrypted, do so now // If the packet is not yet encrypted, do so now
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded); size_t numbytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_Data_msg, &p->decoded);

View File

@ -31,11 +31,9 @@ typedef enum _meshtastic_Channel_Role {
/* Struct definitions */ /* Struct definitions */
typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t; typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t;
/* Full settings (center freq, spread factor, pre-shared secret key etc...) /* This information can be encoded as a QRcode/url so that other users can configure
needed to configure a radio for speaking on a particular channel This
information can be encoded as a QRcode/url so that other users can configure
their radio to join the same channel. their radio to join the same channel.
A note about how channel names are shown to users: channelname-Xy A note about how channel names are shown to users: channelname-X
poundsymbol is a prefix used to indicate this is a channel name (idea from @professr). poundsymbol is a prefix used to indicate this is a channel name (idea from @professr).
Where X is a letter from A-Z (base 26) representing a hash of the PSK for this Where X is a letter from A-Z (base 26) representing a hash of the PSK for this
channel - so that if the user changes anything about the channel (which does channel - so that if the user changes anything about the channel (which does
@ -45,8 +43,6 @@ typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t;
The PSK is hashed into this letter by "0x41 + [xor all bytes of the psk ] modulo 26" The PSK is hashed into this letter by "0x41 + [xor all bytes of the psk ] modulo 26"
This also allows the option of someday if people have the PSK off (zero), the This also allows the option of someday if people have the PSK off (zero), the
users COULD type in a channel name and be able to talk. users COULD type in a channel name and be able to talk.
Y is a lower case letter from a-z that represents the channel 'speed' settings
(for some future definition of speed)
FIXME: Add description of multi-channel support and how primary vs secondary channels are used. FIXME: Add description of multi-channel support and how primary vs secondary channels are used.
FIXME: explain how apps use channels for security. FIXME: explain how apps use channels for security.
explain how remote settings and remote gpio are managed as an example */ explain how remote settings and remote gpio are managed as an example */
@ -60,7 +56,7 @@ typedef struct _meshtastic_ChannelSettings {
because they are listed in this source code. because they are listed in this source code.
Those bytes are mapped using the following scheme: Those bytes are mapped using the following scheme:
`0` = No crypto `0` = No crypto
`1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf} `1` = The special "default" channel key: {0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59, 0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0x01}
`2` through 10 = The default channel key, except with 1 through 9 added to the last byte. `2` through 10 = The default channel key, except with 1 through 9 added to the last byte.
Shown to user as simple1 through 10 */ Shown to user as simple1 through 10 */
meshtastic_ChannelSettings_psk_t psk; meshtastic_ChannelSettings_psk_t psk;

View File

@ -0,0 +1,12 @@
/* Automatically generated nanopb constant definitions */
/* Generated by nanopb-0.4.7 */
#include "meshtastic/clientonly.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
PB_BIND(meshtastic_DeviceProfile, meshtastic_DeviceProfile, 2)

View File

@ -0,0 +1,73 @@
/* Automatically generated nanopb header */
/* Generated by nanopb-0.4.7 */
#ifndef PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED
#define PB_MESHTASTIC_MESHTASTIC_CLIENTONLY_PB_H_INCLUDED
#include <pb.h>
#include "meshtastic/localonly.pb.h"
#if PB_PROTO_HEADER_VERSION != 40
#error Regenerate this file with the current version of nanopb generator.
#endif
/* Struct definitions */
/* This abstraction is used to contain any configuration for provisioning a node on any client.
It is useful for importing and exporting configurations. */
typedef struct _meshtastic_DeviceProfile {
/* Long name for the node */
bool has_long_name;
char long_name[40];
/* Short name of the node */
bool has_short_name;
char short_name[5];
/* The url of the channels from our node */
pb_callback_t channel_url;
/* The Config of the node */
bool has_config;
meshtastic_LocalConfig config;
/* The ModuleConfig of the node */
bool has_module_config;
meshtastic_LocalModuleConfig module_config;
} meshtastic_DeviceProfile;
#ifdef __cplusplus
extern "C" {
#endif
/* Initializer values for message structs */
#define meshtastic_DeviceProfile_init_default {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_default, false, meshtastic_LocalModuleConfig_init_default}
#define meshtastic_DeviceProfile_init_zero {false, "", false, "", {{NULL}, NULL}, false, meshtastic_LocalConfig_init_zero, false, meshtastic_LocalModuleConfig_init_zero}
/* Field tags (for use in manual encoding/decoding) */
#define meshtastic_DeviceProfile_long_name_tag 1
#define meshtastic_DeviceProfile_short_name_tag 2
#define meshtastic_DeviceProfile_channel_url_tag 3
#define meshtastic_DeviceProfile_config_tag 4
#define meshtastic_DeviceProfile_module_config_tag 5
/* Struct field encoding specification for nanopb */
#define meshtastic_DeviceProfile_FIELDLIST(X, a) \
X(a, STATIC, OPTIONAL, STRING, long_name, 1) \
X(a, STATIC, OPTIONAL, STRING, short_name, 2) \
X(a, CALLBACK, OPTIONAL, STRING, channel_url, 3) \
X(a, STATIC, OPTIONAL, MESSAGE, config, 4) \
X(a, STATIC, OPTIONAL, MESSAGE, module_config, 5)
#define meshtastic_DeviceProfile_CALLBACK pb_default_field_callback
#define meshtastic_DeviceProfile_DEFAULT NULL
#define meshtastic_DeviceProfile_config_MSGTYPE meshtastic_LocalConfig
#define meshtastic_DeviceProfile_module_config_MSGTYPE meshtastic_LocalModuleConfig
extern const pb_msgdesc_t meshtastic_DeviceProfile_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define meshtastic_DeviceProfile_fields &meshtastic_DeviceProfile_msg
/* Maximum encoded size of messages (where known) */
/* meshtastic_DeviceProfile_size depends on runtime parameters */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@ -188,7 +188,7 @@ extern const pb_msgdesc_t meshtastic_OEMStore_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define meshtastic_ChannelFile_size 638 #define meshtastic_ChannelFile_size 638
#define meshtastic_DeviceState_size 22040 #define meshtastic_DeviceState_size 22040
#define meshtastic_OEMStore_size 3024 #define meshtastic_OEMStore_size 3041
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -157,7 +157,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define meshtastic_LocalConfig_size 456 #define meshtastic_LocalConfig_size 456
#define meshtastic_LocalModuleConfig_size 422 #define meshtastic_LocalModuleConfig_size 439
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -48,6 +48,12 @@ PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2)
PB_BIND(meshtastic_Compressed, meshtastic_Compressed, AUTO) PB_BIND(meshtastic_Compressed, meshtastic_Compressed, AUTO)
PB_BIND(meshtastic_NeighborInfo, meshtastic_NeighborInfo, AUTO)
PB_BIND(meshtastic_Neighbor, meshtastic_Neighbor, AUTO)
PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO) PB_BIND(meshtastic_DeviceMetadata, meshtastic_DeviceMetadata, AUTO)

View File

@ -680,6 +680,25 @@ typedef struct _meshtastic_Compressed {
meshtastic_Compressed_data_t data; meshtastic_Compressed_data_t data;
} meshtastic_Compressed; } meshtastic_Compressed;
/* A single edge in the mesh */
typedef struct _meshtastic_Neighbor {
/* Node ID of neighbor */
uint32_t node_id;
/* SNR of last heard message */
float snr;
} meshtastic_Neighbor;
/* Full info on edges for a single node */
typedef struct _meshtastic_NeighborInfo {
/* The node ID of the node sending info on its neighbors */
uint32_t node_id;
/* Field to pass neighbor info for the next sending cycle */
uint32_t last_sent_by_id;
/* The list of out edges from this node */
pb_size_t neighbors_count;
meshtastic_Neighbor neighbors[10];
} meshtastic_NeighborInfo;
/* Device metadata response */ /* Device metadata response */
typedef struct _meshtastic_DeviceMetadata { typedef struct _meshtastic_DeviceMetadata {
/* Device firmware version string */ /* Device firmware version string */
@ -813,6 +832,8 @@ extern "C" {
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum #define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
#define meshtastic_DeviceMetadata_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role #define meshtastic_DeviceMetadata_role_ENUMTYPE meshtastic_Config_DeviceConfig_Role
#define meshtastic_DeviceMetadata_hw_model_ENUMTYPE meshtastic_HardwareModel #define meshtastic_DeviceMetadata_hw_model_ENUMTYPE meshtastic_HardwareModel
@ -832,6 +853,8 @@ extern "C" {
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}} #define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}} #define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}} #define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_default {0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
#define meshtastic_Neighbor_init_default {0, 0}
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} #define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0} #define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
@ -847,6 +870,8 @@ extern "C" {
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}} #define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}} #define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
#define meshtastic_Neighbor_init_zero {0, 0}
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN} #define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
@ -948,6 +973,11 @@ extern "C" {
#define meshtastic_ToRadio_xmodemPacket_tag 5 #define meshtastic_ToRadio_xmodemPacket_tag 5
#define meshtastic_Compressed_portnum_tag 1 #define meshtastic_Compressed_portnum_tag 1
#define meshtastic_Compressed_data_tag 2 #define meshtastic_Compressed_data_tag 2
#define meshtastic_Neighbor_node_id_tag 1
#define meshtastic_Neighbor_snr_tag 2
#define meshtastic_NeighborInfo_node_id_tag 1
#define meshtastic_NeighborInfo_last_sent_by_id_tag 2
#define meshtastic_NeighborInfo_neighbors_tag 3
#define meshtastic_DeviceMetadata_firmware_version_tag 1 #define meshtastic_DeviceMetadata_firmware_version_tag 1
#define meshtastic_DeviceMetadata_device_state_version_tag 2 #define meshtastic_DeviceMetadata_device_state_version_tag 2
#define meshtastic_DeviceMetadata_canShutdown_tag 3 #define meshtastic_DeviceMetadata_canShutdown_tag 3
@ -1157,6 +1187,20 @@ X(a, STATIC, SINGULAR, BYTES, data, 2)
#define meshtastic_Compressed_CALLBACK NULL #define meshtastic_Compressed_CALLBACK NULL
#define meshtastic_Compressed_DEFAULT NULL #define meshtastic_Compressed_DEFAULT NULL
#define meshtastic_NeighborInfo_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \
X(a, STATIC, REPEATED, MESSAGE, neighbors, 3)
#define meshtastic_NeighborInfo_CALLBACK NULL
#define meshtastic_NeighborInfo_DEFAULT NULL
#define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor
#define meshtastic_Neighbor_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
X(a, STATIC, SINGULAR, FLOAT, snr, 2)
#define meshtastic_Neighbor_CALLBACK NULL
#define meshtastic_Neighbor_DEFAULT NULL
#define meshtastic_DeviceMetadata_FIELDLIST(X, a) \ #define meshtastic_DeviceMetadata_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \ X(a, STATIC, SINGULAR, STRING, firmware_version, 1) \
X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \ X(a, STATIC, SINGULAR, UINT32, device_state_version, 2) \
@ -1184,6 +1228,8 @@ extern const pb_msgdesc_t meshtastic_QueueStatus_msg;
extern const pb_msgdesc_t meshtastic_FromRadio_msg; extern const pb_msgdesc_t meshtastic_FromRadio_msg;
extern const pb_msgdesc_t meshtastic_ToRadio_msg; extern const pb_msgdesc_t meshtastic_ToRadio_msg;
extern const pb_msgdesc_t meshtastic_Compressed_msg; extern const pb_msgdesc_t meshtastic_Compressed_msg;
extern const pb_msgdesc_t meshtastic_NeighborInfo_msg;
extern const pb_msgdesc_t meshtastic_Neighbor_msg;
extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg; extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ /* Defines for backwards compatibility with code written before nanopb-0.4.0 */
@ -1201,6 +1247,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg #define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg #define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg #define meshtastic_Compressed_fields &meshtastic_Compressed_msg
#define meshtastic_NeighborInfo_fields &meshtastic_NeighborInfo_msg
#define meshtastic_Neighbor_fields &meshtastic_Neighbor_msg
#define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg #define meshtastic_DeviceMetadata_fields &meshtastic_DeviceMetadata_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
@ -1211,6 +1259,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_LogRecord_size 81 #define meshtastic_LogRecord_size 81
#define meshtastic_MeshPacket_size 321 #define meshtastic_MeshPacket_size 321
#define meshtastic_MyNodeInfo_size 179 #define meshtastic_MyNodeInfo_size 179
#define meshtastic_NeighborInfo_size 142
#define meshtastic_Neighbor_size 11
#define meshtastic_NodeInfo_size 261 #define meshtastic_NodeInfo_size 261
#define meshtastic_Position_size 137 #define meshtastic_Position_size 137
#define meshtastic_QueueStatus_size 23 #define meshtastic_QueueStatus_size 23

View File

@ -98,6 +98,9 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig {
bool json_enabled; bool json_enabled;
/* If true, we attempt to establish a secure connection using TLS */ /* If true, we attempt to establish a secure connection using TLS */
bool tls_enabled; bool tls_enabled;
/* The root topic to use for MQTT messages. Default is "msh".
This is useful if you want to use a single MQTT server for multiple meshtastic networks and separate them via ACLs */
char root[16];
} meshtastic_ModuleConfig_MQTTConfig; } meshtastic_ModuleConfig_MQTTConfig;
/* RemoteHardwareModule Config */ /* RemoteHardwareModule Config */
@ -325,7 +328,7 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}} #define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}}
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0} #define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, ""}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0}
#define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0} #define meshtastic_ModuleConfig_AudioConfig_init_default {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN} #define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN}
@ -335,7 +338,7 @@ extern "C" {
#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0}
#define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}} #define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}}
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0} #define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, ""}
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0} #define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0}
#define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0} #define meshtastic_ModuleConfig_AudioConfig_init_zero {0, 0, _meshtastic_ModuleConfig_AudioConfig_Audio_Baud_MIN, 0, 0, 0, 0}
#define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN} #define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN}
@ -353,6 +356,7 @@ extern "C" {
#define meshtastic_ModuleConfig_MQTTConfig_encryption_enabled_tag 5 #define meshtastic_ModuleConfig_MQTTConfig_encryption_enabled_tag 5
#define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6 #define meshtastic_ModuleConfig_MQTTConfig_json_enabled_tag 6
#define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7 #define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7
#define meshtastic_ModuleConfig_MQTTConfig_root_tag 8
#define meshtastic_ModuleConfig_RemoteHardwareConfig_enabled_tag 1 #define meshtastic_ModuleConfig_RemoteHardwareConfig_enabled_tag 1
#define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1 #define meshtastic_ModuleConfig_AudioConfig_codec2_enabled_tag 1
#define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2 #define meshtastic_ModuleConfig_AudioConfig_ptt_pin_tag 2
@ -448,7 +452,8 @@ X(a, STATIC, SINGULAR, STRING, username, 3) \
X(a, STATIC, SINGULAR, STRING, password, 4) \ X(a, STATIC, SINGULAR, STRING, password, 4) \
X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5) \ X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5) \
X(a, STATIC, SINGULAR, BOOL, json_enabled, 6) \ X(a, STATIC, SINGULAR, BOOL, json_enabled, 6) \
X(a, STATIC, SINGULAR, BOOL, tls_enabled, 7) X(a, STATIC, SINGULAR, BOOL, tls_enabled, 7) \
X(a, STATIC, SINGULAR, STRING, root, 8)
#define meshtastic_ModuleConfig_MQTTConfig_CALLBACK NULL #define meshtastic_ModuleConfig_MQTTConfig_CALLBACK NULL
#define meshtastic_ModuleConfig_MQTTConfig_DEFAULT NULL #define meshtastic_ModuleConfig_MQTTConfig_DEFAULT NULL
@ -566,13 +571,13 @@ extern const pb_msgdesc_t meshtastic_ModuleConfig_CannedMessageConfig_msg;
#define meshtastic_ModuleConfig_AudioConfig_size 19 #define meshtastic_ModuleConfig_AudioConfig_size 19
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49 #define meshtastic_ModuleConfig_CannedMessageConfig_size 49
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40 #define meshtastic_ModuleConfig_ExternalNotificationConfig_size 40
#define meshtastic_ModuleConfig_MQTTConfig_size 203 #define meshtastic_ModuleConfig_MQTTConfig_size 220
#define meshtastic_ModuleConfig_RangeTestConfig_size 10 #define meshtastic_ModuleConfig_RangeTestConfig_size 10
#define meshtastic_ModuleConfig_RemoteHardwareConfig_size 2 #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 2
#define meshtastic_ModuleConfig_SerialConfig_size 26 #define meshtastic_ModuleConfig_SerialConfig_size 26
#define meshtastic_ModuleConfig_StoreForwardConfig_size 22 #define meshtastic_ModuleConfig_StoreForwardConfig_size 22
#define meshtastic_ModuleConfig_TelemetryConfig_size 26 #define meshtastic_ModuleConfig_TelemetryConfig_size 26
#define meshtastic_ModuleConfig_size 206 #define meshtastic_ModuleConfig_size 223
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -85,6 +85,8 @@ typedef enum _meshtastic_PortNum {
/* Provides a traceroute functionality to show the route a packet towards /* Provides a traceroute functionality to show the route a packet towards
a certain destination would take on the mesh. */ a certain destination would take on the mesh. */
meshtastic_PortNum_TRACEROUTE_APP = 70, meshtastic_PortNum_TRACEROUTE_APP = 70,
/* Aggregates edge info for the network by sending out a list of each node's neighbors */
meshtastic_PortNum_NEIGHBORINFO_APP = 71,
/* Private applications should use portnums >= 256. /* Private applications should use portnums >= 256.
To simplify initial development and testing you can use "PRIVATE_APP" To simplify initial development and testing you can use "PRIVATE_APP"
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */ in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */

View File

@ -234,15 +234,18 @@ void htmlDeleteDir(const char *dirname)
while (file) { while (file) {
if (file.isDirectory() && !String(file.name()).endsWith(".")) { if (file.isDirectory() && !String(file.name()).endsWith(".")) {
htmlDeleteDir(file.name()); htmlDeleteDir(file.name());
file.flush();
file.close(); file.close();
} else { } else {
String fileName = String(file.name()); String fileName = String(file.name());
file.flush();
file.close(); file.close();
LOG_DEBUG(" %s\n", fileName.c_str()); LOG_DEBUG(" %s\n", fileName.c_str());
FSCom.remove(fileName); FSCom.remove(fileName);
} }
file = root.openNextFile(); file = root.openNextFile();
} }
root.flush();
root.close(); root.close();
} }
@ -521,7 +524,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
std::string pathname = "/static/" + filename; std::string pathname = "/static/" + filename;
// Create a new file to stream the data into // Create a new file to stream the data into
File file = FSCom.open(pathname.c_str(), "w"); File file = FSCom.open(pathname.c_str(), FILE_O_WRITE);
size_t fileLength = 0; size_t fileLength = 0;
didwrite = true; didwrite = true;
@ -536,6 +539,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
// Abort the transfer if there is less than 50k space left on the filesystem. // Abort the transfer if there is less than 50k space left on the filesystem.
if (FSCom.totalBytes() - FSCom.usedBytes() < 51200) { if (FSCom.totalBytes() - FSCom.usedBytes() < 51200) {
file.flush();
file.close(); file.close();
res->println("<p>Write aborted! Reserving 50k on filesystem.</p>"); res->println("<p>Write aborted! Reserving 50k on filesystem.</p>");
@ -553,6 +557,7 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res)
} }
// enableLoopWDT(); // enableLoopWDT();
file.flush();
file.close(); file.close();
res->printf("<p>Saved %d bytes to %s</p>", (int)fileLength, pathname.c_str()); res->printf("<p>Saved %d bytes to %s</p>", (int)fileLength, pathname.c_str());
} }
@ -622,10 +627,10 @@ void handleReport(HTTPRequest *req, HTTPResponse *res)
// data->memory // data->memory
JSONObject jsonObjMemory; JSONObject jsonObjMemory;
jsonObjMemory["heap_total"] = new JSONValue((int)ESP.getHeapSize()); jsonObjMemory["heap_total"] = new JSONValue((int)memGet.getHeapSize());
jsonObjMemory["heap_free"] = new JSONValue((int)ESP.getFreeHeap()); jsonObjMemory["heap_free"] = new JSONValue((int)memGet.getFreeHeap());
jsonObjMemory["psram_total"] = new JSONValue((int)ESP.getPsramSize()); jsonObjMemory["psram_total"] = new JSONValue((int)memGet.getPsramSize());
jsonObjMemory["psram_free"] = new JSONValue((int)ESP.getFreePsram()); jsonObjMemory["psram_free"] = new JSONValue((int)memGet.getFreePsram());
jsonObjMemory["fs_total"] = new JSONValue((int)FSCom.totalBytes()); jsonObjMemory["fs_total"] = new JSONValue((int)FSCom.totalBytes());
jsonObjMemory["fs_used"] = new JSONValue((int)FSCom.usedBytes()); jsonObjMemory["fs_used"] = new JSONValue((int)FSCom.usedBytes());
jsonObjMemory["fs_free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes())); jsonObjMemory["fs_free"] = new JSONValue(int(FSCom.totalBytes() - FSCom.usedBytes()));

View File

@ -12,7 +12,7 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
{ {
auto p = *pptr; auto p = *pptr;
nodeDB.updateUser(getFrom(&mp), p); bool hasChanged = nodeDB.updateUser(getFrom(&mp), p);
bool wasBroadcast = mp.to == NODENUM_BROADCAST; bool wasBroadcast = mp.to == NODENUM_BROADCAST;
@ -23,6 +23,10 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
screen->print(lcd.c_str()); screen->print(lcd.c_str());
} }
// if user has changed while packet was not for us, inform phone
if (hasChanged && !wasBroadcast && mp.to != nodeDB.getNodeNum())
service.sendToPhone(packetPool.allocCopy(mp));
// LOG_DEBUG("did handleReceived\n"); // LOG_DEBUG("did handleReceived\n");
return false; // Let others look at this message also if they want return false; // Let others look at this message also if they want
} }

View File

@ -1,18 +1,26 @@
#include "BME680Sensor.h" #include "BME680Sensor.h"
#include "../mesh/generated/meshtastic/telemetry.pb.h" #include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "FSCommon.h"
#include "TelemetrySensor.h" #include "TelemetrySensor.h"
#include "configuration.h" #include "configuration.h"
#include <Adafruit_BME680.h>
BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {} BME680Sensor::BME680Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_BME680, "BME680") {}
int32_t BME680Sensor::runOnce() int32_t BME680Sensor::runOnce()
{ {
LOG_INFO("Init sensor: %s\n", sensorName); LOG_INFO("Init sensor: %s with the BSEC Library\n", sensorName);
if (!hasSensor()) { if (!hasSensor()) {
return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS; return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
} }
status = bme680.begin(nodeTelemetrySensorsMap[sensorType]); bme680.begin(nodeTelemetrySensorsMap[sensorType], Wire);
if (bme680.bsecStatus == BSEC_OK) {
bme680.setConfig(bsec_config_iaq);
loadState();
bme680.updateSubscription(sensorList, 13, BSEC_SAMPLE_RATE_LP);
status = 1;
} else {
status = 0;
}
return initI2CSensor(); return initI2CSensor();
} }
@ -21,11 +29,76 @@ void BME680Sensor::setup() {}
bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement) bool BME680Sensor::getMetrics(meshtastic_Telemetry *measurement)
{ {
bme680.performReading(); bme680.run();
measurement->variant.environment_metrics.temperature = bme680.temperature; measurement->variant.environment_metrics.temperature = bme680.temperature;
measurement->variant.environment_metrics.relative_humidity = bme680.humidity; measurement->variant.environment_metrics.relative_humidity = bme680.humidity;
measurement->variant.environment_metrics.barometric_pressure = bme680.pressure / 100.0F; measurement->variant.environment_metrics.barometric_pressure = bme680.pressure / 100.0F;
measurement->variant.environment_metrics.gas_resistance = bme680.gas_resistance / 1000.0; measurement->variant.environment_metrics.gas_resistance = bme680.gasResistance / 1000.0;
// Check if we need to save state to filesystem (every STATE_SAVE_PERIOD ms)
updateState();
return true; return true;
} }
void BME680Sensor::loadState()
{
#ifdef FSCom
auto file = FSCom.open(bsecConfigFileName, FILE_O_READ);
if (file) {
file.read((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE);
file.close();
bme680.setState(bsecState);
LOG_INFO("%s state read from %s.\n", sensorName, bsecConfigFileName);
} else {
LOG_INFO("No %s state found (File: %s).\n", sensorName, bsecConfigFileName);
}
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}
void BME680Sensor::updateState()
{
#ifdef FSCom
bool update = false;
if (stateUpdateCounter == 0) {
/* First state update when IAQ accuracy is >= 3 */
if (bme680.iaqAccuracy >= 3) {
LOG_DEBUG("%s state update IAQ accuracy %u >= 3\n", sensorName, bme680.iaqAccuracy);
update = true;
stateUpdateCounter++;
} else {
LOG_DEBUG("%s not updated, IAQ accuracy is %u >= 3\n", sensorName, bme680.iaqAccuracy);
}
} else {
/* Update every STATE_SAVE_PERIOD minutes */
if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) {
LOG_DEBUG("%s state update every %d minutes\n", sensorName, STATE_SAVE_PERIOD);
update = true;
stateUpdateCounter++;
}
}
if (update) {
bme680.getState(bsecState);
std::string filenameTmp = bsecConfigFileName;
filenameTmp += ".tmp";
auto file = FSCom.open(bsecConfigFileName, FILE_O_WRITE);
if (file) {
LOG_INFO("%s state write to %s.\n", sensorName, bsecConfigFileName);
file.write((uint8_t *)&bsecState, BSEC_MAX_STATE_BLOB_SIZE);
file.flush();
file.close();
// brief window of risk here ;-)
if (FSCom.exists(bsecConfigFileName) && !FSCom.remove(bsecConfigFileName))
LOG_WARN("Can't remove old state file\n");
if (!renameFile(filenameTmp.c_str(), bsecConfigFileName))
LOG_ERROR("Error: can't rename new state file\n");
} else {
LOG_INFO("Can't write %s state (File: %s).\n", sensorName, bsecConfigFileName);
}
}
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}

View File

@ -1,14 +1,38 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h" #include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "TelemetrySensor.h" #include "TelemetrySensor.h"
#include <Adafruit_BME680.h> #include <bsec.h>
#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // That's 6 hours worth of millis()
const uint8_t bsec_config_iaq[] = {
#include <config/generic_33v_3s_4d/bsec_iaq.txt>
};
class BME680Sensor : virtual public TelemetrySensor class BME680Sensor : virtual public TelemetrySensor
{ {
private: private:
Adafruit_BME680 bme680; Bsec bme680;
protected: protected:
virtual void setup() override; virtual void setup() override;
const char *bsecConfigFileName = "/prefs/bsec.dat";
uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0};
uint16_t stateUpdateCounter = 0;
bsec_virtual_sensor_t sensorList[13] = {BSEC_OUTPUT_IAQ,
BSEC_OUTPUT_STATIC_IAQ,
BSEC_OUTPUT_CO2_EQUIVALENT,
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
BSEC_OUTPUT_RAW_TEMPERATURE,
BSEC_OUTPUT_RAW_PRESSURE,
BSEC_OUTPUT_RAW_HUMIDITY,
BSEC_OUTPUT_RAW_GAS,
BSEC_OUTPUT_STABILIZATION_STATUS,
BSEC_OUTPUT_RUN_IN_STATUS,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
BSEC_OUTPUT_GAS_PERCENTAGE};
void loadState();
void updateState();
public: public:
BME680Sensor(); BME680Sensor();

View File

@ -226,7 +226,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
} else { } else {
LOG_ERROR("File write failed\n"); LOG_ERROR("File write failed\n");
} }
fileToWrite.flush();
fileToWrite.close(); fileToWrite.close();
} }
@ -275,6 +275,7 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp)
// TODO: If quotes are found in the payload, it has to be escaped. // TODO: If quotes are found in the payload, it has to be escaped.
fileToAppend.printf("\"%s\"\n", p.payload.bytes); fileToAppend.printf("\"%s\"\n", p.payload.bytes);
fileToAppend.flush();
fileToAppend.close(); fileToAppend.close();
return 1; return 1;

View File

@ -5,6 +5,7 @@
#include "Router.h" #include "Router.h"
#include "airtime.h" #include "airtime.h"
#include "configuration.h" #include "configuration.h"
#include "memGet.h"
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
#include "mesh/generated/meshtastic/storeforward.pb.h" #include "mesh/generated/meshtastic/storeforward.pb.h"
#include "modules/ModuleDev.h" #include "modules/ModuleDev.h"
@ -63,8 +64,8 @@ void StoreForwardModule::populatePSRAM()
https://learn.upesy.com/en/programmation/psram.html#psram-tab https://learn.upesy.com/en/programmation/psram.html#psram-tab
*/ */
LOG_DEBUG("*** Before PSRAM initilization: heap %d/%d PSRAM %d/%d\n", ESP.getFreeHeap(), ESP.getHeapSize(), LOG_DEBUG("*** Before PSRAM initilization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(),
ESP.getFreePsram(), ESP.getPsramSize()); memGet.getFreePsram(), memGet.getPsramSize());
this->packetHistoryTXQueue = this->packetHistoryTXQueue =
static_cast<PacketHistoryStruct *>(ps_calloc(this->historyReturnMax, sizeof(PacketHistoryStruct))); static_cast<PacketHistoryStruct *>(ps_calloc(this->historyReturnMax, sizeof(PacketHistoryStruct)));
@ -72,13 +73,14 @@ void StoreForwardModule::populatePSRAM()
/* Use a maximum of 2/3 the available PSRAM unless otherwise specified. /* Use a maximum of 2/3 the available PSRAM unless otherwise specified.
Note: This needs to be done after every thing that would use PSRAM Note: This needs to be done after every thing that would use PSRAM
*/ */
uint32_t numberOfPackets = (this->records ? this->records : (((ESP.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct))); uint32_t numberOfPackets =
(this->records ? this->records : (((memGet.getFreePsram() / 3) * 2) / sizeof(PacketHistoryStruct)));
this->records = numberOfPackets; this->records = numberOfPackets;
this->packetHistory = static_cast<PacketHistoryStruct *>(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct))); this->packetHistory = static_cast<PacketHistoryStruct *>(ps_calloc(numberOfPackets, sizeof(PacketHistoryStruct)));
LOG_DEBUG("*** After PSRAM initilization: heap %d/%d PSRAM %d/%d\n", ESP.getFreeHeap(), ESP.getHeapSize(), ESP.getFreePsram(), LOG_DEBUG("*** After PSRAM initilization: heap %d/%d PSRAM %d/%d\n", memGet.getFreeHeap(), memGet.getHeapSize(),
ESP.getPsramSize()); memGet.getFreePsram(), memGet.getPsramSize());
LOG_DEBUG("*** numberOfPackets for packetHistory - %u\n", numberOfPackets); LOG_DEBUG("*** numberOfPackets for packetHistory - %u\n", numberOfPackets);
} }
@ -445,8 +447,8 @@ StoreForwardModule::StoreForwardModule()
if ((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) || if ((config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) ||
(config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT)) { (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT)) {
LOG_INFO("*** Initializing Store & Forward Module in Router mode\n"); LOG_INFO("*** Initializing Store & Forward Module in Router mode\n");
if (ESP.getPsramSize() > 0) { if (memGet.getPsramSize() > 0) {
if (ESP.getFreePsram() >= 1024 * 1024) { if (memGet.getFreePsram() >= 1024 * 1024) {
// Do the startup here // Do the startup here

View File

@ -19,10 +19,6 @@ const int reconnectMax = 5;
MQTT *mqtt; MQTT *mqtt;
std::string statusTopic = "msh/2/stat/";
std::string cryptTopic = "msh/2/c/"; // msh/2/c/CHANNELID/NODEID
std::string jsonTopic = "msh/2/json/"; // msh/2/json/CHANNELID/NODEID
static MemoryDynamic<meshtastic_ServiceEnvelope> staticMqttPool; static MemoryDynamic<meshtastic_ServiceEnvelope> staticMqttPool;
Allocator<meshtastic_ServiceEnvelope> &mqttPool = staticMqttPool; Allocator<meshtastic_ServiceEnvelope> &mqttPool = staticMqttPool;
@ -164,6 +160,16 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient), mqttQueue(MAX_
assert(!mqtt); assert(!mqtt);
mqtt = this; mqtt = this;
if (*moduleConfig.mqtt.root) {
statusTopic = moduleConfig.mqtt.root + statusTopic;
cryptTopic = moduleConfig.mqtt.root + cryptTopic;
jsonTopic = moduleConfig.mqtt.root + jsonTopic;
} else {
statusTopic = "msh" + statusTopic;
cryptTopic = "msh" + cryptTopic;
jsonTopic = "msh" + jsonTopic;
}
pubSub.setCallback(mqttCallback); pubSub.setCallback(mqttCallback);
// preflightSleepObserver.observe(&preflightSleep); // preflightSleepObserver.observe(&preflightSleep);
@ -192,6 +198,26 @@ void MQTT::reconnect()
mqttPassword = moduleConfig.mqtt.password; mqttPassword = moduleConfig.mqtt.password;
} }
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
if (moduleConfig.mqtt.tls_enabled) {
// change default for encrypted to 8883
try {
serverPort = 8883;
wifiSecureClient.setInsecure();
pubSub.setClient(wifiSecureClient);
LOG_INFO("Using TLS-encrypted session\n");
} catch (const std::exception &e) {
LOG_ERROR("MQTT ERROR: %s\n", e.what());
}
} else {
LOG_INFO("Using non-TLS-encrypted session\n");
pubSub.setClient(mqttClient);
}
#else
pubSub.setClient(mqttClient);
#endif
String server = String(serverAddr); String server = String(serverAddr);
int delimIndex = server.indexOf(':'); int delimIndex = server.indexOf(':');
if (delimIndex > 0) { if (delimIndex > 0) {

View File

@ -8,6 +8,9 @@
#include <PubSubClient.h> #include <PubSubClient.h>
#if HAS_WIFI #if HAS_WIFI
#include <WiFiClient.h> #include <WiFiClient.h>
#if !defined(ARCH_PORTDUINO)
#include <WiFiClientSecure.h>
#endif
#endif #endif
#if HAS_ETHERNET #if HAS_ETHERNET
#include <EthernetClient.h> #include <EthernetClient.h>
@ -23,9 +26,11 @@ class MQTT : private concurrency::OSThread
{ {
// supposedly the current version is busted: // supposedly the current version is busted:
// http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html // http://www.iotsharing.com/2017/08/how-to-use-esp32-mqtts-with-mqtts-mosquitto-broker-tls-ssl.html
// WiFiClientSecure wifiClient;
#if HAS_WIFI #if HAS_WIFI
WiFiClient mqttClient; WiFiClient mqttClient;
#if !defined(ARCH_PORTDUINO)
WiFiClientSecure wifiSecureClient;
#endif
#endif #endif
#if HAS_ETHERNET #if HAS_ETHERNET
EthernetClient mqttClient; EthernetClient mqttClient;
@ -64,6 +69,9 @@ class MQTT : private concurrency::OSThread
virtual int32_t runOnce() override; virtual int32_t runOnce() override;
private: private:
std::string statusTopic = "/2/stat/";
std::string cryptTopic = "/2/c/"; // msh/2/c/CHANNELID/NODEID
std::string jsonTopic = "/2/json/"; // msh/2/json/CHANNELID/NODEID
/** return true if we have a channel that wants uplink/downlink /** return true if we have a channel that wants uplink/downlink
*/ */
bool wantsLink() const; bool wantsLink() const;

View File

@ -162,7 +162,7 @@ void esp32Loop()
// radio.radioIf.canSleep(); // radio.radioIf.canSleep();
} }
void cpuDeepSleep(uint64_t msecToWake) void cpuDeepSleep(uint32_t msecToWake)
{ {
/* /*
Some ESP32 IOs have internal pullups or pulldowns, which are enabled by default. Some ESP32 IOs have internal pullups or pulldowns, which are enabled by default.
@ -202,7 +202,7 @@ void cpuDeepSleep(uint64_t msecToWake)
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
// Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39. // Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39.
#if SOC_RTCIO_HOLD_SUPPORTED #if SOC_RTCIO_HOLD_SUPPORTED
uint64_t gpioMask = (1ULL << BUTTON_PIN); uint64_t gpioMask = (1ULL << config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
#endif #endif
#ifdef BUTTON_NEED_PULLUP #ifdef BUTTON_NEED_PULLUP

View File

@ -92,12 +92,12 @@ void startAdv(void)
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
// IncludeService UUID // IncludeService UUID
Bluefruit.ScanResponse.addService(meshBleService); // Bluefruit.ScanResponse.addService(meshBleService);
Bluefruit.ScanResponse.addTxPower(); Bluefruit.ScanResponse.addTxPower();
Bluefruit.ScanResponse.addName(); Bluefruit.ScanResponse.addName();
// Include Name // Include Name
Bluefruit.Advertising.addName(); // Bluefruit.Advertising.addName();
Bluefruit.Advertising.addService(meshBleService); Bluefruit.Advertising.addService(meshBleService);
/* Start Advertising /* Start Advertising

View File

@ -90,7 +90,7 @@ extern "C" void HardFault_Handler(void)
asm volatile(" mrs r0,msp\n" asm volatile(" mrs r0,msp\n"
" b HardFault_Impl \n"); " b HardFault_Impl \n");
} }
#else #elif !defined(ARCH_NRF52)
/* The prototype shows it is a naked function - in effect this is just an /* The prototype shows it is a naked function - in effect this is just an
assembly function. */ assembly function. */

View File

@ -155,7 +155,7 @@ void nrf52Setup()
nRFCrypto.end(); nRFCrypto.end();
} }
void cpuDeepSleep(uint64_t msecToWake) void cpuDeepSleep(uint32_t msecToWake)
{ {
// FIXME, configure RTC or button press to wake us // FIXME, configure RTC or button press to wake us
// FIXME, power down SPI, I2C, RAMs // FIXME, power down SPI, I2C, RAMs

View File

@ -16,7 +16,7 @@ void setBluetoothEnable(bool on)
// not needed // not needed
} }
void cpuDeepSleep(uint64_t msecs) void cpuDeepSleep(uint32_t msecs)
{ {
notImplemented("cpuDeepSleep"); notImplemented("cpuDeepSleep");
} }

View File

@ -7,7 +7,7 @@ void setBluetoothEnable(bool on)
// not needed // not needed
} }
void cpuDeepSleep(uint64_t msecs) void cpuDeepSleep(uint32_t msecs)
{ {
// not needed // not needed
} }

View File

@ -15,7 +15,7 @@ void getMacAddr(uint8_t *dmac)
dmac[i] = i; dmac[i] = i;
} }
void cpuDeepSleep(uint64_t msecToWake) {} void cpuDeepSleep(uint32_t msecToWake) {}
/* pacify libc_nano */ /* pacify libc_nano */
extern "C" { extern "C" {

View File

@ -19,6 +19,10 @@
esp_sleep_source_t wakeCause; // the reason we booted this time esp_sleep_source_t wakeCause; // the reason we booted this time
#endif #endif
#ifndef INCLUDE_vTaskSuspend
#define INCLUDE_vTaskSuspend 0
#endif
#ifdef HAS_PMU #ifdef HAS_PMU
#include "XPowersLibInterface.hpp" #include "XPowersLibInterface.hpp"
extern XPowersLibInterface *PMU; extern XPowersLibInterface *PMU;
@ -201,9 +205,13 @@ void doGPSpowersave(bool on)
#endif #endif
} }
void doDeepSleep(uint64_t msecToWake) void doDeepSleep(uint32_t msecToWake)
{ {
LOG_INFO("Entering deep sleep for %lu seconds\n", msecToWake / 1000); if (INCLUDE_vTaskSuspend && (msecToWake == portMAX_DELAY)) {
LOG_INFO("Entering deep sleep forever\n");
} else {
LOG_INFO("Entering deep sleep for %u seconds\n", msecToWake / 1000);
}
// not using wifi yet, but once we are this is needed to shutoff the radio hw // not using wifi yet, but once we are this is needed to shutoff the radio hw
// esp_wifi_stop(); // esp_wifi_stop();
@ -301,7 +309,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
// assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK); // assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK);
#endif #endif
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
esp_sleep_enable_ext0_wakeup((gpio_num_t)BUTTON_PIN, LOW); // when user presses, this button goes low esp_sleep_enable_ext0_wakeup((gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN),
LOW); // when user presses, this button goes low
#endif #endif
#if defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC) #if defined(LORA_DIO1) && (LORA_DIO1 != RADIOLIB_NC)
gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high gpio_wakeup_enable((gpio_num_t)LORA_DIO1, GPIO_INTR_HIGH_LEVEL); // SX126x/SX128x interrupt, active high
@ -330,7 +339,8 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
if (cause == ESP_SLEEP_WAKEUP_GPIO) if (cause == ESP_SLEEP_WAKEUP_GPIO)
LOG_INFO("Exit light sleep gpio: btn=%d\n", !digitalRead(BUTTON_PIN)); LOG_INFO("Exit light sleep gpio: btn=%d\n",
!digitalRead(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN));
#endif #endif
return cause; return cause;

View File

@ -4,7 +4,7 @@
#include "Observer.h" #include "Observer.h"
#include "configuration.h" #include "configuration.h"
void doDeepSleep(uint64_t msecToWake), cpuDeepSleep(uint64_t msecToWake); void doDeepSleep(uint32_t msecToWake), cpuDeepSleep(uint32_t msecToWake);
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32
#include "esp_sleep.h" #include "esp_sleep.h"

View File

@ -142,12 +142,14 @@ void XModemAdapter::handlePacket(meshtastic_XModem xmodemPacket)
case meshtastic_XModem_Control_EOT: case meshtastic_XModem_Control_EOT:
// End of transmission // End of transmission
sendControl(meshtastic_XModem_Control_ACK); sendControl(meshtastic_XModem_Control_ACK);
file.flush();
file.close(); file.close();
isReceiving = false; isReceiving = false;
break; break;
case meshtastic_XModem_Control_CAN: case meshtastic_XModem_Control_CAN:
// Cancel transmission and remove file // Cancel transmission and remove file
sendControl(meshtastic_XModem_Control_ACK); sendControl(meshtastic_XModem_Control_ACK);
file.flush();
file.close(); file.close();
FSCom.remove(filename); FSCom.remove(filename);
isReceiving = false; isReceiving = false;

View File

@ -7,7 +7,7 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_eink -
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_eink> build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_eink>
lib_deps = lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
caveman99/ESP32 Codec2@^1.0.1 https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
zinggjm/GxEPD2@^1.4.9 zinggjm/GxEPD2@^1.4.9
debug_tool = jlink debug_tool = jlink
upload_port = /dev/ttyACM4 upload_port = /dev/ttyACM4

View File

@ -6,5 +6,5 @@ build_flags = ${nrf52840_base.build_flags} -Ivariants/MakePython_nRF52840_oled -
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_oled> build_src_filter = ${nrf52_base.build_src_filter} +<../variants/MakePython_nRF52840_oled>
lib_deps = lib_deps =
${nrf52840_base.lib_deps} ${nrf52840_base.lib_deps}
caveman99/ESP32 Codec2@^1.0.1 https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
debug_tool = jlink debug_tool = jlink

View File

@ -12,7 +12,6 @@ platform_packages =
tool-esptoolpy@^1.40500.0 tool-esptoolpy@^1.40500.0
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
caveman99/ESP32 Codec2@^1.0.1
zinggjm/GxEPD2@^1.5.1 zinggjm/GxEPD2@^1.5.1
adafruit/Adafruit NeoPixel@^1.10.7 adafruit/Adafruit NeoPixel@^1.10.7
build_unflags = -DARDUINO_USB_MODE=1 build_unflags = -DARDUINO_USB_MODE=1

View File

@ -12,7 +12,6 @@ platform_packages =
tool-esptoolpy@^1.40500.0 tool-esptoolpy@^1.40500.0
lib_deps = lib_deps =
${esp32_base.lib_deps} ${esp32_base.lib_deps}
caveman99/ESP32 Codec2@^1.0.1
adafruit/Adafruit NeoPixel@^1.10.7 adafruit/Adafruit NeoPixel@^1.10.7
build_unflags = -DARDUINO_USB_MODE=1 build_unflags = -DARDUINO_USB_MODE=1
build_flags = build_flags =

View File

@ -2,9 +2,6 @@
extends = esp32s3_base extends = esp32s3_base
board = tlora-t3s3-v1 board = tlora-t3s3-v1
upload_protocol = esp-builtin upload_protocol = esp-builtin
lib_deps =
${esp32_base.lib_deps}
caveman99/ESP32 Codec2@^1.0.1
build_flags = build_flags =
${esp32_base.build_flags} -D TLORA_T3S3_V1 -I variants/tlora_t3s3_v1 ${esp32_base.build_flags} -D TLORA_T3S3_V1 -I variants/tlora_t3s3_v1

View File

@ -1,9 +1,6 @@
[env:tlora-v2-1-1.8] [env:tlora-v2-1-1.8]
extends = esp32_base extends = esp32_base
board = ttgo-lora32-v21 board = ttgo-lora32-v21
lib_deps =
${esp32_base.lib_deps}
caveman99/ESP32 Codec2@^1.0.1
build_flags = build_flags =
${esp32_base.build_flags} -D TLORA_V2_1_18 -I variants/tlora_v2_1_18 ${esp32_base.build_flags} -D TLORA_V2_1_18 -I variants/tlora_v2_1_18

View File

@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 2 major = 2
minor = 1 minor = 1
build = 7 build = 10