mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-19 08:17:36 +00:00
Compare commits
4 Commits
status-mes
...
trunk-io/u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
769ebf1726 | ||
|
|
caa6ec0e8a | ||
|
|
afbd9e2180 | ||
|
|
64116cd0d3 |
@@ -20,7 +20,7 @@ ENV PIP_ROOT_USER_ACTION=ignore
|
|||||||
RUN apt-get update && apt-get install --no-install-recommends -y \
|
RUN apt-get update && apt-get install --no-install-recommends -y \
|
||||||
cmake git zip libgpiod-dev libbluetooth-dev libi2c-dev \
|
cmake git zip libgpiod-dev libbluetooth-dev libi2c-dev \
|
||||||
libunistring-dev libmicrohttpd-dev libgnutls28-dev libgcrypt20-dev \
|
libunistring-dev libmicrohttpd-dev libgnutls28-dev libgcrypt20-dev \
|
||||||
libusb-1.0-0-dev libssl-dev pkg-config libsqlite3-dev && \
|
libusb-1.0-0-dev libssl-dev pkg-config && \
|
||||||
apt-get clean && rm -rf /var/lib/apt/lists/* && \
|
apt-get clean && rm -rf /var/lib/apt/lists/* && \
|
||||||
pip install --no-cache-dir -U \
|
pip install --no-cache-dir -U \
|
||||||
platformio==6.1.16 \
|
platformio==6.1.16 \
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ plugins:
|
|||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- checkov@3.2.497
|
- checkov@3.2.497
|
||||||
- renovate@42.81.8
|
- renovate@42.84.2
|
||||||
- prettier@3.8.0
|
- prettier@3.8.0
|
||||||
- trufflehog@3.92.4
|
- trufflehog@3.92.5
|
||||||
- yamllint@1.38.0
|
- yamllint@1.38.0
|
||||||
- bandit@1.9.2
|
- bandit@1.9.3
|
||||||
- trivy@0.68.2
|
- trivy@0.68.2
|
||||||
- taplo@0.10.0
|
- taplo@0.10.0
|
||||||
- ruff@0.14.11
|
- ruff@0.14.13
|
||||||
- isort@7.0.0
|
- isort@7.0.0
|
||||||
- markdownlint@0.47.0
|
- markdownlint@0.47.0
|
||||||
- oxipng@10.0.0
|
- oxipng@10.0.0
|
||||||
@@ -26,7 +26,7 @@ lint:
|
|||||||
- hadolint@2.14.0
|
- hadolint@2.14.0
|
||||||
- shfmt@3.6.0
|
- shfmt@3.6.0
|
||||||
- shellcheck@0.11.0
|
- shellcheck@0.11.0
|
||||||
- black@25.12.0
|
- black@26.1.0
|
||||||
- git-diff-check
|
- git-diff-check
|
||||||
- gitleaks@8.30.0
|
- gitleaks@8.30.0
|
||||||
- clang-format@16.0.3
|
- clang-format@16.0.3
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
|
|||||||
curl wget g++ zip git ca-certificates pkg-config \
|
curl wget g++ zip git ca-certificates pkg-config \
|
||||||
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
|
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
|
||||||
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
|
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
|
||||||
libx11-dev libinput-dev libxkbcommon-x11-dev libsqlite3-dev \
|
libx11-dev libinput-dev libxkbcommon-x11-dev \
|
||||||
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
|
||||||
&& pip install --no-cache-dir -U platformio \
|
&& pip install --no-cache-dir -U platformio \
|
||||||
&& mkdir /tmp/firmware
|
&& mkdir /tmp/firmware
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ RUN apk --no-cache add \
|
|||||||
bash g++ libstdc++-dev linux-headers zip git ca-certificates libbsd-dev \
|
bash g++ libstdc++-dev linux-headers zip git ca-certificates libbsd-dev \
|
||||||
libgpiod-dev yaml-cpp-dev bluez-dev \
|
libgpiod-dev yaml-cpp-dev bluez-dev \
|
||||||
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
|
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
|
||||||
libx11-dev libinput-dev libxkbcommon-dev sqlite-dev \
|
libx11-dev libinput-dev libxkbcommon-dev \
|
||||||
&& rm -rf /var/cache/apk/* \
|
&& rm -rf /var/cache/apk/* \
|
||||||
&& pip install --no-cache-dir -U platformio \
|
&& pip install --no-cache-dir -U platformio \
|
||||||
&& mkdir /tmp/firmware
|
&& mkdir /tmp/firmware
|
||||||
|
|||||||
3
debian/control
vendored
3
debian/control
vendored
@@ -25,8 +25,7 @@ Build-Depends: debhelper-compat (= 13),
|
|||||||
liborcania-dev,
|
liborcania-dev,
|
||||||
libx11-dev,
|
libx11-dev,
|
||||||
libinput-dev,
|
libinput-dev,
|
||||||
libxkbcommon-x11-dev,
|
libxkbcommon-x11-dev
|
||||||
libsqlite3-dev
|
|
||||||
Standards-Version: 4.6.2
|
Standards-Version: 4.6.2
|
||||||
Homepage: https://github.com/meshtastic/firmware
|
Homepage: https://github.com/meshtastic/firmware
|
||||||
Rules-Requires-Root: no
|
Rules-Requires-Root: no
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ BuildRequires: pkgconfig(bluez)
|
|||||||
BuildRequires: pkgconfig(libusb-1.0)
|
BuildRequires: pkgconfig(libusb-1.0)
|
||||||
BuildRequires: libi2c-devel
|
BuildRequires: libi2c-devel
|
||||||
BuildRequires: pkgconfig(libuv)
|
BuildRequires: pkgconfig(libuv)
|
||||||
BuildRequires: pkgconfig(sqlite3)
|
|
||||||
# Web components:
|
# Web components:
|
||||||
BuildRequires: pkgconfig(openssl)
|
BuildRequires: pkgconfig(openssl)
|
||||||
BuildRequires: pkgconfig(liborcania)
|
BuildRequires: pkgconfig(liborcania)
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ lib_deps =
|
|||||||
[device-ui_base]
|
[device-ui_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
|
||||||
https://github.com/meshtastic/device-ui/archive/5a870c623a4e9ab7a7abe3d02950536f107d1a31.zip
|
https://github.com/meshtastic/device-ui/archive/3480b731d28b10d73414cf0dd7975bff745de8cf.zip
|
||||||
|
|
||||||
; Common libs for environmental measurements in telemetry module
|
; Common libs for environmental measurements in telemetry module
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
|
|||||||
43
src/main.cpp
43
src/main.cpp
@@ -105,6 +105,43 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr;
|
|||||||
#include <string>
|
#include <string>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
#ifdef DEBUG_PARTITION_TABLE
|
||||||
|
#include "esp_partition.h"
|
||||||
|
|
||||||
|
void printPartitionTable()
|
||||||
|
{
|
||||||
|
printf("\n--- Partition Table ---\n");
|
||||||
|
// Print Column Headers
|
||||||
|
printf("| %-16s | %-4s | %-7s | %-10s | %-10s |\n", "Label", "Type", "Subtype", "Offset", "Size");
|
||||||
|
printf("|------------------|------|---------|------------|------------|\n");
|
||||||
|
|
||||||
|
// Create an iterator to find ALL partitions (Type ANY, Subtype ANY)
|
||||||
|
esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
|
||||||
|
|
||||||
|
// Loop through the iterator
|
||||||
|
if (it != NULL) {
|
||||||
|
do {
|
||||||
|
const esp_partition_t *part = esp_partition_get(it);
|
||||||
|
|
||||||
|
// Print details: Label, Type (Hex), Subtype (Hex), Offset (Hex), Size (Hex)
|
||||||
|
printf("| %-16s | 0x%02x | 0x%02x | 0x%08x | 0x%08x |\n", part->label, part->type, part->subtype, part->address,
|
||||||
|
part->size);
|
||||||
|
|
||||||
|
// Move to next partition
|
||||||
|
it = esp_partition_next(it);
|
||||||
|
} while (it != NULL);
|
||||||
|
|
||||||
|
// Release the iterator memory
|
||||||
|
esp_partition_iterator_release(it);
|
||||||
|
} else {
|
||||||
|
printf("No partitions found.\n");
|
||||||
|
}
|
||||||
|
printf("-----------------------\n");
|
||||||
|
}
|
||||||
|
#endif // DEBUG_PARTITION_TABLE
|
||||||
|
#endif // ARCH_ESP32
|
||||||
|
|
||||||
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
|
#if HAS_BUTTON || defined(ARCH_PORTDUINO)
|
||||||
#include "input/ButtonThread.h"
|
#include "input/ButtonThread.h"
|
||||||
|
|
||||||
@@ -648,7 +685,11 @@ void setup()
|
|||||||
sensor_detected = true;
|
sensor_detected = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
#ifdef DEBUG_PARTITION_TABLE
|
||||||
|
printPartitionTable();
|
||||||
|
#endif
|
||||||
|
#endif // ARCH_ESP32
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// Don't init display if we don't have one or we are waking headless due to a timer event
|
// Don't init display if we don't have one or we are waking headless due to a timer event
|
||||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {
|
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER) {
|
||||||
|
|||||||
@@ -1410,14 +1410,6 @@ void NodeDB::loadFromDisk()
|
|||||||
if (portduino_config.has_configDisplayMode) {
|
if (portduino_config.has_configDisplayMode) {
|
||||||
config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)portduino_config.configDisplayMode;
|
config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)portduino_config.configDisplayMode;
|
||||||
}
|
}
|
||||||
if (portduino_config.has_statusMessage) {
|
|
||||||
moduleConfig.has_statusmessage = true;
|
|
||||||
strncpy(moduleConfig.statusmessage.node_status, portduino_config.statusMessage.c_str(), sizeof(moduleConfig.statusmessage.node_status));
|
|
||||||
moduleConfig.statusmessage.node_status[sizeof(moduleConfig.statusmessage.node_status) - 1] = '\0';
|
|
||||||
}
|
|
||||||
if (portduino_config.enable_UDP) {
|
|
||||||
config.network.enabled_protocols = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1518,7 +1510,6 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
|||||||
moduleConfig.has_ambient_lighting = true;
|
moduleConfig.has_ambient_lighting = true;
|
||||||
moduleConfig.has_audio = true;
|
moduleConfig.has_audio = true;
|
||||||
moduleConfig.has_paxcounter = true;
|
moduleConfig.has_paxcounter = true;
|
||||||
moduleConfig.has_statusmessage = true;
|
|
||||||
|
|
||||||
success &=
|
success &=
|
||||||
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ void handleAPIv1FromRadio(HTTPRequest *req, HTTPResponse *res)
|
|||||||
|
|
||||||
if (req->getMethod() == "OPTIONS") {
|
if (req->getMethod() == "OPTIONS") {
|
||||||
res->setStatusCode(204); // Success with no content
|
res->setStatusCode(204); // Success with no content
|
||||||
res->print("");
|
// res->print(""); @todo remove
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
|||||||
|
|
||||||
if (req->getMethod() == "OPTIONS") {
|
if (req->getMethod() == "OPTIONS") {
|
||||||
res->setStatusCode(204); // Success with no content
|
res->setStatusCode(204); // Success with no content
|
||||||
res->print("");
|
// res->print(""); @todo remove
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,22 +235,46 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
|||||||
}
|
}
|
||||||
case meshtastic_AdminMessage_ota_request_tag: {
|
case meshtastic_AdminMessage_ota_request_tag: {
|
||||||
#if defined(ARCH_ESP32)
|
#if defined(ARCH_ESP32)
|
||||||
|
LOG_INFO("OTA Requested");
|
||||||
|
|
||||||
if (r->ota_request.ota_hash.size != 32) {
|
if (r->ota_request.ota_hash.size != 32) {
|
||||||
suppressRebootBanner = true;
|
suppressRebootBanner = true;
|
||||||
LOG_INFO("OTA Failed: Invalid `ota_hash` provided");
|
sendWarningAndLog("Cannot start OTA: Invalid `ota_hash` provided.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
meshtastic_OTAMode mode = r->ota_request.reboot_ota_mode;
|
meshtastic_OTAMode mode = r->ota_request.reboot_ota_mode;
|
||||||
|
const char *mode_name = (mode == METHOD_OTA_BLE ? "BLE" : "WiFi");
|
||||||
|
|
||||||
|
// Check that we have an OTA partition
|
||||||
|
const esp_partition_t *part = MeshtasticOTA::getAppPartition();
|
||||||
|
if (part == NULL) {
|
||||||
|
suppressRebootBanner = true;
|
||||||
|
sendWarningAndLog("Cannot start OTA: Cannot find OTA Loader partition.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_app_desc_t app_desc;
|
||||||
|
if (!MeshtasticOTA::getAppDesc(part, &app_desc)) {
|
||||||
|
suppressRebootBanner = true;
|
||||||
|
sendWarningAndLog("Cannot start OTA: Device does have a valid OTA Loader.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MeshtasticOTA::checkOTACapability(&app_desc, mode)) {
|
||||||
|
suppressRebootBanner = true;
|
||||||
|
sendWarningAndLog("OTA Loader does not support %s", mode_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (MeshtasticOTA::trySwitchToOTA()) {
|
if (MeshtasticOTA::trySwitchToOTA()) {
|
||||||
LOG_INFO("OTA Requested");
|
|
||||||
suppressRebootBanner = true;
|
suppressRebootBanner = true;
|
||||||
if (screen)
|
if (screen)
|
||||||
screen->startFirmwareUpdateScreen();
|
screen->startFirmwareUpdateScreen();
|
||||||
MeshtasticOTA::saveConfig(&config.network, mode, r->ota_request.ota_hash.bytes);
|
MeshtasticOTA::saveConfig(&config.network, mode, r->ota_request.ota_hash.bytes);
|
||||||
LOG_INFO("Rebooting to WiFi OTA");
|
sendWarningAndLog("Rebooting to %s OTA", mode_name);
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("WIFI OTA Failed");
|
sendWarningAndLog("Unable to switch to the OTA partition.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int s = 1; // Reboot in 1 second, hard coded
|
int s = 1; // Reboot in 1 second, hard coded
|
||||||
@@ -976,11 +1000,6 @@ bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
|||||||
moduleConfig.has_paxcounter = true;
|
moduleConfig.has_paxcounter = true;
|
||||||
moduleConfig.paxcounter = c.payload_variant.paxcounter;
|
moduleConfig.paxcounter = c.payload_variant.paxcounter;
|
||||||
break;
|
break;
|
||||||
case meshtastic_ModuleConfig_statusmessage_tag:
|
|
||||||
LOG_INFO("Set module config: StatusMessage");
|
|
||||||
moduleConfig.has_statusmessage = true;
|
|
||||||
moduleConfig.statusmessage = c.payload_variant.statusmessage;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
saveChanges(SEGMENT_MODULECONFIG);
|
saveChanges(SEGMENT_MODULECONFIG);
|
||||||
return true;
|
return true;
|
||||||
@@ -1161,11 +1180,6 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
|||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||||
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||||
break;
|
break;
|
||||||
case meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG:
|
|
||||||
LOG_INFO("Get module config: StatusMessage");
|
|
||||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_statusmessage_tag;
|
|
||||||
res.get_module_config_response.payload_variant.statusmessage = moduleConfig.statusmessage;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
||||||
@@ -1482,15 +1496,43 @@ void AdminModule::handleSendInputEvent(const meshtastic_AdminMessage_InputEvent
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdminModule::sendWarning(const char *message)
|
void AdminModule::sendWarning(const char *format, ...)
|
||||||
{
|
{
|
||||||
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
|
meshtastic_ClientNotification *cn = clientNotificationPool.allocZeroed();
|
||||||
|
if (!cn)
|
||||||
|
return;
|
||||||
|
|
||||||
cn->level = meshtastic_LogRecord_Level_WARNING;
|
cn->level = meshtastic_LogRecord_Level_WARNING;
|
||||||
cn->time = getValidTime(RTCQualityFromNet);
|
cn->time = getValidTime(RTCQualityFromNet);
|
||||||
strncpy(cn->message, message, sizeof(cn->message));
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
// Format the arguments directly into the notification object
|
||||||
|
vsnprintf(cn->message, sizeof(cn->message), format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
service->sendClientNotification(cn);
|
service->sendClientNotification(cn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdminModule::sendWarningAndLog(const char *format, ...)
|
||||||
|
{
|
||||||
|
// We need a temporary buffer to hold the formatted text so we can log it
|
||||||
|
// Using 250 bytes as a safe upper limit for typical text notifications
|
||||||
|
char buf[250];
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vsnprintf(buf, sizeof(buf), format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
LOG_WARN(buf);
|
||||||
|
// 2. Call sendWarning
|
||||||
|
// SECURITY NOTE: We pass "%s", buf instead of just 'buf'.
|
||||||
|
// If 'buf' contained a % symbol (e.g. "Battery 50%"), passing it directly
|
||||||
|
// would crash sendWarning. "%s" treats it purely as text.
|
||||||
|
sendWarning("%s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
void disableBluetooth()
|
void disableBluetooth()
|
||||||
{
|
{
|
||||||
#if HAS_BLUETOOTH
|
#if HAS_BLUETOOTH
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
#include <esp_ota_ops.h>
|
||||||
|
#endif
|
||||||
#include "ProtobufModule.h"
|
#include "ProtobufModule.h"
|
||||||
|
#include <sys/types.h>
|
||||||
#if HAS_WIFI
|
#if HAS_WIFI
|
||||||
#include "mesh/wifi/WiFiAPClient.h"
|
#include "mesh/wifi/WiFiAPClient.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -71,7 +73,8 @@ class AdminModule : public ProtobufModule<meshtastic_AdminMessage>, public Obser
|
|||||||
|
|
||||||
bool messageIsResponse(const meshtastic_AdminMessage *r);
|
bool messageIsResponse(const meshtastic_AdminMessage *r);
|
||||||
bool messageIsRequest(const meshtastic_AdminMessage *r);
|
bool messageIsRequest(const meshtastic_AdminMessage *r);
|
||||||
void sendWarning(const char *message);
|
void sendWarning(const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||||
|
void sendWarningAndLog(const char *format, ...) __attribute__((format(printf, 2, 3)));
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr const char *licensedModeMessage =
|
static constexpr const char *licensedModeMessage =
|
||||||
|
|||||||
@@ -108,9 +108,6 @@
|
|||||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||||
#include "modules/DropzoneModule.h"
|
#include "modules/DropzoneModule.h"
|
||||||
#endif
|
#endif
|
||||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
|
||||||
#include "modules/StatusMessageModule.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create module instances here. If you are adding a new module, you must 'new' it here (or somewhere else)
|
* Create module instances here. If you are adding a new module, you must 'new' it here (or somewhere else)
|
||||||
@@ -168,9 +165,6 @@ void setupModules()
|
|||||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||||
dropzoneModule = new DropzoneModule();
|
dropzoneModule = new DropzoneModule();
|
||||||
#endif
|
#endif
|
||||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
|
||||||
statusMessageModule = new StatusMessageModule();
|
|
||||||
#endif
|
|
||||||
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
|
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
|
||||||
new GenericThreadModule();
|
new GenericThreadModule();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -50,9 +50,10 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case meshtastic::BluetoothStatus::ConnectionState::CONNECTED: {
|
case meshtastic::BluetoothStatus::ConnectionState::CONNECTED: {
|
||||||
ble_state = connected;
|
if (ble_state != connected) {
|
||||||
PAIRING_LED_starttime = millis();
|
ble_state = connected;
|
||||||
break;
|
PAIRING_LED_starttime = millis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
|
||||||
|
|
||||||
#include "StatusMessageModule.h"
|
|
||||||
#include "ProtobufModule.h"
|
|
||||||
#include "MeshService.h"
|
|
||||||
|
|
||||||
|
|
||||||
StatusMessageModule *statusMessageModule;
|
|
||||||
|
|
||||||
int32_t StatusMessageModule::runOnce()
|
|
||||||
{
|
|
||||||
if (moduleConfig.has_statusmessage && moduleConfig.statusmessage.node_status[0] != '\0') {
|
|
||||||
// create and send message with the status message set
|
|
||||||
meshtastic_StatusMessage ourStatus = meshtastic_StatusMessage_init_zero;
|
|
||||||
strncpy(ourStatus.status, moduleConfig.statusmessage.node_status, sizeof(ourStatus.status));
|
|
||||||
ourStatus.status[sizeof(ourStatus.status) - 1] = '\0'; // ensure null termination
|
|
||||||
meshtastic_MeshPacket *p = allocDataPacket();
|
|
||||||
p->decoded.payload.size =
|
|
||||||
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), meshtastic_StatusMessage_fields, &ourStatus);
|
|
||||||
p->to = NODENUM_BROADCAST;
|
|
||||||
p->decoded.want_response = false;
|
|
||||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
|
||||||
p->channel = 0;
|
|
||||||
service->sendToMesh(p);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1000 * 12 * 60 * 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessMessage StatusMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
|
|
||||||
{
|
|
||||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
|
||||||
meshtastic_StatusMessage incomingMessage;
|
|
||||||
if (pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_StatusMessage_fields,
|
|
||||||
&incomingMessage)) {
|
|
||||||
LOG_INFO("Received a NodeStatus message %s", incomingMessage.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return ProcessMessage::CONTINUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
|
||||||
#include "SinglePortModule.h"
|
|
||||||
#include "configuration.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class StatusMessageModule : public SinglePortModule, private concurrency::OSThread
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Constructor
|
|
||||||
* name is for debugging output
|
|
||||||
*/
|
|
||||||
StatusMessageModule() : SinglePortModule("statusMessage", meshtastic_PortNum_NODE_STATUS_APP), concurrency::OSThread("StatusMessage")
|
|
||||||
{
|
|
||||||
if (moduleConfig.has_statusmessage && moduleConfig.statusmessage.node_status[0] != '\0') {
|
|
||||||
this->setInterval(2 * 60 * 1000);
|
|
||||||
}
|
|
||||||
// TODO: If we have a string, set the initial delay (15 minutes maybe)
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int32_t runOnce() override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Called to handle a particular incoming message
|
|
||||||
*/
|
|
||||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
|
|
||||||
extern StatusMessageModule *statusMessageModule;
|
|
||||||
#endif
|
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
#include "MeshtasticOTA.h"
|
#include "MeshtasticOTA.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
#include <esp_ota_ops.h>
|
#include <esp_ota_ops.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace MeshtasticOTA
|
namespace MeshtasticOTA
|
||||||
{
|
{
|
||||||
|
|
||||||
static const char *nvsNamespace = "MeshtasticOTA";
|
static const char *nvsNamespace = "MeshtasticOTA";
|
||||||
static const char *appProjectName = "MeshtasticOTA";
|
static const char *combinedAppProjectName = "MeshtasticOTA";
|
||||||
|
static const char *bleOnlyAppProjectName = "MeshtasticOTA-BLE";
|
||||||
|
static const char *wifiOnlyAppProjectName = "MeshtasticOTA-WiFi";
|
||||||
|
|
||||||
static bool updated = false;
|
static bool updated = false;
|
||||||
|
|
||||||
@@ -68,21 +72,44 @@ bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc)
|
|||||||
LOG_INFO("esp_ota_get_partition_description failed");
|
LOG_INFO("esp_ota_get_partition_description failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (strcmp(app_desc->project_name, appProjectName) != 0) {
|
|
||||||
LOG_INFO("app_desc->project_name == 0");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool checkOTACapability(esp_app_desc_t *app_desc, uint8_t method)
|
||||||
|
{
|
||||||
|
// Combined loader supports all (both) transports, BLE and WiFi
|
||||||
|
if (strcmp(app_desc->project_name, combinedAppProjectName) == 0) {
|
||||||
|
LOG_INFO("OTA partition contains combined BLE/WiFi OTA Loader");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (method == METHOD_OTA_BLE && strcmp(app_desc->project_name, bleOnlyAppProjectName) == 0) {
|
||||||
|
LOG_INFO("OTA partition contains BLE-only OTA Loader");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (method == METHOD_OTA_WIFI && strcmp(app_desc->project_name, wifiOnlyAppProjectName) == 0) {
|
||||||
|
LOG_INFO("OTA partition contains WiFi-only OTA Loader");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
LOG_INFO("OTA partition does not contain a known OTA loader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool trySwitchToOTA()
|
bool trySwitchToOTA()
|
||||||
{
|
{
|
||||||
const esp_partition_t *part = getAppPartition();
|
const esp_partition_t *part = getAppPartition();
|
||||||
esp_app_desc_t app_desc;
|
|
||||||
if (!getAppDesc(part, &app_desc))
|
if (part == NULL) {
|
||||||
|
LOG_WARN("Unable to get app partition in preparation of OTA reboot");
|
||||||
return false;
|
return false;
|
||||||
if (esp_ota_set_boot_partition(part) != ESP_OK)
|
}
|
||||||
|
|
||||||
|
uint8_t result = esp_ota_set_boot_partition(part);
|
||||||
|
// Partition and app checks should now be done in the AdminModule before this is called
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
LOG_WARN("Unable to switch to OTA partiton. (Reason %d)", result);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,20 @@
|
|||||||
|
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
#include <esp_ota_ops.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define METHOD_OTA_BLE 1
|
||||||
|
#define METHOD_OTA_WIFI 2
|
||||||
|
|
||||||
namespace MeshtasticOTA
|
namespace MeshtasticOTA
|
||||||
{
|
{
|
||||||
void initialize();
|
void initialize();
|
||||||
bool isUpdated();
|
bool isUpdated();
|
||||||
|
const esp_partition_t *getAppPartition();
|
||||||
|
bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc);
|
||||||
|
bool checkOTACapability(esp_app_desc_t *app_desc, uint8_t method);
|
||||||
void recoverConfig(meshtastic_Config_NetworkConfig *network);
|
void recoverConfig(meshtastic_Config_NetworkConfig *network);
|
||||||
void saveConfig(meshtastic_Config_NetworkConfig *network, meshtastic_OTAMode method, uint8_t *ota_hash);
|
void saveConfig(meshtastic_Config_NetworkConfig *network, meshtastic_OTAMode method, uint8_t *ota_hash);
|
||||||
bool trySwitchToOTA();
|
bool trySwitchToOTA();
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ void cpuDeepSleep(uint32_t msecs)
|
|||||||
void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel");
|
void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel");
|
||||||
|
|
||||||
int TCPPort = SERVER_API_DEFAULT_PORT;
|
int TCPPort = SERVER_API_DEFAULT_PORT;
|
||||||
bool checkConfigPort = true;
|
|
||||||
|
|
||||||
static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
||||||
{
|
{
|
||||||
@@ -64,7 +63,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
|
|||||||
if (sscanf(arg, "%d", &TCPPort) < 1)
|
if (sscanf(arg, "%d", &TCPPort) < 1)
|
||||||
return ARGP_ERR_UNKNOWN;
|
return ARGP_ERR_UNKNOWN;
|
||||||
else
|
else
|
||||||
checkConfigPort = false;
|
|
||||||
printf("Using config file %d\n", TCPPort);
|
printf("Using config file %d\n", TCPPort);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
@@ -847,7 +845,6 @@ bool loadConfig(const char *configPath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (yamlConfig["Config"]) {
|
if (yamlConfig["Config"]) {
|
||||||
portduino_config.has_config_overrides = true;
|
|
||||||
if (yamlConfig["Config"]["DisplayMode"]) {
|
if (yamlConfig["Config"]["DisplayMode"]) {
|
||||||
portduino_config.has_configDisplayMode = true;
|
portduino_config.has_configDisplayMode = true;
|
||||||
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
|
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
|
||||||
@@ -860,13 +857,6 @@ bool loadConfig(const char *configPath)
|
|||||||
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
|
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (yamlConfig["Config"]["StatusMessage"]) {
|
|
||||||
portduino_config.has_statusMessage = true;
|
|
||||||
portduino_config.statusMessage = (yamlConfig["Config"]["StatusMessage"]).as<std::string>("");
|
|
||||||
}
|
|
||||||
if ((yamlConfig["Config"]["EnableUDP"]).as<bool>(false)) {
|
|
||||||
portduino_config.enable_UDP = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yamlConfig["General"]) {
|
if (yamlConfig["General"]) {
|
||||||
@@ -880,14 +870,6 @@ bool loadConfig(const char *configPath)
|
|||||||
std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl;
|
std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl;
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (checkConfigPort) {
|
|
||||||
portduino_config.api_port = (yamlConfig["General"]["APIPort"]).as<int>(-1);
|
|
||||||
if (portduino_config.api_port != -1 &&
|
|
||||||
portduino_config.api_port > 1023 &&
|
|
||||||
portduino_config.api_port < 65536) {
|
|
||||||
TCPPort = (portduino_config.api_port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
portduino_config.mac_address = (yamlConfig["General"]["MACAddress"]).as<std::string>("");
|
portduino_config.mac_address = (yamlConfig["General"]["MACAddress"]).as<std::string>("");
|
||||||
if (portduino_config.mac_address != "") {
|
if (portduino_config.mac_address != "") {
|
||||||
portduino_config.mac_address_explicit = true;
|
portduino_config.mac_address_explicit = true;
|
||||||
|
|||||||
@@ -168,18 +168,13 @@ extern struct portduino_config_struct {
|
|||||||
int hostMetrics_channel = 0;
|
int hostMetrics_channel = 0;
|
||||||
|
|
||||||
// config
|
// config
|
||||||
bool has_config_overrides = false;
|
|
||||||
int configDisplayMode = 0;
|
int configDisplayMode = 0;
|
||||||
bool has_configDisplayMode = false;
|
bool has_configDisplayMode = false;
|
||||||
std::string statusMessage = "";
|
|
||||||
bool has_statusMessage = false;
|
|
||||||
bool enable_UDP = false;
|
|
||||||
|
|
||||||
// General
|
// General
|
||||||
std::string mac_address = "";
|
std::string mac_address = "";
|
||||||
bool mac_address_explicit = false;
|
bool mac_address_explicit = false;
|
||||||
std::string mac_address_source = "";
|
std::string mac_address_source = "";
|
||||||
int api_port = -1;
|
|
||||||
std::string config_directory = "";
|
std::string config_directory = "";
|
||||||
std::string available_directory = "/etc/meshtasticd/available.d/";
|
std::string available_directory = "/etc/meshtasticd/available.d/";
|
||||||
int maxtophone = 100;
|
int maxtophone = 100;
|
||||||
@@ -489,32 +484,21 @@ extern struct portduino_config_struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// config
|
// config
|
||||||
if (has_config_overrides) {
|
if (has_configDisplayMode) {
|
||||||
out << YAML::Key << "Config" << YAML::Value << YAML::BeginMap;
|
out << YAML::Key << "Config" << YAML::Value << YAML::BeginMap;
|
||||||
if (has_configDisplayMode) {
|
switch (configDisplayMode) {
|
||||||
|
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
|
||||||
switch (configDisplayMode) {
|
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
|
||||||
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
|
break;
|
||||||
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
|
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
|
||||||
break;
|
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
|
||||||
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
|
break;
|
||||||
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
|
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
|
||||||
break;
|
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
|
||||||
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
|
break;
|
||||||
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
|
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
|
||||||
break;
|
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
|
||||||
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
|
break;
|
||||||
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (has_statusMessage) {
|
|
||||||
out << YAML::Key << "StatusMessage" << YAML::Value << statusMessage;
|
|
||||||
|
|
||||||
}
|
|
||||||
if (enable_UDP) {
|
|
||||||
out << YAML::Key << "EnableUDP" << YAML::Value << true;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out << YAML::EndMap; // Config
|
out << YAML::EndMap; // Config
|
||||||
@@ -524,8 +508,6 @@ extern struct portduino_config_struct {
|
|||||||
out << YAML::Key << "General" << YAML::Value << YAML::BeginMap;
|
out << YAML::Key << "General" << YAML::Value << YAML::BeginMap;
|
||||||
if (config_directory != "")
|
if (config_directory != "")
|
||||||
out << YAML::Key << "ConfigDirectory" << YAML::Value << config_directory;
|
out << YAML::Key << "ConfigDirectory" << YAML::Value << config_directory;
|
||||||
if (api_port != -1)
|
|
||||||
out << YAML::Key << "TCPPort" << YAML::Value << api_port;
|
|
||||||
if (mac_address_explicit)
|
if (mac_address_explicit)
|
||||||
out << YAML::Key << "MACAddress" << YAML::Value << mac_address;
|
out << YAML::Key << "MACAddress" << YAML::Value << mac_address;
|
||||||
if (mac_address_source != "")
|
if (mac_address_source != "")
|
||||||
@@ -537,4 +519,4 @@ extern struct portduino_config_struct {
|
|||||||
out << YAML::EndMap; // General
|
out << YAML::EndMap; // General
|
||||||
return out.c_str();
|
return out.c_str();
|
||||||
}
|
}
|
||||||
} portduino_config;
|
} portduino_config;
|
||||||
@@ -10,6 +10,8 @@ custom_meshtastic_tags = M5Stack
|
|||||||
|
|
||||||
extends = esp32c6_base
|
extends = esp32c6_base
|
||||||
board = esp32-c6-devkitc-1
|
board = esp32-c6-devkitc-1
|
||||||
|
board_upload.flash_size = 16MB
|
||||||
|
board_build.partitions = default_16MB.csv
|
||||||
;OpenOCD flash method
|
;OpenOCD flash method
|
||||||
;upload_protocol = esp-builtin
|
;upload_protocol = esp-builtin
|
||||||
;Normal method
|
;Normal method
|
||||||
|
|||||||
Reference in New Issue
Block a user