mirror of
https://github.com/meshtastic/firmware.git
synced 2026-02-05 08:31:56 +00:00
Compare commits
19 Commits
trunk-io/u
...
LED_POWER
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2626fe5822 | ||
|
|
a6c7c2d690 | ||
|
|
94b7149958 | ||
|
|
50916bcd6e | ||
|
|
ac611c4b62 | ||
|
|
bffe92b23d | ||
|
|
89df5ef669 | ||
|
|
bfc3eebd54 | ||
|
|
538a5f0dfc | ||
|
|
b7db22055d | ||
|
|
4ebc5d433b | ||
|
|
0703e0e6d7 | ||
|
|
d55c652310 | ||
|
|
f514bc230b | ||
|
|
6028797d3e | ||
|
|
167e9cfde2 | ||
|
|
0022148323 | ||
|
|
9d06c1bf34 | ||
|
|
1d30342c00 |
@@ -50,6 +50,7 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DRADIOLIB_EXCLUDE_APRS=1
|
||||
-DRADIOLIB_EXCLUDE_LORAWAN=1
|
||||
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||
-DMESHTASTIC_EXCLUDE_REPLYBOT=1
|
||||
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
|
||||
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
|
||||
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
|
||||
|
||||
@@ -89,22 +89,14 @@ class BluetoothStatus : public Status
|
||||
case ConnectionState::CONNECTED:
|
||||
LOG_DEBUG("BluetoothStatus CONNECTED");
|
||||
#ifdef BLE_LED
|
||||
#ifdef BLE_LED_INVERTED
|
||||
digitalWrite(BLE_LED, LOW);
|
||||
#else
|
||||
digitalWrite(BLE_LED, HIGH);
|
||||
#endif
|
||||
digitalWrite(BLE_LED, LED_STATE_ON);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ConnectionState::DISCONNECTED:
|
||||
LOG_DEBUG("BluetoothStatus DISCONNECTED");
|
||||
#ifdef BLE_LED
|
||||
#ifdef BLE_LED_INVERTED
|
||||
digitalWrite(BLE_LED, HIGH);
|
||||
#else
|
||||
digitalWrite(BLE_LED, LOW);
|
||||
#endif
|
||||
digitalWrite(BLE_LED, LED_STATE_OFF);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
66
src/Led.cpp
66
src/Led.cpp
@@ -1,66 +0,0 @@
|
||||
#include "Led.h"
|
||||
#include "PowerMon.h"
|
||||
#include "main.h"
|
||||
#include "power.h"
|
||||
|
||||
GpioVirtPin ledForceOn, ledBlink;
|
||||
|
||||
#if defined(LED_PIN)
|
||||
// Most boards have a GPIO for LED control
|
||||
static GpioHwPin ledRawHwPin(LED_PIN);
|
||||
#else
|
||||
static GpioVirtPin ledRawHwPin; // Dummy pin for no hardware
|
||||
#endif
|
||||
|
||||
#if LED_STATE_ON == 0
|
||||
static GpioVirtPin ledHwPin;
|
||||
static GpioNotTransformer ledInverter(&ledHwPin, &ledRawHwPin);
|
||||
#else
|
||||
static GpioPin &ledHwPin = ledRawHwPin;
|
||||
#endif
|
||||
|
||||
#if defined(HAS_PMU)
|
||||
/**
|
||||
* A GPIO controlled by the PMU
|
||||
*/
|
||||
class GpioPmuPin : public GpioPin
|
||||
{
|
||||
public:
|
||||
void set(bool value)
|
||||
{
|
||||
if (pmu_found && PMU) {
|
||||
// blink the axp led
|
||||
PMU->setChargingLedMode(value ? XPOWERS_CHG_LED_ON : XPOWERS_CHG_LED_OFF);
|
||||
}
|
||||
}
|
||||
} ledPmuHwPin;
|
||||
|
||||
// In some cases we need to drive a PMU LED and a normal LED
|
||||
static GpioSplitter ledFinalPin(&ledHwPin, &ledPmuHwPin);
|
||||
#else
|
||||
static GpioPin &ledFinalPin = ledHwPin;
|
||||
#endif
|
||||
|
||||
#ifdef USE_POWERMON
|
||||
/**
|
||||
* We monitor changes to the LED drive output because we use that as a sanity test in our power monitor stuff.
|
||||
*/
|
||||
class MonitoredLedPin : public GpioPin
|
||||
{
|
||||
public:
|
||||
void set(bool value)
|
||||
{
|
||||
if (powerMon) {
|
||||
if (value)
|
||||
powerMon->setState(meshtastic_PowerMon_State_LED_On);
|
||||
else
|
||||
powerMon->clearState(meshtastic_PowerMon_State_LED_On);
|
||||
}
|
||||
ledFinalPin.set(value);
|
||||
}
|
||||
} monitoredLedPin;
|
||||
#else
|
||||
static GpioPin &monitoredLedPin = ledFinalPin;
|
||||
#endif
|
||||
|
||||
static GpioBinaryTransformer ledForcer(&ledForceOn, &ledBlink, &monitoredLedPin, GpioBinaryTransformer::Or);
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "GpioLogic.h"
|
||||
#include "configuration.h"
|
||||
|
||||
/**
|
||||
* ledForceOn and ledForceOff both override the normal ledBlinker behavior (which is controlled by main)
|
||||
*/
|
||||
extern GpioVirtPin ledForceOn, ledBlink;
|
||||
@@ -459,6 +459,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
}
|
||||
// if it's not HIGH - check the battery
|
||||
#endif
|
||||
// If we have an EXT_PWR_DETECT pin and it indicates no external power, believe it.
|
||||
return false;
|
||||
|
||||
// technically speaking this should work for all(?) NRF52 boards
|
||||
// but needs testing across multiple devices. NRF52 USB would not even work if
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
*/
|
||||
#include "PowerFSM.h"
|
||||
#include "Default.h"
|
||||
#include "Led.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerMon.h"
|
||||
#include "configuration.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "main.h"
|
||||
#include "modules/StatusLEDModule.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
@@ -103,7 +103,7 @@ static void lsIdle()
|
||||
uint32_t sleepTime = SLEEP_TIME;
|
||||
|
||||
powerMon->setState(meshtastic_PowerMon_State_CPU_LightSleep);
|
||||
ledBlink.set(false); // Never leave led on while in light sleep
|
||||
statusLEDModule->setPowerLED(false);
|
||||
esp_sleep_source_t wakeCause2 = doLightSleep(sleepTime * 1000LL);
|
||||
powerMon->clearState(meshtastic_PowerMon_State_CPU_LightSleep);
|
||||
|
||||
@@ -111,7 +111,7 @@ static void lsIdle()
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
// Normal case: timer expired, we should just go back to sleep ASAP
|
||||
|
||||
ledBlink.set(true); // briefly turn on led
|
||||
statusLEDModule->setPowerLED(true);
|
||||
wakeCause2 = doLightSleep(100); // leave led on for 1ms
|
||||
|
||||
secsSlept += sleepTime;
|
||||
@@ -146,7 +146,7 @@ static void lsIdle()
|
||||
}
|
||||
} else {
|
||||
// Time to stop sleeping!
|
||||
ledBlink.set(false);
|
||||
statusLEDModule->setPowerLED(false);
|
||||
LOG_INFO("Reached ls_secs, service loop()");
|
||||
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||
}
|
||||
|
||||
@@ -221,7 +221,6 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti
|
||||
|
||||
if (rtc_sec > 0) {
|
||||
// === Build Time String ===
|
||||
long hms = (rtc_sec % SEC_PER_DAY + SEC_PER_DAY) % SEC_PER_DAY;
|
||||
int hour, minute, second;
|
||||
graphics::decomposeTime(rtc_sec, hour, minute, second);
|
||||
snprintf(timeStr, sizeof(timeStr), "%d:%02d", hour, minute);
|
||||
|
||||
@@ -877,15 +877,15 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// Send Message (Right side)
|
||||
display->drawRect(x1 + 2 - bubbleW, y1 - bubbleH, bubbleW, bubbleH);
|
||||
// Top Right Corner
|
||||
display->drawRect(x1, topY, 2, 1);
|
||||
display->drawRect(x1 - 1, topY, 2, 1);
|
||||
display->drawRect(x1, topY, 1, 2);
|
||||
// Bottom Right Corner
|
||||
display->drawRect(x1 - 1, bottomY - 2, 2, 1);
|
||||
display->drawRect(x1, bottomY - 3, 1, 2);
|
||||
// Knock the corners off to make a bubble
|
||||
display->setColor(BLACK);
|
||||
display->drawRect(x1 - bubbleW, topY - 1, 1, 1);
|
||||
display->drawRect(x1 - bubbleW, bottomY - 1, 1, 1);
|
||||
display->drawRect(x1 - bubbleW + 2, topY - 1, 1, 1);
|
||||
display->drawRect(x1 - bubbleW + 2, bottomY - 1, 1, 1);
|
||||
display->setColor(WHITE);
|
||||
} else {
|
||||
// Received Message (Left Side)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "graphics/niche/InkHUD/Tile.h"
|
||||
#include <cstdint>
|
||||
#ifdef MESHTASTIC_INCLUDE_INKHUD
|
||||
|
||||
#include "./Applet.h"
|
||||
@@ -785,6 +787,16 @@ void InkHUD::Applet::drawHeader(std::string text)
|
||||
drawPixel(x, 0, BLACK);
|
||||
drawPixel(x, headerDivY, BLACK); // Dotted 50%
|
||||
}
|
||||
|
||||
// Dither near battery
|
||||
if (settings->optionalFeatures.batteryIcon) {
|
||||
constexpr uint16_t ditherSizePx = 4;
|
||||
Tile *batteryTile = ((Applet *)inkhud->getSystemApplet("BatteryIcon"))->getTile();
|
||||
const uint16_t batteryTileLeft = batteryTile->getLeft();
|
||||
const uint16_t batteryTileTop = batteryTile->getTop();
|
||||
const uint16_t batteryTileHeight = batteryTile->getHeight();
|
||||
hatchRegion(batteryTileLeft - ditherSizePx, batteryTileTop, ditherSizePx, batteryTileHeight, 2, WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the height of the standard applet header
|
||||
|
||||
@@ -48,37 +48,27 @@ int InkHUD::BatteryIconApplet::onPowerStatusUpdate(const meshtastic::Status *sta
|
||||
|
||||
void InkHUD::BatteryIconApplet::onRender(bool full)
|
||||
{
|
||||
// Fill entire tile
|
||||
// - size of icon controlled by size of tile
|
||||
int16_t l = 0;
|
||||
int16_t t = 0;
|
||||
uint16_t w = width();
|
||||
int16_t h = height();
|
||||
|
||||
// Clear the region beneath the tile
|
||||
// Clear the region beneath the tile, including the border
|
||||
// Most applets are drawing onto an empty frame buffer and don't need to do this
|
||||
// We do need to do this with the battery though, as it is an "overlay"
|
||||
fillRect(l, t, w, h, WHITE);
|
||||
|
||||
// Vertical centerline
|
||||
const int16_t m = t + (h / 2);
|
||||
fillRect(0, 0, width(), height(), WHITE);
|
||||
|
||||
// =====================
|
||||
// Draw battery outline
|
||||
// =====================
|
||||
|
||||
// Positive terminal "bump"
|
||||
const int16_t &bumpL = l;
|
||||
const uint16_t bumpH = h / 2;
|
||||
const int16_t bumpT = m - (bumpH / 2);
|
||||
constexpr uint16_t bumpW = 2;
|
||||
const int16_t &bumpL = 1;
|
||||
const uint16_t bumpH = (height() - 2) / 2;
|
||||
const int16_t bumpT = (1 + ((height() - 2) / 2)) - (bumpH / 2);
|
||||
fillRect(bumpL, bumpT, bumpW, bumpH, BLACK);
|
||||
|
||||
// Main body of battery
|
||||
const int16_t bodyL = bumpL + bumpW;
|
||||
const int16_t &bodyT = t;
|
||||
const int16_t &bodyH = h;
|
||||
const int16_t bodyW = w - bumpW;
|
||||
const int16_t bodyL = 1 + bumpW;
|
||||
const int16_t &bodyT = 1;
|
||||
const int16_t &bodyH = height() - 2; // Handle top/bottom padding
|
||||
const int16_t bodyW = (width() - 1) - bumpW; // Handle 1px left pad
|
||||
drawRect(bodyL, bodyT, bodyW, bodyH, BLACK);
|
||||
|
||||
// Erase join between bump and body
|
||||
@@ -89,12 +79,13 @@ void InkHUD::BatteryIconApplet::onRender(bool full)
|
||||
// ===================
|
||||
|
||||
constexpr int16_t slicePad = 2;
|
||||
const int16_t sliceL = bodyL + slicePad;
|
||||
int16_t sliceL = bodyL + slicePad;
|
||||
const int16_t sliceT = bodyT + slicePad;
|
||||
const uint16_t sliceH = bodyH - (slicePad * 2);
|
||||
uint16_t sliceW = bodyW - (slicePad * 2);
|
||||
|
||||
sliceW = (sliceW * socRounded) / 100; // Apply percentage
|
||||
sliceW = (sliceW * socRounded) / 100; // Apply percentage
|
||||
sliceL += ((bodyW - (slicePad * 2)) - sliceW); // Shift slice to the battery's negative terminal, correcting drain direction
|
||||
|
||||
hatchRegion(sliceL, sliceT, sliceW, sliceH, 2, BLACK);
|
||||
drawRect(sliceL, sliceT, sliceW, sliceH, BLACK);
|
||||
|
||||
@@ -510,10 +510,10 @@ void InkHUD::WindowManager::placeSystemTiles()
|
||||
const uint16_t batteryIconWidth = batteryIconHeight * 1.8;
|
||||
inkhud->getSystemApplet("BatteryIcon")
|
||||
->getTile()
|
||||
->setRegion(inkhud->width() - batteryIconWidth, // x
|
||||
2, // y
|
||||
batteryIconWidth, // width
|
||||
batteryIconHeight); // height
|
||||
->setRegion(inkhud->width() - batteryIconWidth - 1, // x
|
||||
1, // y
|
||||
batteryIconWidth + 1, // width
|
||||
batteryIconHeight + 2); // height
|
||||
|
||||
// Note: the tiles of placeholder and menu applets are manipulated specially
|
||||
// - menuApplet borrows user tiles
|
||||
|
||||
78
src/main.cpp
78
src/main.cpp
@@ -7,13 +7,13 @@
|
||||
#include "NodeDB.h"
|
||||
#include "PowerFSM.h"
|
||||
#include "PowerMon.h"
|
||||
#include "RadioLibInterface.h"
|
||||
#include "ReliableRouter.h"
|
||||
#include "airtime.h"
|
||||
#include "buzz.h"
|
||||
#include "power/PowerHAL.h"
|
||||
|
||||
#include "FSCommon.h"
|
||||
#include "Led.h"
|
||||
#include "RTC.h"
|
||||
#include "SPILock.h"
|
||||
#include "Throttle.h"
|
||||
@@ -193,6 +193,8 @@ bool kb_found = false;
|
||||
// global bool to record that on-screen keyboard (OSK) is present
|
||||
bool osk_found = false;
|
||||
|
||||
unsigned long last_listen = 0;
|
||||
|
||||
// The I2C address of the RTC Module (if found)
|
||||
ScanI2C::DeviceAddress rtc_found = ScanI2C::ADDRESS_NONE;
|
||||
// The I2C address of the Accelerometer (if found)
|
||||
@@ -242,26 +244,8 @@ const char *getDeviceName()
|
||||
return name;
|
||||
}
|
||||
|
||||
// TODO remove from main.cpp
|
||||
static int32_t ledBlinker()
|
||||
{
|
||||
// Still set up the blinking (heartbeat) interval but skip code path below, so LED will blink if
|
||||
// config.device.led_heartbeat_disabled is changed
|
||||
if (config.device.led_heartbeat_disabled)
|
||||
return 1000;
|
||||
|
||||
static bool ledOn;
|
||||
ledOn ^= 1;
|
||||
|
||||
ledBlink.set(ledOn);
|
||||
|
||||
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
|
||||
return powerStatus->getIsCharging() ? 1000 : (ledOn ? 1 : 1000);
|
||||
}
|
||||
|
||||
uint32_t timeLastPowered = 0;
|
||||
|
||||
static Periodic *ledPeriodic;
|
||||
static OSThread *powerFSMthread;
|
||||
static OSThread *ambientLightingThread;
|
||||
|
||||
@@ -299,21 +283,16 @@ void earlyInitVariant() {}
|
||||
// blink user led in 3 flashes sequence to indicate what is happening
|
||||
void waitUntilPowerLevelSafe()
|
||||
{
|
||||
|
||||
#ifdef LED_PIN
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
#endif
|
||||
|
||||
while (powerHAL_isPowerLevelSafe() == false) {
|
||||
|
||||
#ifdef LED_PIN
|
||||
#ifdef LED_POWER
|
||||
|
||||
// 3x: blink for 300 ms, pause for 300 ms
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
digitalWrite(LED_PIN, LED_STATE_ON);
|
||||
digitalWrite(LED_POWER, LED_STATE_ON);
|
||||
delay(300);
|
||||
digitalWrite(LED_PIN, LED_STATE_OFF);
|
||||
digitalWrite(LED_POWER, LED_STATE_OFF);
|
||||
delay(300);
|
||||
}
|
||||
#endif
|
||||
@@ -337,6 +316,11 @@ void setup()
|
||||
// initialize power HAL layer as early as possible
|
||||
powerHAL_init();
|
||||
|
||||
#ifdef LED_POWER
|
||||
pinMode(LED_POWER, OUTPUT);
|
||||
digitalWrite(LED_POWER, LED_STATE_ON);
|
||||
#endif
|
||||
|
||||
// prevent booting if device is in power failure mode
|
||||
// boot sequence will follow when battery level raises to safe mode
|
||||
waitUntilPowerLevelSafe();
|
||||
@@ -349,11 +333,6 @@ void setup()
|
||||
digitalWrite(PIN_POWER_EN, HIGH);
|
||||
#endif
|
||||
|
||||
#ifdef LED_POWER
|
||||
pinMode(LED_POWER, OUTPUT);
|
||||
digitalWrite(LED_POWER, LED_STATE_ON);
|
||||
#endif
|
||||
|
||||
#ifdef LED_NOTIFICATION
|
||||
pinMode(LED_NOTIFICATION, OUTPUT);
|
||||
digitalWrite(LED_NOTIFICATION, HIGH ^ LED_STATE_ON);
|
||||
@@ -366,11 +345,7 @@ void setup()
|
||||
|
||||
#ifdef BLE_LED
|
||||
pinMode(BLE_LED, OUTPUT);
|
||||
#ifdef BLE_LED_INVERTED
|
||||
digitalWrite(BLE_LED, HIGH);
|
||||
#else
|
||||
digitalWrite(BLE_LED, LOW);
|
||||
#endif
|
||||
digitalWrite(BLE_LED, LED_STATE_OFF);
|
||||
#endif
|
||||
|
||||
concurrency::hasBeenSetup = true;
|
||||
@@ -488,14 +463,6 @@ void setup()
|
||||
|
||||
OSThread::setup();
|
||||
|
||||
// TODO make this ifdef based on defined pins and move from main.cpp
|
||||
#if defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2)
|
||||
// The ThinkNodes have their own blink logic
|
||||
// ledPeriodic = new Periodic("Blink", elecrowLedBlinker);
|
||||
#else
|
||||
ledPeriodic = new Periodic("Blink", ledBlinker);
|
||||
#endif
|
||||
|
||||
fsInit();
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_I2C
|
||||
@@ -720,13 +687,6 @@ void setup()
|
||||
setupSDCard();
|
||||
#endif
|
||||
|
||||
// LED init
|
||||
|
||||
#ifdef LED_PIN
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
digitalWrite(LED_PIN, LED_STATE_ON); // turn on for now
|
||||
#endif
|
||||
|
||||
// Hello
|
||||
printInfo();
|
||||
#ifdef BUILD_EPOCH
|
||||
@@ -834,7 +794,7 @@ void setup()
|
||||
SPI.begin();
|
||||
#endif
|
||||
#else
|
||||
// ESP32
|
||||
// ESP32
|
||||
#if defined(HW_SPI1_DEVICE)
|
||||
SPI1.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
LOG_DEBUG("SPI1.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)", LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||
@@ -960,12 +920,6 @@ void setup()
|
||||
setupNicheGraphics();
|
||||
#endif
|
||||
|
||||
#ifdef LED_PIN
|
||||
// Turn LED off after boot, if heartbeat by config
|
||||
if (config.device.led_heartbeat_disabled)
|
||||
digitalWrite(LED_PIN, HIGH ^ LED_STATE_ON);
|
||||
#endif
|
||||
|
||||
// Do this after service.init (because that clears error_code)
|
||||
#ifdef HAS_PMU
|
||||
if (!pmu_found)
|
||||
@@ -1168,6 +1122,12 @@ void loop()
|
||||
#endif
|
||||
power->powerCommandsCheck();
|
||||
|
||||
if (RadioLibInterface::instance != nullptr && !Throttle::isWithinTimespanMs(last_listen, 1000 * 60) &&
|
||||
!(RadioLibInterface::instance->isSending() || RadioLibInterface::instance->isActivelyReceiving())) {
|
||||
RadioLibInterface::instance->startReceive();
|
||||
LOG_DEBUG("attempting AGC reset");
|
||||
}
|
||||
|
||||
#ifdef DEBUG_STACK
|
||||
static uint32_t lastPrint = 0;
|
||||
if (!Throttle::isWithinTimespanMs(lastPrint, 10 * 1000L)) {
|
||||
|
||||
@@ -33,6 +33,7 @@ extern ScanI2C::DeviceAddress cardkb_found;
|
||||
extern uint8_t kb_model;
|
||||
extern bool kb_found;
|
||||
extern bool osk_found;
|
||||
extern unsigned long last_listen;
|
||||
extern ScanI2C::DeviceAddress rtc_found;
|
||||
extern ScanI2C::DeviceAddress accelerometer_found;
|
||||
extern ScanI2C::FoundDevice rgb_found;
|
||||
|
||||
@@ -1404,6 +1404,15 @@ void NodeDB::loadFromDisk()
|
||||
if (portduino_config.has_configDisplayMode) {
|
||||
config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)portduino_config.configDisplayMode;
|
||||
}
|
||||
if (portduino_config.has_statusMessage) {
|
||||
moduleConfig.has_statusmessage = true;
|
||||
strncpy(moduleConfig.statusmessage.node_status, portduino_config.statusMessage.c_str(),
|
||||
sizeof(moduleConfig.statusmessage.node_status));
|
||||
moduleConfig.statusmessage.node_status[sizeof(moduleConfig.statusmessage.node_status) - 1] = '\0';
|
||||
}
|
||||
if (portduino_config.enable_UDP) {
|
||||
config.network.enabled_protocols = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
@@ -1544,6 +1553,7 @@ bool NodeDB::saveToDiskNoRetry(int saveWhat)
|
||||
moduleConfig.has_ambient_lighting = true;
|
||||
moduleConfig.has_audio = true;
|
||||
moduleConfig.has_paxcounter = true;
|
||||
moduleConfig.has_statusmessage = true;
|
||||
|
||||
success &=
|
||||
saveProto(moduleConfigFileName, meshtastic_LocalModuleConfig_size, &meshtastic_LocalModuleConfig_msg, &moduleConfig);
|
||||
@@ -2213,8 +2223,8 @@ bool NodeDB::restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||
} else if (location == meshtastic_AdminMessage_BackupLocation_SD) {
|
||||
// TODO: After more mainline SD card support
|
||||
}
|
||||
return success;
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
/// Record an error that should be reported via analytics
|
||||
|
||||
@@ -514,6 +514,8 @@ void RadioLibInterface::handleReceiveInterrupt()
|
||||
|
||||
void RadioLibInterface::startReceive()
|
||||
{
|
||||
// Note the updated timestamp, to avoid unneeded AGC resets
|
||||
last_listen = millis();
|
||||
isReceiving = true;
|
||||
powerMon->setState(meshtastic_PowerMon_State_Lora_RXOn);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#if HAS_WIFI
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
#endif
|
||||
#include "Led.h"
|
||||
#include "SPILock.h"
|
||||
#include "power.h"
|
||||
#include "serialization/JSON.h"
|
||||
@@ -92,7 +91,6 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
|
||||
|
||||
ResourceNode *nodeJsonScanNetworks = new ResourceNode("/json/scanNetworks", "GET", &handleScanNetworks);
|
||||
ResourceNode *nodeJsonBlinkLED = new ResourceNode("/json/blink", "POST", &handleBlinkLED);
|
||||
ResourceNode *nodeJsonReport = new ResourceNode("/json/report", "GET", &handleReport);
|
||||
ResourceNode *nodeJsonNodes = new ResourceNode("/json/nodes", "GET", &handleNodes);
|
||||
ResourceNode *nodeJsonFsBrowseStatic = new ResourceNode("/json/fs/browse/static", "GET", &handleFsBrowseStatic);
|
||||
@@ -110,7 +108,6 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
secureServer->registerNode(nodeRestart);
|
||||
secureServer->registerNode(nodeFormUpload);
|
||||
secureServer->registerNode(nodeJsonScanNetworks);
|
||||
secureServer->registerNode(nodeJsonBlinkLED);
|
||||
secureServer->registerNode(nodeJsonFsBrowseStatic);
|
||||
secureServer->registerNode(nodeJsonDelete);
|
||||
secureServer->registerNode(nodeJsonReport);
|
||||
@@ -133,7 +130,6 @@ void registerHandlers(HTTPServer *insecureServer, HTTPSServer *secureServer)
|
||||
insecureServer->registerNode(nodeRestart);
|
||||
insecureServer->registerNode(nodeFormUpload);
|
||||
insecureServer->registerNode(nodeJsonScanNetworks);
|
||||
insecureServer->registerNode(nodeJsonBlinkLED);
|
||||
insecureServer->registerNode(nodeJsonFsBrowseStatic);
|
||||
insecureServer->registerNode(nodeJsonDelete);
|
||||
insecureServer->registerNode(nodeJsonReport);
|
||||
@@ -904,45 +900,6 @@ void handleRestart(HTTPRequest *req, HTTPResponse *res)
|
||||
webServerThread->requestRestart = (millis() / 1000) + 5;
|
||||
}
|
||||
|
||||
void handleBlinkLED(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "application/json");
|
||||
res->setHeader("Access-Control-Allow-Origin", "*");
|
||||
res->setHeader("Access-Control-Allow-Methods", "POST");
|
||||
|
||||
ResourceParameters *params = req->getParams();
|
||||
std::string blink_target;
|
||||
|
||||
if (!params->getQueryParameter("blink_target", blink_target)) {
|
||||
// if no blink_target was supplied in the URL parameters of the
|
||||
// POST request, then assume we should blink the LED
|
||||
blink_target = "LED";
|
||||
}
|
||||
|
||||
if (blink_target == "LED") {
|
||||
uint8_t count = 10;
|
||||
while (count > 0) {
|
||||
ledBlink.set(true);
|
||||
delay(50);
|
||||
ledBlink.set(false);
|
||||
delay(50);
|
||||
count = count - 1;
|
||||
}
|
||||
} else {
|
||||
#if HAS_SCREEN
|
||||
if (screen)
|
||||
screen->blink();
|
||||
#endif
|
||||
}
|
||||
|
||||
JSONObject jsonObjOuter;
|
||||
jsonObjOuter["status"] = new JSONValue("ok");
|
||||
JSONValue *value = new JSONValue(jsonObjOuter);
|
||||
std::string jsonString = value->Stringify();
|
||||
res->print(jsonString.c_str());
|
||||
delete value;
|
||||
}
|
||||
|
||||
void handleScanNetworks(HTTPRequest *req, HTTPResponse *res)
|
||||
{
|
||||
res->setHeader("Content-Type", "application/json");
|
||||
|
||||
@@ -11,7 +11,6 @@ void handleFormUpload(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleScanNetworks(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleFsBrowseStatic(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleFsDeleteStatic(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleBlinkLED(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleReport(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleNodes(HTTPRequest *req, HTTPResponse *res);
|
||||
void handleUpdateFs(HTTPRequest *req, HTTPResponse *res);
|
||||
|
||||
@@ -643,12 +643,6 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
accelerometerThread->enabled = true;
|
||||
accelerometerThread->start();
|
||||
}
|
||||
#endif
|
||||
#ifdef LED_PIN
|
||||
// Turn LED off if heartbeat by config
|
||||
if (c.payload_variant.device.led_heartbeat_disabled) {
|
||||
digitalWrite(LED_PIN, HIGH ^ LED_STATE_ON);
|
||||
}
|
||||
#endif
|
||||
if (config.device.button_gpio == c.payload_variant.device.button_gpio &&
|
||||
config.device.buzzer_gpio == c.payload_variant.device.buzzer_gpio &&
|
||||
@@ -905,10 +899,11 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
|
||||
|
||||
bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||
{
|
||||
bool shouldReboot = true;
|
||||
// If we are in an open transaction or configuring MQTT or Serial (which have validation), defer disabling Bluetooth
|
||||
// Otherwise, disable Bluetooth to prevent the phone from interfering with the config
|
||||
if (!hasOpenEditTransaction &&
|
||||
!IS_ONE_OF(c.which_payload_variant, meshtastic_ModuleConfig_mqtt_tag, meshtastic_ModuleConfig_serial_tag)) {
|
||||
if (!hasOpenEditTransaction && !IS_ONE_OF(c.which_payload_variant, meshtastic_ModuleConfig_mqtt_tag,
|
||||
meshtastic_ModuleConfig_serial_tag, meshtastic_ModuleConfig_statusmessage_tag)) {
|
||||
disableBluetooth();
|
||||
}
|
||||
|
||||
@@ -1000,8 +995,14 @@ bool AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
|
||||
moduleConfig.has_paxcounter = true;
|
||||
moduleConfig.paxcounter = c.payload_variant.paxcounter;
|
||||
break;
|
||||
case meshtastic_ModuleConfig_statusmessage_tag:
|
||||
LOG_INFO("Set module config: StatusMessage");
|
||||
moduleConfig.has_statusmessage = true;
|
||||
moduleConfig.statusmessage = c.payload_variant.statusmessage;
|
||||
shouldReboot = false;
|
||||
break;
|
||||
}
|
||||
saveChanges(SEGMENT_MODULECONFIG);
|
||||
saveChanges(SEGMENT_MODULECONFIG, shouldReboot);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1180,6 +1181,11 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
|
||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_paxcounter_tag;
|
||||
res.get_module_config_response.payload_variant.paxcounter = moduleConfig.paxcounter;
|
||||
break;
|
||||
case meshtastic_AdminMessage_ModuleConfigType_STATUSMESSAGE_CONFIG:
|
||||
LOG_INFO("Get module config: StatusMessage");
|
||||
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_statusmessage_tag;
|
||||
res.get_module_config_response.payload_variant.statusmessage = moduleConfig.statusmessage;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
#include "buzz/BuzzerFeedbackThread.h"
|
||||
#include "modules/StatusLEDModule.h"
|
||||
#include "modules/SystemCommandsModule.h"
|
||||
#endif
|
||||
#include "modules/StatusLEDModule.h"
|
||||
#if !MESHTASTIC_EXCLUDE_REPLYBOT
|
||||
#include "ReplyBotModule.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_PKI
|
||||
#include "KeyVerificationModule.h"
|
||||
#endif
|
||||
@@ -90,6 +93,9 @@
|
||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||
#include "modules/DropzoneModule.h"
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
#include "modules/StatusMessageModule.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAS_HARDWARE_WATCHDOG)
|
||||
#include "watchdog/watchdogThread.h"
|
||||
@@ -106,10 +112,10 @@ void setupModules()
|
||||
buzzerFeedbackThread = new BuzzerFeedbackThread();
|
||||
}
|
||||
#endif
|
||||
#if defined(LED_CHARGE) || defined(LED_PAIRING)
|
||||
statusLEDModule = new StatusLEDModule();
|
||||
#if !MESHTASTIC_EXCLUDE_REPLYBOT
|
||||
new ReplyBotModule();
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ADMIN
|
||||
adminModule = new AdminModule();
|
||||
#endif
|
||||
@@ -150,6 +156,9 @@ void setupModules()
|
||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||
dropzoneModule = new DropzoneModule();
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
statusMessageModule = new StatusMessageModule();
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE
|
||||
new GenericThreadModule();
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "PowerStressModule.h"
|
||||
#include "Led.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "PowerMon.h"
|
||||
@@ -78,10 +77,12 @@ int32_t PowerStressModule::runOnce()
|
||||
|
||||
switch (p.cmd) {
|
||||
case meshtastic_PowerStressMessage_Opcode_LED_ON:
|
||||
ledForceOn.set(true);
|
||||
// FIXME - implement
|
||||
// ledForceOn.set(true);
|
||||
break;
|
||||
case meshtastic_PowerStressMessage_Opcode_LED_OFF:
|
||||
ledForceOn.set(false);
|
||||
// FIXME - implement
|
||||
// ledForceOn.set(false);
|
||||
break;
|
||||
case meshtastic_PowerStressMessage_Opcode_GPS_ON:
|
||||
// FIXME - implement
|
||||
|
||||
183
src/modules/ReplyBotModule.cpp
Normal file
183
src/modules/ReplyBotModule.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_REPLYBOT
|
||||
/*
|
||||
* ReplyBotModule.cpp
|
||||
*
|
||||
* This module implements a simple reply bot for the Meshtastic firmware. It listens for
|
||||
* specific text commands ("/ping", "/hello" and "/test") delivered either via a direct
|
||||
* message (DM) or a broadcast on the primary channel. When a supported command is
|
||||
* received the bot responds with a short status message that includes the hop count
|
||||
* (minimum number of relays), RSSI and SNR of the received packet. To avoid spamming
|
||||
* the network it enforces a per‑sender cooldown between responses. By default the
|
||||
* module is enabled; define MESHTASTIC_EXCLUDE_REPLYBOT at build time to exclude it
|
||||
* entirely. See the official firmware documentation for guidance on adding modules.
|
||||
*/
|
||||
|
||||
#include "Channels.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "ReplyBotModule.h"
|
||||
#include "mesh/MeshTypes.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
|
||||
//
|
||||
// Rate limiting data structures
|
||||
//
|
||||
// Each sender is tracked in a small ring buffer. When a message arrives from a
|
||||
// sender we check the last time we responded to them. If the difference is
|
||||
// less than the configured cooldown (different values for DM vs broadcast)
|
||||
// the message is ignored; otherwise we update the last response time and
|
||||
// proceed with replying.
|
||||
|
||||
struct ReplyBotCooldownEntry {
|
||||
uint32_t from = 0;
|
||||
uint32_t lastMs = 0;
|
||||
};
|
||||
|
||||
static constexpr uint8_t REPLYBOT_COOLDOWN_SLOTS = 8; // ring buffer size
|
||||
static constexpr uint32_t REPLYBOT_DM_COOLDOWN_MS = 15 * 1000; // 15 seconds for DMs
|
||||
static constexpr uint32_t REPLYBOT_LF_COOLDOWN_MS = 60 * 1000; // 60 seconds for LongFast broadcasts
|
||||
|
||||
static ReplyBotCooldownEntry replybotCooldown[REPLYBOT_COOLDOWN_SLOTS];
|
||||
static uint8_t replybotCooldownIdx = 0;
|
||||
|
||||
// Return true if a reply should be rate‑limited for this sender, updating the
|
||||
// entry table as needed.
|
||||
static bool replybotRateLimited(uint32_t from, uint32_t cooldownMs)
|
||||
{
|
||||
const uint32_t now = millis();
|
||||
for (auto &e : replybotCooldown) {
|
||||
if (e.from == from) {
|
||||
// Found existing entry; check if cooldown expired
|
||||
if ((uint32_t)(now - e.lastMs) < cooldownMs) {
|
||||
return true;
|
||||
}
|
||||
e.lastMs = now;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// No entry found – insert new sender into the ring
|
||||
replybotCooldown[replybotCooldownIdx].from = from;
|
||||
replybotCooldown[replybotCooldownIdx].lastMs = now;
|
||||
replybotCooldownIdx = (replybotCooldownIdx + 1) % REPLYBOT_COOLDOWN_SLOTS;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Constructor – registers a single text port and marks the module promiscuous
|
||||
// so that broadcast messages on the primary channel are visible.
|
||||
ReplyBotModule::ReplyBotModule() : SinglePortModule("replybot", meshtastic_PortNum_TEXT_MESSAGE_APP)
|
||||
{
|
||||
isPromiscuous = true;
|
||||
}
|
||||
|
||||
void ReplyBotModule::setup()
|
||||
{
|
||||
// In future we may add a protobuf configuration; for now the module is
|
||||
// always enabled when compiled in.
|
||||
}
|
||||
|
||||
// Determine whether we want to process this packet. We only care about
|
||||
// plain text messages addressed to our port.
|
||||
bool ReplyBotModule::wantPacket(const meshtastic_MeshPacket *p)
|
||||
{
|
||||
return (p && p->decoded.portnum == ourPortNum);
|
||||
}
|
||||
|
||||
ProcessMessage ReplyBotModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
// Accept only direct messages to us or broadcasts on the Primary channel
|
||||
// (regardless of modem preset: LongFast, MediumFast, etc).
|
||||
|
||||
const uint32_t ourNode = nodeDB->getNodeNum();
|
||||
const bool isDM = (mp.to == ourNode);
|
||||
const bool isPrimaryChannel = (mp.channel == channels.getPrimaryIndex()) && isBroadcast(mp.to);
|
||||
if (!isDM && !isPrimaryChannel) {
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
// Ignore empty payloads
|
||||
if (mp.decoded.payload.size == 0) {
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
// Copy payload into a null‑terminated buffer
|
||||
char buf[260];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
size_t n = mp.decoded.payload.size;
|
||||
if (n > sizeof(buf) - 1)
|
||||
n = sizeof(buf) - 1;
|
||||
memcpy(buf, mp.decoded.payload.bytes, n);
|
||||
|
||||
// React only to supported slash commands
|
||||
if (!isCommand(buf)) {
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
// Apply rate limiting per sender depending on DM/broadcast
|
||||
const uint32_t cooldownMs = isDM ? REPLYBOT_DM_COOLDOWN_MS : REPLYBOT_LF_COOLDOWN_MS;
|
||||
if (replybotRateLimited(mp.from, cooldownMs)) {
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
// Compute hop count indicator – if the relay_node is non‑zero we know
|
||||
// there was at least one relay. Some firmware builds support a hop_start
|
||||
// field which could be used for more accurate counts, but here we use
|
||||
// the available relay_node flag only.
|
||||
// int hopsAway = mp.hop_start - mp.hop_limit;
|
||||
int hopsAway = getHopsAway(mp);
|
||||
|
||||
// Normalize RSSI: if positive adjust down by 200 to align with typical values
|
||||
int rssi = mp.rx_rssi;
|
||||
if (rssi > 0) {
|
||||
rssi -= 200;
|
||||
}
|
||||
float snr = mp.rx_snr;
|
||||
|
||||
// Build the reply message and send it back via DM
|
||||
char reply[96];
|
||||
snprintf(reply, sizeof(reply), "🎙️ Mic Check : %d Hops away | RSSI %d | SNR %.1f", hopsAway, rssi, snr);
|
||||
sendDm(mp, reply);
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
// Check if the message starts with one of the supported commands. Leading
|
||||
// whitespace is skipped and commands must be followed by end‑of‑string or
|
||||
// whitespace.
|
||||
bool ReplyBotModule::isCommand(const char *msg) const
|
||||
{
|
||||
if (!msg)
|
||||
return false;
|
||||
while (*msg == ' ' || *msg == '\t')
|
||||
msg++;
|
||||
auto isEndOrSpace = [](char c) { return c == '\0' || std::isspace(static_cast<unsigned char>(c)); };
|
||||
if (strncmp(msg, "/ping", 5) == 0 && isEndOrSpace(msg[5]))
|
||||
return true;
|
||||
if (strncmp(msg, "/hello", 6) == 0 && isEndOrSpace(msg[6]))
|
||||
return true;
|
||||
if (strncmp(msg, "/test", 5) == 0 && isEndOrSpace(msg[5]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send a direct message back to the originating node.
|
||||
void ReplyBotModule::sendDm(const meshtastic_MeshPacket &rx, const char *text)
|
||||
{
|
||||
if (!text)
|
||||
return;
|
||||
meshtastic_MeshPacket *p = allocDataPacket();
|
||||
p->to = rx.from;
|
||||
p->channel = rx.channel;
|
||||
p->want_ack = false;
|
||||
p->decoded.want_response = false;
|
||||
size_t len = strlen(text);
|
||||
if (len > sizeof(p->decoded.payload.bytes)) {
|
||||
len = sizeof(p->decoded.payload.bytes);
|
||||
}
|
||||
p->decoded.payload.size = len;
|
||||
memcpy(p->decoded.payload.bytes, text, len);
|
||||
service->sendToMesh(p);
|
||||
}
|
||||
#endif // MESHTASTIC_EXCLUDE_REPLYBOT
|
||||
19
src/modules/ReplyBotModule.h
Normal file
19
src/modules/ReplyBotModule.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "configuration.h"
|
||||
#if !MESHTASTIC_EXCLUDE_REPLYBOT
|
||||
#include "SinglePortModule.h"
|
||||
#include "mesh/generated/meshtastic/mesh.pb.h"
|
||||
|
||||
class ReplyBotModule : public SinglePortModule
|
||||
{
|
||||
public:
|
||||
ReplyBotModule();
|
||||
void setup() override;
|
||||
bool wantPacket(const meshtastic_MeshPacket *p) override;
|
||||
ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
|
||||
protected:
|
||||
bool isCommand(const char *msg) const;
|
||||
void sendDm(const meshtastic_MeshPacket &rx, const char *text);
|
||||
};
|
||||
#endif // MESHTASTIC_EXCLUDE_REPLYBOT
|
||||
@@ -13,8 +13,10 @@ StatusLEDModule::StatusLEDModule() : concurrency::OSThread("StatusLEDModule")
|
||||
{
|
||||
bluetoothStatusObserver.observe(&bluetoothStatus->onNewStatus);
|
||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
if (inputBroker)
|
||||
inputObserver.observe(inputBroker);
|
||||
#endif
|
||||
}
|
||||
|
||||
int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
@@ -62,19 +64,22 @@ int StatusLEDModule::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
int StatusLEDModule::handleInputEvent(const InputEvent *event)
|
||||
{
|
||||
lastUserbuttonTime = millis();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t StatusLEDModule::runOnce()
|
||||
{
|
||||
my_interval = 1000;
|
||||
|
||||
if (power_state == charging) {
|
||||
#ifndef POWER_LED_HARDWARE_BLINKS_WHILE_CHARGING
|
||||
CHARGE_LED_state = !CHARGE_LED_state;
|
||||
#endif
|
||||
} else if (power_state == charged) {
|
||||
CHARGE_LED_state = LED_STATE_ON;
|
||||
} else if (power_state == critical) {
|
||||
@@ -94,7 +99,15 @@ int32_t StatusLEDModule::runOnce()
|
||||
}
|
||||
|
||||
} else {
|
||||
CHARGE_LED_state = LED_STATE_OFF;
|
||||
if (doing_fast_blink) {
|
||||
CHARGE_LED_state = LED_STATE_OFF;
|
||||
doing_fast_blink = false;
|
||||
my_interval = 999;
|
||||
} else {
|
||||
CHARGE_LED_state = LED_STATE_ON;
|
||||
doing_fast_blink = true;
|
||||
my_interval = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.bluetooth.enabled || PAIRING_LED_starttime + 30 * 1000 < millis() || doing_fast_blink) {
|
||||
@@ -112,6 +125,11 @@ int32_t StatusLEDModule::runOnce()
|
||||
PAIRING_LED_state = LED_STATE_ON;
|
||||
}
|
||||
|
||||
// Override if disabled in config
|
||||
if (config.device.led_heartbeat_disabled) {
|
||||
CHARGE_LED_state = LED_STATE_OFF;
|
||||
}
|
||||
#ifdef Battery_LED_1
|
||||
bool chargeIndicatorLED1 = LED_STATE_OFF;
|
||||
bool chargeIndicatorLED2 = LED_STATE_OFF;
|
||||
bool chargeIndicatorLED3 = LED_STATE_OFF;
|
||||
@@ -126,9 +144,23 @@ int32_t StatusLEDModule::runOnce()
|
||||
if (powerStatus && powerStatus->getBatteryChargePercent() >= 75)
|
||||
chargeIndicatorLED4 = LED_STATE_ON;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LED_CHARGE
|
||||
digitalWrite(LED_CHARGE, CHARGE_LED_state);
|
||||
#if defined(HAS_PMU)
|
||||
if (pmu_found && PMU) {
|
||||
// blink the axp led
|
||||
PMU->setChargingLedMode(CHARGE_LED_state ? XPOWERS_CHG_LED_ON : XPOWERS_CHG_LED_OFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PCA_LED_POWER
|
||||
io.digitalWrite(PCA_LED_POWER, CHARGE_LED_state);
|
||||
#endif
|
||||
#ifdef PCA_LED_ENABLE
|
||||
io.digitalWrite(PCA_LED_ENABLE, CHARGE_LED_state);
|
||||
#endif
|
||||
#ifdef LED_POWER
|
||||
digitalWrite(LED_POWER, CHARGE_LED_state);
|
||||
#endif
|
||||
#ifdef LED_PAIRING
|
||||
digitalWrite(LED_PAIRING, PAIRING_LED_state);
|
||||
@@ -149,3 +181,43 @@ int32_t StatusLEDModule::runOnce()
|
||||
|
||||
return (my_interval);
|
||||
}
|
||||
|
||||
void StatusLEDModule::setPowerLED(bool LEDon)
|
||||
{
|
||||
|
||||
#if defined(HAS_PMU)
|
||||
if (pmu_found && PMU) {
|
||||
// blink the axp led
|
||||
PMU->setChargingLedMode(LEDon ? XPOWERS_CHG_LED_ON : XPOWERS_CHG_LED_OFF);
|
||||
}
|
||||
#endif
|
||||
if (LEDon)
|
||||
LEDon = LED_STATE_ON;
|
||||
else
|
||||
LEDon = LED_STATE_OFF;
|
||||
#ifdef PCA_LED_POWER
|
||||
io.digitalWrite(PCA_LED_POWER, LEDon);
|
||||
#endif
|
||||
#ifdef PCA_LED_ENABLE
|
||||
io.digitalWrite(PCA_LED_ENABLE, LEDon);
|
||||
#endif
|
||||
#ifdef LED_POWER
|
||||
digitalWrite(LED_POWER, LEDon);
|
||||
#endif
|
||||
#ifdef LED_PAIRING
|
||||
digitalWrite(LED_PAIRING, LEDon);
|
||||
#endif
|
||||
|
||||
#ifdef Battery_LED_1
|
||||
digitalWrite(Battery_LED_1, LEDon);
|
||||
#endif
|
||||
#ifdef Battery_LED_2
|
||||
digitalWrite(Battery_LED_2, LEDon);
|
||||
#endif
|
||||
#ifdef Battery_LED_3
|
||||
digitalWrite(Battery_LED_3, LEDon);
|
||||
#endif
|
||||
#ifdef Battery_LED_4
|
||||
digitalWrite(Battery_LED_4, LEDon);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
#include "PowerStatus.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "configuration.h"
|
||||
#include "input/InputBroker.h"
|
||||
#include "main.h"
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
#include "input/InputBroker.h"
|
||||
#endif
|
||||
|
||||
class StatusLEDModule : private concurrency::OSThread
|
||||
{
|
||||
bool slowTrack = false;
|
||||
@@ -17,8 +21,11 @@ class StatusLEDModule : private concurrency::OSThread
|
||||
StatusLEDModule();
|
||||
|
||||
int handleStatusUpdate(const meshtastic::Status *);
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
int handleInputEvent(const InputEvent *arg);
|
||||
#endif
|
||||
|
||||
void setPowerLED(bool);
|
||||
|
||||
protected:
|
||||
unsigned int my_interval = 1000; // interval in millisconds
|
||||
@@ -28,8 +35,10 @@ class StatusLEDModule : private concurrency::OSThread
|
||||
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
|
||||
CallbackObserver<StatusLEDModule, const meshtastic::Status *> powerStatusObserver =
|
||||
CallbackObserver<StatusLEDModule, const meshtastic::Status *>(this, &StatusLEDModule::handleStatusUpdate);
|
||||
#if !MESHTASTIC_EXCLUDE_INPUTBROKER
|
||||
CallbackObserver<StatusLEDModule, const InputEvent *> inputObserver =
|
||||
CallbackObserver<StatusLEDModule, const InputEvent *>(this, &StatusLEDModule::handleInputEvent);
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool CHARGE_LED_state = LED_STATE_OFF;
|
||||
|
||||
41
src/modules/StatusMessageModule.cpp
Normal file
41
src/modules/StatusMessageModule.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
|
||||
#include "StatusMessageModule.h"
|
||||
#include "MeshService.h"
|
||||
#include "ProtobufModule.h"
|
||||
|
||||
StatusMessageModule *statusMessageModule;
|
||||
|
||||
int32_t StatusMessageModule::runOnce()
|
||||
{
|
||||
if (moduleConfig.has_statusmessage && moduleConfig.statusmessage.node_status[0] != '\0') {
|
||||
// create and send message with the status message set
|
||||
meshtastic_StatusMessage ourStatus = meshtastic_StatusMessage_init_zero;
|
||||
strncpy(ourStatus.status, moduleConfig.statusmessage.node_status, sizeof(ourStatus.status));
|
||||
ourStatus.status[sizeof(ourStatus.status) - 1] = '\0'; // ensure null termination
|
||||
meshtastic_MeshPacket *p = allocDataPacket();
|
||||
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes),
|
||||
meshtastic_StatusMessage_fields, &ourStatus);
|
||||
p->to = NODENUM_BROADCAST;
|
||||
p->decoded.want_response = false;
|
||||
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
|
||||
p->channel = 0;
|
||||
service->sendToMesh(p);
|
||||
}
|
||||
|
||||
return 1000 * 12 * 60 * 60;
|
||||
}
|
||||
|
||||
ProcessMessage StatusMessageModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
||||
meshtastic_StatusMessage incomingMessage;
|
||||
if (pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_StatusMessage_fields,
|
||||
&incomingMessage)) {
|
||||
LOG_INFO("Received a NodeStatus message %s", incomingMessage.status);
|
||||
}
|
||||
}
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
35
src/modules/StatusMessageModule.h
Normal file
35
src/modules/StatusMessageModule.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#if !MESHTASTIC_EXCLUDE_STATUS
|
||||
#include "SinglePortModule.h"
|
||||
#include "configuration.h"
|
||||
|
||||
class StatusMessageModule : public SinglePortModule, private concurrency::OSThread
|
||||
{
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
* name is for debugging output
|
||||
*/
|
||||
StatusMessageModule()
|
||||
: SinglePortModule("statusMessage", meshtastic_PortNum_NODE_STATUS_APP), concurrency::OSThread("StatusMessage")
|
||||
{
|
||||
if (moduleConfig.has_statusmessage && moduleConfig.statusmessage.node_status[0] != '\0') {
|
||||
this->setInterval(2 * 60 * 1000);
|
||||
} else {
|
||||
this->setInterval(1000 * 12 * 60 * 60);
|
||||
}
|
||||
// TODO: If we have a string, set the initial delay (15 minutes maybe)
|
||||
}
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
extern StatusMessageModule *statusMessageModule;
|
||||
#endif
|
||||
@@ -757,11 +757,7 @@ void NimbleBluetooth::deinit()
|
||||
isDeInit = true;
|
||||
|
||||
#ifdef BLE_LED
|
||||
#ifdef BLE_LED_INVERTED
|
||||
digitalWrite(BLE_LED, HIGH);
|
||||
#else
|
||||
digitalWrite(BLE_LED, LOW);
|
||||
#endif
|
||||
digitalWrite(BLE_LED, LED_STATE_OFF);
|
||||
#endif
|
||||
#ifndef NIMBLE_TWO
|
||||
NimBLEDevice::deinit();
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef PIN_LED1
|
||||
#define LED_PIN PIN_LED1 // LED1 on nrf52840-DK
|
||||
#define LED_POWER PIN_LED1 // LED1 on nrf52840-DK
|
||||
#endif
|
||||
|
||||
#ifdef PIN_BUTTON1
|
||||
|
||||
@@ -872,6 +872,7 @@ bool loadConfig(const char *configPath)
|
||||
}
|
||||
|
||||
if (yamlConfig["Config"]) {
|
||||
portduino_config.has_config_overrides = true;
|
||||
if (yamlConfig["Config"]["DisplayMode"]) {
|
||||
portduino_config.has_configDisplayMode = true;
|
||||
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
|
||||
@@ -884,6 +885,13 @@ bool loadConfig(const char *configPath)
|
||||
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Config"]["StatusMessage"]) {
|
||||
portduino_config.has_statusMessage = true;
|
||||
portduino_config.statusMessage = (yamlConfig["Config"]["StatusMessage"]).as<std::string>("");
|
||||
}
|
||||
if ((yamlConfig["Config"]["EnableUDP"]).as<bool>(false)) {
|
||||
portduino_config.enable_UDP = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (yamlConfig["General"]) {
|
||||
|
||||
@@ -177,8 +177,12 @@ extern struct portduino_config_struct {
|
||||
int hostMetrics_channel = 0;
|
||||
|
||||
// config
|
||||
bool has_config_overrides = false;
|
||||
int configDisplayMode = 0;
|
||||
bool has_configDisplayMode = false;
|
||||
std::string statusMessage = "";
|
||||
bool has_statusMessage = false;
|
||||
bool enable_UDP = false;
|
||||
|
||||
// General
|
||||
std::string mac_address = "";
|
||||
@@ -505,21 +509,30 @@ extern struct portduino_config_struct {
|
||||
}
|
||||
|
||||
// config
|
||||
if (has_configDisplayMode) {
|
||||
if (has_config_overrides) {
|
||||
out << YAML::Key << "Config" << YAML::Value << YAML::BeginMap;
|
||||
switch (configDisplayMode) {
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
|
||||
break;
|
||||
if (has_configDisplayMode) {
|
||||
|
||||
switch (configDisplayMode) {
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_statusMessage) {
|
||||
out << YAML::Key << "StatusMessage" << YAML::Value << statusMessage;
|
||||
}
|
||||
if (enable_UDP) {
|
||||
out << YAML::Key << "EnableUDP" << YAML::Value << true;
|
||||
}
|
||||
|
||||
out << YAML::EndMap; // Config
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#endif
|
||||
|
||||
#include "Default.h"
|
||||
#include "Led.h"
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
@@ -13,6 +12,7 @@
|
||||
#include "detect/LoRaRadioType.h"
|
||||
#include "error.h"
|
||||
#include "main.h"
|
||||
#include "modules/StatusLEDModule.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
|
||||
@@ -268,8 +268,7 @@ void doDeepSleep(uint32_t msecToWake, bool skipPreflight = false, bool skipSaveN
|
||||
digitalWrite(PIN_WD_EN, LOW);
|
||||
#endif
|
||||
#endif
|
||||
ledBlink.set(false);
|
||||
|
||||
statusLEDModule->setPowerLED(false);
|
||||
#ifdef RESET_OLED
|
||||
digitalWrite(RESET_OLED, 1); // put the display in reset before killing its power
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#define LORA_CS 5
|
||||
#define RF95_FAN_EN 17
|
||||
|
||||
// #define LED_PIN 16 // This is a LED_WS2812 not a standard LED
|
||||
// This is a LED_WS2812 not a standard LED
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
|
||||
#define NEOPIXEL_DATA 16 // gpio pin used to send data to the neopixels
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define LORA_DIO2
|
||||
#define LORA_DIO3
|
||||
|
||||
#define LED_PIN 16 // green - blue is at 17
|
||||
#define LED_POWER 16 // green - blue is at 17
|
||||
|
||||
#define BUTTON_PIN 25
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
#define SX126X_TXEN RADIOLIB_NC
|
||||
#define SX126X_RXEN RADIOLIB_NC
|
||||
|
||||
// Status
|
||||
// #define LED_PIN 1
|
||||
// External notification
|
||||
// FIXME: Check if EXT_NOTIFY_OUT actualy has any effect and removes the need for setting the external notication pin in the
|
||||
// app/preferences
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#define BUTTON_PIN 15 // Right side button - if not available, set device.button_gpio to 0 from Meshtastic client
|
||||
|
||||
// LEDs
|
||||
#define LED_PIN 13 // Tx LED
|
||||
#define USER_LED 2 // Rx LED
|
||||
#define LED_POWER 13 // Tx LED
|
||||
#define USER_LED 2 // Rx LED
|
||||
|
||||
// Buzzer
|
||||
#define PIN_BUZZER 33
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define ADC_MULTIPLIER 1.85 // (R1 = 470k, R2 = 680k)
|
||||
#define EXT_PWR_DETECT 4 // Pin to detect connected external power source for LILYGO® TTGO T-Energy T18 and other DIY boards
|
||||
#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Module (#975).
|
||||
#define LED_PIN 2 // add status LED (compatible with core-pcb and DIY targets)
|
||||
#define LED_POWER 2 // add status LED (compatible with core-pcb and DIY targets)
|
||||
|
||||
// Radio
|
||||
#define USE_SX1262 // E22-900M30S uses SX1262
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define ADC_MULTIPLIER 1.85 // (R1 = 470k, R2 = 680k)
|
||||
#define EXT_PWR_DETECT 4 // Pin to detect connected external power source for LILYGO® TTGO T-Energy T18 and other DIY boards
|
||||
#define EXT_NOTIFY_OUT 12 // Overridden default pin to use for Ext Notify Module (#975).
|
||||
#define LED_PIN 2 // add status LED (compatible with core-pcb and DIY targets)
|
||||
#define LED_POWER 2 // add status LED (compatible with core-pcb and DIY targets)
|
||||
|
||||
#define LORA_DIO0 26 // a No connect on the SX1262/SX1268 module
|
||||
#define LORA_RESET 23 // RST for SX1276, and for SX1262/SX1268
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// HACKBOX LoRa IO Kit
|
||||
// Uses a ESP-32-WROOM and a RA-01SH (SX1262) LoRa Board
|
||||
|
||||
#define LED_PIN 2 // LED
|
||||
#define LED_POWER 2 // LED
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
|
||||
#define HAS_SCREEN 0
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define LED_POWER 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
|
||||
#define USE_RF95
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define LED_POWER 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
|
||||
#define USE_RF95
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define LED_POWER 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
|
||||
#define USE_RF95
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#undef GPS_TX_PIN
|
||||
|
||||
// Green / Lora = PIN 22 / GPIO2, Yellow / Wifi = PIN 23 / GPIO0, Blue / BLE = PIN 25 / GPIO16
|
||||
#define LED_PIN 22
|
||||
#define LED_POWER 22
|
||||
#define WIFI_LED 23
|
||||
#define BLE_LED 25
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define I2C_SCL SCL
|
||||
#define I2C_SDA SDA
|
||||
|
||||
#define LED_PIN LED
|
||||
#define LED_POWER LED
|
||||
|
||||
// active low, powers the Battery reader, but no lora antenna boost (?)
|
||||
// #define VEXT_ENABLE Vext
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
// Green LED
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
#define LED_PIN 10
|
||||
#define LED_POWER 10
|
||||
|
||||
// PCF8563 RTC Module
|
||||
#define PCF8563_RTC 0x51
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
/*
|
||||
LED PIN setup.
|
||||
*/
|
||||
#define LED_PIN 15
|
||||
#define LED_POWER 15
|
||||
|
||||
/*
|
||||
Five way button when using ADC.
|
||||
|
||||
@@ -43,7 +43,7 @@ static const uint8_t SCK = 33;
|
||||
#undef GPS_TX_PIN
|
||||
#define GPS_TX_PIN (TX1)
|
||||
|
||||
#define LED_PIN LED_BLUE
|
||||
#define LED_POWER LED_BLUE
|
||||
|
||||
#define PIN_VBAT WB_A0
|
||||
#define BATTERY_PIN PIN_VBAT
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
|
||||
|
||||
#define LED_STATE_ON 0 // State when LED is lit
|
||||
#define LED_PIN 4 // Newer tbeams (1.1) have an extra led on GPIO4
|
||||
#define LED_POWER 4 // Newer tbeams (1.1) have an extra led on GPIO4
|
||||
|
||||
// TTGO uses a common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
|
||||
// not found then probe for SX1262
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
#undef EXT_NOTIFY_OUT
|
||||
#undef LED_STATE_ON
|
||||
#undef LED_PIN
|
||||
#undef LED_POWER
|
||||
|
||||
#define HAS_CST226SE 1
|
||||
#define HAS_TOUCHSCREEN 1
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define VEXT_ON_VALUE LOW
|
||||
#define LED_PIN 2 // If defined we will blink this LED
|
||||
#define LED_POWER 2 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
#define BUTTON_NEED_PULLUP
|
||||
#define EXT_NOTIFY_OUT 13 // Default pin to use for Ext Notify Module.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define RESET_OLED 16 // If defined, this pin will be used to reset the display controller
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define LED_POWER 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 36
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#define I2C_SCL 22
|
||||
|
||||
#define VEXT_ENABLE 21 // active low, powers the oled display and the lora antenna boost
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define LED_POWER 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN \
|
||||
0 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one
|
||||
// between this pin and ground
|
||||
|
||||
@@ -22,4 +22,4 @@ build_flags =
|
||||
${env:tlora-v2-1-1_6.build_flags}
|
||||
-DBUTTON_PIN=0
|
||||
-DPIN_BUZZER=25
|
||||
-DLED_PIN=-1
|
||||
-DLED_POWER=-1
|
||||
@@ -8,10 +8,10 @@
|
||||
#define I2C_SDA 21 // I2C pins for this board
|
||||
#define I2C_SCL 22
|
||||
|
||||
#if defined(LED_PIN) && LED_PIN == -1
|
||||
#undef LED_PIN
|
||||
#if defined(LED_POWER) && LED_POWER == -1
|
||||
#undef LED_POWER
|
||||
#else
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define LED_POWER 25 // If defined we will blink this LED
|
||||
#endif
|
||||
|
||||
#define USE_RF95
|
||||
|
||||
@@ -7,4 +7,5 @@ build_flags =
|
||||
-D TLORA_V2_1_16
|
||||
-I variants/esp32/tlora_v2_1_16
|
||||
-D LORA_TCXO_GPIO=33
|
||||
upload_speed = 115200
|
||||
-ULED_BUILTIN
|
||||
upload_speed = 115200
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define I2C_SDA 21 // I2C pins for this board
|
||||
#define I2C_SCL 22
|
||||
|
||||
#define LED_PIN 25 // If defined we will blink this LED
|
||||
#define LED_POWER 25 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 12 // If defined, this will be used for user button presses,
|
||||
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define GPS_RX_PIN 9
|
||||
#define GPS_TX_PIN 10
|
||||
|
||||
#define LED_PIN 13 // 13 red, 2 blue, 15 red
|
||||
#define LED_POWER 13 // 13 red, 2 blue, 15 red
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#undef GPS_TX_PIN
|
||||
#define NO_GPS 1
|
||||
#define HAS_GPS 0
|
||||
#define NO_SCREEN
|
||||
#define HAS_SCREEN 0
|
||||
|
||||
// Default SPI1 will be mapped to the display
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define I2C_SCL SCL
|
||||
|
||||
#define BUTTON_PIN 9 // BOOT button
|
||||
#define LED_PIN 30 // RGB LED
|
||||
#define LED_POWER 30 // RGB LED
|
||||
|
||||
#define USE_RF95
|
||||
#define LORA_SCK 4
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Hackerboxes LoRa ESP32-C3 OLED Kit
|
||||
// Uses a ESP32-C3 OLED Board and a RA-01SH (SX1262) LoRa Board
|
||||
|
||||
#define LED_PIN 8 // LED
|
||||
#define LED_POWER 8 // LED
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
|
||||
#define HAS_SCREEN 0
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// LED pin on HT-DEV-ESP_V2 and HT-DEV-ESP_V3
|
||||
// https://resource.heltec.cn/download/HT-CT62/HT-CT62_Reference_Design.pdf
|
||||
// https://resource.heltec.cn/download/HT-DEV-ESP/HT-DEV-ESP_V3_Sch.pdf
|
||||
#define LED_PIN 2 // LED
|
||||
#define LED_POWER 2 // LED
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
|
||||
#define HAS_SCREEN 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define I2C_SDA 8 // I2C pins for this board
|
||||
#define I2C_SCL 9
|
||||
|
||||
#define LED_PIN 7 // If defined we will blink this LED
|
||||
#define LED_POWER 7 // If defined we will blink this LED
|
||||
#define LED_STATE_ON 0 // State when LED is lit
|
||||
|
||||
#define USE_SX1262
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define I2C_SDA 34 // I2C pins for this board
|
||||
#define I2C_SCL 36
|
||||
|
||||
#define LED_PIN 15 // If defined we will blink this LED
|
||||
#define LED_POWER 15 // If defined we will blink this LED
|
||||
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 3 // How many neopixels are connected
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// EByte EoRA-Hub
|
||||
// Uses E80 (LR1121) LoRa module
|
||||
|
||||
#define LED_PIN 35
|
||||
#define LED_POWER 35
|
||||
|
||||
// Button - user interface
|
||||
#define BUTTON_PIN 0 // BOOT button
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// LED - status indication
|
||||
#define LED_PIN 37
|
||||
#define LED_POWER 37
|
||||
|
||||
// Button - user interface
|
||||
#define BUTTON_PIN 0 // This is the BOOT button, and it has its own pull-up resistor
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
*/
|
||||
|
||||
// Status
|
||||
#define LED_PIN 1
|
||||
#define LED_POWER 1
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
// External notification
|
||||
// FIXME: Check if EXT_NOTIFY_OUT actualy has any effect and removes the need for setting the external notication pin in the
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Status
|
||||
#define LED_PIN 1
|
||||
#define LED_POWER 1
|
||||
|
||||
#define PIN_BUTTON1 47 // 功能键
|
||||
#define PIN_BUTTON2 4 // 电源键
|
||||
|
||||
@@ -8,5 +8,11 @@ void earlyInitVariant()
|
||||
Wire.begin(48, 47);
|
||||
io.pinMode(PCA_PIN_EINK_EN, OUTPUT);
|
||||
io.pinMode(PCA_PIN_POWER_EN, OUTPUT);
|
||||
io.pinMode(PCA_LED_POWER, OUTPUT);
|
||||
io.pinMode(PCA_LED_USER, OUTPUT);
|
||||
io.pinMode(PCA_LED_ENABLE, OUTPUT);
|
||||
|
||||
io.digitalWrite(PCA_PIN_POWER_EN, HIGH);
|
||||
io.digitalWrite(PCA_LED_USER, LOW);
|
||||
io.digitalWrite(PCA_LED_ENABLE, LOW);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
// LED
|
||||
// Both of these are on the GPIO expander
|
||||
#define PCA_LED_USER 1 // the Blue LED
|
||||
#define PCA_LED_POWER 3 // the Red LED? Seems to have hardware logic to blink when USB is plugged in.
|
||||
#define PCA_LED_USER 1 // the Blue LED
|
||||
#define PCA_LED_ENABLE 2 // the power supply to the LEDs, in an OR arrangement with VBUS power
|
||||
#define PCA_LED_POWER 3 // the Red LED? Seems to have hardware logic to blink when USB is plugged in.
|
||||
#define POWER_LED_HARDWARE_BLINKS_WHILE_CHARGING
|
||||
|
||||
// USB_CHECK
|
||||
#define EXT_PWR_DETECT 12
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define I2C_SDA 12
|
||||
#define I2C_SCL 14
|
||||
|
||||
#define LED_PIN 46
|
||||
#define LED_POWER 46
|
||||
#define LED_STATE_ON 0 // State when LED is litted
|
||||
|
||||
// #define BUTTON_PIN 15 // Pico OLED 1.3 User key 0 - removed User key 1 (17)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// #define GPS_RX_PIN 44
|
||||
// #define GPS_TX_PIN 43
|
||||
|
||||
#define LED_PIN 41
|
||||
#define LED_POWER 41
|
||||
#define BUTTON_PIN 2
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define I2C_SDA 18 // 1 // I2C pins for this board
|
||||
#define I2C_SCL 17 // 2
|
||||
|
||||
// #define LED_PIN 38 // This is a RGB LED not a standard LED
|
||||
// #define LED_POWER 38 // This is a RGB LED not a standard LED
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
|
||||
#define NEOPIXEL_DATA 38 // gpio pin used to send data to the neopixels
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#define I2C_SDA 18 // 1 // I2C pins for this board
|
||||
#define I2C_SCL 17 // 2
|
||||
|
||||
// #define LED_PIN 38 // This is a RGB LED not a standard LED
|
||||
// #define LED_POWER 38 // This is a RGB LED not a standard LED
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
|
||||
#define NEOPIXEL_DATA 38 // gpio pin used to send data to the neopixels
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#define I2C_SDA1 45
|
||||
#define I2C_SCL1 46
|
||||
|
||||
#define LED_PIN 6
|
||||
#define LED_POWER 6
|
||||
#define LED_STATE_ON 1
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#define EXT_NOTIFY_OUT 22
|
||||
#define BUTTON_PIN 0 // 17
|
||||
|
||||
// #define LED_PIN PIN_LED
|
||||
// Board has RGB LED 21
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 1 // How many neopixels are connected
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define LED_PIN 33
|
||||
#define LED_PIN2 34
|
||||
#define LED_POWER 33
|
||||
#define LED_POWER2 34
|
||||
#define EXT_PWR_DETECT 35
|
||||
|
||||
#define BUTTON_PIN 18
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN LED
|
||||
#define LED_POWER LED
|
||||
|
||||
#define USE_SSD1306 // Heltec_v3 has a SSD1306 display
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ build_flags =
|
||||
${heltec_v4_base.build_flags}
|
||||
-D HELTEC_V4_OLED
|
||||
-D USE_SSD1306 ; Heltec_v4 has an SSD1315 display (compatible with SSD1306 driver)
|
||||
-D LED_PIN=35
|
||||
-D LED_POWER=35
|
||||
-D RESET_OLED=21
|
||||
-D I2C_SDA=17
|
||||
-D I2C_SCL=18
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 45 // LED is not populated on earliest board variant
|
||||
#define LED_POWER 45 // LED is not populated on earliest board variant
|
||||
#define BUTTON_PIN 0
|
||||
#define PIN_BUTTON2 21 // Second built-in button
|
||||
#define ALT_BUTTON_PIN PIN_BUTTON2 // Send the up event
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 45 // LED is not populated on earliest board variant
|
||||
#define LED_POWER 45 // LED is not populated on earliest board variant
|
||||
#define BUTTON_PIN 0
|
||||
#define PIN_BUTTON2 21 // Second built-in button
|
||||
#define ALT_BUTTON_PIN PIN_BUTTON2 // Send the up event
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
// I2C
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
// I2C
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
|
||||
#define _VARIANT_HELTEC_WIRELESS_TRACKER
|
||||
#define HELTEC_TRACKER_V1_X
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
|
||||
#define HELTEC_TRACKER_V1_X
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
|
||||
#define _VARIANT_HELTEC_WIRELESS_TRACKER
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define I2C_SCL SCL
|
||||
#define I2C_SDA SDA
|
||||
|
||||
#define LED_PIN LED
|
||||
#define LED_POWER LED
|
||||
|
||||
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
|
||||
#define VEXT_ON_VALUE LOW
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#define ADC_CHANNEL ADC1_GPIO4_CHANNEL
|
||||
|
||||
// LED
|
||||
#define LED_PIN 21
|
||||
#define LED_POWER 21
|
||||
|
||||
// Button
|
||||
#define BUTTON_PIN 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define I2C_SDA 11 // I2C pins for this board
|
||||
#define I2C_SCL 10
|
||||
|
||||
#define LED_PIN 1 // If defined we will blink this LED
|
||||
#define LED_POWER 1 // If defined we will blink this LED
|
||||
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#define USE_SSD1306
|
||||
#define DISPLAY_FLIP_SCREEN
|
||||
|
||||
#define LED_PIN 15 // If defined we will blink this LED
|
||||
#define LED_POWER 15 // If defined we will blink this LED
|
||||
|
||||
#define HAS_NEOPIXEL // Enable the use of neopixels
|
||||
#define NEOPIXEL_COUNT 3 // How many neopixels are connected
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define PIN_LED1 LED_GREEN
|
||||
#define LED_NOTIFICATION LED_BLUE
|
||||
|
||||
#define LED_PIN LED_GREEN
|
||||
#define LED_POWER LED_GREEN
|
||||
#define ledOff(pin) pinMode(pin, INPUT)
|
||||
|
||||
#define LED_STATE_ON 1 // State when LED is litted
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define PIN_LED1 LED_GREEN
|
||||
#define LED_NOTIFICATION LED_BLUE
|
||||
|
||||
#define LED_PIN LED_GREEN
|
||||
#define LED_POWER LED_GREEN
|
||||
#define ledOff(pin) pinMode(pin, INPUT)
|
||||
|
||||
#define LED_STATE_ON 1 // State when LED is litted
|
||||
|
||||
@@ -30,7 +30,7 @@ Expansion Board Infomation : https://www.seeedstudio.com/Seeeduino-XIAO-Expansio
|
||||
L76K GPS Module Information : https://www.seeedstudio.com/L76K-GNSS-Module-for-Seeed-Studio-XIAO-p-5864.html
|
||||
*/
|
||||
|
||||
#define LED_PIN 48
|
||||
#define LED_POWER 48
|
||||
#define LED_STATE_ON 1 // State when LED is lit
|
||||
|
||||
#define BUTTON_PIN 21 // This is the Program Button
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
#endif
|
||||
|
||||
// LED
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
#define LED_STATE_ON 1 // HIGH = ON
|
||||
|
||||
// Battery ADC
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#define HAS_SCREEN 1 // Allow for OLED Screens on I2C Header of shield
|
||||
|
||||
#define LED_PIN 38 // If defined we will blink this LED
|
||||
#define LED_POWER 38 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses,
|
||||
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define GPS_RX_PIN 44
|
||||
#define GPS_TX_PIN 43
|
||||
|
||||
#define LED_PIN 37
|
||||
#define LED_POWER 37
|
||||
#define BUTTON_PIN 0
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#define I2C_SDA1 43
|
||||
#define I2C_SCL1 44
|
||||
|
||||
#define LED_PIN 37 // If defined we will blink this LED
|
||||
#define LED_POWER 37 // If defined we will blink this LED
|
||||
#define BUTTON_PIN 0 // If defined, this will be used for user button presses,
|
||||
|
||||
#define BUTTON_NEED_PULLUP
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
|
||||
#define HELTEC_TRACKER_V1_X
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
|
||||
#define HELTEC_TRACKER_V1_X
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define LED_PIN 18
|
||||
#define LED_POWER 18
|
||||
|
||||
#define HELTEC_TRACKER_V1_X
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
|
||||
#define SD_SPI_FREQUENCY 25000000
|
||||
|
||||
#define LED_PIN 13 // the red part of the RGB LED
|
||||
#define LED_POWER 13 // the red part of the RGB LED
|
||||
#define LED_STATE_ON 0 // State when LED is lit
|
||||
|
||||
#define ALT_BUTTON_PIN 21 // Button 3 - square - top button in landscape mode
|
||||
|
||||
@@ -52,7 +52,6 @@ extern "C" {
|
||||
// LED
|
||||
#define LED_RED 33
|
||||
#define LED_POWER LED_RED
|
||||
#define LED_CHARGE LED_POWER // Signals the Status LED Module to handle this LED
|
||||
#define LED_GREEN 35
|
||||
#define LED_NOTIFICATION LED_GREEN
|
||||
#define LED_BLUE 37
|
||||
|
||||
@@ -32,9 +32,6 @@ const uint32_t g_ADigitalPinMap[] = {
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
pinMode(LED_CHARGE, OUTPUT);
|
||||
ledOff(LED_CHARGE);
|
||||
|
||||
pinMode(LED_PAIRING, OUTPUT);
|
||||
ledOff(LED_PAIRING);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user