mirror of
https://github.com/meshtastic/firmware.git
synced 2025-07-30 02:15:41 +00:00
Merge branch 'master' into add-traceroute
This commit is contained in:
commit
d7a3dee1be
24
.github/workflows/pr_enforce_labels.yml
vendored
Normal file
24
.github/workflows/pr_enforce_labels.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: Check PR Labels
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, labeled, unlabeled, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
pull-requests: read
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
check-label:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Check for PR labels
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const labels = context.payload.pull_request.labels.map(label => label.name);
|
||||
const requiredLabels = ['bugfix', 'enhancement', 'hardware-support', 'dependencies', 'submodules', 'github_actions', 'trunk'];
|
||||
const hasRequiredLabel = labels.some(label => requiredLabels.includes(label));
|
||||
if (!hasRequiredLabel) {
|
||||
core.setFailed(`PR must have at least one of the following labels before it can be merged: ${requiredLabels.join(', ')}.`);
|
||||
}
|
3
.github/workflows/release_channels.yml
vendored
3
.github/workflows/release_channels.yml
vendored
@ -103,8 +103,9 @@ jobs:
|
||||
with:
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
branch: create-pull-request/bump-version
|
||||
labels: github_actions
|
||||
title: Bump release version
|
||||
commit-message: automated bumps
|
||||
commit-message: Automated version bumps
|
||||
add-paths: |
|
||||
version.properties
|
||||
debian/changelog
|
||||
|
2
.github/workflows/update_protobufs.yml
vendored
2
.github/workflows/update_protobufs.yml
vendored
@ -34,7 +34,9 @@ jobs:
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
branch: create-pull-request/update-protobufs
|
||||
labels: submodules
|
||||
title: Update protobufs and classes
|
||||
commit-message: Update protobufs
|
||||
add-paths: |
|
||||
protobufs
|
||||
src/mesh
|
||||
|
@ -8,15 +8,15 @@ plugins:
|
||||
uri: https://github.com/trunk-io/plugins
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.450
|
||||
- renovate@41.30.5
|
||||
- checkov@3.2.451
|
||||
- renovate@41.37.9
|
||||
- prettier@3.6.2
|
||||
- trufflehog@3.89.2
|
||||
- trufflehog@3.90.0
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.8.6
|
||||
- trivy@0.64.1
|
||||
- taplo@0.9.3
|
||||
- ruff@0.12.2
|
||||
- ruff@0.12.3
|
||||
- isort@6.0.1
|
||||
- markdownlint@0.45.0
|
||||
- oxipng@9.1.5
|
||||
|
@ -39,7 +39,7 @@ build_flags =
|
||||
-Isrc/platform/portduino
|
||||
-DRADIOLIB_EEPROM_UNSUPPORTED
|
||||
-DPORTDUINO_LINUX_HARDWARE
|
||||
-DHAS_UDP_MULTICAST
|
||||
-DHAS_UDP_MULTICAST=1
|
||||
-lpthread
|
||||
-lstdc++fs
|
||||
-lbluetooth
|
||||
|
@ -87,6 +87,9 @@
|
||||
</screenshots>
|
||||
|
||||
<releases>
|
||||
<release version="2.7.4" date="2025-07-19">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.4</url>
|
||||
</release>
|
||||
<release version="2.7.3" date="2025-07-10">
|
||||
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.3</url>
|
||||
</release>
|
||||
|
7
debian/changelog
vendored
7
debian/changelog
vendored
@ -1,4 +1,4 @@
|
||||
meshtasticd (2.7.3.0) UNRELEASED; urgency=medium
|
||||
meshtasticd (2.7.4.0) UNRELEASED; urgency=medium
|
||||
|
||||
[ Austin Lane ]
|
||||
* Initial packaging
|
||||
@ -31,4 +31,7 @@ meshtasticd (2.7.3.0) UNRELEASED; urgency=medium
|
||||
[ Ubuntu ]
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
-- Ubuntu <github-actions[bot]@users.noreply.github.com> Thu, 10 Jul 2025 16:29:27 +0000
|
||||
[ ]
|
||||
* GitHub Actions Automatic version bump
|
||||
|
||||
-- <github-actions[bot]@users.noreply.github.com> Sat, 19 Jul 2025 11:36:55 +0000
|
||||
|
@ -6,7 +6,9 @@ default_envs = tbeam
|
||||
|
||||
extra_configs =
|
||||
arch/*/*.ini
|
||||
variants/*/platformio.ini
|
||||
variants/*/platformio.ini ; Remove when all variants migrated to new dir structure
|
||||
variants/*/*/platformio.ini
|
||||
variants/*/diy/*/platformio.ini
|
||||
src/graphics/niche/InkHUD/PlatformioConfig.ini
|
||||
|
||||
description = Meshtastic
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit f6448be7770a3521bf52407ff8f5fa5b9b06da7b
|
||||
Subproject commit 15c1fbde882de953dec279160fa984d0e00569d0
|
@ -681,7 +681,16 @@ bool Power::setup()
|
||||
|
||||
void Power::shutdown()
|
||||
{
|
||||
LOG_INFO("Shutting Down");
|
||||
|
||||
#if HAS_SCREEN
|
||||
if (screen) {
|
||||
screen->showSimpleBanner("Shutting Down...", 0); // stays on screen
|
||||
}
|
||||
#endif
|
||||
#if !defined(ARCH_STM32WL)
|
||||
playShutdownMelody();
|
||||
#endif
|
||||
nodeDB->saveToDisk();
|
||||
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32) || defined(ARCH_RP2040)
|
||||
#ifdef PIN_LED1
|
||||
@ -693,7 +702,11 @@ void Power::shutdown()
|
||||
#ifdef PIN_LED3
|
||||
ledOff(PIN_LED3);
|
||||
#endif
|
||||
doDeepSleep(DELAY_FOREVER, false, false);
|
||||
doDeepSleep(DELAY_FOREVER, false, true);
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
exit(EXIT_SUCCESS);
|
||||
#else
|
||||
LOG_WARN("FIXME implement shutdown for this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -47,10 +47,6 @@ int BuzzerFeedbackThread::handleInputEvent(const InputEvent *event)
|
||||
playComboTune(); // Ping sent feedback
|
||||
break;
|
||||
|
||||
case INPUT_BROKER_SHUTDOWN:
|
||||
playShutdownMelody(); // Shutdown feedback
|
||||
break;
|
||||
|
||||
default:
|
||||
// For other events, check if it's a printable character
|
||||
if (event->kbchar >= 32 && event->kbchar <= 126) {
|
||||
@ -69,10 +65,7 @@ int32_t BuzzerFeedbackThread::runOnce()
|
||||
// This thread is primarily event-driven, but we can use runOnce
|
||||
// for any periodic tasks if needed in the future
|
||||
|
||||
if (needsUpdate) {
|
||||
needsUpdate = false;
|
||||
// Could add any periodic processing here
|
||||
}
|
||||
needsUpdate = false;
|
||||
|
||||
// Run every 100ms when active, less frequently when idle
|
||||
return needsUpdate ? 100 : 1000;
|
||||
|
@ -1001,7 +1001,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
// Insert favorite frames *after* collecting them all
|
||||
if (!favoriteFrames.empty()) {
|
||||
fsi.positions.firstFavorite = numframes;
|
||||
for (auto &f : favoriteFrames) {
|
||||
for (const auto &f : favoriteFrames) {
|
||||
normalFrames[numframes++] = f;
|
||||
indicatorIcons.push_back(icon_node);
|
||||
}
|
||||
|
@ -218,7 +218,6 @@ void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int1
|
||||
hour %= 12;
|
||||
if (hour == 0)
|
||||
hour = 12;
|
||||
bool isPM = hour >= 12;
|
||||
snprintf(timeString, sizeof(timeString), "%d:%02d", hour, minute);
|
||||
} else {
|
||||
snprintf(timeString, sizeof(timeString), "%02d:%02d", hour, minute);
|
||||
@ -367,7 +366,7 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// hour hand radius and y coordinate
|
||||
int16_t hourHandRadius = radius * 0.35;
|
||||
if (isHighResolution) {
|
||||
int16_t hourHandRadius = radius * 0.55;
|
||||
hourHandRadius = radius * 0.55;
|
||||
}
|
||||
int16_t hourHandNoonY = centerY - hourHandRadius;
|
||||
|
||||
@ -386,7 +385,7 @@ void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
|
||||
bool isPM = hour >= 12;
|
||||
if (config.display.use_12h_clock) {
|
||||
bool isPM = hour >= 12;
|
||||
isPM = hour >= 12;
|
||||
display->setFont(FONT_SMALL);
|
||||
int yOffset = isHighResolution ? 1 : 0;
|
||||
#ifdef USE_EINK
|
||||
|
@ -825,9 +825,8 @@ void menuHandler::shutdownMenu()
|
||||
bannerOptions.optionsCount = 2;
|
||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||
if (selected == 1) {
|
||||
IF_SCREEN(screen->showSimpleBanner("Shutting Down...", 0));
|
||||
nodeDB->saveToDisk();
|
||||
power->shutdown();
|
||||
InputEvent event = {.inputEvent = (input_broker_event)INPUT_BROKER_SHUTDOWN, .kbchar = 0, .touchX = 0, .touchY = 0};
|
||||
inputBroker->injectInputEvent(&event);
|
||||
} else {
|
||||
menuQueue = power_menu;
|
||||
screen->runNow();
|
||||
|
@ -53,23 +53,21 @@ bool ButtonThread::initButton(const ButtonConfig &config)
|
||||
},
|
||||
this);
|
||||
|
||||
if (config.longPress != INPUT_BROKER_NONE) {
|
||||
_longPress = config.longPress;
|
||||
userButton.attachLongPressStart(
|
||||
[](void *callerThread) -> void {
|
||||
ButtonThread *thread = (ButtonThread *)callerThread;
|
||||
// if (millis() > 30000) // hold off 30s after boot
|
||||
thread->btnEvent = BUTTON_EVENT_LONG_PRESSED;
|
||||
},
|
||||
this);
|
||||
userButton.attachLongPressStop(
|
||||
[](void *callerThread) -> void {
|
||||
ButtonThread *thread = (ButtonThread *)callerThread;
|
||||
// if (millis() > 30000) // hold off 30s after boot
|
||||
thread->btnEvent = BUTTON_EVENT_LONG_RELEASED;
|
||||
},
|
||||
this);
|
||||
}
|
||||
_longPress = config.longPress;
|
||||
userButton.attachLongPressStart(
|
||||
[](void *callerThread) -> void {
|
||||
ButtonThread *thread = (ButtonThread *)callerThread;
|
||||
// if (millis() > 30000) // hold off 30s after boot
|
||||
thread->btnEvent = BUTTON_EVENT_LONG_PRESSED;
|
||||
},
|
||||
this);
|
||||
userButton.attachLongPressStop(
|
||||
[](void *callerThread) -> void {
|
||||
ButtonThread *thread = (ButtonThread *)callerThread;
|
||||
// if (millis() > 30000) // hold off 30s after boot
|
||||
thread->btnEvent = BUTTON_EVENT_LONG_RELEASED;
|
||||
},
|
||||
this);
|
||||
|
||||
if (config.doublePress != INPUT_BROKER_NONE) {
|
||||
_doublePress = config.doublePress;
|
||||
@ -202,11 +200,11 @@ int32_t ButtonThread::runOnce()
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Forward long press to InputBroker (but NOT as DOWN/SELECT, just forward a "button long press" event)
|
||||
evt.inputEvent = _longPress;
|
||||
this->notifyObservers(&evt);
|
||||
|
||||
if (_longPress != INPUT_BROKER_NONE) {
|
||||
// Forward long press to InputBroker (but NOT as DOWN/SELECT, just forward a "button long press" event)
|
||||
evt.inputEvent = _longPress;
|
||||
this->notifyObservers(&evt);
|
||||
}
|
||||
// Reset combination tracking
|
||||
waitingForLongPress = false;
|
||||
|
||||
@ -253,7 +251,7 @@ int32_t ButtonThread::runOnce()
|
||||
// may wake the board immediatedly.
|
||||
case BUTTON_EVENT_LONG_RELEASED: {
|
||||
|
||||
LOG_INFO("LONG PRESS RELEASE");
|
||||
LOG_INFO("LONG PRESS RELEASE AFTER %u MILLIS", millis() - buttonPressStartTime);
|
||||
if (millis() > 30000 && _longLongPress != INPUT_BROKER_NONE &&
|
||||
(millis() - buttonPressStartTime) >= _longLongPressTime) {
|
||||
evt.inputEvent = _longLongPress;
|
||||
|
@ -18,13 +18,13 @@ struct ButtonConfig {
|
||||
uint16_t longPressTime = 500;
|
||||
input_broker_event doublePress = INPUT_BROKER_NONE;
|
||||
input_broker_event longLongPress = INPUT_BROKER_NONE;
|
||||
uint16_t longLongPressTime = 5000;
|
||||
uint16_t longLongPressTime = 3900;
|
||||
input_broker_event triplePress = INPUT_BROKER_NONE;
|
||||
input_broker_event shortLong = INPUT_BROKER_NONE;
|
||||
bool touchQuirk = false;
|
||||
|
||||
// Constructor to set required parameter
|
||||
ButtonConfig(uint8_t pin = 0) : pinNumber(pin) {}
|
||||
explicit ButtonConfig(uint8_t pin = 0) : pinNumber(pin) {}
|
||||
};
|
||||
|
||||
#ifndef BUTTON_CLICK_MS
|
||||
@ -62,7 +62,7 @@ class ButtonThread : public Observable<const InputEvent *>, public concurrency::
|
||||
BUTTON_EVENT_COMBO_SHORT_LONG,
|
||||
};
|
||||
|
||||
ButtonThread(const char *name);
|
||||
explicit ButtonThread(const char *name);
|
||||
int32_t runOnce() override;
|
||||
OneButton userButton;
|
||||
void attachButtonInterrupts();
|
||||
|
@ -233,14 +233,7 @@ void ExpressLRSFiveWay::sendAdhocPing()
|
||||
// Contained as one method for easier remapping of buttons by user
|
||||
void ExpressLRSFiveWay::shutdown()
|
||||
{
|
||||
LOG_INFO("Shutdown from long press");
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
screen->startAlert("Shutting Down...");
|
||||
// Don't set alerting = true. We don't want to auto-dismiss this alert.
|
||||
|
||||
playShutdownMelody(); // In case user adds a buzzer
|
||||
|
||||
shutdownAtMsec = millis() + 3000;
|
||||
sendKey(INPUT_BROKER_SHUTDOWN);
|
||||
}
|
||||
|
||||
void ExpressLRSFiveWay::click()
|
||||
|
@ -1042,8 +1042,9 @@ void setup()
|
||||
mainDelay.interruptFromISR(&higherWake);
|
||||
};
|
||||
userConfigNoScreen.singlePress = INPUT_BROKER_USER_PRESS;
|
||||
userConfigNoScreen.longPress = INPUT_BROKER_SHUTDOWN;
|
||||
userConfigNoScreen.longPressTime = 5000;
|
||||
userConfigNoScreen.longPress = INPUT_BROKER_NONE;
|
||||
userConfigNoScreen.longPressTime = 500;
|
||||
userConfigNoScreen.longLongPress = INPUT_BROKER_SHUTDOWN;
|
||||
userConfigNoScreen.doublePress = INPUT_BROKER_SEND_PING;
|
||||
userConfigNoScreen.triplePress = INPUT_BROKER_GPS_TOGGLE;
|
||||
UserButtonThread->initButton(userConfigNoScreen);
|
||||
|
@ -121,7 +121,7 @@ meshtastic_MeshPacket *MeshPacketQueue::remove(NodeNum from, PacketId id, bool t
|
||||
bool MeshPacketQueue::find(const NodeNum from, const PacketId id)
|
||||
{
|
||||
for (auto it = queue.begin(); it != queue.end(); it++) {
|
||||
const auto p = (*it);
|
||||
const auto *p = *it;
|
||||
if (getFrom(p) == from && p->id == id) {
|
||||
return true;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "meshUtils.h"
|
||||
#include "modules/NodeInfoModule.h"
|
||||
#include "modules/PositionModule.h"
|
||||
#include "modules/RoutingModule.h"
|
||||
#include "power.h"
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
@ -333,6 +334,21 @@ void MeshService::sendMqttMessageToClientProxy(meshtastic_MqttClientProxyMessage
|
||||
fromNum++;
|
||||
}
|
||||
|
||||
void MeshService::sendRoutingErrorResponse(meshtastic_Routing_Error error, const meshtastic_MeshPacket *mp)
|
||||
{
|
||||
if (!mp) {
|
||||
LOG_WARN("Cannot send routing error response: null packet");
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the routing module to send the error response
|
||||
if (routingModule) {
|
||||
routingModule->sendAckNak(error, mp->from, mp->id, mp->channel);
|
||||
} else {
|
||||
LOG_ERROR("Cannot send routing error response: no routing module");
|
||||
}
|
||||
}
|
||||
|
||||
void MeshService::sendClientNotification(meshtastic_ClientNotification *n)
|
||||
{
|
||||
LOG_DEBUG("Send client notification to phone");
|
||||
|
@ -148,6 +148,9 @@ class MeshService
|
||||
/// Send a ClientNotification to the phone
|
||||
void sendClientNotification(meshtastic_ClientNotification *cn);
|
||||
|
||||
/// Send an error response to the phone
|
||||
void sendRoutingErrorResponse(meshtastic_Routing_Error error, const meshtastic_MeshPacket *mp);
|
||||
|
||||
bool isToPhoneQueueEmpty();
|
||||
|
||||
ErrorCode sendQueueStatusToPhone(const meshtastic_QueueStatus &qs, ErrorCode res, uint32_t mesh_packet_id);
|
||||
|
@ -1868,7 +1868,7 @@ UserLicenseStatus NodeDB::getLicenseStatus(uint32_t nodeNum)
|
||||
return info->user.is_licensed ? UserLicenseStatus::Licensed : UserLicenseStatus::NotLicensed;
|
||||
}
|
||||
|
||||
bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t keyToTest)
|
||||
bool NodeDB::checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest)
|
||||
{
|
||||
if (keyToTest.size == 32) {
|
||||
uint8_t keyHash[32] = {0};
|
||||
|
@ -279,7 +279,7 @@ class NodeDB
|
||||
|
||||
bool hasValidPosition(const meshtastic_NodeInfoLite *n);
|
||||
|
||||
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t keyToTest);
|
||||
bool checkLowEntropyPublicKey(const meshtastic_Config_SecurityConfig_public_key_t &keyToTest);
|
||||
|
||||
bool backupPreferences(meshtastic_AdminMessage_BackupLocation location);
|
||||
bool restorePreferences(meshtastic_AdminMessage_BackupLocation location,
|
||||
|
@ -181,7 +181,7 @@ PacketHistory::PacketRecord *PacketHistory::find(NodeNum sender, PacketId id)
|
||||
}
|
||||
|
||||
/** Insert/Replace oldest PacketRecord in recentPackets. */
|
||||
void PacketHistory::insert(PacketRecord &r)
|
||||
void PacketHistory::insert(const PacketRecord &r)
|
||||
{
|
||||
uint32_t now_millis = millis(); // Should not jump with time changes
|
||||
uint32_t OldtrxTimeMsec = 0;
|
||||
@ -308,7 +308,7 @@ bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const N
|
||||
return false;
|
||||
}
|
||||
|
||||
PacketRecord *found = find(sender, id);
|
||||
const PacketRecord *found = find(sender, id);
|
||||
|
||||
if (found == NULL) {
|
||||
#if VERBOSE_PACKET_HISTORY
|
||||
@ -327,7 +327,7 @@ bool PacketHistory::wasRelayer(const uint8_t relayer, const uint32_t id, const N
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, PacketRecord &r)
|
||||
bool PacketHistory::wasRelayer(const uint8_t relayer, const PacketRecord &r)
|
||||
{
|
||||
for (uint8_t i = 0; i < NUM_RELAYERS; i++) {
|
||||
if (r.relayed_by[i] == relayer) {
|
||||
|
@ -31,11 +31,11 @@ class PacketHistory
|
||||
|
||||
/** Insert/Replace oldest PacketRecord in mx_recentPackets.
|
||||
* @param r PacketRecord to insert or replace */
|
||||
void insert(PacketRecord &r); // Insert or replace a packet record in the history
|
||||
void insert(const PacketRecord &r); // Insert or replace a packet record in the history
|
||||
|
||||
/* Check if a certain node was a relayer of a packet in the history given iterator
|
||||
* @return true if node was indeed a relayer, false if not */
|
||||
bool wasRelayer(const uint8_t relayer, PacketRecord &r);
|
||||
bool wasRelayer(const uint8_t relayer, const PacketRecord &r);
|
||||
|
||||
PacketHistory(const PacketHistory &); // non construction-copyable
|
||||
PacketHistory &operator=(const PacketHistory &); // non copyable
|
||||
|
@ -686,7 +686,8 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
|
||||
LOG_WARN("Rate limit portnum %d", p.decoded.portnum);
|
||||
meshtastic_QueueStatus qs = router->getQueueStatus();
|
||||
service->sendQueueStatusToPhone(qs, 0, p.id);
|
||||
sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "Text messages can only be sent once every 2 seconds");
|
||||
service->sendRoutingErrorResponse(meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED, &p);
|
||||
// sendNotification(meshtastic_LogRecord_Level_WARNING, p.id, "Text messages can only be sent once every 2 seconds");
|
||||
return false;
|
||||
}
|
||||
lastPortNumToRadio[p.decoded.portnum] = millis();
|
||||
|
@ -68,6 +68,11 @@ static int32_t reconnectETH()
|
||||
initApiServer();
|
||||
}
|
||||
#endif
|
||||
#if HAS_UDP_MULTICAST
|
||||
if (udpHandler && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
|
||||
udpHandler->start();
|
||||
}
|
||||
#endif
|
||||
|
||||
ethStartupComplete = true;
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
|
||||
bool initEthernet();
|
||||
bool isEthernetAvailable();
|
||||
|
@ -480,7 +480,8 @@ typedef struct _meshtastic_Config_DisplayConfig {
|
||||
/* Number of seconds the screen stays on after pressing the user button or receiving a message
|
||||
0 for default of one minute MAXUINT for always on */
|
||||
uint32_t screen_on_secs;
|
||||
/* How the GPS coordinates are formatted on the OLED screen. */
|
||||
/* Deprecated in 2.7.4: Unused
|
||||
How the GPS coordinates are formatted on the OLED screen. */
|
||||
meshtastic_Config_DisplayConfig_GpsCoordinateFormat gps_format;
|
||||
/* Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds.
|
||||
Potentially useful for devices without user buttons. */
|
||||
|
@ -426,7 +426,10 @@ typedef enum _meshtastic_Routing_Error {
|
||||
/* Admin packet otherwise checks out, but uses a bogus or expired session key */
|
||||
meshtastic_Routing_Error_ADMIN_BAD_SESSION_KEY = 36,
|
||||
/* Admin packet sent using PKC, but not from a public key on the admin key list */
|
||||
meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED = 37
|
||||
meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED = 37,
|
||||
/* Airtime fairness rate limit exceeded for a packet
|
||||
This typically enforced per portnum and is used to prevent a single node from monopolizing airtime */
|
||||
meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED = 38
|
||||
} meshtastic_Routing_Error;
|
||||
|
||||
/* The priority of this message for sending.
|
||||
@ -1222,8 +1225,8 @@ extern "C" {
|
||||
#define _meshtastic_Position_AltSource_ARRAYSIZE ((meshtastic_Position_AltSource)(meshtastic_Position_AltSource_ALT_BAROMETRIC+1))
|
||||
|
||||
#define _meshtastic_Routing_Error_MIN meshtastic_Routing_Error_NONE
|
||||
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED
|
||||
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED+1))
|
||||
#define _meshtastic_Routing_Error_MAX meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED
|
||||
#define _meshtastic_Routing_Error_ARRAYSIZE ((meshtastic_Routing_Error)(meshtastic_Routing_Error_RATE_LIMIT_EXCEEDED+1))
|
||||
|
||||
#define _meshtastic_MeshPacket_Priority_MIN meshtastic_MeshPacket_Priority_UNSET
|
||||
#define _meshtastic_MeshPacket_Priority_MAX meshtastic_MeshPacket_Priority_MAX
|
||||
|
@ -93,7 +93,11 @@ typedef enum _meshtastic_TelemetrySensorType {
|
||||
/* PCT2075 Temperature Sensor */
|
||||
meshtastic_TelemetrySensorType_PCT2075 = 39,
|
||||
/* ADS1X15 ADC */
|
||||
meshtastic_TelemetrySensorType_ADS1X15 = 40
|
||||
meshtastic_TelemetrySensorType_ADS1X15 = 40,
|
||||
/* ADS1X15 ADC_ALT */
|
||||
meshtastic_TelemetrySensorType_ADS1X15_ALT = 41,
|
||||
/* Sensirion SFA30 Formaldehyde sensor */
|
||||
meshtastic_TelemetrySensorType_SFA30 = 42
|
||||
} meshtastic_TelemetrySensorType;
|
||||
|
||||
/* Struct definitions */
|
||||
@ -287,6 +291,15 @@ typedef struct _meshtastic_AirQualityMetrics {
|
||||
/* CO2 sensor relative humidity in % */
|
||||
bool has_co2_humidity;
|
||||
float co2_humidity;
|
||||
/* Formaldehyde sensor formaldehyde concentration in ppb */
|
||||
bool has_form_formaldehyde;
|
||||
float form_formaldehyde;
|
||||
/* Formaldehyde sensor relative humidity in %RH */
|
||||
bool has_form_humidity;
|
||||
float form_humidity;
|
||||
/* Formaldehyde sensor temperature in degrees Celsius */
|
||||
bool has_form_temperature;
|
||||
float form_temperature;
|
||||
} meshtastic_AirQualityMetrics;
|
||||
|
||||
/* Local device mesh statistics */
|
||||
@ -398,8 +411,8 @@ extern "C" {
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_ADS1X15
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_ADS1X15+1))
|
||||
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SFA30
|
||||
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SFA30+1))
|
||||
|
||||
|
||||
|
||||
@ -415,7 +428,7 @@ extern "C" {
|
||||
#define meshtastic_DeviceMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0}
|
||||
#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
|
||||
@ -424,7 +437,7 @@ extern "C" {
|
||||
#define meshtastic_DeviceMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
|
||||
#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0}
|
||||
#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
|
||||
@ -490,6 +503,9 @@ extern "C" {
|
||||
#define meshtastic_AirQualityMetrics_co2_tag 13
|
||||
#define meshtastic_AirQualityMetrics_co2_temperature_tag 14
|
||||
#define meshtastic_AirQualityMetrics_co2_humidity_tag 15
|
||||
#define meshtastic_AirQualityMetrics_form_formaldehyde_tag 16
|
||||
#define meshtastic_AirQualityMetrics_form_humidity_tag 17
|
||||
#define meshtastic_AirQualityMetrics_form_temperature_tag 18
|
||||
#define meshtastic_LocalStats_uptime_seconds_tag 1
|
||||
#define meshtastic_LocalStats_channel_utilization_tag 2
|
||||
#define meshtastic_LocalStats_air_util_tx_tag 3
|
||||
@ -597,7 +613,10 @@ X(a, STATIC, OPTIONAL, UINT32, particles_50um, 11) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, particles_100um, 12) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, co2, 13) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, co2_temperature, 14) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, co2_humidity, 15)
|
||||
X(a, STATIC, OPTIONAL, FLOAT, co2_humidity, 15) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, form_formaldehyde, 16) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, form_humidity, 17) \
|
||||
X(a, STATIC, OPTIONAL, FLOAT, form_temperature, 18)
|
||||
#define meshtastic_AirQualityMetrics_CALLBACK NULL
|
||||
#define meshtastic_AirQualityMetrics_DEFAULT NULL
|
||||
|
||||
@ -686,7 +705,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define MESHTASTIC_MESHTASTIC_TELEMETRY_PB_H_MAX_SIZE meshtastic_Telemetry_size
|
||||
#define meshtastic_AirQualityMetrics_size 88
|
||||
#define meshtastic_AirQualityMetrics_size 106
|
||||
#define meshtastic_DeviceMetrics_size 27
|
||||
#define meshtastic_EnvironmentMetrics_size 113
|
||||
#define meshtastic_HealthMetrics_size 11
|
||||
|
@ -4,8 +4,13 @@
|
||||
#include "main.h"
|
||||
#include "mesh/Router.h"
|
||||
|
||||
#include <AsyncUDP.h>
|
||||
#if HAS_ETHERNET && defined(ARCH_NRF52)
|
||||
#include "mesh/eth/ethClient.h"
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#endif
|
||||
|
||||
#include <AsyncUDP.h>
|
||||
|
||||
#if HAS_ETHERNET && defined(USE_WS5500)
|
||||
#include <ETHClass2.h>
|
||||
@ -22,11 +27,11 @@ class UdpMulticastHandler final
|
||||
void start()
|
||||
{
|
||||
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT, 64)) {
|
||||
#ifndef ARCH_PORTDUINO
|
||||
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
||||
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_PORTDUINO)
|
||||
LOG_DEBUG("UDP Listening on IP: %u.%u.%u.%u:%u", udpIpAddress[0], udpIpAddress[1], udpIpAddress[2], udpIpAddress[3],
|
||||
UDP_MULTICAST_DEFAUL_PORT);
|
||||
#else
|
||||
LOG_DEBUG("UDP Listening");
|
||||
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
|
||||
#endif
|
||||
udp.onPacket([this](AsyncUDPPacket packet) { onReceive(packet); });
|
||||
} else {
|
||||
@ -37,7 +42,10 @@ class UdpMulticastHandler final
|
||||
void onReceive(AsyncUDPPacket packet)
|
||||
{
|
||||
size_t packetLength = packet.length();
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#if defined(ARCH_NRF52)
|
||||
IPAddress ip = packet.remoteIP();
|
||||
LOG_DEBUG("UDP broadcast from: %u.%u.%u.%u, len=%u", ip[0], ip[1], ip[2], ip[3], packetLength);
|
||||
#elif !defined(ARCH_PORTDUINO)
|
||||
// FIXME(PORTDUINO): arduino lacks IPAddress::toString()
|
||||
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
|
||||
#endif
|
||||
@ -61,7 +69,11 @@ class UdpMulticastHandler final
|
||||
if (!mp || !udp) {
|
||||
return false;
|
||||
}
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#if defined(ARCH_NRF52)
|
||||
if (!isEthernetAvailable()) {
|
||||
return false;
|
||||
}
|
||||
#elif !defined(ARCH_PORTDUINO)
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1447,7 +1447,7 @@ void CannedMessageModule::drawEmotePickerScreen(OLEDDisplay *display, OLEDDispla
|
||||
int headerY = y;
|
||||
int listTop = headerY + headerFontHeight + headerMargin;
|
||||
|
||||
int visibleRows = (display->getHeight() - listTop - 2) / rowHeight;
|
||||
int _visibleRows = (display->getHeight() - listTop - 2) / rowHeight;
|
||||
int numEmotes = graphics::numEmotes;
|
||||
|
||||
// Clamp highlight index
|
||||
@ -1457,11 +1457,11 @@ void CannedMessageModule::drawEmotePickerScreen(OLEDDisplay *display, OLEDDispla
|
||||
emotePickerIndex = numEmotes - 1;
|
||||
|
||||
// Determine which emote is at the top
|
||||
int topIndex = emotePickerIndex - visibleRows / 2;
|
||||
int topIndex = emotePickerIndex - _visibleRows / 2;
|
||||
if (topIndex < 0)
|
||||
topIndex = 0;
|
||||
if (topIndex > numEmotes - visibleRows)
|
||||
topIndex = std::max(0, numEmotes - visibleRows);
|
||||
if (topIndex > numEmotes - _visibleRows)
|
||||
topIndex = std::max(0, numEmotes - _visibleRows);
|
||||
|
||||
// Draw header/title
|
||||
display->setFont(FONT_SMALL);
|
||||
@ -1709,7 +1709,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
} else {
|
||||
// Text: split by words and wrap inside word if needed
|
||||
String text = token.second;
|
||||
uint16_t pos = 0;
|
||||
pos = 0;
|
||||
while (pos < text.length()) {
|
||||
// Find next space (or end)
|
||||
int spacePos = text.indexOf(' ', pos);
|
||||
@ -1753,7 +1753,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
int yLine = inputY;
|
||||
for (auto &line : lines) {
|
||||
int nextX = x;
|
||||
for (auto &token : line) {
|
||||
for (const auto &token : line) {
|
||||
if (token.first) {
|
||||
const graphics::Emote *emote = nullptr;
|
||||
for (int j = 0; j < graphics::numEmotes; j++) {
|
||||
@ -1789,19 +1789,20 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
|
||||
int topMsg;
|
||||
std::vector<int> rowHeights;
|
||||
int visibleRows;
|
||||
int _visibleRows;
|
||||
|
||||
// Draw header (To: ...)
|
||||
drawHeader(display, x, y, buffer);
|
||||
|
||||
// Shift message list upward by 3 pixels to reduce spacing between header and first message
|
||||
const int listYOffset = y + FONT_HEIGHT_SMALL - 3;
|
||||
visibleRows = (display->getHeight() - listYOffset) / baseRowSpacing;
|
||||
_visibleRows = (display->getHeight() - listYOffset) / baseRowSpacing;
|
||||
|
||||
// Figure out which messages are visible and their needed heights
|
||||
topMsg =
|
||||
(messagesCount > visibleRows && currentMessageIndex >= visibleRows - 1) ? currentMessageIndex - visibleRows + 2 : 0;
|
||||
int countRows = std::min(messagesCount, visibleRows);
|
||||
topMsg = (messagesCount > _visibleRows && currentMessageIndex >= _visibleRows - 1)
|
||||
? currentMessageIndex - _visibleRows + 2
|
||||
: 0;
|
||||
int countRows = std::min(messagesCount, _visibleRows);
|
||||
|
||||
// --- Build per-row max height based on all emotes in line ---
|
||||
for (int i = 0; i < countRows; i++) {
|
||||
@ -1828,7 +1829,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
int lineY = yCursor;
|
||||
const char *msg = getMessageByIndex(msgIdx);
|
||||
int rowHeight = rowHeights[vis];
|
||||
bool highlight = (msgIdx == currentMessageIndex);
|
||||
bool _highlight = (msgIdx == currentMessageIndex);
|
||||
|
||||
// --- Multi-emote tokenization ---
|
||||
std::vector<std::pair<bool, String>> tokens; // (isEmote, token)
|
||||
@ -1881,20 +1882,20 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
int textYOffset = (rowHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
|
||||
#ifdef USE_EINK
|
||||
int nextX = x + (highlight ? 12 : 0);
|
||||
if (highlight)
|
||||
int nextX = x + (_highlight ? 12 : 0);
|
||||
if (_highlight)
|
||||
display->drawString(x + 0, lineY + textYOffset, ">");
|
||||
#else
|
||||
int scrollPadding = 8;
|
||||
if (highlight) {
|
||||
if (_highlight) {
|
||||
display->fillRect(x + 0, lineY, display->getWidth() - scrollPadding, rowHeight);
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
int nextX = x + (highlight ? 2 : 0);
|
||||
int nextX = x + (_highlight ? 2 : 0);
|
||||
#endif
|
||||
|
||||
// Draw all tokens left to right
|
||||
for (auto &token : tokens) {
|
||||
for (const auto &token : tokens) {
|
||||
if (token.first) {
|
||||
// Emote
|
||||
const graphics::Emote *emote = nullptr;
|
||||
@ -1916,7 +1917,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
}
|
||||
}
|
||||
#ifndef USE_EINK
|
||||
if (highlight)
|
||||
if (_highlight)
|
||||
display->setColor(WHITE);
|
||||
#endif
|
||||
|
||||
@ -1924,11 +1925,11 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
}
|
||||
|
||||
// Scrollbar
|
||||
if (messagesCount > visibleRows) {
|
||||
if (messagesCount > _visibleRows) {
|
||||
int scrollHeight = display->getHeight() - listYOffset;
|
||||
int scrollTrackX = display->getWidth() - 6;
|
||||
display->drawRect(scrollTrackX, listYOffset, 4, scrollHeight);
|
||||
int barHeight = (scrollHeight * visibleRows) / messagesCount;
|
||||
int barHeight = (scrollHeight * _visibleRows) / messagesCount;
|
||||
int scrollPos = listYOffset + (scrollHeight * topMsg) / messagesCount;
|
||||
display->fillRect(scrollTrackX, scrollPos, 4, barHeight);
|
||||
}
|
||||
|
@ -107,11 +107,7 @@ int SystemCommandsModule::handleInputEvent(const InputEvent *event)
|
||||
return true;
|
||||
// Power control
|
||||
case INPUT_BROKER_SHUTDOWN:
|
||||
LOG_ERROR("Shutting Down");
|
||||
IF_SCREEN(screen->showSimpleBanner("Shutting Down..."));
|
||||
nodeDB->saveToDisk();
|
||||
shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000;
|
||||
// runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||
shutdownAtMsec = millis();
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
73
src/platform/nrf52/AsyncUDP.cpp
Normal file
73
src/platform/nrf52/AsyncUDP.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "AsyncUDP.h"
|
||||
|
||||
#if HAS_ETHERNET
|
||||
|
||||
AsyncUDP::AsyncUDP() : OSThread("AsyncUDP"), localPort(0) {}
|
||||
|
||||
bool AsyncUDP::listenMulticast(IPAddress multicastIP, uint16_t port, uint8_t ttl)
|
||||
{
|
||||
if (!isMulticast(multicastIP))
|
||||
return false;
|
||||
localPort = port;
|
||||
udp.beginMulticast(multicastIP, port);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t AsyncUDP::write(uint8_t b)
|
||||
{
|
||||
return udp.write(&b, 1);
|
||||
}
|
||||
|
||||
size_t AsyncUDP::write(const uint8_t *data, size_t len)
|
||||
{
|
||||
return udp.write(data, len);
|
||||
}
|
||||
|
||||
void AsyncUDP::onPacket(const std::function<void(AsyncUDPPacket)> &callback)
|
||||
{
|
||||
_onPacket = callback;
|
||||
}
|
||||
|
||||
bool AsyncUDP::writeTo(const uint8_t *data, size_t len, IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (!udp.beginPacket(ip, port))
|
||||
return false;
|
||||
udp.write(data, len);
|
||||
return udp.endPacket();
|
||||
}
|
||||
|
||||
// AsyncUDPPacket
|
||||
AsyncUDPPacket::AsyncUDPPacket(EthernetUDP &source) : _udp(source), _remoteIP(source.remoteIP()), _remotePort(source.remotePort())
|
||||
{
|
||||
if (_udp.available() > 0) {
|
||||
_readLength = _udp.read(_buffer, sizeof(_buffer));
|
||||
} else {
|
||||
_readLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
IPAddress AsyncUDPPacket::remoteIP()
|
||||
{
|
||||
return _remoteIP;
|
||||
}
|
||||
|
||||
uint16_t AsyncUDPPacket::length()
|
||||
{
|
||||
return _readLength;
|
||||
}
|
||||
|
||||
const uint8_t *AsyncUDPPacket::data()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
int32_t AsyncUDP::runOnce()
|
||||
{
|
||||
if (_onPacket && udp.parsePacket() > 0) {
|
||||
AsyncUDPPacket packet(udp);
|
||||
_onPacket(packet);
|
||||
}
|
||||
return 5; // check every 5ms
|
||||
}
|
||||
|
||||
#endif // HAS_ETHERNET
|
63
src/platform/nrf52/AsyncUDP.h
Normal file
63
src/platform/nrf52/AsyncUDP.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef ASYNC_UDP_H
|
||||
#define ASYNC_UDP_H
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
#if HAS_ETHERNET
|
||||
|
||||
#include "concurrency/OSThread.h"
|
||||
#include <IPAddress.h>
|
||||
#include <Print.h>
|
||||
#include <RAK13800_W5100S.h>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
class AsyncUDPPacket;
|
||||
|
||||
class AsyncUDP : public Print, private concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
AsyncUDP();
|
||||
explicit operator bool() const { return localPort != 0; }
|
||||
|
||||
bool listenMulticast(IPAddress multicastIP, uint16_t port, uint8_t ttl = 64);
|
||||
bool writeTo(const uint8_t *data, size_t len, IPAddress ip, uint16_t port);
|
||||
|
||||
size_t write(uint8_t b) override;
|
||||
size_t write(const uint8_t *data, size_t len) override;
|
||||
void onPacket(const std::function<void(AsyncUDPPacket)> &callback);
|
||||
|
||||
private:
|
||||
EthernetUDP udp;
|
||||
uint16_t localPort;
|
||||
std::function<void(AsyncUDPPacket)> _onPacket;
|
||||
virtual int32_t runOnce() override;
|
||||
};
|
||||
|
||||
class AsyncUDPPacket
|
||||
{
|
||||
public:
|
||||
AsyncUDPPacket(EthernetUDP &source);
|
||||
|
||||
IPAddress remoteIP();
|
||||
uint16_t length();
|
||||
const uint8_t *data();
|
||||
|
||||
private:
|
||||
EthernetUDP &_udp;
|
||||
IPAddress _remoteIP;
|
||||
uint16_t _remotePort;
|
||||
size_t _readLength = 0;
|
||||
|
||||
static constexpr size_t BUF_SIZE = 512;
|
||||
uint8_t _buffer[BUF_SIZE];
|
||||
};
|
||||
|
||||
inline bool isMulticast(const IPAddress &ip)
|
||||
{
|
||||
return (ip[0] & 0xF0) == 0xE0;
|
||||
}
|
||||
|
||||
#endif // HAS_ETHERNET
|
||||
|
||||
#endif // ASYNC_UDP_H
|
@ -40,21 +40,8 @@ void powerCommandsCheck()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||
if (shutdownAtMsec && screen) {
|
||||
screen->showSimpleBanner("Shutting Down...", 0); // stays on screen
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shutdownAtMsec && millis() > shutdownAtMsec) {
|
||||
LOG_INFO("Shut down from admin command");
|
||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32) || defined(ARCH_RP2040)
|
||||
playShutdownMelody();
|
||||
shutdownAtMsec = 0;
|
||||
power->shutdown();
|
||||
#elif defined(ARCH_PORTDUINO)
|
||||
exit(EXIT_SUCCESS);
|
||||
#else
|
||||
LOG_WARN("FIXME implement shutdown for this platform");
|
||||
#endif
|
||||
}
|
||||
}
|
@ -1,47 +1,3 @@
|
||||
; Meshtastic DIY v1 by Nano VHF Schematic based on ESP32-WROOM-32 (38 pins) devkit & EBYTE E22 SX1262/SX1268 module
|
||||
[env:meshtastic-diy-v1]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_check = true
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DIY_V1
|
||||
-D EBYTE_E22
|
||||
-I variants/diy/v1
|
||||
|
||||
; Meshtastic DIY v1.1 new schematic based on ESP32-WROOM-32 & SX1262/SX1268 modules
|
||||
[env:meshtastic-diy-v1_1]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DIY_V1
|
||||
-D EBYTE_E22
|
||||
-I variants/diy/v1_1
|
||||
|
||||
; Port to Disaster Radio's ESP32-v3 Dev Board
|
||||
[env:meshtastic-dr-dev]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 532480
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DR_DEV
|
||||
-D EBYTE_E22
|
||||
-I variants/diy/dr-dev
|
||||
|
||||
; Hydra - Meshtastic DIY v1 hardware with some specific changes
|
||||
[env:hydra]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DIY_V1
|
||||
-I variants/diy/hydra
|
||||
|
||||
|
||||
; Promicro + E22(0)-xxxMM / RA-01SH modules board variant - DIY - without TCXO
|
||||
[env:nrf52_promicro_diy_xtal]
|
||||
extends = nrf52840_base
|
||||
@ -122,35 +78,3 @@ build_src_filter = ${nrf52_base.build_src_filter} +<../variants/diy/seeed-xiao-n
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
debug_tool = jlink
|
||||
|
||||
; NanoVHF T-Energy-S3 + E22(0)-xxxM - DIY
|
||||
[env:t-energy-s3_e22]
|
||||
extends = esp32s3_base
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = default_16MB.csv
|
||||
board_level = extra
|
||||
board_upload.flash_size = 16MB ;Specify the FLASH capacity as 16MB
|
||||
board_build.arduino.memory_type = qio_opi ;Enable internal PSRAM
|
||||
build_unflags =
|
||||
${esp32s3_base.build_unflags}
|
||||
-D ARDUINO_USB_MODE=1
|
||||
build_flags =
|
||||
${esp32s3_base.build_flags}
|
||||
-D EBYTE_ESP32_S3
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
-I variants/diy/t-energy-s3_e22
|
||||
|
||||
; ESP32 C3 Super Mini Development Board
|
||||
; https://www.espboards.dev/esp32/esp32-c3-super-mini/
|
||||
[env:esp32c3_super_mini]
|
||||
extends = esp32c3_base
|
||||
board = esp32-c3-devkitm-1
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D PRIVATE_HW
|
||||
-I variants/diy/esp32c3_super_mini
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1
|
||||
board_level = extra
|
||||
|
@ -8,11 +8,11 @@ build_flags =
|
||||
-D VTABLES_IN_FLASH=1
|
||||
-D CONFIG_DISABLE_HAL_LOCKS=1
|
||||
-O2
|
||||
-I variants/betafpv_2400_tx_micro
|
||||
-I variants/esp32/betafpv_2400_tx_micro
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
;upload_port = /dev/ttyUSB0
|
||||
upload_speed = 460800
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
adafruit/Adafruit NeoPixel @ ^1.12.0
|
||||
adafruit/Adafruit NeoPixel @ ^1.12.0
|
@ -8,10 +8,10 @@ build_flags =
|
||||
-D VTABLES_IN_FLASH=1
|
||||
-D CONFIG_DISABLE_HAL_LOCKS=1
|
||||
-O2
|
||||
-I variants/betafpv_900_tx_nano
|
||||
-I variants/esp32/betafpv_900_tx_nano
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
;upload_port = /dev/ttyUSB0
|
||||
upload_speed = 460800
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
${esp32_base.lib_deps}
|
@ -5,7 +5,7 @@ board = esp32doit-devkit-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D CHATTER_2
|
||||
-I variants/chatter2
|
||||
-I variants/esp32/chatter2
|
||||
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
11
variants/esp32/diy/dr-dev/platformio.ini
Normal file
11
variants/esp32/diy/dr-dev/platformio.ini
Normal file
@ -0,0 +1,11 @@
|
||||
; Port to Disaster Radio's ESP32-v3 Dev Board
|
||||
[env:meshtastic-dr-dev]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 532480
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DR_DEV
|
||||
-D EBYTE_E22
|
||||
-I variants/esp32/diy/dr-dev
|
8
variants/esp32/diy/hydra/platformio.ini
Normal file
8
variants/esp32/diy/hydra/platformio.ini
Normal file
@ -0,0 +1,8 @@
|
||||
; Hydra - Meshtastic DIY v1 hardware with some specific changes
|
||||
[env:hydra]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DIY_V1
|
||||
-I variants/esp32/diy/hydra
|
10
variants/esp32/diy/v1/platformio.ini
Normal file
10
variants/esp32/diy/v1/platformio.ini
Normal file
@ -0,0 +1,10 @@
|
||||
; Meshtastic DIY v1 by Nano VHF Schematic based on ESP32-WROOM-32 (38 pins) devkit & EBYTE E22 SX1262/SX1268 module
|
||||
[env:meshtastic-diy-v1]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_check = true
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DIY_V1
|
||||
-D EBYTE_E22
|
||||
-I variants/esp32/diy/v1
|
10
variants/esp32/diy/v1_1/platformio.ini
Normal file
10
variants/esp32/diy/v1_1/platformio.ini
Normal file
@ -0,0 +1,10 @@
|
||||
; Meshtastic DIY v1.1 new schematic based on ESP32-WROOM-32 & SX1262/SX1268 modules
|
||||
[env:meshtastic-diy-v1_1]
|
||||
extends = esp32_base
|
||||
board = esp32doit-devkit-v1
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D DIY_V1
|
||||
-D EBYTE_E22
|
||||
-I variants/esp32/diy/v1_1
|
@ -5,7 +5,7 @@ board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D PRIVATE_HW
|
||||
-I variants/hackerboxes_esp32_io
|
||||
-I variants/esp32/hackerboxes_esp32_io
|
||||
monitor_speed = 115200
|
||||
upload_protocol = esptool
|
||||
;upload_port = /dev/ttyUSB0
|
@ -4,4 +4,6 @@ extends = esp32_base
|
||||
board_level = extra
|
||||
board = heltec_wifi_lora_32
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D HELTEC_V1 -I variants/heltec_v1
|
||||
${esp32_base.build_flags}
|
||||
-D HELTEC_V1
|
||||
-I variants/esp32/heltec_v1
|
@ -4,5 +4,7 @@ board_level = extra
|
||||
extends = esp32_base
|
||||
board = heltec_wifi_lora_32_V2
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D HELTEC_V2_1 -I variants/heltec_v2.1
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
${esp32_base.build_flags}
|
||||
-D HELTEC_V2_1
|
||||
-I variants/esp32/heltec_v2.1
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
@ -4,4 +4,6 @@ board_level = extra
|
||||
extends = esp32_base
|
||||
board = heltec_wifi_lora_32_V2
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D HELTEC_V2_0 -I variants/heltec_v2
|
||||
${esp32_base.build_flags}
|
||||
-D HELTEC_V2_0
|
||||
-I variants/esp32/heltec_v2
|
@ -4,7 +4,7 @@ extends = esp32_base
|
||||
board = heltec_wifi_lora_32
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-I variants/heltec_wireless_bridge
|
||||
-I variants/esp32/heltec_wireless_bridge
|
||||
-D HELTEC_WIRELESS_BRIDGE
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D RADIOLIB_EXCLUDE_LR11X0=1
|
@ -3,5 +3,7 @@ extends = esp32_base
|
||||
board = heltec_wireless_stick_lite
|
||||
board_level = extra
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D PRIVATE_HW -I variants/heltec_wsl_v2.1
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
${esp32_base.build_flags}
|
||||
-D PRIVATE_HW
|
||||
-I variants/esp32/heltec_wsl_v2.1
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
@ -5,7 +5,8 @@ monitor_filters = esp32_exception_decoder
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -I variants/m5stack_core
|
||||
${esp32_base.build_flags}
|
||||
-I variants/esp32/m5stack_core
|
||||
-DILI9341_DRIVER
|
||||
-DM5STACK
|
||||
-DUSER_SETUP_LOADED
|
@ -5,7 +5,8 @@ board_check = true
|
||||
build_src_filter =
|
||||
${esp32_base.build_src_filter}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -I variants/m5stack_coreink
|
||||
${esp32_base.build_flags}
|
||||
-I variants/esp32/m5stack_coreink
|
||||
;-D RADIOLIB_VERBOSE
|
||||
-Ofast
|
||||
-D__MCUXPRESSO
|
@ -5,4 +5,6 @@ board = ttgo-t-beam
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D NANO_G1_EXPLORER -I variants/nano-g1-explorer
|
||||
${esp32_base.build_flags}
|
||||
-D NANO_G1_EXPLORER
|
||||
-I variants/esp32/nano-g1-explorer
|
@ -5,4 +5,6 @@ board = ttgo-t-beam
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D NANO_G1 -I variants/nano-g1
|
||||
${esp32_base.build_flags}
|
||||
-D NANO_G1
|
||||
-I variants/esp32/nano-g1
|
@ -8,7 +8,7 @@ build_flags =
|
||||
-DCONFIG_DISABLE_HAL_LOCKS=1
|
||||
-DHAS_STK8XXX=1
|
||||
-O2
|
||||
-Ivariants/radiomaster_900_bandit
|
||||
-I variants/esp32/radiomaster_900_bandit
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
lib_deps =
|
@ -12,8 +12,8 @@ build_flags =
|
||||
-DVTABLES_IN_FLASH=1
|
||||
-DCONFIG_DISABLE_HAL_LOCKS=1
|
||||
-O2
|
||||
-Ivariants/radiomaster_900_bandit_nano
|
||||
-I variants/esp32/radiomaster_900_bandit_nano
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
${esp32_base.lib_deps}
|
@ -7,8 +7,8 @@ build_flags =
|
||||
-DVTABLES_IN_FLASH=1
|
||||
-DCONFIG_DISABLE_HAL_LOCKS=1
|
||||
-O2
|
||||
-Ivariants/radiomaster_900_bandit_nano
|
||||
-I variants/esp32/radiomaster_900_bandit_nano
|
||||
board_build.f_cpu = 240000000L
|
||||
upload_protocol = esptool
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
${esp32_base.lib_deps}
|
@ -3,5 +3,7 @@ extends = esp32_base
|
||||
board = wiscore_rak11200
|
||||
board_check = true
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D RAK_11200 -I variants/rak11200
|
||||
upload_speed = 115200
|
||||
${esp32_base.build_flags}
|
||||
-D RAK_11200
|
||||
-I variants/esp32/rak11200
|
||||
upload_speed = 115200
|
@ -5,4 +5,6 @@ board = ttgo-t-beam
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D STATION_G1 -I variants/station-g1
|
||||
${esp32_base.build_flags}
|
||||
-D STATION_G1
|
||||
-I variants/esp32/station-g1
|
@ -6,8 +6,10 @@ board_check = true
|
||||
lib_deps =
|
||||
${esp32_base.lib_deps}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TBEAM_V10 -I variants/tbeam
|
||||
${esp32_base.build_flags}
|
||||
-D TBEAM_V10
|
||||
-I variants/esp32/tbeam
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable double press function on the user button to turn off gps entirely.
|
||||
-DBOARD_HAS_PSRAM
|
||||
-mfix-esp32-psram-cache-issue
|
||||
upload_speed = 921600
|
||||
upload_speed = 921600
|
@ -4,4 +4,6 @@ board_level = extra
|
||||
extends = esp32_base
|
||||
board = ttgo-t-beam
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TBEAM_V07 -I variants/tbeam_v07
|
||||
${esp32_base.build_flags}
|
||||
-D TBEAM_V07
|
||||
-I variants/esp32/tbeam_v07
|
@ -3,5 +3,7 @@ board_level = extra
|
||||
extends = esp32_base
|
||||
board = ttgo-lora32-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TLORA_V1 -I variants/tlora_v1
|
||||
upload_speed = 115200
|
||||
${esp32_base.build_flags}
|
||||
-D TLORA_V1
|
||||
-I variants/esp32/tlora_v1
|
||||
upload_speed = 115200
|
@ -3,5 +3,5 @@ board_level = extra
|
||||
extends = esp32_base
|
||||
board = ttgo-lora32-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TLORA_V1_3 -I variants/tlora_v1_3
|
||||
upload_speed = 115200
|
||||
${esp32_base.build_flags} -D TLORA_V1_3 -I variants/esp32/tlora_v1_3
|
||||
upload_speed = 115200
|
@ -3,4 +3,6 @@ board_level = extra
|
||||
extends = esp32_base
|
||||
board = ttgo-lora32-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TLORA_V2 -I variants/tlora_v2
|
||||
${esp32_base.build_flags}
|
||||
-D TLORA_V2
|
||||
-I variants/esp32/tlora_v2
|
@ -3,6 +3,6 @@ extends = esp32_base
|
||||
board = ttgo-lora32-v21
|
||||
board_check = true
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/tlora_v2_1_16
|
||||
${esp32_base.build_flags} -D TLORA_V2_1_16 -I variants/esp32/tlora_v2_1_16
|
||||
-DGPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
upload_speed = 115200
|
||||
upload_speed = 115200
|
@ -5,7 +5,7 @@ board = ttgo-lora32-v21
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D TLORA_V2_1_16
|
||||
-I variants/tlora_v2_1_16
|
||||
-I variants/esp32/tlora_v2_1_16
|
||||
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
-D LORA_TCXO_GPIO=33
|
||||
upload_speed = 115200
|
@ -4,4 +4,6 @@ board_level = extra
|
||||
board = ttgo-lora32-v21
|
||||
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TLORA_V2_1_18 -I variants/tlora_v2_1_18
|
||||
${esp32_base.build_flags}
|
||||
-D TLORA_V2_1_18
|
||||
-I variants/esp32/tlora_v2_1_18
|
@ -4,7 +4,7 @@ board = ttgo-lora32-v21
|
||||
build_flags =
|
||||
${esp32_base.build_flags}
|
||||
-D TLORA_V2_1_16
|
||||
-I variants/tlora_v2_1_16
|
||||
-I variants/esp32/tlora_v2_1_16
|
||||
-D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely.
|
||||
-D LORA_TCXO_GPIO=12
|
||||
-D BUTTON_PIN=0
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user