Merge branch 'master' into issue5194-external-notification-module-refactor

This commit is contained in:
Ben Meadors 2024-11-23 06:10:37 -06:00 committed by GitHub
commit 29308c207a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 222 additions and 182 deletions

View File

@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#a606be683748c73e9a0d46baf70163478d298f0f ; For arduino-pico 4.2.0
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.2.1
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#996c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@ -23,4 +23,4 @@ lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto
rweather/Crypto

View File

@ -1,8 +1,8 @@
; Common settings for rp2040 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#a606be683748c73e9a0d46baf70163478d298f0f ; For arduino-pico 4.2.0
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#4.2.1
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#96c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@ -22,4 +22,4 @@ lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto
rweather/Crypto

View File

@ -27,5 +27,4 @@ rm -r $OUTDIR/* || true
platformio pkg update --environment native || platformioFailed
pio run --environment native || platformioFailed
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
cp bin/device-install.* $OUTDIR
cp bin/device-update.* $OUTDIR
cp bin/native-install.* $OUTDIR

View File

@ -1,6 +1,7 @@
@ECHO OFF
set PYTHON=python
set WEB_APP=0
:: Determine the correct esptool command to use
where esptool >nul 2>&1
@ -12,13 +13,14 @@ if %ERRORLEVEL% EQU 0 (
goto GETOPTS
:HELP
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME]
echo Usage: %~nx0 [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME^|FILENAME] [--web]
echo Flash image file to device, but first erasing and writing system information
echo.
echo -h Display this help and exit
echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%)
echo -f FILENAME The .bin file to flash. Custom to your device type and region.
echo --web Flash WEB APP.
goto EOF
:GETOPTS
@ -27,6 +29,7 @@ if /I "%1"=="--help" goto HELP
if /I "%1"=="-F" set "FILENAME=%2" & SHIFT
if /I "%1"=="-p" set ESPTOOL_PORT=%2 & SHIFT
if /I "%1"=="-P" set PYTHON=%2 & SHIFT
if /I "%1"=="--web" set WEB_APP=1 & SHIFT
SHIFT
IF NOT "__%1__"=="____" goto GETOPTS
@ -49,8 +52,14 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
) else (
%ESPTOOL_CMD% --baud 115200 write_flash 0x260000 bleota-s3.bin
)
for %%f in (littlefs-*.bin) do (
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
IF %WEB_APP%==1 (
for %%f in (littlefswebui-*.bin) do (
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
)
) else (
for %%f in (littlefs-*.bin) do (
%ESPTOOL_CMD% --baud 115200 write_flash 0x300000 %%f
)
)
) else (
echo "Invalid file: %FILENAME%"

View File

@ -1,6 +1,7 @@
#!/bin/sh
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
WEB_APP=false
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
@ -19,16 +20,26 @@ set -e
# Usage info
show_help() {
cat <<EOF
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--web]
Flash image file to device, but first erasing and writing system information"
-h Display this help and exit
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The .bin file to flash. Custom to your device type and region.
--web Flash WEB APP.
EOF
}
# Preprocess long options like --web
for arg in "$@"; do
case "$arg" in
--web)
WEB_APP=true
shift # Remove this argument from the list
;;
esac
done
while getopts ":hp:P:f:" opt; do
case "${opt}" in
@ -73,7 +84,11 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
else
$ESPTOOL_CMD write_flash 0x260000 bleota-s3.bin
fi
$ESPTOOL_CMD write_flash 0x300000 littlefs-*.bin
if [ "$WEB_APP" = true ]; then
$ESPTOOL_CMD write_flash 0x300000 littlefswebui-*.bin
else
$ESPTOOL_CMD write_flash 0x300000 littlefs-*.bin
fi
else
show_help

View File

@ -1 +0,0 @@
curfirmwareversion.xml

View File

@ -64,7 +64,7 @@ class AudioThread : public concurrency::OSThread
void initOutput()
{
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT, DAC_I2S_MCLK);
audioOut->SetGain(0.2);
};

View File

@ -64,6 +64,95 @@ const char *getDOPString(uint32_t dop);
*/
class GPS : private concurrency::OSThread
{
public:
meshtastic_Position p = meshtastic_Position_init_default;
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
* implementations. Those boards will set this public variable to a custom implementation.
*
* Normally set by GPS::createGPS()
*/
GpioVirtPin *enablePin = NULL;
virtual ~GPS();
/** We will notify this observable anytime GPS state has changed meaningfully */
Observable<const meshtastic::GPSStatus *> newStatus;
/**
* Returns true if we succeeded
*/
virtual bool setup();
// re-enable the thread
void enable();
// Disable the thread
int32_t disable() override;
// toggle between enabled/disabled
void toggleGpsMode();
// Change the power state of the GPS - for power saving / shutdown
void setPowerState(GPSPowerState newState, uint32_t sleepMs = 0);
/// Returns true if we have acquired GPS lock.
virtual bool hasLock();
/// Returns true if there's valid data flow with the chip.
virtual bool hasFlow();
/// Return true if we are connected to a GPS
bool isConnected() const { return hasGPS; }
bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; }
// Empty the input buffer as quickly as possible
void clearBuffer();
virtual bool factoryReset();
// Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present.
static GPS *createGps();
// Wake the GPS hardware - ready for an update
void up();
// Let the GPS hardware save power between updates
void down();
protected:
/// Record that we have a GPS
void setConnected();
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
*/
virtual bool whileActive();
/**
* 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
*
* @return true if we've acquired a time
*/
virtual bool lookForTime();
/**
* 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
*
* @return true if we've acquired a new location
*/
virtual bool lookForLocation();
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
private:
GPS() : concurrency::OSThread("GPS") {}
TinyGPSPlus reader;
uint8_t fixQual = 0; // fix quality from GPGGA
uint32_t lastChecksumFailCount = 0;
@ -75,7 +164,6 @@ class GPS : private concurrency::OSThread
TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA
uint8_t fixType = 0; // fix type from GPGSA
#endif
private:
#if GPS_BAUDRATE_FIXED
// if GPS_BAUDRATE is specified in variant, only try that.
const int serialSpeeds[1] = {GPS_BAUDRATE};
@ -113,7 +201,6 @@ class GPS : private concurrency::OSThread
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
public:
/** If !NULL we will use this serial port to construct our GPS */
#if defined(ARCH_RP2040)
static SerialUART *_serial_gps;
@ -167,53 +254,6 @@ class GPS : private concurrency::OSThread
const char *ACK_SUCCESS_MESSAGE = "Get ack success!";
meshtastic_Position p = meshtastic_Position_init_default;
/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
* implementations. Those boards will set this public variable to a custom implementation.
*
* Normally set by GPS::createGPS()
*/
GpioVirtPin *enablePin = NULL;
GPS() : concurrency::OSThread("GPS") {}
virtual ~GPS();
/** We will notify this observable anytime GPS state has changed meaningfully */
Observable<const meshtastic::GPSStatus *> newStatus;
/**
* Returns true if we succeeded
*/
virtual bool setup();
// re-enable the thread
void enable();
// Disable the thread
int32_t disable() override;
// toggle between enabled/disabled
void toggleGpsMode();
// Change the power state of the GPS - for power saving / shutdown
void setPowerState(GPSPowerState newState, uint32_t sleepMs = 0);
/// Returns true if we have acquired GPS lock.
virtual bool hasLock();
/// Returns true if there's valid data flow with the chip.
virtual bool hasFlow();
/// Return true if we are connected to a GPS
bool isConnected() const { return hasGPS; }
bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; }
// Empty the input buffer as quickly as possible
void clearBuffer();
// Create a ublox packet for editing in memory
uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
uint8_t makeCASPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg);
@ -229,59 +269,6 @@ class GPS : private concurrency::OSThread
GPS_RESPONSE getACKCas(uint8_t class_id, uint8_t msg_id, uint32_t waitMillis);
virtual bool factoryReset();
// Creates an instance of the GPS class.
// Returns the new instance or null if the GPS is not present.
static GPS *createGps();
// Wake the GPS hardware - ready for an update
void up();
// Let the GPS hardware save power between updates
void down();
protected:
/**
* 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
*
* @return true if we've acquired a time
*/
/**
* 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
*
* @return true if we've acquired a new location
*/
/// Record that we have a GPS
void setConnected();
/** Subclasses should look for serial rx characters here and feed it to their GPS parser
*
* Return true if we received a valid message from the GPS
*/
virtual bool whileActive();
/**
* 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
*
* @return true if we've acquired a time
*/
virtual bool lookForTime();
/**
* 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
*
* @return true if we've acquired a new location
*/
virtual bool lookForLocation();
private:
/// Prepare the GPS for the cpu entering deep sleep, expect to be gone for at least 100s of msecs
/// always returns 0 to indicate okay to sleep
int prepareDeepSleep(void *unused);
@ -320,10 +307,7 @@ class GPS : private concurrency::OSThread
uint8_t fixeddelayCtr = 0;
const char *powerStateToString();
protected:
GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN;
};
extern GPS *gps;
#endif // Exclude GPS
#endif // Exclude GPS

View File

@ -23,7 +23,7 @@ uint32_t printWPL(char *buf, size_t bufsz, const meshtastic_PositionLite &pos, c
{
GeoCoord geoCoord(pos.latitude_i, pos.longitude_i, pos.altitude);
char type = isCaltopoMode ? 'P' : 'N';
uint32_t len = snprintf(buf, bufsz, "$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
uint32_t len = snprintf(buf, bufsz, "\r\n$G%cWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s", type, geoCoord.getDMSLatDeg(),
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6, geoCoord.getDMSLatCP(),
geoCoord.getDMSLonDeg(), (abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
geoCoord.getDMSLonCP(), name);

View File

@ -396,7 +396,7 @@ static void drawBattery(OLEDDisplay *display, int16_t x, int16_t y, uint8_t *img
display->drawFastImage(x, y, 16, 8, imgBuffer);
}
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
void Screen::drawWatchFaceToggleButton(OLEDDisplay *display, int16_t x, int16_t y, bool digitalMode, float scale)
{
@ -2068,7 +2068,7 @@ void Screen::setFrames(FrameFocus focus)
focus = FOCUS_FAULT; // Change our "focus" parameter, to ensure we show the fault frame
}
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
normalFrames[numframes++] = screen->digitalWatchFace ? &Screen::drawDigitalClockFrame : &Screen::drawAnalogClockFrame;
#endif
@ -2699,7 +2699,7 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
int Screen::handleInputEvent(const InputEvent *event)
{
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
// For the T-Watch, intercept touches to the 'toggle digital/analog watch face' button
uint8_t watchFaceFrame = error_code ? 1 : 0;

View File

@ -554,7 +554,7 @@ class Screen : public concurrency::OSThread
static void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
static void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

View File

@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
#ifdef T_WATCH_S3
#if defined(DISPLAY_CLOCK_FRAME)
const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0xe3, 0x1f,
0xf3, 0x3f, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x03, 0x33, 0xff, 0x33,
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};

View File

@ -114,7 +114,7 @@ NodeDB::NodeDB()
uint32_t channelFileCRC = crc32Buffer(&channelFile, sizeof(channelFile));
int saveWhat = 0;
bool hasUniqueId = false;
// bool hasUniqueId = false;
// Get device unique id
#if defined(ARCH_ESP32) && defined(ESP_EFUSE_OPTIONAL_UNIQUE_ID)
uint32_t unique_id[4];
@ -503,7 +503,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#ifdef RAK4630
config.display.wake_on_tap_or_motion = true;
#endif
#ifdef T_WATCH_S3
#if defined(T_WATCH_S3) || defined(SENSECAP_INDICATOR)
config.display.screen_on_secs = 30;
config.display.wake_on_tap_or_motion = true;
#endif
@ -527,7 +527,7 @@ void NodeDB::initConfigIntervals()
config.display.screen_on_secs = default_screen_on_secs;
#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014)
#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014) || defined(SENSECAP_INDICATOR)
config.power.is_power_saving = true;
config.display.screen_on_secs = 30;
config.power.wait_bluetooth_secs = 30;

View File

@ -62,7 +62,11 @@ static void onNetworkConnected()
LOG_INFO("Start WiFi network services");
// start mdns
if (!MDNS.begin("Meshtastic")) {
if (
#ifdef ARCH_RP2040
!moduleConfig.mqtt.enabled && // MDNS is not supported when MQTT is enabled on ARCH_RP2040
#endif
!MDNS.begin("Meshtastic")) {
LOG_ERROR("Error setting up MDNS responder!");
} else {
LOG_INFO("mDNS Host: Meshtastic.local");

View File

@ -55,7 +55,7 @@ CannedMessageModule::CannedMessageModule()
LOG_INFO("CannedMessageModule is enabled");
// T-Watch interface currently has no way to select destination type, so default to 'node'
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
#endif
@ -81,7 +81,7 @@ int CannedMessageModule::splitConfiguredMessages()
String canned_messages = cannedMessageModuleConfig.messages;
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
String separator = canned_messages.length() ? "|" : "";
canned_messages = "[---- Free Text ----]" + separator + canned_messages;
@ -150,7 +150,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
}
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT)) {
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
if (this->currentMessageIndex == 0) {
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
@ -177,7 +177,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
this->currentMessageIndex = -1;
#if !defined(T_WATCH_S3) && !defined(RAK14014)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->freetext = ""; // clear freetext
this->cursor = 0;
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
@ -190,7 +190,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
this->payload = INPUT_BROKER_MSG_LEFT;
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
@ -312,7 +312,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
}
}
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
String keyTapped = keyForCoordinates(event->touchX, event->touchY);
@ -446,7 +446,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
#if !defined(T_WATCH_S3) && !defined(RAK14014)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(SENSECAP_INDICATOR)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@ -459,7 +459,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
#if !defined(T_WATCH_S3) && !defined(RAK14014)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@ -479,7 +479,7 @@ int32_t CannedMessageModule::runOnce()
powerFSM.trigger(EVENT_PRESS);
return INT32_MAX;
} else {
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
sendText(this->dest, indexChannels[this->channel], this->messages[this->currentMessageIndex], true);
#else
sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true);
@ -496,7 +496,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
#if !defined(T_WATCH_S3) && !defined(RAK14014)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@ -513,7 +513,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
#if !defined(T_WATCH_S3) && !defined(RAK14014)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@ -526,7 +526,7 @@ int32_t CannedMessageModule::runOnce()
this->freetext = ""; // clear freetext
this->cursor = 0;
#if !defined(T_WATCH_S3) && !defined(RAK14014)
#if !defined(T_WATCH_S3) && !defined(RAK14014) && !defined(USE_VIRTUAL_KEYBOARD)
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
#endif
@ -769,7 +769,7 @@ void CannedMessageModule::showTemporaryMessage(const String &message)
setIntervalFromNow(2000);
}
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
String CannedMessageModule::keyForCoordinates(uint x, uint y)
{
@ -1055,7 +1055,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
requestFocus(); // Tell Screen::setFrames to move to our module's frame
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
drawKeyboard(display, state, 0, 0);
#else

View File

@ -102,7 +102,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
int getNextIndex();
int getPrevIndex();
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
void drawKeyboard(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
String keyForCoordinates(uint x, uint y);
bool shift = false;
@ -156,7 +156,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
unsigned long lastTouchMillis = 0;
String temporaryMessage;
#if defined(T_WATCH_S3) || defined(RAK14014)
#if defined(USE_VIRTUAL_KEYBOARD)
Letter keyboard[2][4][10] = {{{{"Q", 20, 0, 0, 0, 0},
{"W", 22, 0, 0, 0, 0},
{"E", 17, 0, 0, 0, 0},

View File

@ -146,11 +146,20 @@ bool PositionModule::hasQualityTimesource()
#if MESHTASTIC_EXCLUDE_GPS
bool hasGpsOrRtc = (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
#else
bool hasGpsOrRtc = (gps && gps->isConnected()) || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
bool hasGpsOrRtc = hasGPS() || (rtc_found.address != ScanI2C::ADDRESS_NONE.address);
#endif
return hasGpsOrRtc || setFromPhoneOrNtpToday;
}
bool PositionModule::hasGPS()
{
#if MESHTASTIC_EXCLUDE_GPS
return false;
#else
return gps && gps->isConnected();
#endif
}
meshtastic_MeshPacket *PositionModule::allocReply()
{
if (precision == 0) {
@ -194,10 +203,21 @@ meshtastic_MeshPacket *PositionModule::allocReply()
p.precision_bits = precision;
p.has_latitude_i = true;
p.has_longitude_i = true;
p.time = getValidTime(RTCQualityNTP) > 0 ? getValidTime(RTCQualityNTP) : localPosition.time;
// Always use NTP / GPS time if available
if (getValidTime(RTCQualityNTP) > 0) {
p.time = getValidTime(RTCQualityNTP);
} else if (rtc_found.address != ScanI2C::ADDRESS_NONE.address) {
LOG_INFO("Use RTC time for position");
p.time = getValidTime(RTCQualityDevice);
} else if (getRTCQuality() < RTCQualityNTP) {
LOG_INFO("Strip low RTCQuality (%d) time from position", getRTCQuality());
p.time = 0;
}
if (config.position.fixed_position) {
p.location_source = meshtastic_Position_LocSource_LOC_MANUAL;
} else {
p.location_source = localPosition.location_source;
}
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) {
@ -242,20 +262,6 @@ meshtastic_MeshPacket *PositionModule::allocReply()
p.has_ground_speed = true;
}
// Strip out any time information before sending packets to other nodes - to keep the wire size small (and because other
// nodes shouldn't trust it anyways) Note: we allow a device with a local GPS or NTP to include the time, so that devices
// without can get time.
if (getRTCQuality() < RTCQualityNTP) {
LOG_INFO("Strip time %u from position", p.time);
p.time = 0;
} else if (rtc_found.address != ScanI2C::ADDRESS_NONE.address) {
LOG_INFO("Use RTC time %u for position", p.time);
p.time = getValidTime(RTCQualityDevice);
} else {
p.time = getValidTime(RTCQualityNTP);
LOG_INFO("Provide time to mesh %u", p.time);
}
LOG_INFO("Position reply: time=%i lat=%i lon=%i", p.time, p.latitude_i, p.longitude_i);
// TAK Tracker devices should send their position in a TAK packet over the ATAK port

View File

@ -61,6 +61,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
uint32_t precision;
void sendLostAndFoundText();
bool hasQualityTimesource();
bool hasGPS();
const uint32_t minimumTimeThreshold =
Default::getConfiguredOrDefaultMs(config.position.broadcast_smart_minimum_interval_secs, 30);

View File

@ -204,9 +204,11 @@ int32_t SerialModule::runOnce()
lastNmeaTime = millis();
uint32_t readIndex = 0;
const meshtastic_NodeInfoLite *tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
while (tempNodeInfo != NULL && tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) {
printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true);
serialPrint->printf("%s", outbuf);
while (tempNodeInfo != NULL) {
if (tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) {
printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true);
serialPrint->printf("%s", outbuf);
}
tempNodeInfo = nodeDB->readNextMeshNode(readIndex);
}
}

View File

@ -77,9 +77,10 @@ meshtastic_MeshPacket *DeviceTelemetryModule::allocReply()
// Check for a request for device metrics
if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) {
LOG_INFO("Device telemetry reply to request");
meshtastic_Telemetry telemetry = getDeviceTelemetry();
return allocDataProtobuf(telemetry);
return allocDataProtobuf(getDeviceTelemetry());
} else if (decoded->which_variant == meshtastic_Telemetry_local_stats_tag) {
LOG_INFO("Device telemetry reply w/ LocalStats to request");
return allocDataProtobuf(getLocalStatsTelemetry());
}
}
return NULL;
@ -112,7 +113,7 @@ meshtastic_Telemetry DeviceTelemetryModule::getDeviceTelemetry()
return t;
}
void DeviceTelemetryModule::sendLocalStatsToPhone()
meshtastic_Telemetry DeviceTelemetryModule::getLocalStatsTelemetry()
{
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
telemetry.which_variant = meshtastic_Telemetry_local_stats_tag;
@ -142,7 +143,12 @@ void DeviceTelemetryModule::sendLocalStatsToPhone()
LOG_INFO("num_packets_tx=%i, num_packets_rx=%i, num_packets_rx_bad=%i", telemetry.variant.local_stats.num_packets_tx,
telemetry.variant.local_stats.num_packets_rx, telemetry.variant.local_stats.num_packets_rx_bad);
meshtastic_MeshPacket *p = allocDataProtobuf(telemetry);
return telemetry;
}
void DeviceTelemetryModule::sendLocalStatsToPhone()
{
meshtastic_MeshPacket *p = allocDataProtobuf(getLocalStatsTelemetry());
p->to = NODENUM_BROADCAST;
p->decoded.want_response = false;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;

View File

@ -42,6 +42,8 @@ class DeviceTelemetryModule : private concurrency::OSThread, public ProtobufModu
private:
meshtastic_Telemetry getDeviceTelemetry();
meshtastic_Telemetry getLocalStatsTelemetry();
void sendLocalStatsToPhone();
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t sendStatsToPhoneIntervalMs = 15 * SECONDS_IN_MINUTE * 1000; // Send stats to phone every 15 minutes

View File

@ -545,9 +545,11 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me
// mp_decoded will not be decoded when it's PKI encrypted and not directed to us
if (mp_decoded.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
// For uplinking other's packets, check if it's not OK to MQTT or if it's an older packet without the bitfield
bool dontUplink = !mp_decoded.decoded.has_bitfield ||
(mp_decoded.decoded.has_bitfield && !(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK));
// check for the lowest bit of the data bitfield set false, and the use of one of the default keys.
if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && mp_decoded.decoded.has_bitfield &&
!(mp_decoded.decoded.bitfield & BITFIELD_OK_TO_MQTT_MASK) &&
if (!isFromUs(&mp_decoded) && !isMqttServerAddressPrivate && dontUplink &&
(ch.settings.psk.size < 2 || (ch.settings.psk.size == 16 && memcmp(ch.settings.psk.bytes, defaultpsk, 16)) ||
(ch.settings.psk.size == 32 && memcmp(ch.settings.psk.bytes, eventpsk, 32)))) {
LOG_INFO("MQTT onSend - Not forwarding packet due to DontMqttMeBro flag");

View File

@ -2,6 +2,7 @@
[env:meshtastic-diy-v1]
extends = esp32_base
board = esp32doit-devkit-v1
board_level = extra
board_check = true
build_flags =
${esp32_base.build_flags}

View File

@ -11,7 +11,7 @@ build_flags =
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps = ${esp32s3_base.lib_deps}
earlephilhower/ESP8266Audio@^1.9.7
earlephilhower/ESP8266Audio@^1.9.9
earlephilhower/ESP8266SAM@^1.0.1
[env:dreamcatcher-2206]

View File

@ -60,6 +60,7 @@
#define DAC_I2S_BCK 21
#define DAC_I2S_WS 9
#define DAC_I2S_DOUT 48
#define DAC_I2S_MCLK 44
#define BIAS_T_ENABLE 7 // needs to be low
#define BIAS_T_VALUE 0

View File

@ -306,7 +306,7 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#define SCREEN_TOUCH_INT WB_IO6
#define CANNED_MESSAGE_MODULE_ENABLE 1
#define USE_VIRTUAL_KEYBOARD 1
/*----------------------------------------------------------------------------
* Arduino objects - C++ only
*----------------------------------------------------------------------------*/

View File

@ -36,12 +36,13 @@
#define TOUCH_I2C_PORT 0
#define TOUCH_SLAVE_ADDRESS 0x48
// Buzzer
#define PIN_BUZZER 19
// in future, we may want to add a buzzer and add all sensors to the indicator via a data protocol for now only GPS is supported
// // Buzzer
// #define PIN_BUZZER 19
#define HAS_GPS 0
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define GPS_RX_PIN 20
#define GPS_TX_PIN 19
#define HAS_GPS 1
#define USE_SX1262
#define USE_SX1268
@ -62,3 +63,6 @@
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#define USE_VIRTUAL_KEYBOARD 1
#define DISPLAY_CLOCK_FRAME 1

View File

@ -15,5 +15,5 @@ build_flags = ${esp32_base.build_flags}
lib_deps = ${esp32s3_base.lib_deps}
lovyan03/LovyanGFX@^1.1.9
earlephilhower/ESP8266Audio@^1.9.7
earlephilhower/ESP8266Audio@^1.9.9
earlephilhower/ESP8266SAM@^1.0.1

View File

@ -73,6 +73,7 @@
#define DAC_I2S_BCK 7
#define DAC_I2S_WS 5
#define DAC_I2S_DOUT 6
#define DAC_I2S_MCLK 21 // GPIO lrck mic
// LoRa
#define USE_SX1262

View File

@ -14,5 +14,5 @@ lib_deps = ${esp32s3_base.lib_deps}
lovyan03/LovyanGFX@^1.1.9
lewisxhe/PCF8563_Library@1.0.1
adafruit/Adafruit DRV2605 Library@^1.2.2
earlephilhower/ESP8266Audio@^1.9.7
earlephilhower/ESP8266Audio@^1.9.9
earlephilhower/ESP8266SAM@^1.0.1

View File

@ -34,6 +34,7 @@
#define DAC_I2S_BCK 48
#define DAC_I2S_WS 15
#define DAC_I2S_DOUT 46
#define DAC_I2S_MCLK 0
#define HAS_AXP2101
@ -71,3 +72,6 @@
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for
// the sx1262interface code)
#define USE_VIRTUAL_KEYBOARD 1
#define DISPLAY_CLOCK_FRAME 1