mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-29 11:01:15 +00:00
Merge branch 'master' into apollo
This commit is contained in:
commit
b2a313780f
8
.github/workflows/main_matrix.yml
vendored
8
.github/workflows/main_matrix.yml
vendored
@ -66,6 +66,7 @@ jobs:
|
|||||||
- board: tlora-v2-1-1_6
|
- board: tlora-v2-1-1_6
|
||||||
- board: tlora-v2-1-1_8
|
- board: tlora-v2-1-1_8
|
||||||
- board: tbeam
|
- board: tbeam
|
||||||
|
- board: heltec-ht62-esp32c3-sx1262
|
||||||
- board: heltec-v1
|
- board: heltec-v1
|
||||||
- board: heltec-v2_0
|
- board: heltec-v2_0
|
||||||
- board: heltec-v2_1
|
- board: heltec-v2_1
|
||||||
@ -125,6 +126,7 @@ jobs:
|
|||||||
- board: pico
|
- board: pico
|
||||||
- board: picow
|
- board: picow
|
||||||
- board: rak11310
|
- board: rak11310
|
||||||
|
- board: senselora_rp2040
|
||||||
uses: ./.github/workflows/build_rpi2040.yml
|
uses: ./.github/workflows/build_rpi2040.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
@ -211,6 +213,9 @@ jobs:
|
|||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
gather-artifacts:
|
gather-artifacts:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
[
|
[
|
||||||
@ -284,14 +289,13 @@ jobs:
|
|||||||
- name: Create request artifacts
|
- name: Create request artifacts
|
||||||
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
|
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
|
||||||
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
||||||
uses: gavv/pull-request-artifacts@v1.1.0
|
uses: gavv/pull-request-artifacts@v2.1.0
|
||||||
with:
|
with:
|
||||||
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
|
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
|
artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
|
||||||
artifacts-repo: meshtastic/artifacts
|
artifacts-repo: meshtastic/artifacts
|
||||||
artifacts-branch: device
|
artifacts-branch: device
|
||||||
artifacts-dir: pr
|
|
||||||
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||||
|
|
||||||
release-artifacts:
|
release-artifacts:
|
||||||
|
@ -12,10 +12,9 @@ lint:
|
|||||||
- checkov@3.1.9
|
- checkov@3.1.9
|
||||||
- terrascan@1.18.5
|
- terrascan@1.18.5
|
||||||
- trivy@0.47.0
|
- trivy@0.47.0
|
||||||
- trufflehog@3.63.2-rc0
|
#- trufflehog@3.63.2-rc0
|
||||||
- taplo@0.8.1
|
- taplo@0.8.1
|
||||||
- ruff@0.1.6
|
- ruff@0.1.6
|
||||||
- yamllint@1.33.0
|
|
||||||
- isort@5.12.0
|
- isort@5.12.0
|
||||||
- markdownlint@0.37.0
|
- markdownlint@0.37.0
|
||||||
- oxipng@9.0.0
|
- oxipng@9.0.0
|
||||||
|
@ -44,7 +44,6 @@ lib_deps =
|
|||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||||
h2zero/NimBLE-Arduino@^1.4.1
|
h2zero/NimBLE-Arduino@^1.4.1
|
||||||
jgromes/RadioLib@^6.2.0
|
|
||||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ build_src_filter =
|
|||||||
|
|
||||||
lib_deps=
|
lib_deps=
|
||||||
${arduino_base.lib_deps}
|
${arduino_base.lib_deps}
|
||||||
jgromes/RadioLib@^6.2.0
|
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
BluetoothOTA
|
BluetoothOTA
|
@ -24,7 +24,6 @@ lib_deps =
|
|||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
${networking_base.lib_deps}
|
${networking_base.lib_deps}
|
||||||
rweather/Crypto@^0.4.0
|
rweather/Crypto@^0.4.0
|
||||||
jgromes/RadioLib@^6.1.0
|
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
[rp2040_base]
|
[rp2040_base]
|
||||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
|
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#612de5399d68b359053f1307ed223d400aea975c
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#d2461a14ad5aa920e44508d236c2f459e3befbf8
|
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.6.2
|
||||||
|
|
||||||
board_build.core = earlephilhower
|
board_build.core = earlephilhower
|
||||||
board_build.filesystem_size = 0.5m
|
board_build.filesystem_size = 0.5m
|
||||||
@ -29,5 +29,4 @@ lib_ignore =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${arduino_base.lib_deps}
|
${arduino_base.lib_deps}
|
||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
jgromes/RadioLib@^6.2.0
|
|
||||||
rweather/Crypto
|
rweather/Crypto
|
@ -34,7 +34,6 @@ upload_protocol = stlink
|
|||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
jgromes/RadioLib@^6.2.0
|
|
||||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||||
https://github.com/littlefs-project/littlefs.git#v2.5.1
|
https://github.com/littlefs-project/littlefs.git#v2.5.1
|
||||||
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
|
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
|
||||||
|
@ -68,6 +68,7 @@ build_flags = -Wno-missing-field-initializers
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
jgromes/RadioLib@^6.3.0
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306
|
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306
|
||||||
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
||||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 9148427a3be535c9e3f17e846ecbb64ce04b6521
|
Subproject commit a34b2c680e2c1c240643c515e57c5532b29c91a7
|
77
src/AudioThread.h
Normal file
77
src/AudioThread.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PowerFSM.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "sleep.h"
|
||||||
|
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
#include <AudioFileSourcePROGMEM.h>
|
||||||
|
#include <AudioGeneratorRTTTL.h>
|
||||||
|
#include <AudioOutputI2S.h>
|
||||||
|
#include <ESP8266SAM.h>
|
||||||
|
|
||||||
|
#define AUDIO_THREAD_INTERVAL_MS 100
|
||||||
|
|
||||||
|
class AudioThread : public concurrency::OSThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AudioThread() : OSThread("AudioThread") { initOutput(); }
|
||||||
|
|
||||||
|
void beginRttl(const void *data, uint32_t len)
|
||||||
|
{
|
||||||
|
setCPUFast(true);
|
||||||
|
rtttlFile = new AudioFileSourcePROGMEM(data, len);
|
||||||
|
i2sRtttl = new AudioGeneratorRTTTL();
|
||||||
|
i2sRtttl->begin(rtttlFile, audioOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPlaying()
|
||||||
|
{
|
||||||
|
if (i2sRtttl != nullptr) {
|
||||||
|
return i2sRtttl->isRunning() && i2sRtttl->loop();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
if (i2sRtttl != nullptr) {
|
||||||
|
i2sRtttl->stop();
|
||||||
|
delete i2sRtttl;
|
||||||
|
i2sRtttl = nullptr;
|
||||||
|
}
|
||||||
|
if (rtttlFile != nullptr) {
|
||||||
|
delete rtttlFile;
|
||||||
|
rtttlFile = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCPUFast(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32_t runOnce() override
|
||||||
|
{
|
||||||
|
canSleep = true; // Assume we should not keep the board awake
|
||||||
|
|
||||||
|
// if (i2sRtttl != nullptr && i2sRtttl->isRunning()) {
|
||||||
|
// i2sRtttl->loop();
|
||||||
|
// }
|
||||||
|
return AUDIO_THREAD_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initOutput()
|
||||||
|
{
|
||||||
|
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
|
||||||
|
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
|
||||||
|
audioOut->SetGain(0.2);
|
||||||
|
};
|
||||||
|
|
||||||
|
AudioGeneratorRTTTL *i2sRtttl = nullptr;
|
||||||
|
AudioOutputI2S *audioOut;
|
||||||
|
|
||||||
|
AudioFileSourcePROGMEM *rtttlFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -5,6 +5,7 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "graphics/Screen.h"
|
#include "graphics/Screen.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "modules/ExternalNotificationModule.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include <OneButton.h>
|
#include <OneButton.h>
|
||||||
|
|
||||||
@ -205,6 +206,12 @@ class ButtonThread : public concurrency::OSThread
|
|||||||
|
|
||||||
static void userButtonPressedLongStart()
|
static void userButtonPressedLongStart()
|
||||||
{
|
{
|
||||||
|
#ifdef T_DECK
|
||||||
|
// False positive long-press triggered on T-Deck with i2s audio, so short circuit
|
||||||
|
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (millis() > 30 * 1000) {
|
if (millis() > 30 * 1000) {
|
||||||
LOG_DEBUG("Long press start!\n");
|
LOG_DEBUG("Long press start!\n");
|
||||||
longPressTime = millis();
|
longPressTime = millis();
|
||||||
|
@ -33,7 +33,7 @@ class PowerFSMThread : public OSThread
|
|||||||
powerFSM.trigger(EVENT_SHUTDOWN);
|
powerFSM.trigger(EVENT_SHUTDOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 10;
|
return 100;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ bool GPS::setup()
|
|||||||
gnssModel = GNSS_MODEL_UNKNOWN;
|
gnssModel = GNSS_MODEL_UNKNOWN;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
gnssModel = GNSS_MODEL_UC6850;
|
gnssModel = GNSS_MODEL_UC6580;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (gnssModel == GNSS_MODEL_MTK) {
|
if (gnssModel == GNSS_MODEL_MTK) {
|
||||||
@ -311,11 +311,23 @@ bool GPS::setup()
|
|||||||
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
|
// Switch to Vehicle Mode, since SoftRF enables Aviation < 2g
|
||||||
_serial_gps->write("$PCAS11,3*1E\r\n");
|
_serial_gps->write("$PCAS11,3*1E\r\n");
|
||||||
delay(250);
|
delay(250);
|
||||||
} else if (gnssModel == GNSS_MODEL_UC6850) {
|
} else if (gnssModel == GNSS_MODEL_UC6580) {
|
||||||
|
// The Unicore UC6580 can use a lot of sat systems, enable it to
|
||||||
// use GPS + GLONASS
|
// use GPS L1 & L5 + BDS B1I & B2a + GLONASS L1 + GALILEO E1 & E5a + SBAS
|
||||||
_serial_gps->write("$CFGSYS,h15\r\n");
|
// This will reset the receiver, so wait a bit afterwards
|
||||||
|
// The paranoid will wait for the OK*04 confirmation response after each command.
|
||||||
|
_serial_gps->write("$CFGSYS,h25155\r\n");
|
||||||
|
delay(750);
|
||||||
|
// Must be done after the CFGSYS command
|
||||||
|
// Turn off GSV messages, we don't really care about which and where the sats are, maybe someday.
|
||||||
|
_serial_gps->write("$CFGMSG,0,3,0\r\n");
|
||||||
delay(250);
|
delay(250);
|
||||||
|
// Turn off NOTICE __TXT messages, these may provide Unicore some info but we don't care.
|
||||||
|
_serial_gps->write("$CFGMSG,6,0,0\r\n");
|
||||||
|
delay(250);
|
||||||
|
_serial_gps->write("$CFGMSG,6,1,0\r\n");
|
||||||
|
delay(250);
|
||||||
|
|
||||||
} else if (gnssModel == GNSS_MODEL_UBLOX) {
|
} else if (gnssModel == GNSS_MODEL_UBLOX) {
|
||||||
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
|
// Configure GNSS system to GPS+SBAS+GLONASS (Module may restart after this command)
|
||||||
// We need set it because by default it is GPS only, and we want to use GLONASS too
|
// We need set it because by default it is GPS only, and we want to use GLONASS too
|
||||||
|
@ -23,7 +23,7 @@ struct uBloxGnssModelInfo {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
GNSS_MODEL_MTK,
|
GNSS_MODEL_MTK,
|
||||||
GNSS_MODEL_UBLOX,
|
GNSS_MODEL_UBLOX,
|
||||||
GNSS_MODEL_UC6850,
|
GNSS_MODEL_UC6580,
|
||||||
GNSS_MODEL_UNKNOWN,
|
GNSS_MODEL_UNKNOWN,
|
||||||
} GnssModel_t;
|
} GnssModel_t;
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// nrf52 doesn't have a readable RTC (yet - software not written)
|
// nrf52 doesn't have a readable RTC (yet - software not written)
|
||||||
#ifdef HAS_RTC
|
#if HAS_RTC
|
||||||
readFromRTC();
|
readFromRTC();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -208,4 +208,4 @@ uint32_t getTime()
|
|||||||
uint32_t getValidTime(RTCQuality minQuality)
|
uint32_t getValidTime(RTCQuality minQuality)
|
||||||
{
|
{
|
||||||
return (currentQuality >= minQuality) ? getTime() : 0;
|
return (currentQuality >= minQuality) ? getTime() : 0;
|
||||||
}
|
}
|
||||||
|
@ -43,9 +43,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#include "sleep.h"
|
#include "sleep.h"
|
||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
|
|
||||||
|
#if HAS_WIFI && !defined(ARCH_RASPBERRY_PI)
|
||||||
|
#include "mesh/wifi/WiFiAPClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
#include "esp_task_wdt.h"
|
#include "esp_task_wdt.h"
|
||||||
#include "mesh/wifi/WiFiAPClient.h"
|
|
||||||
#include "modules/esp32/StoreForwardModule.h"
|
#include "modules/esp32/StoreForwardModule.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1294,7 +1297,7 @@ void Screen::setFrames()
|
|||||||
// call a method on debugInfoScreen object (for more details)
|
// call a method on debugInfoScreen object (for more details)
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
|
||||||
|
|
||||||
#ifdef ARCH_ESP32
|
#if HAS_WIFI && !defined(ARCH_RASPBERRY_PI)
|
||||||
if (isWifiAvailable()) {
|
if (isWifiAvailable()) {
|
||||||
// call a method on debugInfoScreen object (for more details)
|
// call a method on debugInfoScreen object (for more details)
|
||||||
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
|
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "InputBroker.h"
|
#include "InputBroker.h"
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#include "modules/ExternalNotificationModule.h"
|
||||||
|
|
||||||
TouchScreenImpl1 *touchScreenImpl1;
|
TouchScreenImpl1 *touchScreenImpl1;
|
||||||
|
|
||||||
@ -63,7 +64,11 @@ void TouchScreenImpl1::onEvent(const TouchEvent &event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOUCH_ACTION_TAP: {
|
case TOUCH_ACTION_TAP: {
|
||||||
powerFSM.trigger(EVENT_INPUT);
|
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||||
|
externalNotificationModule->stopNow();
|
||||||
|
} else {
|
||||||
|
powerFSM.trigger(EVENT_INPUT);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
32
src/main.cpp
32
src/main.cpp
@ -84,6 +84,11 @@ NRF52Bluetooth *nrf52Bluetooth;
|
|||||||
#include "AmbientLightingThread.h"
|
#include "AmbientLightingThread.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
#include "AudioThread.h"
|
||||||
|
AudioThread *audioThread;
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace concurrency;
|
using namespace concurrency;
|
||||||
|
|
||||||
// We always create a screen object, but we only init it if we find the hardware
|
// We always create a screen object, but we only init it if we find the hardware
|
||||||
@ -122,6 +127,7 @@ ATECCX08A atecc;
|
|||||||
#ifdef T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
Adafruit_DRV2605 drv;
|
Adafruit_DRV2605 drv;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool isVibrating = false;
|
bool isVibrating = false;
|
||||||
|
|
||||||
bool eink_found = true;
|
bool eink_found = true;
|
||||||
@ -432,6 +438,10 @@ void setup()
|
|||||||
auto i2cCount = i2cScanner->countDevices();
|
auto i2cCount = i2cScanner->countDevices();
|
||||||
if (i2cCount == 0) {
|
if (i2cCount == 0) {
|
||||||
LOG_INFO("No I2C devices found\n");
|
LOG_INFO("No I2C devices found\n");
|
||||||
|
Wire.end();
|
||||||
|
#ifdef I2C_SDA1
|
||||||
|
Wire1.end();
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO("%i I2C devices found\n", i2cCount);
|
LOG_INFO("%i I2C devices found\n", i2cCount);
|
||||||
}
|
}
|
||||||
@ -576,10 +586,13 @@ void setup()
|
|||||||
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
|
||||||
nodeDB.init();
|
nodeDB.init();
|
||||||
|
|
||||||
// If we're taking on the repeater role, use flood router
|
// If we're taking on the repeater role, use flood router and turn off 3V3_S rail because peripherals are not needed
|
||||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER)
|
if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||||
router = new FloodingRouter();
|
router = new FloodingRouter();
|
||||||
else
|
#ifdef PIN_3V3_EN
|
||||||
|
digitalWrite(PIN_3V3_EN, LOW);
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
router = new ReliableRouter();
|
router = new ReliableRouter();
|
||||||
|
|
||||||
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
|
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI)
|
||||||
@ -656,7 +669,10 @@ void setup()
|
|||||||
|
|
||||||
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time)
|
||||||
|
|
||||||
gps = GPS::createGps();
|
// If we're taking on the repeater role, ignore GPS
|
||||||
|
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||||
|
gps = GPS::createGps();
|
||||||
|
}
|
||||||
if (gps) {
|
if (gps) {
|
||||||
gpsStatus->observe(&gps->newStatus);
|
gpsStatus->observe(&gps->newStatus);
|
||||||
} else {
|
} else {
|
||||||
@ -664,6 +680,11 @@ void setup()
|
|||||||
}
|
}
|
||||||
nodeStatus->observe(&nodeDB.newStatus);
|
nodeStatus->observe(&nodeDB.newStatus);
|
||||||
|
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
LOG_DEBUG("Starting audio thread\n");
|
||||||
|
audioThread = new AudioThread();
|
||||||
|
#endif
|
||||||
|
|
||||||
service.init();
|
service.init();
|
||||||
|
|
||||||
// Now that the mesh service is created, create any modules
|
// Now that the mesh service is created, create any modules
|
||||||
@ -873,7 +894,6 @@ void setup()
|
|||||||
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
|
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
|
||||||
PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS
|
PowerFSM_setup(); // we will transition to ON in a couple of seconds, FIXME, only do this for cold boots, not waking from SDS
|
||||||
powerFSMthread = new PowerFSMThread();
|
powerFSMthread = new PowerFSMThread();
|
||||||
|
|
||||||
setCPUFast(false); // 80MHz is fine for our slow peripherals
|
setCPUFast(false); // 80MHz is fine for our slow peripherals
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -944,4 +964,4 @@ void loop()
|
|||||||
mainDelay.delay(delayMsec);
|
mainDelay.delay(delayMsec);
|
||||||
}
|
}
|
||||||
// if (didWake) LOG_DEBUG("wake!\n");
|
// if (didWake) LOG_DEBUG("wake!\n");
|
||||||
}
|
}
|
@ -42,6 +42,12 @@ extern ATECCX08A atecc;
|
|||||||
#include <Adafruit_DRV2605.h>
|
#include <Adafruit_DRV2605.h>
|
||||||
extern Adafruit_DRV2605 drv;
|
extern Adafruit_DRV2605 drv;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
#include "AudioThread.h"
|
||||||
|
extern AudioThread *audioThread;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern bool isVibrating;
|
extern bool isVibrating;
|
||||||
|
|
||||||
extern int TCPPort; // set by Portduino
|
extern int TCPPort; // set by Portduino
|
||||||
|
@ -73,58 +73,3 @@ template <class T> class MemoryDynamic : public Allocator<T>
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* A pool based allocator
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
template <class T> class MemoryPool : public Allocator<T>
|
|
||||||
{
|
|
||||||
PointerQueue<T> dead;
|
|
||||||
|
|
||||||
T *buf; // our large raw block of memory
|
|
||||||
|
|
||||||
size_t maxElements;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MemoryPool(size_t _maxElements) : dead(_maxElements), maxElements(_maxElements)
|
|
||||||
{
|
|
||||||
buf = new T[maxElements];
|
|
||||||
|
|
||||||
// prefill dead
|
|
||||||
for (size_t i = 0; i < maxElements; i++)
|
|
||||||
release(&buf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
~MemoryPool() { delete[] buf; }
|
|
||||||
|
|
||||||
/// Return a buffer for use by others
|
|
||||||
void release(T *p)
|
|
||||||
{
|
|
||||||
assert(p >= buf &&
|
|
||||||
(size_t)(p - buf) <
|
|
||||||
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
|
|
||||||
assert(dead.enqueue(p, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAS_FREE_RTOS
|
|
||||||
/// Return a buffer from an ISR, if higherPriWoken is set to true you have some work to do ;-)
|
|
||||||
void releaseFromISR(T *p, BaseType_t *higherPriWoken)
|
|
||||||
{
|
|
||||||
assert(p >= buf &&
|
|
||||||
(size_t)(p - buf) <
|
|
||||||
maxElements); // sanity check to make sure a programmer didn't free something that didn't come from this pool
|
|
||||||
assert(dead.enqueueFromISR(p, higherPriWoken));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/// Return a queable object which has been prefilled with zeros - allow timeout to wait for available buffers (you
|
|
||||||
/// probably don't want this version).
|
|
||||||
virtual T *alloc(TickType_t maxWait)
|
|
||||||
{
|
|
||||||
T *p = dead.dequeuePtr(maxWait);
|
|
||||||
assert(p);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -140,6 +140,22 @@ void MeshService::reloadOwner(bool shouldSave)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search the queue for a request id and return the matching nodenum
|
||||||
|
NodeNum MeshService::getNodenumFromRequestId(uint32_t request_id)
|
||||||
|
{
|
||||||
|
NodeNum nodenum = 0;
|
||||||
|
for (int i = 0; i < toPhoneQueue.numUsed(); i++) {
|
||||||
|
meshtastic_MeshPacket *p = toPhoneQueue.dequeuePtr(0);
|
||||||
|
if (p->id == request_id) {
|
||||||
|
nodenum = p->to;
|
||||||
|
// make sure to continue this to make one full loop
|
||||||
|
}
|
||||||
|
// put it right back on the queue
|
||||||
|
toPhoneQueue.enqueue(p, 0);
|
||||||
|
}
|
||||||
|
return nodenum;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a ToRadio buffer parse it and properly handle it (setup radio, owner or send packet into the mesh)
|
* Given a ToRadio buffer parse it and properly handle it (setup radio, owner or send packet into the mesh)
|
||||||
* Called by PhoneAPI.handleToRadio. Note: p is a scratch buffer, this function is allowed to write to it but it can not keep a
|
* Called by PhoneAPI.handleToRadio. Note: p is a scratch buffer, this function is allowed to write to it but it can not keep a
|
||||||
|
@ -82,6 +82,9 @@ class MeshService
|
|||||||
/// Return the next MqttClientProxyMessage packet destined to the phone.
|
/// Return the next MqttClientProxyMessage packet destined to the phone.
|
||||||
meshtastic_MqttClientProxyMessage *getMqttClientProxyMessageForPhone() { return toPhoneMqttProxyQueue.dequeuePtr(0); }
|
meshtastic_MqttClientProxyMessage *getMqttClientProxyMessageForPhone() { return toPhoneMqttProxyQueue.dequeuePtr(0); }
|
||||||
|
|
||||||
|
// search the queue for a request id and return the matching nodenum
|
||||||
|
NodeNum getNodenumFromRequestId(uint32_t request_id);
|
||||||
|
|
||||||
// Release QueueStatus packet to pool
|
// Release QueueStatus packet to pool
|
||||||
void releaseQueueStatusToPool(meshtastic_QueueStatus *p) { queueStatusPool.release(p); }
|
void releaseQueueStatusToPool(meshtastic_QueueStatus *p) { queueStatusPool.release(p); }
|
||||||
|
|
||||||
|
@ -245,9 +245,12 @@ void NodeDB::installDefaultModuleConfig()
|
|||||||
moduleConfig.external_notification.output_ms = 1000;
|
moduleConfig.external_notification.output_ms = 1000;
|
||||||
moduleConfig.external_notification.nag_timeout = 60;
|
moduleConfig.external_notification.nag_timeout = 60;
|
||||||
#endif
|
#endif
|
||||||
#ifdef T_WATCH_S3
|
#ifdef HAS_I2S
|
||||||
// Don't worry about the other settings, we'll use the DRV2056 behavior for notifications
|
// Don't worry about the other settings for T-Watch, we'll also use the DRV2056 behavior for notifications
|
||||||
moduleConfig.external_notification.enabled = true;
|
moduleConfig.external_notification.enabled = true;
|
||||||
|
moduleConfig.external_notification.use_i2s_as_buzzer = true;
|
||||||
|
moduleConfig.external_notification.alert_message_buzzer = true;
|
||||||
|
moduleConfig.external_notification.nag_timeout = 60;
|
||||||
#endif
|
#endif
|
||||||
#ifdef NANO_G2_ULTRA
|
#ifdef NANO_G2_ULTRA
|
||||||
moduleConfig.external_notification.enabled = true;
|
moduleConfig.external_notification.enabled = true;
|
||||||
@ -302,6 +305,15 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role)
|
|||||||
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED |
|
(meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE | meshtastic_Config_PositionConfig_PositionFlags_SPEED |
|
||||||
meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP);
|
meshtastic_Config_PositionConfig_PositionFlags_HEADING | meshtastic_Config_PositionConfig_PositionFlags_DOP);
|
||||||
moduleConfig.telemetry.device_update_interval = ONE_DAY;
|
moduleConfig.telemetry.device_update_interval = ONE_DAY;
|
||||||
|
} else if (role == meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||||
|
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY;
|
||||||
|
config.device.node_info_broadcast_secs = UINT32_MAX;
|
||||||
|
config.position.position_broadcast_smart_enabled = false;
|
||||||
|
config.position.position_broadcast_secs = UINT32_MAX;
|
||||||
|
moduleConfig.neighbor_info.update_interval = UINT32_MAX;
|
||||||
|
moduleConfig.telemetry.device_update_interval = UINT32_MAX;
|
||||||
|
moduleConfig.telemetry.environment_update_interval = UINT32_MAX;
|
||||||
|
moduleConfig.telemetry.air_quality_interval = UINT32_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,6 +299,12 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
|
|||||||
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING)
|
config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY &&
|
||||||
|
!nodeDB.getMeshNode(p->from)->has_user) {
|
||||||
|
LOG_DEBUG("Node 0x%x not in NodeDB. Rebroadcast mode KNOWN_ONLY will ignore packet\n", p->from);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag)
|
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag)
|
||||||
return true; // If packet was already decoded just return
|
return true; // If packet was already decoded just return
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@ template <class T> class TypedQueue
|
|||||||
|
|
||||||
bool isEmpty() { return uxQueueMessagesWaiting(h) == 0; }
|
bool isEmpty() { return uxQueueMessagesWaiting(h) == 0; }
|
||||||
|
|
||||||
|
int numUsed() { return uxQueueMessagesWaiting(h); }
|
||||||
|
|
||||||
/** euqueue a packet. Also, maxWait used to default to portMAX_DELAY, but we now want to callers to THINK about what blocking
|
/** euqueue a packet. Also, maxWait used to default to portMAX_DELAY, but we now want to callers to THINK about what blocking
|
||||||
* they want */
|
* they want */
|
||||||
bool enqueue(T x, TickType_t maxWait)
|
bool enqueue(T x, TickType_t maxWait)
|
||||||
@ -80,6 +82,8 @@ template <class T> class TypedQueue
|
|||||||
|
|
||||||
bool isEmpty() { return q.empty(); }
|
bool isEmpty() { return q.empty(); }
|
||||||
|
|
||||||
|
int numUsed() { return q.size(); }
|
||||||
|
|
||||||
bool enqueue(T x, TickType_t maxWait = portMAX_DELAY)
|
bool enqueue(T x, TickType_t maxWait = portMAX_DELAY)
|
||||||
{
|
{
|
||||||
if (reader) {
|
if (reader) {
|
||||||
|
@ -43,7 +43,18 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
|||||||
Used for nodes dedicated for connection to an ATAK EUD.
|
Used for nodes dedicated for connection to an ATAK EUD.
|
||||||
Turns off many of the routine broadcasts to favor CoT packet stream
|
Turns off many of the routine broadcasts to favor CoT packet stream
|
||||||
from the Meshtastic ATAK plugin -> IMeshService -> Node */
|
from the Meshtastic ATAK plugin -> IMeshService -> Node */
|
||||||
meshtastic_Config_DeviceConfig_Role_TAK = 7
|
meshtastic_Config_DeviceConfig_Role_TAK = 7,
|
||||||
|
/* Client Hidden device role
|
||||||
|
Used for nodes that "only speak when spoken to"
|
||||||
|
Turns all of the routine broadcasts but allows for ad-hoc communication
|
||||||
|
Still rebroadcasts, but with local only rebroadcast mode (known meshes only)
|
||||||
|
Can be used for clandestine operation or to dramatically reduce airtime / power consumption */
|
||||||
|
meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN = 8,
|
||||||
|
/* Lost and Found device role
|
||||||
|
Used to automatically send a text message to the mesh
|
||||||
|
with the current position of the device on a frequent interval:
|
||||||
|
"I'm lost! Position: lat / long" */
|
||||||
|
meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND = 9
|
||||||
} meshtastic_Config_DeviceConfig_Role;
|
} meshtastic_Config_DeviceConfig_Role;
|
||||||
|
|
||||||
/* Defines the device's behavior for how messages are rebroadcast */
|
/* Defines the device's behavior for how messages are rebroadcast */
|
||||||
@ -56,7 +67,10 @@ typedef enum _meshtastic_Config_DeviceConfig_RebroadcastMode {
|
|||||||
meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING = 1,
|
meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING = 1,
|
||||||
/* Ignores observed messages from foreign meshes that are open or those which it cannot decrypt.
|
/* Ignores observed messages from foreign meshes that are open or those which it cannot decrypt.
|
||||||
Only rebroadcasts message on the nodes local primary / secondary channels. */
|
Only rebroadcasts message on the nodes local primary / secondary channels. */
|
||||||
meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY = 2
|
meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY = 2,
|
||||||
|
/* Ignores observed messages from foreign meshes like LOCAL_ONLY,
|
||||||
|
but takes it step further by also ignoring messages from nodenums not in the node's known list (NodeDB) */
|
||||||
|
meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY = 3
|
||||||
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
} meshtastic_Config_DeviceConfig_RebroadcastMode;
|
||||||
|
|
||||||
/* Bit field of boolean configuration options, indicating which optional
|
/* Bit field of boolean configuration options, indicating which optional
|
||||||
@ -479,12 +493,12 @@ extern "C" {
|
|||||||
|
|
||||||
/* Helper constants for enums */
|
/* Helper constants for enums */
|
||||||
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
|
#define _meshtastic_Config_DeviceConfig_Role_MIN meshtastic_Config_DeviceConfig_Role_CLIENT
|
||||||
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_TAK
|
#define _meshtastic_Config_DeviceConfig_Role_MAX meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND
|
||||||
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_TAK+1))
|
#define _meshtastic_Config_DeviceConfig_Role_ARRAYSIZE ((meshtastic_Config_DeviceConfig_Role)(meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN meshtastic_Config_DeviceConfig_RebroadcastMode_ALL
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_MAX meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY
|
||||||
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY+1))
|
#define _meshtastic_Config_DeviceConfig_RebroadcastMode_ARRAYSIZE ((meshtastic_Config_DeviceConfig_RebroadcastMode)(meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY+1))
|
||||||
|
|
||||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET
|
#define _meshtastic_Config_PositionConfig_PositionFlags_MIN meshtastic_Config_PositionConfig_PositionFlags_UNSET
|
||||||
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
|
#define _meshtastic_Config_PositionConfig_PositionFlags_MAX meshtastic_Config_PositionConfig_PositionFlags_SPEED
|
||||||
|
@ -67,6 +67,10 @@ typedef enum _meshtastic_HardwareModel {
|
|||||||
meshtastic_HardwareModel_STATION_G1 = 25,
|
meshtastic_HardwareModel_STATION_G1 = 25,
|
||||||
/* RAK11310 (RP2040 + SX1262) */
|
/* RAK11310 (RP2040 + SX1262) */
|
||||||
meshtastic_HardwareModel_RAK11310 = 26,
|
meshtastic_HardwareModel_RAK11310 = 26,
|
||||||
|
/* Makerfabs SenseLoRA Receiver (RP2040 + RFM96) */
|
||||||
|
meshtastic_HardwareModel_SENSELORA_RP2040 = 27,
|
||||||
|
/* Makerfabs SenseLoRA Industrial Monitor (ESP32-S3 + RFM96) */
|
||||||
|
meshtastic_HardwareModel_SENSELORA_S3 = 28,
|
||||||
/* ---------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------
|
||||||
Less common/prototype boards listed here (needs one more byte over the air)
|
Less common/prototype boards listed here (needs one more byte over the air)
|
||||||
--------------------------------------------------------------------------- */
|
--------------------------------------------------------------------------- */
|
||||||
|
@ -9,13 +9,11 @@
|
|||||||
#include "target_specific.h"
|
#include "target_specific.h"
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
#ifndef ARCH_RP2040
|
#ifdef ARCH_ESP32
|
||||||
#include "mesh/http/WebServer.h"
|
#include "mesh/http/WebServer.h"
|
||||||
#include <ESPmDNS.h>
|
#include <ESPmDNS.h>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
static void WiFiEvent(WiFiEvent_t event);
|
static void WiFiEvent(WiFiEvent_t event);
|
||||||
#else
|
|
||||||
#include <ESP8266mDNS.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_NTP
|
#ifndef DISABLE_NTP
|
||||||
@ -53,6 +51,7 @@ static void onNetworkConnected()
|
|||||||
// Start web server
|
// Start web server
|
||||||
LOG_INFO("Starting network services\n");
|
LOG_INFO("Starting network services\n");
|
||||||
|
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
// start mdns
|
// start mdns
|
||||||
if (!MDNS.begin("Meshtastic")) {
|
if (!MDNS.begin("Meshtastic")) {
|
||||||
LOG_ERROR("Error setting up MDNS responder!\n");
|
LOG_ERROR("Error setting up MDNS responder!\n");
|
||||||
@ -62,6 +61,9 @@ static void onNetworkConnected()
|
|||||||
MDNS.addService("http", "tcp", 80);
|
MDNS.addService("http", "tcp", 80);
|
||||||
MDNS.addService("https", "tcp", 443);
|
MDNS.addService("https", "tcp", 443);
|
||||||
}
|
}
|
||||||
|
#else // ESP32 handles this in WiFiEvent
|
||||||
|
LOG_INFO("Obtained IP address: %s\n", WiFi.localIP().toString().c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DISABLE_NTP
|
#ifndef DISABLE_NTP
|
||||||
LOG_INFO("Starting NTP time client\n");
|
LOG_INFO("Starting NTP time client\n");
|
||||||
@ -89,7 +91,7 @@ static void onNetworkConnected()
|
|||||||
syslog.enable();
|
syslog.enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ARCH_RP2040
|
#ifdef ARCH_ESP32
|
||||||
initWebServer();
|
initWebServer();
|
||||||
#endif
|
#endif
|
||||||
initApiServer();
|
initApiServer();
|
||||||
@ -149,6 +151,11 @@ static int32_t reconnectWiFi()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (config.network.wifi_enabled && !WiFi.isConnected()) {
|
if (config.network.wifi_enabled && !WiFi.isConnected()) {
|
||||||
|
#ifdef ARCH_RP2040 // (ESP32 handles this in WiFiEvent)
|
||||||
|
/* If APStartupComplete, but we're not connected, try again.
|
||||||
|
Shouldn't try again before APStartupComplete. */
|
||||||
|
needReconnect = APStartupComplete;
|
||||||
|
#endif
|
||||||
return 1000; // check once per second
|
return 1000; // check once per second
|
||||||
} else {
|
} else {
|
||||||
#ifdef ARCH_RP2040
|
#ifdef ARCH_RP2040
|
||||||
@ -245,7 +252,7 @@ bool initWifi()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ARCH_RP2040
|
#ifdef ARCH_ESP32
|
||||||
// Called by the Espressif SDK to
|
// Called by the Espressif SDK to
|
||||||
static void WiFiEvent(WiFiEvent_t event)
|
static void WiFiEvent(WiFiEvent_t event)
|
||||||
{
|
{
|
||||||
@ -279,11 +286,11 @@ static void WiFiEvent(WiFiEvent_t event)
|
|||||||
LOG_INFO("Authentication mode of access point has changed\n");
|
LOG_INFO("Authentication mode of access point has changed\n");
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
LOG_INFO("Obtained IP address: ", WiFi.localIPv6());
|
LOG_INFO("Obtained IP address: %s\n", WiFi.localIP().toString().c_str());
|
||||||
onNetworkConnected();
|
onNetworkConnected();
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||||
LOG_INFO("Obtained IP6 address: %s", WiFi.localIPv6());
|
LOG_INFO("Obtained IP6 address: %s\n", WiFi.localIPv6().toString().c_str());
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||||
LOG_INFO("Lost IP address and IP address is reset to 0\n");
|
LOG_INFO("Lost IP address and IP address is reset to 0\n");
|
||||||
@ -391,4 +398,4 @@ static void WiFiEvent(WiFiEvent_t event)
|
|||||||
uint8_t getWifiDisconnectReason()
|
uint8_t getWifiDisconnectReason()
|
||||||
{
|
{
|
||||||
return wifiDisconnectReason;
|
return wifiDisconnectReason;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,9 @@ void CannedMessageModule::sendText(NodeNum dest, const char *message, bool wantR
|
|||||||
|
|
||||||
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
|
||||||
|
|
||||||
service.sendToMesh(p);
|
service.sendToMesh(
|
||||||
|
p, RX_SRC_LOCAL,
|
||||||
|
true); // send to mesh, cc to phone. Even if there's no phone connected, this stores the message to match ACKs
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CannedMessageModule::runOnce()
|
int32_t CannedMessageModule::runOnce()
|
||||||
@ -244,7 +246,8 @@ int32_t CannedMessageModule::runOnce()
|
|||||||
}
|
}
|
||||||
// LOG_DEBUG("Check status\n");
|
// LOG_DEBUG("Check status\n");
|
||||||
UIFrameEvent e = {false, true};
|
UIFrameEvent e = {false, true};
|
||||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
if ((this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) ||
|
||||||
|
(this->runState == CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED)) {
|
||||||
// TODO: might have some feedback of sendig state
|
// TODO: might have some feedback of sendig state
|
||||||
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
this->runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||||
e.frameChanged = true;
|
e.frameChanged = true;
|
||||||
@ -483,7 +486,18 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
|||||||
{
|
{
|
||||||
char buffer[50];
|
char buffer[50];
|
||||||
|
|
||||||
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED) {
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
String displayString;
|
||||||
|
if (this->ack) {
|
||||||
|
displayString = "Delivered to\n%s";
|
||||||
|
} else {
|
||||||
|
displayString = "Delivery failed\nto %s";
|
||||||
|
}
|
||||||
|
display->drawStringf(display->getWidth() / 2 + x, 0 + y + 12, buffer, displayString,
|
||||||
|
cannedMessageModule->getNodeName(this->incoming));
|
||||||
|
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
display->setFont(FONT_MEDIUM);
|
display->setFont(FONT_MEDIUM);
|
||||||
display->drawString(display->getWidth() / 2 + x, 0 + y + 12, "Sending...");
|
display->drawString(display->getWidth() / 2 + x, 0 + y + 12, "Sending...");
|
||||||
@ -546,6 +560,27 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||||
|
{
|
||||||
|
if (mp.decoded.portnum == meshtastic_PortNum_ROUTING_APP) {
|
||||||
|
// look for a request_id
|
||||||
|
if (mp.decoded.request_id != 0) {
|
||||||
|
UIFrameEvent e = {false, true};
|
||||||
|
e.frameChanged = true;
|
||||||
|
this->runState = CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED;
|
||||||
|
this->incoming = service.getNodenumFromRequestId(mp.decoded.request_id);
|
||||||
|
meshtastic_Routing decoded = meshtastic_Routing_init_default;
|
||||||
|
pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_Routing_fields, &decoded);
|
||||||
|
this->ack = decoded.error_reason == meshtastic_Routing_Error_NONE;
|
||||||
|
this->notifyObservers(&e);
|
||||||
|
// run the next time 2 seconds later
|
||||||
|
setIntervalFromNow(2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessMessage::CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
void CannedMessageModule::loadProtoForModule()
|
void CannedMessageModule::loadProtoForModule()
|
||||||
{
|
{
|
||||||
if (!nodeDB.loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
if (!nodeDB.loadProto(cannedMessagesConfigFile, meshtastic_CannedMessageModuleConfig_size,
|
||||||
@ -650,4 +685,4 @@ String CannedMessageModule::drawWithCursor(String text, int cursor)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -9,6 +9,7 @@ enum cannedMessageModuleRunState {
|
|||||||
CANNED_MESSAGE_RUN_STATE_ACTIVE,
|
CANNED_MESSAGE_RUN_STATE_ACTIVE,
|
||||||
CANNED_MESSAGE_RUN_STATE_FREETEXT,
|
CANNED_MESSAGE_RUN_STATE_FREETEXT,
|
||||||
CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE,
|
CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE,
|
||||||
|
CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED,
|
||||||
CANNED_MESSAGE_RUN_STATE_ACTION_SELECT,
|
CANNED_MESSAGE_RUN_STATE_ACTION_SELECT,
|
||||||
CANNED_MESSAGE_RUN_STATE_ACTION_UP,
|
CANNED_MESSAGE_RUN_STATE_ACTION_UP,
|
||||||
CANNED_MESSAGE_RUN_STATE_ACTION_DOWN,
|
CANNED_MESSAGE_RUN_STATE_ACTION_DOWN,
|
||||||
@ -37,15 +38,29 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
|||||||
const char *getMessageByIndex(int index);
|
const char *getMessageByIndex(int index);
|
||||||
const char *getNodeName(NodeNum node);
|
const char *getNodeName(NodeNum node);
|
||||||
bool shouldDraw();
|
bool shouldDraw();
|
||||||
void eventUp();
|
// void eventUp();
|
||||||
void eventDown();
|
// void eventDown();
|
||||||
void eventSelect();
|
// void eventSelect();
|
||||||
|
|
||||||
void handleGetCannedMessageModuleMessages(const meshtastic_MeshPacket &req, meshtastic_AdminMessage *response);
|
void handleGetCannedMessageModuleMessages(const meshtastic_MeshPacket &req, meshtastic_AdminMessage *response);
|
||||||
void handleSetCannedMessageModuleMessages(const char *from_msg);
|
void handleSetCannedMessageModuleMessages(const char *from_msg);
|
||||||
|
|
||||||
String drawWithCursor(String text, int cursor);
|
String drawWithCursor(String text, int cursor);
|
||||||
|
|
||||||
|
/*
|
||||||
|
-Override the wantPacket method. We need the Routing Messages to look for ACKs.
|
||||||
|
*/
|
||||||
|
virtual bool wantPacket(const meshtastic_MeshPacket *p) override
|
||||||
|
{
|
||||||
|
switch (p->decoded.portnum) {
|
||||||
|
case meshtastic_PortNum_TEXT_MESSAGE_APP:
|
||||||
|
case meshtastic_PortNum_ROUTING_APP:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int32_t runOnce() override;
|
virtual int32_t runOnce() override;
|
||||||
|
|
||||||
@ -63,6 +78,12 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
|||||||
meshtastic_AdminMessage *request,
|
meshtastic_AdminMessage *request,
|
||||||
meshtastic_AdminMessage *response) override;
|
meshtastic_AdminMessage *response) override;
|
||||||
|
|
||||||
|
/** Called to handle a particular incoming message
|
||||||
|
* @return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered
|
||||||
|
* for it
|
||||||
|
*/
|
||||||
|
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||||
|
|
||||||
void loadProtoForModule();
|
void loadProtoForModule();
|
||||||
bool saveProtoForModule();
|
bool saveProtoForModule();
|
||||||
|
|
||||||
@ -75,6 +96,8 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
|||||||
String freetext = ""; // Text Buffer for Freetext Editor
|
String freetext = ""; // Text Buffer for Freetext Editor
|
||||||
bool destSelect = false; // Freetext Editor Mode
|
bool destSelect = false; // Freetext Editor Mode
|
||||||
NodeNum dest = NODENUM_BROADCAST;
|
NodeNum dest = NODENUM_BROADCAST;
|
||||||
|
NodeNum incoming = NODENUM_BROADCAST;
|
||||||
|
bool ack = false; // True means ACK, false means NAK (error_reason != NONE)
|
||||||
|
|
||||||
char messageStore[CANNED_MESSAGE_MODULE_MESSAGES_SIZE + 1];
|
char messageStore[CANNED_MESSAGE_MODULE_MESSAGES_SIZE + 1];
|
||||||
char *messages[CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT];
|
char *messages[CANNED_MESSAGE_MODULE_MESSAGE_MAX_COUNT];
|
||||||
@ -83,4 +106,4 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern CannedMessageModule *cannedMessageModule;
|
extern CannedMessageModule *cannedMessageModule;
|
||||||
#endif
|
#endif
|
@ -20,11 +20,10 @@
|
|||||||
#include "Router.h"
|
#include "Router.h"
|
||||||
#include "buzz/buzz.h"
|
#include "buzz/buzz.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#include "main.h"
|
||||||
#include "mesh/generated/meshtastic/rtttl.pb.h"
|
#include "mesh/generated/meshtastic/rtttl.pb.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
#include <graphics/RAKled.h>
|
#include <graphics/RAKled.h>
|
||||||
|
|
||||||
@ -54,6 +53,8 @@ bool ascending = true;
|
|||||||
#endif
|
#endif
|
||||||
#define EXT_NOTIFICATION_MODULE_OUTPUT_MS 1000
|
#define EXT_NOTIFICATION_MODULE_OUTPUT_MS 1000
|
||||||
|
|
||||||
|
#define EXT_NOTIFICATION_DEFAULT_THREAD_MS 25
|
||||||
|
|
||||||
#define ASCII_BELL 0x07
|
#define ASCII_BELL 0x07
|
||||||
|
|
||||||
meshtastic_RTTTLConfig rtttlConfig;
|
meshtastic_RTTTLConfig rtttlConfig;
|
||||||
@ -71,7 +72,12 @@ int32_t ExternalNotificationModule::runOnce()
|
|||||||
if (!moduleConfig.external_notification.enabled) {
|
if (!moduleConfig.external_notification.enabled) {
|
||||||
return INT32_MAX; // we don't need this thread here...
|
return INT32_MAX; // we don't need this thread here...
|
||||||
} else {
|
} else {
|
||||||
if ((nagCycleCutoff < millis()) && !rtttl::isPlaying()) {
|
|
||||||
|
bool isPlaying = rtttl::isPlaying();
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
isPlaying = rtttl::isPlaying() || audioThread->isPlaying();
|
||||||
|
#endif
|
||||||
|
if ((nagCycleCutoff < millis()) && !isPlaying) {
|
||||||
// let the song finish if we reach timeout
|
// let the song finish if we reach timeout
|
||||||
nagCycleCutoff = UINT32_MAX;
|
nagCycleCutoff = UINT32_MAX;
|
||||||
LOG_INFO("Turning off external notification: ");
|
LOG_INFO("Turning off external notification: ");
|
||||||
@ -132,6 +138,16 @@ int32_t ExternalNotificationModule::runOnce()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Play RTTTL over i2s audio interface if enabled as buzzer
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
if (moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||||
|
if (audioThread->isPlaying()) {
|
||||||
|
// Continue playing
|
||||||
|
} else if (isNagging && (nagCycleCutoff >= millis())) {
|
||||||
|
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// now let the PWM buzzer play
|
// now let the PWM buzzer play
|
||||||
if (moduleConfig.external_notification.use_pwm) {
|
if (moduleConfig.external_notification.use_pwm) {
|
||||||
if (rtttl::isPlaying()) {
|
if (rtttl::isPlaying()) {
|
||||||
@ -142,7 +158,7 @@ int32_t ExternalNotificationModule::runOnce()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 25;
|
return EXT_NOTIFICATION_DEFAULT_THREAD_MS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +191,7 @@ void ExternalNotificationModule::setExternalOn(uint8_t index)
|
|||||||
digitalWrite(output, (moduleConfig.external_notification.active ? true : false));
|
digitalWrite(output, (moduleConfig.external_notification.active ? true : false));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
if (rgb_found.type == ScanI2C::NCP5623) {
|
if (rgb_found.type == ScanI2C::NCP5623) {
|
||||||
rgb.setColor(red, green, blue);
|
rgb.setColor(red, green, blue);
|
||||||
@ -226,6 +243,9 @@ bool ExternalNotificationModule::getExternal(uint8_t index)
|
|||||||
void ExternalNotificationModule::stopNow()
|
void ExternalNotificationModule::stopNow()
|
||||||
{
|
{
|
||||||
rtttl::stop();
|
rtttl::stop();
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
audioThread->stop();
|
||||||
|
#endif
|
||||||
nagCycleCutoff = 1; // small value
|
nagCycleCutoff = 1; // small value
|
||||||
isNagging = false;
|
isNagging = false;
|
||||||
setIntervalFromNow(0);
|
setIntervalFromNow(0);
|
||||||
@ -246,6 +266,7 @@ ExternalNotificationModule::ExternalNotificationModule()
|
|||||||
// moduleConfig.external_notification.alert_message = true;
|
// moduleConfig.external_notification.alert_message = true;
|
||||||
// moduleConfig.external_notification.alert_message_buzzer = true;
|
// moduleConfig.external_notification.alert_message_buzzer = true;
|
||||||
// moduleConfig.external_notification.alert_message_vibra = true;
|
// moduleConfig.external_notification.alert_message_vibra = true;
|
||||||
|
// moduleConfig.external_notification.use_i2s_as_buzzer = true;
|
||||||
|
|
||||||
// moduleConfig.external_notification.active = true;
|
// moduleConfig.external_notification.active = true;
|
||||||
// moduleConfig.external_notification.alert_bell = 1;
|
// moduleConfig.external_notification.alert_bell = 1;
|
||||||
@ -255,6 +276,13 @@ ExternalNotificationModule::ExternalNotificationModule()
|
|||||||
// moduleConfig.external_notification.output_vibra = 28; // RAK4631 IO7
|
// moduleConfig.external_notification.output_vibra = 28; // RAK4631 IO7
|
||||||
// moduleConfig.external_notification.nag_timeout = 300;
|
// moduleConfig.external_notification.nag_timeout = 300;
|
||||||
|
|
||||||
|
// T-Watch / T-Deck i2s audio as buzzer:
|
||||||
|
// moduleConfig.external_notification.enabled = true;
|
||||||
|
// moduleConfig.external_notification.nag_timeout = 300;
|
||||||
|
// moduleConfig.external_notification.output_ms = 1000;
|
||||||
|
// moduleConfig.external_notification.use_i2s_as_buzzer = true;
|
||||||
|
// moduleConfig.external_notification.alert_message_buzzer = true;
|
||||||
|
|
||||||
if (moduleConfig.external_notification.enabled) {
|
if (moduleConfig.external_notification.enabled) {
|
||||||
if (!nodeDB.loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig),
|
if (!nodeDB.loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig),
|
||||||
&meshtastic_RTTTLConfig_msg, &rtttlConfig)) {
|
&meshtastic_RTTTLConfig_msg, &rtttlConfig)) {
|
||||||
@ -309,14 +337,13 @@ ExternalNotificationModule::ExternalNotificationModule()
|
|||||||
ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshPacket &mp)
|
ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||||
{
|
{
|
||||||
if (moduleConfig.external_notification.enabled) {
|
if (moduleConfig.external_notification.enabled) {
|
||||||
#if T_WATCH_S3
|
#ifdef T_WATCH_S3
|
||||||
drv.setWaveform(0, 75);
|
drv.setWaveform(0, 75);
|
||||||
drv.setWaveform(1, 56);
|
drv.setWaveform(1, 56);
|
||||||
drv.setWaveform(2, 0);
|
drv.setWaveform(2, 0);
|
||||||
drv.go();
|
drv.go();
|
||||||
#endif
|
#endif
|
||||||
if (getFrom(&mp) != nodeDB.getNodeNum()) {
|
if (getFrom(&mp) != nodeDB.getNodeNum()) {
|
||||||
|
|
||||||
// Check if the message contains a bell character. Don't do this loop for every pin, just once.
|
// Check if the message contains a bell character. Don't do this loop for every pin, just once.
|
||||||
auto &p = mp.decoded;
|
auto &p = mp.decoded;
|
||||||
bool containsBell = false;
|
bool containsBell = false;
|
||||||
@ -359,7 +386,11 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
if (!moduleConfig.external_notification.use_pwm) {
|
if (!moduleConfig.external_notification.use_pwm) {
|
||||||
setExternalOn(2);
|
setExternalOn(2);
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
||||||
|
#else
|
||||||
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (moduleConfig.external_notification.nag_timeout) {
|
if (moduleConfig.external_notification.nag_timeout) {
|
||||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||||
@ -394,10 +425,16 @@ ProcessMessage ExternalNotificationModule::handleReceived(const meshtastic_MeshP
|
|||||||
if (moduleConfig.external_notification.alert_message_buzzer) {
|
if (moduleConfig.external_notification.alert_message_buzzer) {
|
||||||
LOG_INFO("externalNotificationModule - Notification Module (Buzzer)\n");
|
LOG_INFO("externalNotificationModule - Notification Module (Buzzer)\n");
|
||||||
isNagging = true;
|
isNagging = true;
|
||||||
if (!moduleConfig.external_notification.use_pwm) {
|
if (!moduleConfig.external_notification.use_pwm && !moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||||
setExternalOn(2);
|
setExternalOn(2);
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
if (moduleConfig.external_notification.use_i2s_as_buzzer) {
|
||||||
|
audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone));
|
||||||
|
}
|
||||||
|
#else
|
||||||
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (moduleConfig.external_notification.nag_timeout) {
|
if (moduleConfig.external_notification.nag_timeout) {
|
||||||
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
nagCycleCutoff = millis() + moduleConfig.external_notification.nag_timeout * 1000;
|
||||||
|
@ -89,7 +89,7 @@ int32_t NodeInfoModule::runOnce()
|
|||||||
bool requestReplies = currentGeneration != radioGeneration;
|
bool requestReplies = currentGeneration != radioGeneration;
|
||||||
currentGeneration = radioGeneration;
|
currentGeneration = radioGeneration;
|
||||||
|
|
||||||
if (airTime->isTxAllowedAirUtil()) {
|
if (airTime->isTxAllowedAirUtil() && config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||||
LOG_INFO("Sending our nodeinfo to mesh (wantReplies=%d)\n", requestReplies);
|
LOG_INFO("Sending our nodeinfo to mesh (wantReplies=%d)\n", requestReplies);
|
||||||
sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
sendOurNodeInfo(NODENUM_BROADCAST, requestReplies); // Send our info (don't request replies)
|
||||||
}
|
}
|
||||||
|
@ -46,5 +46,6 @@ void RoutingModule::sendAckNak(meshtastic_Routing_Error err, NodeNum to, PacketI
|
|||||||
RoutingModule::RoutingModule() : ProtobufModule("routing", meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg)
|
RoutingModule::RoutingModule() : ProtobufModule("routing", meshtastic_PortNum_ROUTING_APP, &meshtastic_Routing_msg)
|
||||||
{
|
{
|
||||||
isPromiscuous = true;
|
isPromiscuous = true;
|
||||||
encryptedOk = config.device.rebroadcast_mode != meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY;
|
encryptedOk = config.device.rebroadcast_mode != meshtastic_Config_DeviceConfig_RebroadcastMode_LOCAL_ONLY &&
|
||||||
|
config.device.rebroadcast_mode != meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ int32_t DeviceTelemetryModule::runOnce()
|
|||||||
if (((lastSentToMesh == 0) ||
|
if (((lastSentToMesh == 0) ||
|
||||||
((now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))) &&
|
((now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.device_update_interval))) &&
|
||||||
airTime->isTxAllowedChannelUtil() && airTime->isTxAllowedAirUtil() &&
|
airTime->isTxAllowedChannelUtil() && airTime->isTxAllowedAirUtil() &&
|
||||||
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER &&
|
||||||
|
config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
|
||||||
sendTelemetry();
|
sendTelemetry();
|
||||||
lastSentToMesh = now;
|
lastSentToMesh = now;
|
||||||
} else if (service.isToPhoneQueueEmpty()) {
|
} else if (service.isToPhoneQueueEmpty()) {
|
||||||
|
@ -97,9 +97,9 @@ int32_t EnvironmentTelemetryModule::runOnce()
|
|||||||
result = lps22hbSensor.runOnce();
|
result = lps22hbSensor.runOnce();
|
||||||
if (sht31Sensor.hasSensor())
|
if (sht31Sensor.hasSensor())
|
||||||
result = sht31Sensor.runOnce();
|
result = sht31Sensor.runOnce();
|
||||||
if (ina219Sensor.hasSensor() && !ina219Sensor.isInitialized())
|
if (ina219Sensor.hasSensor())
|
||||||
result = ina219Sensor.runOnce();
|
result = ina219Sensor.runOnce();
|
||||||
if (ina260Sensor.hasSensor() && !ina260Sensor.isInitialized())
|
if (ina260Sensor.hasSensor())
|
||||||
result = ina260Sensor.runOnce();
|
result = ina260Sensor.runOnce();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -121,6 +121,10 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3
|
#define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3
|
||||||
#elif defined(HELTEC_HT62)
|
#elif defined(HELTEC_HT62)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
|
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
|
||||||
|
#elif defined(SENSELORA_S3)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_SENSELORA_S3
|
||||||
|
#elif defined(HELTEC_HT62)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_HELTEC_HT62
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -211,6 +211,7 @@ void NRF52Bluetooth::shutdown()
|
|||||||
// Shutdown bluetooth for minimum power draw
|
// Shutdown bluetooth for minimum power draw
|
||||||
LOG_INFO("Disable NRF52 bluetooth\n");
|
LOG_INFO("Disable NRF52 bluetooth\n");
|
||||||
Bluefruit.Advertising.stop();
|
Bluefruit.Advertising.stop();
|
||||||
|
Bluefruit.setTxPower(0); // Minimum power
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NRF52Bluetooth::isConnected()
|
bool NRF52Bluetooth::isConnected()
|
||||||
@ -333,4 +334,4 @@ void NRF52Bluetooth::onPairingCompleted(uint16_t conn_handle, uint8_t auth_statu
|
|||||||
LOG_INFO("BLE pairing failed\n");
|
LOG_INFO("BLE pairing failed\n");
|
||||||
|
|
||||||
screen->stopBluetoothPinScreen();
|
screen->stopBluetoothPinScreen();
|
||||||
}
|
}
|
@ -25,4 +25,6 @@
|
|||||||
#define HW_VENDOR meshtastic_HardwareModel_RPI_PICO
|
#define HW_VENDOR meshtastic_HardwareModel_RPI_PICO
|
||||||
#elif defined(RAK11310)
|
#elif defined(RAK11310)
|
||||||
#define HW_VENDOR meshtastic_HardwareModel_RAK11310
|
#define HW_VENDOR meshtastic_HardwareModel_RAK11310
|
||||||
|
#elif defined(SENSELORA_RP2040)
|
||||||
|
#define HW_VENDOR meshtastic_HardwareModel_SENSELORA_RP2040
|
||||||
#endif
|
#endif
|
@ -49,4 +49,5 @@ virtualCallInConstructor
|
|||||||
|
|
||||||
passedByValue:*/RedirectablePrint.h
|
passedByValue:*/RedirectablePrint.h
|
||||||
|
|
||||||
internalAstError:*/CrossPlatformCryptoEngine.cpp
|
internalAstError:*/CrossPlatformCryptoEngine.cpp
|
||||||
|
uninitMemberVar:*/AudioThread.h
|
50
variants/senselora_rp2040/pins_arduino.h
Normal file
50
variants/senselora_rp2040/pins_arduino.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define PIN_A0 (26u)
|
||||||
|
#define PIN_A1 (27u)
|
||||||
|
#define PIN_A2 (28u)
|
||||||
|
#define PIN_A3 (29u)
|
||||||
|
|
||||||
|
static const uint8_t A0 = PIN_A0;
|
||||||
|
static const uint8_t A1 = PIN_A1;
|
||||||
|
static const uint8_t A2 = PIN_A2;
|
||||||
|
static const uint8_t A3 = PIN_A3;
|
||||||
|
|
||||||
|
// LEDs
|
||||||
|
#define PIN_LED (23u)
|
||||||
|
#define PIN_LED1 PIN_LED
|
||||||
|
#define LED_BUILTIN PIN_LED
|
||||||
|
|
||||||
|
#define ADC_RESOLUTION 12
|
||||||
|
|
||||||
|
// Serial
|
||||||
|
#define PIN_SERIAL1_TX (0ul)
|
||||||
|
#define PIN_SERIAL1_RX (1ul)
|
||||||
|
|
||||||
|
#define PIN_SERIAL2_TX (4ul)
|
||||||
|
#define PIN_SERIAL2_RX (5ul)
|
||||||
|
|
||||||
|
// SPI
|
||||||
|
#define PIN_SPI0_MISO (16u)
|
||||||
|
#define PIN_SPI0_MOSI (19u)
|
||||||
|
#define PIN_SPI0_SCK (18u)
|
||||||
|
#define PIN_SPI0_SS (17u)
|
||||||
|
|
||||||
|
// Wire
|
||||||
|
#define PIN_WIRE0_SDA (6u)
|
||||||
|
#define PIN_WIRE0_SCL (7u)
|
||||||
|
|
||||||
|
#define PIN_WIRE1_SDA (-1)
|
||||||
|
#define PIN_WIRE1_SCL (-1)
|
||||||
|
|
||||||
|
#define SERIAL_HOWMANY (3u)
|
||||||
|
#define SPI_HOWMANY (2u)
|
||||||
|
#define WIRE_HOWMANY (1u)
|
||||||
|
|
||||||
|
static const uint8_t SS = PIN_SPI0_SS;
|
||||||
|
static const uint8_t MOSI = PIN_SPI0_MOSI;
|
||||||
|
static const uint8_t MISO = PIN_SPI0_MISO;
|
||||||
|
static const uint8_t SCK = PIN_SPI0_SCK;
|
||||||
|
|
||||||
|
static const uint8_t SDA = PIN_WIRE0_SDA;
|
||||||
|
static const uint8_t SCL = PIN_WIRE0_SCL;
|
13
variants/senselora_rp2040/platformio.ini
Normal file
13
variants/senselora_rp2040/platformio.ini
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[env:senselora_rp2040]
|
||||||
|
extends = rp2040_base
|
||||||
|
board = rpipico
|
||||||
|
upload_protocol = picotool
|
||||||
|
|
||||||
|
# add our variants files to the include and src paths
|
||||||
|
build_flags = ${rp2040_base.build_flags}
|
||||||
|
-DSENSELORA_RP2040
|
||||||
|
-Ivariants/senselora_rp2040
|
||||||
|
-DDEBUG_RP2040_PORT=Serial
|
||||||
|
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m0plus"
|
||||||
|
lib_deps =
|
||||||
|
${rp2040_base.lib_deps}
|
26
variants/senselora_rp2040/variant.h
Normal file
26
variants/senselora_rp2040/variant.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#define ARDUINO_ARCH_AVR
|
||||||
|
|
||||||
|
#define USE_SSD1306
|
||||||
|
|
||||||
|
#define BUTTON_PIN 2
|
||||||
|
#define BUTTON_NEED_PULLUP
|
||||||
|
|
||||||
|
#define LED_PIN PIN_LED
|
||||||
|
|
||||||
|
#undef BATTERY_PIN
|
||||||
|
|
||||||
|
#undef LORA_SCK
|
||||||
|
#undef LORA_MISO
|
||||||
|
#undef LORA_MOSI
|
||||||
|
#undef LORA_CS
|
||||||
|
|
||||||
|
#define USE_RF95
|
||||||
|
#define LORA_SCK PIN_SPI0_SCK
|
||||||
|
#define LORA_MISO PIN_SPI0_MISO
|
||||||
|
#define LORA_MOSI PIN_SPI0_MOSI
|
||||||
|
#define LORA_CS PIN_SPI0_SS
|
||||||
|
|
||||||
|
#define LORA_DIO0 21
|
||||||
|
#define LORA_DIO1 22
|
||||||
|
#define LORA_DIO2 RADIOLIB_NC
|
||||||
|
#define LORA_RESET 20
|
@ -2,8 +2,8 @@
|
|||||||
[env:t-deck]
|
[env:t-deck]
|
||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = t-deck
|
board = t-deck
|
||||||
upload_protocol = esp-builtin
|
upload_protocol = esptool
|
||||||
debug_tool = esp-builtin
|
#upload_port = COM29
|
||||||
|
|
||||||
build_flags = ${esp32_base.build_flags}
|
build_flags = ${esp32_base.build_flags}
|
||||||
-DT_DECK
|
-DT_DECK
|
||||||
@ -12,4 +12,6 @@ build_flags = ${esp32_base.build_flags}
|
|||||||
-Ivariants/t-deck
|
-Ivariants/t-deck
|
||||||
|
|
||||||
lib_deps = ${esp32s3_base.lib_deps}
|
lib_deps = ${esp32s3_base.lib_deps}
|
||||||
lovyan03/LovyanGFX@^1.1.9
|
lovyan03/LovyanGFX@^1.1.9
|
||||||
|
earlephilhower/ESP8266Audio@^1.9.7
|
||||||
|
earlephilhower/ESP8266SAM@^1.0.1
|
@ -65,6 +65,12 @@
|
|||||||
#define ES7210_LRCK 21
|
#define ES7210_LRCK 21
|
||||||
#define ES7210_MCLK 48
|
#define ES7210_MCLK 48
|
||||||
|
|
||||||
|
// dac / amp
|
||||||
|
#define HAS_I2S
|
||||||
|
#define DAC_I2S_BCK 7
|
||||||
|
#define DAC_I2S_WS 5
|
||||||
|
#define DAC_I2S_DOUT 6
|
||||||
|
|
||||||
// LoRa
|
// LoRa
|
||||||
#define USE_SX1262
|
#define USE_SX1262
|
||||||
#define USE_SX1268
|
#define USE_SX1268
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
extends = esp32s3_base
|
extends = esp32s3_base
|
||||||
board = t-watch-s3
|
board = t-watch-s3
|
||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
|
upload_speed = 115200
|
||||||
|
upload_port = /dev/tty.usbmodem3485188D636C1
|
||||||
|
|
||||||
build_flags = ${esp32_base.build_flags}
|
build_flags = ${esp32_base.build_flags}
|
||||||
-DT_WATCH_S3
|
-DT_WATCH_S3
|
||||||
@ -12,4 +14,6 @@ build_flags = ${esp32_base.build_flags}
|
|||||||
lib_deps = ${esp32s3_base.lib_deps}
|
lib_deps = ${esp32s3_base.lib_deps}
|
||||||
lovyan03/LovyanGFX@^1.1.9
|
lovyan03/LovyanGFX@^1.1.9
|
||||||
lewisxhe/PCF8563_Library@1.0.1
|
lewisxhe/PCF8563_Library@1.0.1
|
||||||
adafruit/Adafruit DRV2605 Library@^1.2.2
|
adafruit/Adafruit DRV2605 Library@^1.2.2
|
||||||
|
earlephilhower/ESP8266Audio@^1.9.7
|
||||||
|
earlephilhower/ESP8266SAM@^1.0.1
|
@ -30,6 +30,11 @@
|
|||||||
|
|
||||||
#define TFT_BL ST7789_BACKLIGHT_EN
|
#define TFT_BL ST7789_BACKLIGHT_EN
|
||||||
|
|
||||||
|
#define HAS_I2S
|
||||||
|
#define DAC_I2S_BCK 48
|
||||||
|
#define DAC_I2S_WS 15
|
||||||
|
#define DAC_I2S_DOUT 46
|
||||||
|
|
||||||
#define HAS_AXP2101
|
#define HAS_AXP2101
|
||||||
|
|
||||||
#define HAS_RTC 1
|
#define HAS_RTC 1
|
||||||
@ -37,8 +42,6 @@
|
|||||||
#define I2C_SDA 10 // For QMC6310 sensors and screens
|
#define I2C_SDA 10 // For QMC6310 sensors and screens
|
||||||
#define I2C_SCL 11 // For QMC6310 sensors and screens
|
#define I2C_SCL 11 // For QMC6310 sensors and screens
|
||||||
|
|
||||||
#define BUTTON_PIN 0
|
|
||||||
|
|
||||||
#define BMA4XX_INT 14 // Interrupt for BMA_423 axis sensor
|
#define BMA4XX_INT 14 // Interrupt for BMA_423 axis sensor
|
||||||
|
|
||||||
#define HAS_GPS 0
|
#define HAS_GPS 0
|
||||||
|
Loading…
Reference in New Issue
Block a user