Merge branch 'master' into tft-gui-work

This commit is contained in:
Manuel 2024-07-04 12:50:02 +02:00 committed by GitHub
commit 1670205903
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 410 additions and 93 deletions

View File

@ -0,0 +1,12 @@
# shellcheck shell=bash
# (this minor script is actually shell agnostic, and is intended to be sourced rather than run in a subshell)
# This is a little script you can source if you want to make ESP debugging work on a modern (24.04) ubuntu machine
# It assumes you have built and installed python 2.7 from source with:
# ./configure --enable-optimizations --enable-shared --enable-unicode=ucs4
# sudo make clean
# make
# sudo make altinstall
export LD_LIBRARY_PATH=$HOME/packages/python-2.7.18/
export PYTHON_HOME=/usr/local/lib/python2.7/

View File

@ -27,7 +27,7 @@
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd"
},
"frameworks": ["arduino"],
"frameworks": ["arduino", "freertos"],
"name": "Seeed WIO WM1110",
"upload": {
"maximum_ram_size": 248832,

View File

@ -11,5 +11,7 @@ const uint8_t FROMRADIO_UUID_16[16u] = {0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78
0xed, 0x11, 0x93, 0x49, 0x9e, 0xe6, 0x55, 0x2c};
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};
const uint8_t LOGRADIO_UUID_16[16u] = {0xe2, 0xf2, 0x1e, 0xbe, 0xc5, 0x15, 0xcf, 0xaa,
0x6b, 0x43, 0xfa, 0x78, 0x38, 0xd2, 0x6f, 0x6c};
const uint8_t LEGACY_LOGRADIO_UUID_16[16u] = {0xe2, 0xf2, 0x1e, 0xbe, 0xc5, 0x15, 0xcf, 0xaa,
0x6b, 0x43, 0xfa, 0x78, 0x38, 0xd2, 0x6f, 0x6c};
const uint8_t LOGRADIO_UUID_16[16u] = {0x47, 0x95, 0xDF, 0x8C, 0xDE, 0xE9, 0x44, 0x99,
0x23, 0x44, 0xE6, 0x06, 0x49, 0x6E, 0x3D, 0x5A};

View File

@ -11,7 +11,8 @@
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
#define FROMRADIO_UUID "2c55e69e-4993-11ed-b878-0242ac120002"
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
#define LOGRADIO_UUID "6c6fd238-78fa-436b-aacf-15c5be1ef2e2"
#define LEGACY_LOGRADIO_UUID "6c6fd238-78fa-436b-aacf-15c5be1ef2e2"
#define LOGRADIO_UUID "5a3d6e49-06e6-4423-9944-e9de8cdf9547"
// NRF52 wants these constants as byte arrays
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
@ -28,5 +29,4 @@ class BluetoothApi
virtual void clearBonds();
virtual bool isConnected();
virtual int getRssi() = 0;
virtual void sendLog(const char *logMessage);
};

View File

@ -26,7 +26,7 @@ SOFTWARE.*/
#include "DebugConfiguration.h"
#if HAS_WIFI || HAS_ETHERNET
#if HAS_NETWORKING
Syslog::Syslog(UDP &client)
{

View File

@ -1,5 +1,6 @@
#ifndef SYSLOG_H
#define SYSLOG_H
#pragma once
#include "configuration.h"
// DEBUG LED
#ifndef LED_INVERTED
@ -125,7 +126,7 @@
#include <WiFi.h>
#endif // HAS_WIFI
#if HAS_WIFI || HAS_ETHERNET
#if HAS_NETWORKING
class Syslog
{
@ -160,6 +161,4 @@ class Syslog
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
};
#endif // HAS_ETHERNET || HAS_WIFI
#endif // SYSLOG_H
#endif // HAS_ETHERNET || HAS_WIFI

View File

@ -27,7 +27,7 @@
#if defined(DEBUG_HEAP_MQTT) && !MESHTASTIC_EXCLUDE_MQTT
#include "mqtt/MQTT.h"
#include "target_specific.h"
#if !MESTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include <WiFi.h>
#endif
#endif

View File

@ -11,6 +11,7 @@
#include "Default.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "configuration.h"
#include "graphics/Screen.h"
#include "main.h"
@ -49,6 +50,7 @@ static bool isPowered()
static void sdsEnter()
{
LOG_DEBUG("Enter state: SDS\n");
powerMon->setState(meshtastic_PowerMon_State_CPU_DeepSleep);
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
doDeepSleep(Default::getConfiguredOrDefaultMs(config.power.sds_secs), false);
}
@ -68,6 +70,7 @@ static uint32_t secsSlept;
static void lsEnter()
{
LOG_INFO("lsEnter begin, ls_secs=%u\n", config.power.ls_secs);
powerMon->clearState(meshtastic_PowerMon_State_Screen_On);
screen->setOn(false);
secsSlept = 0; // How long have we been sleeping this time
@ -87,8 +90,10 @@ static void lsIdle()
// Briefly come out of sleep long enough to blink the led once every few seconds
uint32_t sleepTime = SLEEP_TIME;
powerMon->setState(meshtastic_PowerMon_State_CPU_LightSleep);
setLed(false); // Never leave led on while in light sleep
esp_sleep_source_t wakeCause2 = doLightSleep(sleepTime * 1000LL);
powerMon->clearState(meshtastic_PowerMon_State_CPU_LightSleep);
switch (wakeCause2) {
case ESP_SLEEP_WAKEUP_TIMER:
@ -144,6 +149,7 @@ static void lsExit()
static void nbEnter()
{
LOG_DEBUG("Enter state: NB\n");
powerMon->clearState(meshtastic_PowerMon_State_BT_On);
screen->setOn(false);
#ifdef ARCH_ESP32
// Only ESP32 should turn off bluetooth
@ -155,6 +161,8 @@ static void nbEnter()
static void darkEnter()
{
powerMon->clearState(meshtastic_PowerMon_State_BT_On);
powerMon->clearState(meshtastic_PowerMon_State_Screen_On);
setBluetoothEnable(true);
screen->setOn(false);
}
@ -162,6 +170,8 @@ static void darkEnter()
static void serialEnter()
{
LOG_DEBUG("Enter state: SERIAL\n");
powerMon->clearState(meshtastic_PowerMon_State_BT_On);
powerMon->setState(meshtastic_PowerMon_State_Screen_On);
setBluetoothEnable(false);
screen->setOn(true);
screen->print("Serial connected\n");
@ -170,6 +180,7 @@ static void serialEnter()
static void serialExit()
{
// Turn bluetooth back on when we leave serial stream API
powerMon->setState(meshtastic_PowerMon_State_BT_On);
setBluetoothEnable(true);
screen->print("Serial disconnected\n");
}
@ -182,6 +193,8 @@ static void powerEnter()
LOG_INFO("Loss of power in Powered\n");
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
} else {
powerMon->setState(meshtastic_PowerMon_State_BT_On);
powerMon->setState(meshtastic_PowerMon_State_Screen_On);
screen->setOn(true);
setBluetoothEnable(true);
// within enter() the function getState() returns the state we came from
@ -205,6 +218,8 @@ static void powerIdle()
static void powerExit()
{
powerMon->setState(meshtastic_PowerMon_State_BT_On);
powerMon->setState(meshtastic_PowerMon_State_Screen_On);
screen->setOn(true);
setBluetoothEnable(true);
@ -216,6 +231,8 @@ static void powerExit()
static void onEnter()
{
LOG_DEBUG("Enter state: ON\n");
powerMon->setState(meshtastic_PowerMon_State_BT_On);
powerMon->setState(meshtastic_PowerMon_State_Screen_On);
screen->setOn(true);
setBluetoothEnable(true);
}

45
src/PowerMon.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "PowerMon.h"
#include "NodeDB.h"
// Use the 'live' config flag to figure out if we should be showing this message
static bool is_power_enabled(uint64_t m)
{
return (m & config.power.powermon_enables) ? true : false;
}
void PowerMon::setState(_meshtastic_PowerMon_State state, const char *reason)
{
#ifdef USE_POWERMON
auto oldstates = states;
states |= state;
if (oldstates != states && is_power_enabled(state)) {
emitLog(reason);
}
#endif
}
void PowerMon::clearState(_meshtastic_PowerMon_State state, const char *reason)
{
#ifdef USE_POWERMON
auto oldstates = states;
states &= ~state;
if (oldstates != states && is_power_enabled(state)) {
emitLog(reason);
}
#endif
}
void PowerMon::emitLog(const char *reason)
{
#ifdef USE_POWERMON
// The nrf52 printf doesn't understand 64 bit ints, so if we ever reach that point this function will need to change.
LOG_INFO("S:PM:0x%08lx,%s\n", (uint32_t)states, reason);
#endif
}
PowerMon *powerMon;
void powerMonInit()
{
powerMon = new PowerMon();
}

34
src/PowerMon.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include "configuration.h"
#include "meshtastic/powermon.pb.h"
#ifndef MESHTASTIC_EXCLUDE_POWERMON
#define USE_POWERMON // FIXME turn this only for certain builds
#endif
/**
* The singleton class for monitoring power consumption of device
* subsystems/modes.
*
* For more information see the PowerMon docs.
*/
class PowerMon
{
uint64_t states = 0UL;
public:
PowerMon() {}
// Mark entry/exit of a power consuming state
void setState(_meshtastic_PowerMon_State state, const char *reason = "");
void clearState(_meshtastic_PowerMon_State state, const char *reason = "");
private:
// Emit the coded log message
void emitLog(const char *reason);
};
extern PowerMon *powerMon;
void powerMonInit();

View File

@ -4,6 +4,7 @@
#include "concurrency/OSThread.h"
#include "configuration.h"
#include "main.h"
#include "mesh/generated/meshtastic/mesh.pb.h"
#include <assert.h>
#include <cstring>
#include <memory>
@ -15,7 +16,7 @@
#include "platform/portduino/PortduinoGlue.h"
#endif
#if HAS_WIFI || HAS_ETHERNET
#if HAS_NETWORKING
extern Syslog syslog;
#endif
void RedirectablePrint::rpInit()
@ -137,7 +138,7 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
void RedirectablePrint::log_to_syslog(const char *logLevel, const char *format, va_list arg)
{
#if (HAS_WIFI || HAS_ETHERNET) && !defined(ARCH_PORTDUINO)
#if HAS_NETWORKING && !defined(ARCH_PORTDUINO)
// if syslog is in use, collect the log messages and send them to syslog
if (syslog.isEnabled()) {
int ll = 0;
@ -192,22 +193,49 @@ void RedirectablePrint::log_to_ble(const char *logLevel, const char *format, va_
vsnprintf(message, len + 1, format, arg);
}
auto thread = concurrency::OSThread::currentThread;
meshtastic_LogRecord logRecord = meshtastic_LogRecord_init_zero;
logRecord.level = getLogLevel(logLevel);
strcpy(logRecord.message, message);
if (thread)
strcpy(logRecord.source, thread->ThreadName.c_str());
logRecord.time = getValidTime(RTCQuality::RTCQualityDevice, true);
uint8_t *buffer = new uint8_t[meshtastic_LogRecord_size];
size_t size = pb_encode_to_bytes(buffer, meshtastic_LogRecord_size, meshtastic_LogRecord_fields, &logRecord);
#ifdef ARCH_ESP32
if (thread)
nimbleBluetooth->sendLog(mt_sprintf("%s | [%s] %s", logLevel, thread->ThreadName.c_str(), message).c_str());
else
nimbleBluetooth->sendLog(mt_sprintf("%s | %s", logLevel, message).c_str());
nimbleBluetooth->sendLog(buffer, size);
#elif defined(ARCH_NRF52)
if (thread)
nrf52Bluetooth->sendLog(mt_sprintf("%s | [%s] %s", logLevel, thread->ThreadName.c_str(), message).c_str());
else
nrf52Bluetooth->sendLog(mt_sprintf("%s | %s", logLevel, message).c_str());
nrf52Bluetooth->sendLog(reinterpret_cast<const char *>(buffer));
#endif
delete[] message;
delete[] buffer;
}
}
}
meshtastic_LogRecord_Level RedirectablePrint::getLogLevel(const char *logLevel)
{
meshtastic_LogRecord_Level ll = meshtastic_LogRecord_Level_UNSET; // default to unset
switch (logLevel[0]) {
case 'D':
ll = meshtastic_LogRecord_Level_DEBUG;
break;
case 'I':
ll = meshtastic_LogRecord_Level_INFO;
break;
case 'W':
ll = meshtastic_LogRecord_Level_WARNING;
break;
case 'E':
ll = meshtastic_LogRecord_Level_ERROR;
break;
case 'C':
ll = meshtastic_LogRecord_Level_CRITICAL;
break;
}
return ll;
}
void RedirectablePrint::log(const char *logLevel, const char *format, ...)
{
#ifdef ARCH_PORTDUINO

View File

@ -1,6 +1,7 @@
#pragma once
#include "../freertosinc.h"
#include "mesh/generated/meshtastic/mesh.pb.h"
#include <Print.h>
#include <stdarg.h>
#include <string>
@ -57,4 +58,5 @@ class RedirectablePrint : public Print
private:
void log_to_syslog(const char *logLevel, const char *format, va_list arg);
void log_to_ble(const char *logLevel, const char *format, va_list arg);
meshtastic_LogRecord_Level getLogLevel(const char *logLevel);
};

View File

@ -245,9 +245,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define HAS_BLUETOOTH 0
#endif
#include "DebugConfiguration.h"
#include "RF95Configuration.h"
#ifndef HW_VENDOR
#error HW_VENDOR must be defined
#endif
@ -264,6 +261,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MESHTASTIC_EXCLUDE_GPS 1
#define MESHTASTIC_EXCLUDE_SCREEN 1
#define MESHTASTIC_EXCLUDE_MQTT 1
#define MESHTASTIC_EXCLUDE_POWERMON 1
#endif
// Turn off all optional modules
@ -284,6 +282,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MESHTASTIC_EXCLUDE_WAYPOINT 1
#define MESHTASTIC_EXCLUDE_INPUTBROKER 1
#define MESHTASTIC_EXCLUDE_SERIAL 1
#define MESHTASTIC_EXCLUDE_POWERSTRESS 1
#endif
// // Turn off wifi even if HW supports wifi (webserver relies on wifi and is also disabled)
@ -293,6 +292,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define HAS_WIFI 0
#endif
// Allow code that needs internet to just check HAS_NETWORKING rather than HAS_WIFI || HAS_ETHERNET
#define HAS_NETWORKING (HAS_WIFI || HAS_ETHERNET)
// // Turn off Bluetooth
#ifdef MESHTASTIC_EXCLUDE_BLUETOOTH
#undef HAS_BLUETOOTH
@ -311,4 +313,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef MESHTASTIC_EXCLUDE_SCREEN
#undef HAS_SCREEN
#define HAS_SCREEN 0
#endif
#endif
#include "DebugConfiguration.h"
#include "RF95Configuration.h"

View File

@ -3,6 +3,7 @@
#include "Default.h"
#include "GPS.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "RTC.h"
#include "main.h" // pmu_found
@ -815,9 +816,12 @@ void GPS::setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime)
return;
if (on) {
powerMon->setState(meshtastic_PowerMon_State_GPS_Active);
clearBuffer(); // drop any old data waiting in the buffer before re-enabling
if (en_gpio)
digitalWrite(en_gpio, on ? GPS_EN_ACTIVE : !GPS_EN_ACTIVE); // turn this on if defined, every time
} else {
powerMon->clearState(meshtastic_PowerMon_State_GPS_Active);
}
isInPowersave = !on;
if (!standbyOnly && en_gpio != 0 &&

View File

@ -6,6 +6,7 @@
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "PowerMon.h"
#include "ReliableRouter.h"
#include "airtime.h"
#include "buzz.h"
@ -229,6 +230,14 @@ __attribute__((weak, noinline)) bool loopCanSleep()
return true;
}
/**
* Print info as a structured log message (for automated log processing)
*/
void printInfo()
{
LOG_INFO("S:B:%d,%s\n", HW_VENDOR, optstr(APP_VERSION));
}
void setup()
{
concurrency::hasBeenSetup = true;
@ -249,10 +258,13 @@ void setup()
#ifdef DEBUG_PORT
consoleInit(); // Set serial baud rate and init our mesh console
#endif
#ifdef UNPHONE
unphone.printStore();
#endif
powerMonInit();
serialSinceMsec = millis();
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n\n");
@ -570,7 +582,7 @@ void setup()
#endif
// Hello
LOG_INFO("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
printInfo();
#ifdef ARCH_ESP32
esp32Setup();

View File

@ -184,6 +184,7 @@ template <typename T> void LR11x0Interface<T>::setStandby()
activeReceiveStart = 0;
disableInterrupt();
completeSending(); // If we were sending, not anymore
RadioLibInterface::setStandby();
}
/**
@ -223,7 +224,7 @@ template <typename T> void LR11x0Interface<T>::startReceive()
0); // only RX_DONE IRQ is needed, we'll check for PREAMBLE_DETECTED and HEADER_VALID in isActivelyReceiving
assert(err == RADIOLIB_ERR_NONE);
isReceiving = true;
RadioLibInterface::startReceive();
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);

View File

@ -26,7 +26,7 @@
#include <vector>
#ifdef ARCH_ESP32
#if !MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
#include "modules/esp32/StoreForwardModule.h"

View File

@ -25,7 +25,8 @@ typedef struct {
} DACDB;
// Interpolation function
DACDB interpolate(uint8_t dbm, uint8_t dbm1, uint8_t dbm2, DACDB val1, DACDB val2) {
DACDB interpolate(uint8_t dbm, uint8_t dbm1, uint8_t dbm2, DACDB val1, DACDB val2)
{
DACDB result;
double fraction = (double)(dbm - dbm1) / (dbm2 - dbm1);
result.dac = (uint8_t)(val1.dac + fraction * (val2.dac - val1.dac));
@ -34,16 +35,17 @@ DACDB interpolate(uint8_t dbm, uint8_t dbm1, uint8_t dbm2, DACDB val1, DACDB val
}
// Function to find the correct DAC and DB values based on dBm using interpolation
DACDB getDACandDB(uint8_t dbm) {
DACDB getDACandDB(uint8_t dbm)
{
// Predefined values
static const struct {
uint8_t dbm;
DACDB values;
} dbmToDACDB[] = {
{20, {168, 2}}, // 100mW
{24, {148, 6}}, // 250mW
{27, {128, 9}}, // 500mW
{30, {90, 12}} // 1000mW
{20, {168, 2}}, // 100mW
{24, {148, 6}}, // 250mW
{27, {128, 9}}, // 500mW
{30, {90, 12}} // 1000mW
};
const int numValues = sizeof(dbmToDACDB) / sizeof(dbmToDACDB[0]);
@ -103,7 +105,7 @@ bool RF95Interface::init()
if (power > RF95_MAX_POWER) // This chip has lower power limits than some
power = RF95_MAX_POWER;
limitPower();
iface = lora = new RadioLibRF95(&module);
@ -116,13 +118,13 @@ bool RF95Interface::init()
// enable PA
#ifdef RF95_PA_EN
#if defined(RF95_PA_DAC_EN)
#ifdef RADIOMASTER_900_BANDIT_NANO
// Use calculated DAC value
dacWrite(RF95_PA_EN, powerDAC);
#else
// Use Value set in /*/variant.h
dacWrite(RF95_PA_EN, RF95_PA_LEVEL);
#endif
#ifdef RADIOMASTER_900_BANDIT_NANO
// Use calculated DAC value
dacWrite(RF95_PA_EN, powerDAC);
#else
// Use Value set in /*/variant.h
dacWrite(RF95_PA_EN, RF95_PA_LEVEL);
#endif
#endif
#endif
@ -254,6 +256,7 @@ void RF95Interface::setStandby()
isReceiving = false; // If we were receiving, not any more
disableInterrupt();
completeSending(); // If we were sending, not anymore
RadioLibInterface::setStandby();
}
/** We override to turn on transmitter power as needed.

View File

@ -521,7 +521,7 @@ void RadioInterface::applyModemConfig()
LOG_INFO("Radio freq=%.3f, config.lora.frequency_offset=%.3f\n", freq, loraConfig.frequency_offset);
LOG_INFO("Set radio: region=%s, name=%s, config=%u, ch=%d, power=%d\n", myRegion->name, channelName, loraConfig.modem_preset,
channel_num, power);
LOG_INFO("Radio myRegion->freqStart -> myRegion->freqEnd: %f -> %f (%f mhz)\n", myRegion->freqStart, myRegion->freqEnd,
LOG_INFO("Radio myRegion->freqStart -> myRegion->freqEnd: %f -> %f (%f MHz)\n", myRegion->freqStart, myRegion->freqEnd,
myRegion->freqEnd - myRegion->freqStart);
LOG_INFO("Radio myRegion->numChannels: %d x %.3fkHz\n", numChannels, bw);
LOG_INFO("Radio channel_num: %d\n", channel_num + 1);

View File

@ -1,6 +1,7 @@
#include "RadioLibInterface.h"
#include "MeshTypes.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "SPILock.h"
#include "configuration.h"
#include "error.h"
@ -317,6 +318,7 @@ void RadioLibInterface::handleTransmitInterrupt()
// ignore the transmit interrupt
if (sendingPacket)
completeSending();
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // But our transmitter is deffinitely off now
}
void RadioLibInterface::completeSending()
@ -412,6 +414,24 @@ void RadioLibInterface::handleReceiveInterrupt()
}
}
void RadioLibInterface::startReceive()
{
isReceiving = true;
powerMon->setState(meshtastic_PowerMon_State_Lora_RXOn);
}
void RadioLibInterface::configHardwareForSend()
{
powerMon->setState(meshtastic_PowerMon_State_Lora_TXOn);
}
void RadioLibInterface::setStandby()
{
// neither sending nor receiving
powerMon->clearState(meshtastic_PowerMon_State_Lora_RXOn);
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn);
}
/** start an immediate transmit */
void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
{
@ -431,6 +451,7 @@ void RadioLibInterface::startSend(meshtastic_MeshPacket *txp)
// This send failed, but make sure to 'complete' it properly
completeSending();
powerMon->clearState(meshtastic_PowerMon_State_Lora_TXOn); // Transmitter off now
startReceive(); // Restart receive mode (because startTransmit failed to put us in xmit mode)
}

View File

@ -126,8 +126,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
* Start waiting to receive a message
*
* External functions can call this method to wake the device from sleep.
* Subclasses must override and call this base method
*/
virtual void startReceive() = 0;
virtual void startReceive();
/** can we detect a LoRa preamble on the current channel? */
virtual bool isChannelActive() = 0;
@ -166,8 +167,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
meshtastic_QueueStatus getQueueStatus();
protected:
/** Do any hardware setup needed on entry into send configuration for the radio. Subclasses can customize */
virtual void configHardwareForSend() {}
/** Do any hardware setup needed on entry into send configuration for the radio.
* Subclasses can customize, but must also call this base method */
virtual void configHardwareForSend();
/** Could we send right now (i.e. either not actively receiving or transmitting)? */
virtual bool canSendImmediately();
@ -186,5 +188,8 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified
*/
virtual void addReceiveMetadata(meshtastic_MeshPacket *mp) = 0;
virtual void setStandby() = 0;
/**
* Subclasses must override, implement and then call into this base class implementation
*/
virtual void setStandby();
};

View File

@ -244,8 +244,10 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
// If the packet hasn't yet been encrypted, do so now (it might already be encrypted if we are just forwarding it)
assert(p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag ||
p->which_payload_variant == meshtastic_MeshPacket_decoded_tag); // I _think_ all packets should have a payload by now
if (!(p->which_payload_variant == meshtastic_MeshPacket_encrypted_tag ||
p->which_payload_variant == meshtastic_MeshPacket_decoded_tag)) {
return meshtastic_Routing_Error_BAD_REQUEST;
}
// If the packet is not yet encrypted, do so now
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {

View File

@ -231,6 +231,7 @@ template <typename T> void SX126xInterface<T>::setStandby()
activeReceiveStart = 0;
disableInterrupt();
completeSending(); // If we were sending, not anymore
RadioLibInterface::setStandby();
}
/**
@ -270,7 +271,7 @@ template <typename T> void SX126xInterface<T>::startReceive()
LOG_ERROR("Radiolib error %d when attempting SX126X startReceiveDutyCycleAuto!\n", err);
assert(err == RADIOLIB_ERR_NONE);
isReceiving = true;
RadioLibInterface::startReceive();
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);

View File

@ -190,6 +190,7 @@ template <typename T> void SX128xInterface<T>::setStandby()
activeReceiveStart = 0;
disableInterrupt();
completeSending(); // If we were sending, not anymore
RadioLibInterface::setStandby();
}
/**
@ -263,7 +264,7 @@ template <typename T> void SX128xInterface<T>::startReceive()
LOG_ERROR("Radiolib error %d when attempting SX128X startReceive!\n", err);
assert(err == RADIOLIB_ERR_NONE);
isReceiving = true;
RadioLibInterface::startReceive();
// Must be done AFTER, starting transmit, because startTransmit clears (possibly stale) interrupt pending register bits
enableInterrupt(isrRxLevel0);

View File

@ -6,7 +6,7 @@
#include "main.h"
#include "mesh/http/ContentHelper.h"
#include "mesh/http/WebServer.h"
#if !MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
#include "mqtt/JSON.h"

View File

@ -1,5 +1,5 @@
#include "configuration.h"
#if !MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include "NodeDB.h"
#include "RTC.h"
#include "concurrency/Periodic.h"

View File

@ -1,6 +1,6 @@
#pragma once
#include "ProtobufModule.h"
#if HAS_WIFI && !MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif

View File

@ -27,6 +27,9 @@
#if !MESHTASTIC_EXCLUDE_REMOTEHARDWARE
#include "modules/RemoteHardwareModule.h"
#endif
#if !MESHTASTIC_EXCLUDE_POWERSTRESS
#include "modules/PowerStressModule.h"
#endif
#include "modules/RoutingModule.h"
#include "modules/TextMessageModule.h"
#if !MESHTASTIC_EXCLUDE_TRACEROUTE
@ -115,6 +118,9 @@ void setupModules()
#if !MESHTASTIC_EXCLUDE_REMOTEHARDWARE
new RemoteHardwareModule();
#endif
#if !MESHTASTIC_EXCLUDE_POWERSTRESS
new PowerStressModule();
#endif
// Example: Put your module here
// new ReplyModule();

View File

@ -0,0 +1,77 @@
#include "PowerStressModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "main.h"
extern void printInfo();
PowerStressModule::PowerStressModule()
: ProtobufModule("powerstress", meshtastic_PortNum_POWERSTRESS_APP, &meshtastic_PowerStressMessage_msg),
concurrency::OSThread("PowerStressModule")
{
}
bool PowerStressModule::handleReceivedProtobuf(const meshtastic_MeshPacket &req, meshtastic_PowerStressMessage *pptr)
{
// We only respond to messages if powermon debugging is already on
if (config.power.powermon_enables) {
auto p = *pptr;
LOG_INFO("Received PowerStress cmd=%d\n", p.cmd);
// Some commands we can handle immediately, anything else gets deferred to be handled by our thread
switch (p.cmd) {
case meshtastic_PowerStressMessage_Opcode_UNSET:
LOG_ERROR("PowerStress operation unset\n");
break;
case meshtastic_PowerStressMessage_Opcode_PRINT_INFO:
printInfo();
break;
default:
if (currentMessage.cmd != meshtastic_PowerStressMessage_Opcode_UNSET)
LOG_ERROR("PowerStress operation %d already in progress! Can't start new command\n", currentMessage.cmd);
else
currentMessage = p; // copy for use by thread (the message provided to us will be getting freed)
break;
}
}
return true;
}
int32_t PowerStressModule::runOnce()
{
if (!config.power.powermon_enables) {
// Powermon not enabled - stop using CPU/stop this thread
return disable();
}
int32_t sleep_msec = 10; // when not active check for new messages every 10ms
auto &p = currentMessage;
if (isRunningCommand) {
// Done with the previous command - our sleep must have finished
p.cmd = meshtastic_PowerStressMessage_Opcode_UNSET;
p.num_seconds = 0;
} else {
sleep_msec = (int32_t)(p.num_seconds * 1000);
isRunningCommand = !!sleep_msec; // if the command wants us to sleep, make sure to mark that we have something running
switch (p.cmd) {
case meshtastic_PowerStressMessage_Opcode_UNSET: // No need to start a new command
break;
case meshtastic_PowerStressMessage_Opcode_LED_ON:
break;
default:
LOG_ERROR("PowerStress operation %d not yet implemented!\n", p.cmd);
sleep_msec = 0; // Don't do whatever sleep was requested...
break;
}
}
return sleep_msec;
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "ProtobufModule.h"
#include "concurrency/OSThread.h"
#include "mesh/generated/meshtastic/powermon.pb.h"
/**
* A module that provides easy low-level remote access to device hardware.
*/
class PowerStressModule : public ProtobufModule<meshtastic_PowerStressMessage>, private concurrency::OSThread
{
meshtastic_PowerStressMessage currentMessage = meshtastic_PowerStressMessage_init_default;
bool isRunningCommand = false;
public:
/** Constructor
* name is for debugging output
*/
PowerStressModule();
protected:
/** Called to handle a particular incoming message
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it
*/
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_PowerStressMessage *p) override;
/**
* Periodically read the gpios we have been asked to WATCH, if they have changed,
* broadcast a message with the change information.
*
* The method that will be called each time our thread gets a chance to run
*
* Returns desired period for next invocation (or RUN_SAME for no change)
*/
virtual int32_t runOnce() override;
};
extern PowerStressModule powerStressModule;

View File

@ -14,7 +14,7 @@
#endif
#include "mesh/generated/meshtastic/remote_hardware.pb.h"
#include "sleep.h"
#if HAS_WIFI && !MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#include <WiFi.h>
#endif
@ -175,7 +175,7 @@ void mqttInit()
new MQTT();
}
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
MQTT::MQTT() : concurrency::OSThread("mqtt"), pubSub(mqttClient), mqttQueue(MAX_MQTT_QUEUE)
#else
MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
@ -206,7 +206,7 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
moduleConfig.mqtt.map_report_settings.publish_interval_secs, default_map_publish_interval_secs);
}
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
if (!moduleConfig.mqtt.proxy_to_client_enabled)
pubSub.setCallback(mqttCallback);
#endif
@ -226,7 +226,7 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
bool MQTT::isConnectedDirectly()
{
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
return pubSub.connected();
#else
return false;
@ -244,7 +244,7 @@ bool MQTT::publish(const char *topic, const char *payload, bool retained)
service.sendMqttMessageToClientProxy(msg);
return true;
}
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
else if (isConnectedDirectly()) {
return pubSub.publish(topic, payload, retained);
}
@ -264,7 +264,7 @@ bool MQTT::publish(const char *topic, const uint8_t *payload, size_t length, boo
service.sendMqttMessageToClientProxy(msg);
return true;
}
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
else if (isConnectedDirectly()) {
return pubSub.publish(topic, payload, length, retained);
}
@ -284,7 +284,7 @@ void MQTT::reconnect()
publishStatus();
return; // Don't try to connect directly to the server
}
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
// Defaults
int serverPort = 1883;
const char *serverAddr = default_mqtt_address;
@ -357,7 +357,7 @@ void MQTT::reconnect()
void MQTT::sendSubscriptions()
{
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
size_t numChan = channels.getNumChannels();
for (size_t i = 0; i < numChan; i++) {
const auto &ch = channels.getByIndex(i);
@ -396,7 +396,7 @@ bool MQTT::wantsLink() const
int32_t MQTT::runOnce()
{
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
if (!moduleConfig.mqtt.enabled || !(moduleConfig.mqtt.map_reporting_enabled || channels.anyMqttEnabled()))
return disable();

View File

@ -8,17 +8,15 @@
#include "mqtt/JSON.h"
#if HAS_WIFI
#include <WiFiClient.h>
#define HAS_NETWORKING 1
#if !defined(ARCH_PORTDUINO)
#include <WiFiClientSecure.h>
#endif
#endif
#if HAS_ETHERNET
#include <EthernetClient.h>
#define HAS_NETWORKING 1
#endif
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
#include <PubSubClient.h>
#endif
@ -43,7 +41,7 @@ class MQTT : private concurrency::OSThread
#endif
public:
#ifdef HAS_NETWORKING
#if HAS_NETWORKING
PubSubClient pubSub;
#endif
MQTT();

View File

@ -219,7 +219,6 @@ void NimbleBluetooth::setupService()
logRadioCharacteristic = bleService->createCharacteristic(
LOGRADIO_UUID,
NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::READ_AUTHEN | NIMBLE_PROPERTY::READ_ENC, 512U);
logRadioCharacteristic->setValue("Init");
}
bluetoothPhoneAPI = new BluetoothPhoneAPI();
@ -268,12 +267,12 @@ void NimbleBluetooth::clearBonds()
NimBLEDevice::deleteAllBonds();
}
void NimbleBluetooth::sendLog(const char *logMessage)
void NimbleBluetooth::sendLog(const uint8_t *logMessage, size_t length)
{
if (!bleServer || !isConnected() || strlen(logMessage) > 512) {
if (!bleServer || !isConnected() || length > 512) {
return;
}
logRadioCharacteristic->notify(reinterpret_cast<const uint8_t *>(logMessage), strlen(logMessage), true);
logRadioCharacteristic->notify(logMessage, length, true);
}
void clearNVS()

View File

@ -11,7 +11,7 @@ class NimbleBluetooth : BluetoothApi
bool isActive();
bool isConnected();
int getRssi();
void sendLog(const char *logMessage);
void sendLog(const uint8_t *logMessage, size_t length);
private:
void setupService();

View File

@ -8,7 +8,7 @@
#include "nimble/NimbleBluetooth.h"
#endif
#if !MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
@ -24,23 +24,22 @@
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
void setBluetoothEnable(bool enable)
{
#ifndef MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
if (!isWifiAvailable() && config.bluetooth.enabled == true)
#else
if (config.bluetooth.enabled == true)
#endif
#ifdef MESHTASTIC_EXCLUDE_WIFI
if (config.bluetooth.enabled == true)
#endif
{
if (!nimbleBluetooth) {
nimbleBluetooth = new NimbleBluetooth();
}
if (enable && !nimbleBluetooth->isActive()) {
nimbleBluetooth->setup();
}
// For ESP32, no way to recover from bluetooth shutdown without reboot
// BLE advertising automatically stops when MCU enters light-sleep(?)
// For deep-sleep, shutdown hardware with nimbleBluetooth->deinit(). Requires reboot to reverse
{
if (!nimbleBluetooth) {
nimbleBluetooth = new NimbleBluetooth();
}
if (enable && !nimbleBluetooth->isActive()) {
nimbleBluetooth->setup();
}
// For ESP32, no way to recover from bluetooth shutdown without reboot
// BLE advertising automatically stops when MCU enters light-sleep(?)
// For deep-sleep, shutdown hardware with nimbleBluetooth->deinit(). Requires reboot to reverse
}
}
#else
void setBluetoothEnable(bool enable) {}

View File

@ -8,6 +8,7 @@
#include "MeshRadio.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "detect/LoRaRadioType.h"
#include "error.h"
#include "main.h"
@ -17,7 +18,7 @@
#ifdef ARCH_ESP32
#include "esp32/pm.h"
#include "esp_pm.h"
#if !MESHTASTIC_EXCLUDE_WIFI
#if HAS_WIFI
#include "mesh/wifi/WiFiAPClient.h"
#endif
#include "rom/rtc.h"
@ -56,20 +57,20 @@ RTC_DATA_ATTR int bootCount = 0;
*/
void setCPUFast(bool on)
{
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_WIFI
#if defined(ARCH_ESP32) && HAS_WIFI
if (isWifiAvailable()) {
/*
*
* There's a newly introduced bug in the espressif framework where WiFi is
* unstable when the frequency is less than 240mhz.
* unstable when the frequency is less than 240MHz.
*
* This mostly impacts WiFi AP mode but we'll bump the frequency for
* all WiFi use cases.
* (Added: Dec 23, 2021 by Jm Casler)
*/
#ifndef CONFIG_IDF_TARGET_ESP32C3
LOG_DEBUG("Setting CPU to 240mhz because WiFi is in use.\n");
LOG_DEBUG("Setting CPU to 240MHz because WiFi is in use.\n");
setCpuFrequencyMhz(240);
#endif
return;
@ -85,6 +86,11 @@ void setCPUFast(bool on)
void setLed(bool ledOn)
{
if (ledOn)
powerMon->setState(meshtastic_PowerMon_State_LED_On);
else
powerMon->clearState(meshtastic_PowerMon_State_LED_On);
#ifdef LED_PIN
// toggle the led so we can get some rough sense of how often loop is pausing
digitalWrite(LED_PIN, ledOn ^ LED_INVERTED);