Compare commits

...

3 Commits

Author SHA1 Message Date
Jake-B
e93abf85c0 Initial commit of combined BLE and WiFi OTA 2025-12-21 20:38:44 -05:00
Ben Meadors
83c6161ac6 Revert "Automated version bumps (#9025)"
This reverts commit 1021d967da.
2025-12-20 14:10:02 -06:00
Ben Meadors
d93d68d31e Fix -ota.zip in manifest and build output 2025-12-20 14:09:05 -06:00
13 changed files with 45 additions and 125 deletions

View File

@@ -21,13 +21,14 @@ rm -f $BUILDDIR/firmware*
export APP_VERSION=$VERSION export APP_VERSION=$VERSION
basename=firmware-$1-$VERSION basename=firmware-$1-$VERSION
ota_basename=${basename}-ota
pio run --environment $1 -t mtjson # -v pio run --environment $1 -t mtjson # -v
cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf cp $BUILDDIR/$basename.elf $OUTDIR/$basename.elf
echo "Copying NRF52 dfu (OTA) file" echo "Copying NRF52 dfu (OTA) file"
cp $BUILDDIR/$basename.zip $OUTDIR/$basename.zip cp $BUILDDIR/$basename.zip $OUTDIR/$ota_basename.zip
echo "Copying NRF52 UF2 file" echo "Copying NRF52 UF2 file"
cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2 cp $BUILDDIR/$basename.uf2 $OUTDIR/$basename.uf2

View File

@@ -87,9 +87,6 @@
</screenshots> </screenshots>
<releases> <releases>
<release version="2.7.18" date="2025-12-20">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.18</url>
</release>
<release version="2.7.17" date="2025-11-28"> <release version="2.7.17" date="2025-11-28">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.17</url> <url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.17</url>
</release> </release>

View File

@@ -17,6 +17,8 @@ lfsbin = f"{progname.replace('firmware-', 'littlefs-')}.bin"
def manifest_gather(source, target, env): def manifest_gather(source, target, env):
out = [] out = []
board_platform = env.BoardConfig().get("platform")
needs_ota_suffix = board_platform == "nordicnrf52"
check_paths = [ check_paths = [
progname, progname,
f"{progname}.elf", f"{progname}.elf",
@@ -32,8 +34,11 @@ def manifest_gather(source, target, env):
for p in check_paths: for p in check_paths:
f = env.File(env.subst(f"$BUILD_DIR/{p}")) f = env.File(env.subst(f"$BUILD_DIR/{p}"))
if f.exists(): if f.exists():
manifest_name = p
if needs_ota_suffix and p == f"{progname}.zip":
manifest_name = f"{progname}-ota.zip"
d = { d = {
"name": p, "name": manifest_name,
"md5": f.get_content_hash(), # Returns MD5 hash "md5": f.get_content_hash(), # Returns MD5 hash
"bytes": f.get_size() # Returns file size in bytes "bytes": f.get_size() # Returns file size in bytes
} }

6
debian/changelog vendored
View File

@@ -1,9 +1,3 @@
meshtasticd (2.7.18.0) unstable; urgency=medium
* Version 2.7.18
-- GitHub Actions <github-actions[bot]@users.noreply.github.com> Sat, 20 Dec 2025 15:47:25 +0000
meshtasticd (2.7.17.0) unstable; urgency=medium meshtasticd (2.7.17.0) unstable; urgency=medium
* Version 2.7.17 * Version 2.7.17

View File

@@ -53,7 +53,7 @@
#endif #endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
#include <WiFiOTA.h> #include <MeshtasticOTA.h>
#endif #endif
NodeDB *nodeDB = nullptr; NodeDB *nodeDB = nullptr;
@@ -739,8 +739,8 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
config.display.compass_orientation = COMPASS_ORIENTATION; config.display.compass_orientation = COMPASS_ORIENTATION;
#endif #endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
if (WiFiOTA::isUpdated()) { if (MeshtasticOTA::isUpdated()) {
WiFiOTA::recoverConfig(&config.network); MeshtasticOTA::recoverConfig(&config.network);
} }
#endif #endif

View File

@@ -9,11 +9,8 @@
#include "meshUtils.h" #include "meshUtils.h"
#include <FSCommon.h> #include <FSCommon.h>
#include <ctype.h> // for better whitespace handling #include <ctype.h> // for better whitespace handling
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
#include "BleOta.h"
#endif
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI #if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
#include "WiFiOTA.h" #include "MeshtasticOTA.h"
#endif #endif
#include "Router.h" #include "Router.h"
#include "configuration.h" #include "configuration.h"
@@ -237,24 +234,18 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
break; break;
} }
case meshtastic_AdminMessage_reboot_ota_seconds_tag: { case meshtastic_AdminMessage_reboot_ota_seconds_tag: {
// TODO: Update to new protobufs
int32_t s = r->reboot_ota_seconds; int32_t s = r->reboot_ota_seconds;
#if defined(ARCH_ESP32) #if defined(ARCH_ESP32)
#if !MESHTASTIC_EXCLUDE_BLUETOOTH if (MeshtasticOTA::trySwitchToOTA()) {
if (!BleOta::getOtaAppVersion().isEmpty()) { LOG_INFO("OTA Requested");
if (screen) if (screen)
screen->startFirmwareUpdateScreen(); screen->startFirmwareUpdateScreen();
BleOta::switchToOtaApp(); MeshtasticOTA::saveConfig(&config.network, (s % 2) & 0b1);
LOG_INFO("Rebooting to BLE OTA");
}
#endif
#if !MESHTASTIC_EXCLUDE_WIFI
if (WiFiOTA::trySwitchToOTA()) {
if (screen)
screen->startFirmwareUpdateScreen();
WiFiOTA::saveConfig(&config.network);
LOG_INFO("Rebooting to WiFi OTA"); LOG_INFO("Rebooting to WiFi OTA");
} else {
LOG_INFO("WIFI OTA Failed");
} }
#endif
#endif #endif
LOG_INFO("Reboot in %d seconds", s); LOG_INFO("Reboot in %d seconds", s);
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000); rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);

View File

@@ -429,7 +429,9 @@ int32_t PositionModule::runOnce()
if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) { if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) {
if (waitingForFreshPosition) { if (waitingForFreshPosition) {
#ifdef GPS_DEBUG
LOG_DEBUG("Skip initial position send; no fresh position since boot"); LOG_DEBUG("Skip initial position send; no fresh position since boot");
#endif
} else if (nodeDB->hasValidPosition(node)) { } else if (nodeDB->hasValidPosition(node)) {
lastGpsSend = now; lastGpsSend = now;

View File

@@ -1,46 +0,0 @@
#include "BleOta.h"
#include "Arduino.h"
#include <esp_ota_ops.h>
static const String MESHTASTIC_OTA_APP_PROJECT_NAME("Meshtastic-OTA");
const esp_partition_t *BleOta::findEspOtaAppPartition()
{
const esp_partition_t *part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, nullptr);
esp_app_desc_t app_desc;
esp_err_t ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
if (ret != ESP_OK || MESHTASTIC_OTA_APP_PROJECT_NAME != app_desc.project_name) {
part = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_1, nullptr);
ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
}
if (ret == ESP_OK && MESHTASTIC_OTA_APP_PROJECT_NAME == app_desc.project_name) {
return part;
} else {
return nullptr;
}
}
String BleOta::getOtaAppVersion()
{
const esp_partition_t *part = findEspOtaAppPartition();
esp_app_desc_t app_desc;
esp_err_t ret = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_get_partition_description(part, &app_desc));
String version;
if (ret == ESP_OK) {
version = app_desc.version;
}
return version;
}
bool BleOta::switchToOtaApp()
{
bool success = false;
const esp_partition_t *part = findEspOtaAppPartition();
if (part) {
success = (ESP_ERROR_CHECK_WITHOUT_ABORT(esp_ota_set_boot_partition(part)) == ESP_OK);
}
return success;
}

View File

@@ -1,20 +0,0 @@
#ifndef BLEOTA_H
#define BLEOTA_H
#include <Arduino.h>
#include <functional>
class BleOta
{
public:
explicit BleOta(){};
static String getOtaAppVersion();
static bool switchToOtaApp();
private:
String mUserAgent;
static const esp_partition_t *findEspOtaAppPartition();
};
#endif // BLEOTA_H

View File

@@ -1,13 +1,13 @@
#include "WiFiOTA.h" #include "MeshtasticOTA.h"
#include "configuration.h" #include "configuration.h"
#include <Preferences.h> #include <Preferences.h>
#include <esp_ota_ops.h> #include <esp_ota_ops.h>
namespace WiFiOTA namespace MeshtasticOTA
{ {
static const char *nvsNamespace = "ota-wifi"; static const char *nvsNamespace = "MeshtasticOTA";
static const char *appProjectName = "OTA-WiFi"; static const char *appProjectName = "MeshtasticOTA";
static bool updated = false; static bool updated = false;
@@ -43,12 +43,13 @@ void recoverConfig(meshtastic_Config_NetworkConfig *network)
strncpy(network->wifi_psk, psk.c_str(), sizeof(network->wifi_psk)); strncpy(network->wifi_psk, psk.c_str(), sizeof(network->wifi_psk));
} }
void saveConfig(meshtastic_Config_NetworkConfig *network) void saveConfig(meshtastic_Config_NetworkConfig *network, bool method)
{ {
LOG_INFO("Saving WiFi settings for upcoming OTA update"); LOG_INFO("Saving WiFi settings for upcoming OTA update");
Preferences prefs; Preferences prefs;
prefs.begin(nvsNamespace); prefs.begin(nvsNamespace);
prefs.putUChar("method", method);
prefs.putString("ssid", network->wifi_ssid); prefs.putString("ssid", network->wifi_ssid);
prefs.putString("psk", network->wifi_psk); prefs.putString("psk", network->wifi_psk);
prefs.putBool("updated", false); prefs.putBool("updated", false);
@@ -62,10 +63,14 @@ const esp_partition_t *getAppPartition()
bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc) bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc)
{ {
if (esp_ota_get_partition_description(part, app_desc) != ESP_OK) if (esp_ota_get_partition_description(part, app_desc) != ESP_OK) {
LOG_INFO("esp_ota_get_partition_description failed");
return false; return false;
if (strcmp(app_desc->project_name, appProjectName) != 0) }
if (strcmp(app_desc->project_name, appProjectName) != 0) {
LOG_INFO("app_desc->project_name == 0");
return false; return false;
}
return true; return true;
} }
@@ -89,4 +94,4 @@ const char *getVersion()
return app_desc.version; return app_desc.version;
} }
} // namespace WiFiOTA } // namespace MeshtasticOTA

View File

@@ -1,18 +1,18 @@
#ifndef WIFIOTA_H #ifndef MESHTASTICOTA_H
#define WIFIOTA_H #define MESHTASTICOTA_H
#include "mesh-pb-constants.h" #include "mesh-pb-constants.h"
#include <Arduino.h> #include <Arduino.h>
namespace WiFiOTA namespace MeshtasticOTA
{ {
void initialize(); void initialize();
bool isUpdated(); bool isUpdated();
void recoverConfig(meshtastic_Config_NetworkConfig *network); void recoverConfig(meshtastic_Config_NetworkConfig *network);
void saveConfig(meshtastic_Config_NetworkConfig *network); void saveConfig(meshtastic_Config_NetworkConfig *network, bool method);
bool trySwitchToOTA(); bool trySwitchToOTA();
const char *getVersion(); const char *getVersion();
} // namespace WiFiOTA } // namespace MeshtasticOTA
#endif // WIFIOTA_H #endif // MESHTASTICOTA_H

View File

@@ -5,11 +5,10 @@
#include "main.h" #include "main.h"
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
#include "BleOta.h"
#include "nimble/NimbleBluetooth.h" #include "nimble/NimbleBluetooth.h"
#endif #endif
#include <WiFiOTA.h> #include <MeshtasticOTA.h>
#if HAS_WIFI #if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h" #include "mesh/wifi/WiFiAPClient.h"
@@ -144,22 +143,14 @@ void esp32Setup()
preferences.putUInt("hwVendor", HW_VENDOR); preferences.putUInt("hwVendor", HW_VENDOR);
preferences.end(); preferences.end();
LOG_DEBUG("Number of Device Reboots: %d", rebootCounter); LOG_DEBUG("Number of Device Reboots: %d", rebootCounter);
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
String BLEOTA = BleOta::getOtaAppVersion();
if (BLEOTA.isEmpty()) {
LOG_INFO("No BLE OTA firmware available");
} else {
LOG_INFO("BLE OTA firmware version %s", BLEOTA.c_str());
}
#endif
#if !MESHTASTIC_EXCLUDE_WIFI #if !MESHTASTIC_EXCLUDE_WIFI
String version = WiFiOTA::getVersion(); String version = MeshtasticOTA::getVersion();
if (version.isEmpty()) { if (version.isEmpty()) {
LOG_INFO("No WiFi OTA firmware available"); LOG_INFO("MeshtasticOTA firmware not available");
} else { } else {
LOG_INFO("WiFi OTA firmware version %s", version.c_str()); LOG_INFO("MeshtasticOTA firmware version %s", version.c_str());
} }
WiFiOTA::initialize(); MeshtasticOTA::initialize();
#endif #endif
// enableModemSleep(); // enableModemSleep();

View File

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