Compare commits

..

7 Commits

Author SHA1 Message Date
Ben Meadors
857c16faa2 Guard portduino 2026-02-03 20:36:55 -06:00
Ben Meadors
3aa0cbd26a Add close method to AsyncUDP and improve UDP multicast handler lifecycle management 2026-02-03 19:44:53 -06:00
Ben Meadors
17ccd6f921 Merge branch 'master' into udp-cleanup 2026-02-03 19:44:21 -06:00
Jason P
b008c7a170 Fix config.display.use_long_node_name not saving (#9522) 2026-02-03 12:21:51 -06:00
Ben Meadors
a08e7f07ff Implement UDP multicast handler start/stop to ensure proper lifecycle 2026-02-03 08:58:10 -06:00
Eric Sesterhenn
c8a9cdc148 Make sure we always return a value in NodeDB::restorePreferences() (#9516)
In case FScom is not defined there is no return statement. This
moves the return outside of the ifdef to make sure a defined
value is returned.
2026-02-03 06:23:49 -06:00
Jonathan Bennett
644fa5b54e Power off control pin on Thinknode m5 during deepsleep and add RTC (#9510)
* Power off control pin on Thinknode m5 during deepsleep

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Finish HAS_RTC cleanup

* Add RTC for Thinknode M5

* Don't double-init Wire

* Specify the RTC chip directly rather than use SensorRtcHelper.
Saves a bit of flash, and avoid mis-detection

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-03 06:07:33 -06:00
24 changed files with 73 additions and 50 deletions

View File

@@ -120,7 +120,7 @@ lib_deps =
[device-ui_base]
lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/48e3a59ddfd746dfbde562a7f447cf9da4f369cf.zip
https://github.com/meshtastic/device-ui/archive/63967a4a557d33d56fc5746f9128200dde2d88c5.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]

View File

@@ -274,9 +274,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TCA9535_ADDR 0x20
#define TCA9555_ADDR 0x26
// used for display brightness control
#define STC8H1K28_ADDR 0x30
// -----------------------------------------------------------------------------
// Touchscreen
// -----------------------------------------------------------------------------

View File

@@ -63,7 +63,6 @@ class ScanI2C
NAU7802,
FT6336U,
STK8BAXX,
STC8H1K28,
ICM20948,
SCD4X,
MAX30102,

View File

@@ -243,8 +243,6 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#endif
#ifdef HAS_LP5562
SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address);
#else
SCAN_SIMPLE_CASE(STC8H1K28_ADDR, LP5562, "STC8H1K28", (uint8_t)addr.address);
#endif
case XPOWERS_AXP192_AXP2101_ADDRESS:
// Do we have the axp2101/192 or the TCA8418

View File

@@ -72,11 +72,13 @@ RTCSetResult readFromRTC()
#elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
#if defined(PCF8563_RTC)
if (rtc_found.address == PCF8563_RTC) {
SensorPCF8563 rtc;
#elif defined(PCF85063_RTC)
if (rtc_found.address == PCF85063_RTC) {
SensorPCF85063 rtc;
#endif
uint32_t now = millis();
SensorRtcHelper rtc;
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);
@@ -240,10 +242,12 @@ RTCSetResult perhapsSetRTC(RTCQuality q, const struct timeval *tv, bool forceUpd
#elif defined(PCF8563_RTC) || defined(PCF85063_RTC)
#if defined(PCF8563_RTC)
if (rtc_found.address == PCF8563_RTC) {
SensorPCF8563 rtc;
#elif defined(PCF85063_RTC)
if (rtc_found.address == PCF85063_RTC) {
SensorPCF85063 rtc;
#endif
SensorRtcHelper rtc;
#if WIRE_INTERFACES_COUNT == 2
rtc.begin(rtc_found.port == ScanI2C::I2CPort::WIRE1 ? Wire1 : Wire);

View File

@@ -1498,6 +1498,7 @@ void menuHandler::nodeNameLengthMenu()
config.display.use_long_node_name = option.value;
saveUIConfig();
service->reloadConfig(SEGMENT_CONFIG);
LOG_INFO("Setting names to %s", option.value ? "long" : "short");
});

View File

@@ -2213,8 +2213,8 @@ bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location,
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
// TODO: After more mainline SD card support
}
return success;
#endif
return success;
}
/// Record an error that should be reported via analytics

View File

@@ -22,10 +22,14 @@
class UdpMulticastHandler final
{
public:
UdpMulticastHandler() { udpIpAddress = IPAddress(224, 0, 0, 69); }
UdpMulticastHandler() : isRunning(false) { udpIpAddress = IPAddress(224, 0, 0, 69); }
void start()
{
if (isRunning) {
LOG_DEBUG("UDP multicast already running");
return;
}
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT, 64)) {
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
LOG_DEBUG("UDP Listening on IP: %u.%u.%u.%u:%u", udpIpAddress[0], udpIpAddress[1], udpIpAddress[2], udpIpAddress[3],
@@ -34,13 +38,29 @@ class UdpMulticastHandler final
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
#endif
udp.onPacket([this](AsyncUDPPacket packet) { onReceive(packet); });
isRunning = true;
} else {
LOG_DEBUG("Failed to listen on UDP");
}
}
void stop()
{
if (!isRunning) {
return;
}
LOG_DEBUG("Stopping UDP multicast");
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
udp.close();
#endif
isRunning = false;
}
void onReceive(AsyncUDPPacket packet)
{
if (!isRunning) {
return;
}
size_t packetLength = packet.length();
#if defined(ARCH_NRF52)
IPAddress ip = packet.remoteIP();
@@ -67,7 +87,7 @@ class UdpMulticastHandler final
bool onSend(const meshtastic_MeshPacket *mp)
{
if (!mp || !udp) {
if (!isRunning || !mp || !udp) {
return false;
}
#if defined(ARCH_NRF52)
@@ -92,5 +112,6 @@ class UdpMulticastHandler final
private:
IPAddress udpIpAddress;
AsyncUDP udp;
bool isRunning;
};
#endif // HAS_UDP_MULTICAST

View File

@@ -391,6 +391,11 @@ static void WiFiEvent(WiFiEvent_t event)
LOG_INFO("Disconnected from WiFi access point");
#ifdef WIFI_LED
digitalWrite(WIFI_LED, LOW);
#endif
#if HAS_UDP_MULTICAST
if (udpHandler) {
udpHandler->stop();
}
#endif
if (!isReconnecting) {
WiFi.disconnect(false, true);
@@ -417,6 +422,11 @@ static void WiFiEvent(WiFiEvent_t event)
break;
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
LOG_INFO("Lost IP address and IP address is reset to 0");
#if HAS_UDP_MULTICAST
if (udpHandler) {
udpHandler->stop();
}
#endif
if (!isReconnecting) {
WiFi.disconnect(false, true);
syslog.disable();

View File

@@ -24,6 +24,11 @@
#include <nvs.h>
#include <nvs_flash.h>
// Weak empty variant shutdown prep function.
// May be redefined by variant files.
void variant_shutdown() __attribute__((weak));
void variant_shutdown() {}
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
void setBluetoothEnable(bool enable)
{
@@ -249,6 +254,7 @@ void cpuDeepSleep(uint32_t msecToWake)
#endif // #end ESP32S3_WAKE_TYPE
#endif
variant_shutdown();
// We want RTC peripherals to stay on
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);

View File

@@ -36,6 +36,13 @@ bool AsyncUDP::writeTo(const uint8_t *data, size_t len, IPAddress ip, uint16_t p
return udp.endPacket();
}
void AsyncUDP::close()
{
udp.stop();
localPort = 0;
_onPacket = nullptr;
}
// AsyncUDPPacket
AsyncUDPPacket::AsyncUDPPacket(EthernetUDP &source) : _udp(source), _remoteIP(source.remoteIP()), _remotePort(source.remotePort())
{

View File

@@ -22,6 +22,7 @@ class AsyncUDP : public Print, private concurrency::OSThread
bool listenMulticast(IPAddress multicastIP, uint16_t port, uint8_t ttl = 64);
bool writeTo(const uint8_t *data, size_t len, IPAddress ip, uint16_t port);
void close();
size_t write(uint8_t b) override;
size_t write(const uint8_t *data, size_t len) override;

View File

@@ -46,7 +46,7 @@
uint16_t getVDDVoltage();
// Weak empty variant initialization function.
// Weak empty variant shutdown prep function.
// May be redefined by variant files.
void variant_shutdown() __attribute__((weak));
void variant_shutdown() {}

View File

@@ -34,3 +34,5 @@ lib_deps = ${esp32s3_base.lib_deps}
https://github.com/meshtastic/GxEPD2/archive/a05c11c02862624266b61599b0d6ba93e33c6f24.zip
# renovate: datasource=custom.pio depName=PCA9557-arduino packageName=maxpromer/library/PCA9557-arduino
maxpromer/PCA9557-arduino@1.0.0
# renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/SensorLib@0.3.4

View File

@@ -1,12 +1,17 @@
#include "variant.h"
#include <PCA9557.h>
PCA9557 io(0x18, &Wire);
PCA9557 io(0x18, &Wire1);
void earlyInitVariant()
{
Wire.begin(48, 47);
Wire1.begin(48, 47);
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
}
void variant_shutdown()
{
io.digitalWrite(PCA_PIN_POWER_EN, LOW);
}

View File

@@ -30,6 +30,9 @@
#define I2C_SCL 1
#define I2C_SDA 2
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
// GPS pins
#define GPS_SWITH 10
#define HAS_GPS 1

View File

@@ -164,6 +164,3 @@ build_flags =
${crowpanel_large_esp32s3_base.build_flags}
-D VIEW_320x240
-D DISPLAY_SIZE=800x480 ; landscape mode
build_src_filter =
${esp32s3_base.build_src_filter}
+<../variants/esp32s3/elecrow_panel>

View File

@@ -1,21 +0,0 @@
// meshtastic/firmware/variants/elecrow_panel/variant.cpp
#include "variant.h"
#include "Arduino.h"
#include "Wire.h"
bool elecrow_v2 = false; // false = v1, true = v2
extern "C" {
void initVariant()
{
Wire.begin(I2C_SDA, I2C_SCL, 100000);
delay(50);
Wire.beginTransmission(0x30);
if (Wire.endTransmission() == 0) {
elecrow_v2 = true;
}
Wire.end();
}
}

View File

@@ -1,8 +1,6 @@
#define I2C_SDA 15
#define I2C_SCL 16
extern bool elecrow_v2; // false = v1, true = v2
#if CROW_SELECT == 1
#define WAKE_ON_TOUCH
#define SCREEN_TOUCH_INT 47
@@ -19,7 +17,7 @@ extern bool elecrow_v2; // false = v1, true = v2
#define DAC_I2S_DOUT 12
#define DAC_I2S_MCLK 8 // don't use GPIO0 because it's assigned to LoRa or button
#else
#define PIN_BUZZER (elecrow_v2 ? 0 : 8)
#define PIN_BUZZER 8
#endif
// GPS via UART1 connector
@@ -74,7 +72,7 @@ extern bool elecrow_v2; // false = v1, true = v2
#define SENSOR_POWER_ON LOW
#else
// 4.3", 5.0", 7.0"
#define LORA_CS (elecrow_v2 ? 8 : 0)
#define LORA_CS 0
#define LORA_SCK 5
#define LORA_MISO 4
#define LORA_MOSI 6

View File

@@ -24,5 +24,5 @@ lib_deps =
${nrf52840_base.lib_deps}
# renovate: datasource=custom.pio depName=nRF52_PWM packageName=khoih-prog/library/nRF52_PWM
khoih-prog/nRF52_PWM@1.0.1
; # renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
# renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/SensorLib@0.3.4

View File

@@ -116,7 +116,6 @@ extern "C" {
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
#define HAS_RTC 1
#ifdef __cplusplus
}

View File

@@ -21,5 +21,5 @@ build_flags = ${nrf52840_base.build_flags}
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nrf52840/ELECROW-ThinkNode-M6>
lib_deps =
${nrf52840_base.lib_deps}
; # renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
# renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib
lewisxhe/SensorLib@0.3.4

View File

@@ -121,7 +121,6 @@ static const uint8_t A0 = PIN_A0;
// PCF8563 RTC Module
#define PCF8563_RTC 0x51
#define HAS_RTC 1
// SPI
#define SPI_INTERFACES_COUNT 1

View File

@@ -132,9 +132,6 @@ static const uint8_t A0 = PIN_A0;
#define HAS_DRV2605 1
// Battery / ADC already defined above
#define HAS_RTC 1
#define SERIAL_PRINT_PORT 0
#ifdef __cplusplus