Merge branch 'meshtastic:master' into master

This commit is contained in:
Mictronics 2025-02-22 17:08:53 +01:00 committed by GitHub
commit 9485909ef7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 65 additions and 119 deletions

1
debian/control vendored
View File

@ -3,6 +3,7 @@ Section: misc
Priority: optional Priority: optional
Maintainer: Austin Lane <vidplace7@gmail.com> Maintainer: Austin Lane <vidplace7@gmail.com>
Build-Depends: debhelper-compat (= 13), Build-Depends: debhelper-compat (= 13),
lsb-release,
tar, tar,
gzip, gzip,
platformio, platformio,

9
debian/rules vendored
View File

@ -11,6 +11,15 @@ PIO_ENV:=\
PLATFORMIO_LIBDEPS_DIR=pio/libdeps \ PLATFORMIO_LIBDEPS_DIR=pio/libdeps \
PLATFORMIO_PACKAGES_DIR=pio/packages PLATFORMIO_PACKAGES_DIR=pio/packages
# Raspbian armhf builds should be compatible with armv6-hardfloat
# https://www.valvers.com/open-software/raspberry-pi/bare-metal-programming-in-c-part-1/#rpi1-compiler-flags
ifneq (,$(findstring Raspbian,$(shell lsb_release -is)))
ifeq ($(DEB_BUILD_ARCH),armhf)
PIO_ENV+=\
PLATFORMIO_BUILD_FLAGS="-mfloat-abi=hard -mfpu=vfp -march=armv6zk"
endif
endif
override_dh_auto_build: override_dh_auto_build:
# Extract tarballs within source deb # Extract tarballs within source deb
tar -xf pio.tar tar -xf pio.tar

View File

@ -6,28 +6,28 @@
void d_writeCommand(uint8_t c) void d_writeCommand(uint8_t c)
{ {
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
if (PIN_EINK_DC >= 0) if (PIN_EINK_DC >= 0)
digitalWrite(PIN_EINK_DC, LOW); digitalWrite(PIN_EINK_DC, LOW);
if (PIN_EINK_CS >= 0) if (PIN_EINK_CS >= 0)
digitalWrite(PIN_EINK_CS, LOW); digitalWrite(PIN_EINK_CS, LOW);
SPI.transfer(c); SPI1.transfer(c);
if (PIN_EINK_CS >= 0) if (PIN_EINK_CS >= 0)
digitalWrite(PIN_EINK_CS, HIGH); digitalWrite(PIN_EINK_CS, HIGH);
if (PIN_EINK_DC >= 0) if (PIN_EINK_DC >= 0)
digitalWrite(PIN_EINK_DC, HIGH); digitalWrite(PIN_EINK_DC, HIGH);
SPI.endTransaction(); SPI1.endTransaction();
} }
void d_writeData(uint8_t d) void d_writeData(uint8_t d)
{ {
SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); SPI1.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
if (PIN_EINK_CS >= 0) if (PIN_EINK_CS >= 0)
digitalWrite(PIN_EINK_CS, LOW); digitalWrite(PIN_EINK_CS, LOW);
SPI.transfer(d); SPI1.transfer(d);
if (PIN_EINK_CS >= 0) if (PIN_EINK_CS >= 0)
digitalWrite(PIN_EINK_CS, HIGH); digitalWrite(PIN_EINK_CS, HIGH);
SPI.endTransaction(); SPI1.endTransaction();
} }
unsigned long d_waitWhileBusy(uint16_t busy_time) unsigned long d_waitWhileBusy(uint16_t busy_time)
@ -53,7 +53,7 @@ unsigned long d_waitWhileBusy(uint16_t busy_time)
void scanEInkDevice(void) void scanEInkDevice(void)
{ {
SPI.begin(); SPI1.begin();
d_writeCommand(0x22); d_writeCommand(0x22);
d_writeData(0x83); d_writeData(0x83);
d_writeCommand(0x20); d_writeCommand(0x20);
@ -62,6 +62,6 @@ void scanEInkDevice(void)
LOG_DEBUG("EInk display found"); LOG_DEBUG("EInk display found");
else else
LOG_DEBUG("EInk display not found"); LOG_DEBUG("EInk display not found");
SPI.end(); SPI1.end();
} }
#endif #endif

View File

@ -48,8 +48,6 @@ HardwareSerial *GPS::_serial_gps = nullptr;
GPS *gps = nullptr; GPS *gps = nullptr;
static const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
static GPSUpdateScheduling scheduling; static GPSUpdateScheduling scheduling;
/// Multiple GPS instances might use the same serial port (in sequence), but we can /// Multiple GPS instances might use the same serial port (in sequence), but we can
@ -1039,14 +1037,6 @@ int32_t GPS::runOnce()
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) { if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
return disable(); return disable();
} }
// ONCE we will factory reset the GPS for bug #327
if (!devicestate.did_gps_reset) {
LOG_WARN("GPS FactoryReset requested");
if (gps->factoryReset()) { // If we don't succeed try again next time
devicestate.did_gps_reset = true;
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
}
}
GPSInitFinished = true; GPSInitFinished = true;
publishUpdate(); publishUpdate();
} }
@ -1059,24 +1049,6 @@ int32_t GPS::runOnce()
if (whileActive()) { if (whileActive()) {
// if we have received valid NMEA claim we are connected // if we have received valid NMEA claim we are connected
setConnected(); setConnected();
} else {
if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) &&
IS_ONE_OF(gnssModel, GNSS_MODEL_UBLOX6, GNSS_MODEL_UBLOX7, GNSS_MODEL_UBLOX8, GNSS_MODEL_UBLOX9,
GNSS_MODEL_UBLOX10)) {
// reset the GPS on next bootup
if (devicestate.did_gps_reset && scheduling.elapsedSearchMs() > 60 * 1000UL && !hasFlow()) {
LOG_DEBUG("GPS is not found, try factory reset on next boot");
devicestate.did_gps_reset = false;
nodeDB->saveToDisk(SEGMENT_DEVICESTATE);
return disable(); // Stop the GPS thread as it can do nothing useful until next reboot.
}
}
}
// At least one GPS has a bad habit of losing its mind from time to time
if (rebootsSeen > 2) {
rebootsSeen = 0;
LOG_DEBUG("Would normally factoryReset()");
// gps->factoryReset();
} }
// If we're due for an update, wake the GPS // If we're due for an update, wake the GPS
@ -1411,62 +1383,6 @@ static int32_t toDegInt(RawDegrees d)
return r; return r;
} }
bool GPS::factoryReset()
{
#ifdef PIN_GPS_REINIT
// The L76K GNSS on the T-Echo requires the RESET pin to be pulled LOW
pinMode(PIN_GPS_REINIT, OUTPUT);
digitalWrite(PIN_GPS_REINIT, 0);
delay(150); // The L76K datasheet calls for at least 100MS delay
digitalWrite(PIN_GPS_REINIT, 1);
#endif
if (HW_VENDOR == meshtastic_HardwareModel_TBEAM) {
byte _message_reset1[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1C, 0xA2};
_serial_gps->write(_message_reset1, sizeof(_message_reset1));
if (getACK(0x05, 0x01, 10000)) {
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
delay(100);
byte _message_reset2[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xA1};
_serial_gps->write(_message_reset2, sizeof(_message_reset2));
if (getACK(0x05, 0x01, 10000)) {
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
delay(100);
byte _message_reset3[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0x1D, 0xB3};
_serial_gps->write(_message_reset3, sizeof(_message_reset3));
if (getACK(0x05, 0x01, 10000)) {
LOG_DEBUG(ACK_SUCCESS_MESSAGE);
}
} else if (gnssModel == GNSS_MODEL_MTK) {
// send the CAS10 to perform a factory restart of the device (and other device that support PCAS statements)
LOG_INFO("GNSS Factory Reset via PCAS10,3");
_serial_gps->write("$PCAS10,3*1F\r\n");
delay(100);
} else if (gnssModel == GNSS_MODEL_ATGM336H) {
LOG_INFO("Factory Reset via CAS-CFG-RST");
uint8_t msglen = makeCASPacket(0x06, 0x02, sizeof(_message_CAS_CFG_RST_FACTORY), _message_CAS_CFG_RST_FACTORY);
_serial_gps->write(UBXscratch, msglen);
delay(100);
} else {
// fire this for good measure, if we have an L76B - won't harm other devices.
_serial_gps->write("$PMTK104*37\r\n");
// No PMTK_ACK for this command.
delay(100);
// send the UBLOX Factory Reset Command regardless of detect state, something is very wrong, just assume it's
// UBLOX. Factory Reset
byte _message_reset[] = {0xB5, 0x62, 0x06, 0x09, 0x0D, 0x00, 0xFF, 0xFB, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x17, 0x2B, 0x7E};
_serial_gps->write(_message_reset, sizeof(_message_reset));
}
delay(1000);
return true;
}
/** /**
* Perform any processing that should be done only while the GPS is awake and looking for a fix. * Perform any processing that should be done only while the GPS is awake and looking for a fix.
* Override this method to check for new locations * Override this method to check for new locations

View File

@ -101,8 +101,6 @@ class GPS : private concurrency::OSThread
// Empty the input buffer as quickly as possible // Empty the input buffer as quickly as possible
void clearBuffer(); void clearBuffer();
virtual bool factoryReset();
// Creates an instance of the GPS class. // Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present. // Returns the new instance or null if the GPS is not present.
static GPS *createGps(); static GPS *createGps();

View File

@ -931,6 +931,7 @@ void setup()
if (!sxIf->init()) { if (!sxIf->init()) {
LOG_WARN("No SX1262 radio"); LOG_WARN("No SX1262 radio");
delete sxIf; delete sxIf;
rIf = NULL;
} else { } else {
LOG_INFO("SX1262 init success"); LOG_INFO("SX1262 init success");
rIf = sxIf; rIf = sxIf;
@ -947,6 +948,7 @@ void setup()
if (!sxIf->init()) { if (!sxIf->init()) {
LOG_WARN("No SX1262 radio with TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE); LOG_WARN("No SX1262 radio with TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE);
delete sxIf; delete sxIf;
rIf = NULL;
} else { } else {
LOG_INFO("SX1262 init success, TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE); LOG_INFO("SX1262 init success, TCXO, Vref %fV", SX126X_DIO3_TCXO_VOLTAGE);
rIf = sxIf; rIf = sxIf;

View File

@ -643,6 +643,11 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
meshtastic_QueueStatus qs = router->getQueueStatus(); meshtastic_QueueStatus qs = router->getQueueStatus();
service->sendQueueStatusToPhone(qs, 0, p.id); service->sendQueueStatusToPhone(qs, 0, p.id);
return false; return false;
} else if (p.decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP && isBroadcast(p.to) && p.hop_limit > 0) {
sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "Multi-hop traceroute to broadcast address is not allowed");
meshtastic_QueueStatus qs = router->getQueueStatus();
service->sendQueueStatusToPhone(qs, 0, p.id);
return false;
} else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] && } else if (p.decoded.portnum == meshtastic_PortNum_POSITION_APP && lastPortNumToRadio[p.decoded.portnum] &&
Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) { Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], FIVE_SECONDS_MS)) {
LOG_WARN("Rate limit portnum %d", p.decoded.portnum); LOG_WARN("Rate limit portnum %d", p.decoded.portnum);

View File

@ -31,7 +31,6 @@ int32_t PowerTelemetryModule::runOnce()
doDeepSleep(nightyNightMs, true, false); doDeepSleep(nightyNightMs, true, false);
} }
uint32_t result = UINT32_MAX;
/* /*
Uncomment the preferences below if you want to use the module Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI. without having to configure it from the PythonAPI or WebUI.
@ -46,25 +45,33 @@ int32_t PowerTelemetryModule::runOnce()
return disable(); return disable();
} }
uint32_t sendToMeshIntervalMs = Default::getConfiguredOrDefaultMsScaled(
moduleConfig.telemetry.power_update_interval, default_telemetry_broadcast_interval_secs, numOnlineNodes);
if (firstTime) { if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup // This is the first time the OSThread library has called this function, so do some setup
firstTime = 0; firstTime = 0;
uint32_t result = UINT32_MAX;
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) #if HAS_TELEMETRY && !defined(ARCH_PORTDUINO)
if (moduleConfig.telemetry.power_measurement_enabled) { if (moduleConfig.telemetry.power_measurement_enabled) {
LOG_INFO("Power Telemetry: init"); LOG_INFO("Power Telemetry: init");
// If sensor is already initialized by EnvironmentTelemetryModule, then we don't need to initialize it again,
// but we need to set the result to != UINT32_MAX to avoid it being disabled
if (ina219Sensor.hasSensor())
result = ina219Sensor.isInitialized() ? 0 : ina219Sensor.runOnce();
if (ina226Sensor.hasSensor())
result = ina226Sensor.isInitialized() ? 0 : ina226Sensor.runOnce();
if (ina260Sensor.hasSensor())
result = ina260Sensor.isInitialized() ? 0 : ina260Sensor.runOnce();
if (ina3221Sensor.hasSensor())
result = ina3221Sensor.isInitialized() ? 0 : ina3221Sensor.runOnce();
if (max17048Sensor.hasSensor())
result = max17048Sensor.isInitialized() ? 0 : max17048Sensor.runOnce();
}
// it's possible to have this module enabled, only for displaying values on the screen. // it's possible to have this module enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled // therefore, we should only enable the sensor loop if measurement is also enabled
if (ina219Sensor.hasSensor() && !ina219Sensor.isInitialized())
result = ina219Sensor.runOnce();
if (ina226Sensor.hasSensor() && !ina226Sensor.isInitialized())
result = ina226Sensor.runOnce();
if (ina260Sensor.hasSensor() && !ina260Sensor.isInitialized())
result = ina260Sensor.runOnce();
if (ina3221Sensor.hasSensor() && !ina3221Sensor.isInitialized())
result = ina3221Sensor.runOnce();
if (max17048Sensor.hasSensor() && !max17048Sensor.isInitialized())
result = max17048Sensor.runOnce();
}
return result == UINT32_MAX ? disable() : setStartDelay(); return result == UINT32_MAX ? disable() : setStartDelay();
#else #else
return disable(); return disable();
@ -74,10 +81,7 @@ int32_t PowerTelemetryModule::runOnce()
if (!moduleConfig.telemetry.power_measurement_enabled) if (!moduleConfig.telemetry.power_measurement_enabled)
return disable(); return disable();
if (((lastSentToMesh == 0) || if (((lastSentToMesh == 0) || !Throttle::isWithinTimespanMs(lastSentToMesh, sendToMeshIntervalMs)) &&
!Throttle::isWithinTimespanMs(lastSentToMesh, Default::getConfiguredOrDefaultMsScaled(
moduleConfig.telemetry.power_update_interval,
default_telemetry_broadcast_interval_secs, numOnlineNodes))) &&
airTime->isTxAllowedAirUtil()) { airTime->isTxAllowedAirUtil()) {
sendTelemetry(); sendTelemetry();
lastSentToMesh = millis(); lastSentToMesh = millis();
@ -89,8 +93,9 @@ int32_t PowerTelemetryModule::runOnce()
lastSentToPhone = millis(); lastSentToPhone = millis();
} }
} }
return min(sendToPhoneIntervalMs, result); return min(sendToPhoneIntervalMs, sendToMeshIntervalMs);
} }
bool PowerTelemetryModule::wantUIFrame() bool PowerTelemetryModule::wantUIFrame()
{ {
return moduleConfig.telemetry.power_screen_enabled; return moduleConfig.telemetry.power_screen_enabled;

View File

@ -150,6 +150,12 @@ meshtastic_MeshPacket *TraceRouteModule::allocReply()
{ {
assert(currentRequest); assert(currentRequest);
// Ignore multi-hop broadcast requests
if (isBroadcast(currentRequest->to) && currentRequest->hop_limit < currentRequest->hop_start) {
ignoreRequest = true;
return NULL;
}
// Copy the payload of the current request // Copy the payload of the current request
auto req = *currentRequest; auto req = *currentRequest;
const auto &p = req.decoded; const auto &p = req.decoded;

View File

@ -107,11 +107,15 @@ static const uint8_t AREF = PIN_AREF;
/* /*
* SPI Interfaces * SPI Interfaces
*/ */
#define SPI_INTERFACES_COUNT 1 #define SPI_INTERFACES_COUNT 2
#define PIN_SPI_MISO (29) #define PIN_SPI_MISO (45)
#define PIN_SPI_MOSI (30) #define PIN_SPI_MOSI (44)
#define PIN_SPI_SCK (3) #define PIN_SPI_SCK (43)
#define PIN_SPI1_MISO (29) // (0 + 29)
#define PIN_SPI1_MOSI (30) // (0 + 30)
#define PIN_SPI1_SCK (3) // (0 + 3)
static const uint8_t SS = 42; static const uint8_t SS = 42;
static const uint8_t MOSI = PIN_SPI_MOSI; static const uint8_t MOSI = PIN_SPI_MOSI;
@ -126,8 +130,8 @@ static const uint8_t SCK = PIN_SPI_SCK;
#define PIN_EINK_BUSY (0 + 4) #define PIN_EINK_BUSY (0 + 4)
#define PIN_EINK_DC (0 + 17) #define PIN_EINK_DC (0 + 17)
#define PIN_EINK_RES (-1) #define PIN_EINK_RES (-1)
#define PIN_EINK_SCLK PIN_SPI_SCK #define PIN_EINK_SCLK (0 + 3)
#define PIN_EINK_MOSI PIN_SPI_MOSI // also called SDI #define PIN_EINK_MOSI (0 + 30) // also called SDI
// #define USE_EINK // #define USE_EINK
@ -255,7 +259,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#define PIN_ETHERNET_RESET 21 #define PIN_ETHERNET_RESET 21
#define PIN_ETHERNET_SS PIN_EINK_CS #define PIN_ETHERNET_SS PIN_EINK_CS
#define ETH_SPI_PORT SPI #define ETH_SPI_PORT SPI1
#define AQ_SET_PIN 10 #define AQ_SET_PIN 10
#ifdef __cplusplus #ifdef __cplusplus