mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-20 16:56:17 +00:00
Merge branch 'meshtastic:master' into master
This commit is contained in:
commit
f41c5f54ae
1
.github/workflows/main_matrix.yml
vendored
1
.github/workflows/main_matrix.yml
vendored
@ -68,7 +68,6 @@ jobs:
|
||||
- board: tlora-v2-1-1_8
|
||||
- board: tbeam
|
||||
- board: heltec-ht62-esp32c3-sx1262
|
||||
- board: heltec-v1
|
||||
- board: heltec-v2_0
|
||||
- board: heltec-v2_1
|
||||
- board: tbeam0_7
|
||||
|
@ -13,7 +13,7 @@ if [[ $# -gt 0 ]]; then
|
||||
# can override which environment by passing arg
|
||||
BOARDS="$@"
|
||||
else
|
||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo canaryone pca10059_diy_eink"
|
||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo canaryone pca10059_diy_eink"
|
||||
fi
|
||||
|
||||
echo "BOARDS:${BOARDS}"
|
||||
|
@ -8,7 +8,7 @@ if [[ $# -gt 0 ]]; then
|
||||
# can override which environment by passing arg
|
||||
BOARDS="$@"
|
||||
else
|
||||
BOARDS="rak4631 rak4631_eink t-echo canaryone pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core"
|
||||
BOARDS="rak4631 rak4631_eink t-echo canaryone pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core"
|
||||
fi
|
||||
|
||||
echo "BOARDS:${BOARDS}"
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5f28be497a5518334c86378335e8ffcd177ed661
|
||||
Subproject commit 24edea64429de4474c00d09990ef4c496614dc5d
|
@ -444,6 +444,11 @@ bool GPS::setup()
|
||||
if (getACK(0x06, 0x86, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving for GPS.\n");
|
||||
}
|
||||
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving details for GPS.\n");
|
||||
}
|
||||
// For M8 we want to enable NMEA vserion 4.10 so we can see the additional sats.
|
||||
if (strncmp(info.hwVersion, "00080000", 8) == 0) {
|
||||
msglen = makeUBXPacket(0x06, 0x17, sizeof(_message_NMEA), _message_NMEA);
|
||||
@ -477,6 +482,12 @@ bool GPS::setup()
|
||||
if (getACK(0x06, 0x11, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving mode for GPS.\n");
|
||||
}
|
||||
|
||||
msglen = makeUBXPacket(0x06, 0x3B, sizeof(_message_CFG_PM2), _message_CFG_PM2);
|
||||
_serial_gps->write(UBXscratch, msglen);
|
||||
if (getACK(0x06, 0x3B, 500) != GNSS_RESPONSE_OK) {
|
||||
LOG_WARN("Unable to enable powersaving details for GPS.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ SPIClass *hspi = NULL;
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_154_D67
|
||||
#elif defined(RAK4630)
|
||||
|
||||
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update
|
||||
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give fast refresh
|
||||
// support
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN
|
||||
|
||||
@ -65,7 +65,7 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY
|
||||
|
||||
// GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122
|
||||
setGeometry(GEOMETRY_RAWMODE, 250, 122);
|
||||
|
||||
this->displayBufferSize = 250 * (128 / 8);
|
||||
// GxEPD2_420_M01
|
||||
// setGeometry(GEOMETRY_RAWMODE, 300, 400);
|
||||
|
||||
@ -131,8 +131,8 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
// No need to grab this lock because we are on our own SPI bus
|
||||
// concurrency::LockGuard g(spiLock);
|
||||
|
||||
#if defined(USE_EINK_DYNAMIC_PARTIAL)
|
||||
// Decide if update is partial or full
|
||||
#if defined(USE_EINK_DYNAMIC_REFRESH)
|
||||
// Decide between full refresh, fast refresh, or skipping the update
|
||||
bool continueUpdate = determineRefreshMode();
|
||||
if (!continueUpdate)
|
||||
return false;
|
||||
@ -165,12 +165,12 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
adafruitDisplay->nextPage();
|
||||
#elif defined(RAK4630) || defined(MAKERPYTHON)
|
||||
|
||||
// RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
|
||||
// RAK14000 2.13 inch b/w 250x122 actually now does support fast refresh
|
||||
|
||||
// Full update mode (slow)
|
||||
// adafruitDisplay->display(false); // FIXME, use partial update mode
|
||||
// adafruitDisplay->display(false); // FIXME, use fast refresh mode
|
||||
|
||||
// Only enable for e-Paper with support for partial updates and comment out above adafruitDisplay->display(false);
|
||||
// Only enable for e-Paper with support for fast updates and comment out above adafruitDisplay->display(false);
|
||||
// 1.54 inch 200x200 - GxEPD2_154_M09
|
||||
// 2.13 inch 250x122 - GxEPD2_213_BN
|
||||
// 2.9 inch 296x128 - GxEPD2_290_T5D
|
||||
@ -203,7 +203,7 @@ void EInkDisplay::display(void)
|
||||
// at least one forceDisplay() keyframe. This prevents flashing when we should the critical
|
||||
// bootscreen (that we want to look nice)
|
||||
|
||||
#ifdef USE_EINK_DYNAMIC_PARTIAL
|
||||
#ifdef USE_EINK_DYNAMIC_REFRESH
|
||||
lowPriority();
|
||||
forceDisplay();
|
||||
highPriority();
|
||||
@ -257,9 +257,9 @@ bool EInkDisplay::connect()
|
||||
auto lowLevel = new TECHO_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY);
|
||||
adafruitDisplay = new GxEPD2_BW<TECHO_DISPLAY_MODEL, TECHO_DISPLAY_MODEL::HEIGHT>(*lowLevel);
|
||||
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
// RAK14000 2.13 inch b/w 250x122 does actually now support partial updates
|
||||
// RAK14000 2.13 inch b/w 250x122 does actually now support fast refresh
|
||||
adafruitDisplay->setRotation(3);
|
||||
// Partial update support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2
|
||||
// Fast refresh support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2
|
||||
// adafruitDisplay->setRotation(1);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
} else {
|
||||
@ -347,10 +347,10 @@ bool EInkDisplay::connect()
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use a mix of full and partial refreshes, to preserve display health
|
||||
#if defined(USE_EINK_DYNAMIC_PARTIAL)
|
||||
// Use a mix of full refresh, fast refresh, and update skipping, to balance urgency and display health
|
||||
#if defined(USE_EINK_DYNAMIC_REFRESH)
|
||||
|
||||
// Suggest that subsequent updates should use partial-refresh
|
||||
// Suggest that subsequent updates should use fast-refresh
|
||||
void EInkDisplay::highPriority()
|
||||
{
|
||||
isHighPriority = true;
|
||||
@ -362,8 +362,14 @@ void EInkDisplay::lowPriority()
|
||||
isHighPriority = false;
|
||||
}
|
||||
|
||||
// configure display for partial-refresh
|
||||
void EInkDisplay::configForPartialRefresh()
|
||||
// Full-refresh is explicitly requested for next one update - no skipping please
|
||||
void EInkDisplay::demandFullRefresh()
|
||||
{
|
||||
demandingFull = true;
|
||||
}
|
||||
|
||||
// configure display for fast-refresh
|
||||
void EInkDisplay::configForFastRefresh()
|
||||
{
|
||||
// Display-specific code can go here
|
||||
#if defined(PRIVATE_HW)
|
||||
@ -384,6 +390,49 @@ void EInkDisplay::configForFullRefresh()
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||
// Count black pixels in an image. Used for "erasure tracking"
|
||||
int32_t EInkDisplay::countBlackPixels()
|
||||
{
|
||||
int32_t blackCount = 0; // Signed, to avoid underflow when comparing
|
||||
for (uint16_t b = 0; b < (displayWidth / 8) * displayHeight; b++) {
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
// Check if each bit is black or white
|
||||
blackCount += (buffer[b] >> i) & 1;
|
||||
}
|
||||
}
|
||||
return blackCount;
|
||||
}
|
||||
|
||||
// Evaluate the (rough) amount of black->white pixel change since last full refresh
|
||||
bool EInkDisplay::tooManyErasures()
|
||||
{
|
||||
// Ideally, we would compare the new and old buffers, to count *actual* white-to-black pixel changes
|
||||
// but that would require substantially more "code tampering"
|
||||
|
||||
// Get the black pixel stats for this image
|
||||
int32_t blackCount = countBlackPixels();
|
||||
int32_t blackDifference = blackCount - prevBlackCount;
|
||||
|
||||
// Update the running total of "erasures" - black pixels which have become white, since last full-refresh
|
||||
if (blackDifference < 0)
|
||||
erasedSinceFull -= blackDifference;
|
||||
|
||||
// Store black pixel count for next time
|
||||
prevBlackCount = blackCount;
|
||||
|
||||
// Log the running total - help devs setup new boards
|
||||
LOG_DEBUG("Dynamic Refresh: erasedSinceFull=%hu, EINK_FASTREFRESH_ERASURE_LIMIT=%hu\n", erasedSinceFull,
|
||||
EINK_FASTREFRESH_ERASURE_LIMIT);
|
||||
|
||||
// Check if too many pixels have been erased
|
||||
if (erasedSinceFull > EINK_FASTREFRESH_ERASURE_LIMIT)
|
||||
return true; // Too many
|
||||
else
|
||||
return false; // Still okay
|
||||
}
|
||||
#endif // ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||
|
||||
bool EInkDisplay::newImageMatchesOld()
|
||||
{
|
||||
uint32_t newImageHash = 0;
|
||||
@ -403,7 +452,7 @@ bool EInkDisplay::newImageMatchesOld()
|
||||
return hashMatches;
|
||||
}
|
||||
|
||||
// Change between partial and full refresh config, or skip update, balancing urgency and display health.
|
||||
// Choose between, full-refresh, fast refresh, and update skipping, to balance urgency and display health.
|
||||
bool EInkDisplay::determineRefreshMode()
|
||||
{
|
||||
uint32_t now = millis();
|
||||
@ -416,25 +465,36 @@ bool EInkDisplay::determineRefreshMode()
|
||||
missedHighPriorityUpdate = false;
|
||||
}
|
||||
|
||||
// Abort: if too soon for a new frame
|
||||
if (isHighPriority && partialRefreshCount > 0 && sinceLast < highPriorityLimitMsec) {
|
||||
LOG_DEBUG("Update skipped: exceeded EINK_HIGHPRIORITY_LIMIT_SECONDS\n");
|
||||
// Abort: if too soon for a new frame (unless demanding full)
|
||||
if (!demandingFull && isHighPriority && fastRefreshCount > 0 && sinceLast < highPriorityLimitMsec) {
|
||||
LOG_DEBUG("Dynamic Refresh: update skipped. Exceeded EINK_HIGHPRIORITY_LIMIT_SECONDS\n");
|
||||
missedHighPriorityUpdate = true;
|
||||
return false;
|
||||
}
|
||||
if (!isHighPriority && sinceLast < lowPriorityLimitMsec) {
|
||||
if (!demandingFull && !isHighPriority && !demandingFull && sinceLast < lowPriorityLimitMsec) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if old image (partial) should be redrawn (as full), for image quality
|
||||
if (partialRefreshCount > 0 && !isHighPriority)
|
||||
// If demanded full refresh: give it to them
|
||||
if (demandingFull)
|
||||
needsFull = true;
|
||||
|
||||
// If too many partials, require a full-refresh (display health)
|
||||
if (partialRefreshCount >= partialRefreshLimit)
|
||||
// Check if old image (fast-refresh) should be redrawn (as full), for image quality
|
||||
if (fastRefreshCount > 0 && !isHighPriority)
|
||||
needsFull = true;
|
||||
|
||||
// If too many fast updates, require a full-refresh (display health)
|
||||
if (fastRefreshCount >= fastRefreshLimit)
|
||||
needsFull = true;
|
||||
|
||||
#ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||
// Some displays struggle with erasing black pixels to white, during fast-refresh
|
||||
if (tooManyErasures())
|
||||
needsFull = true;
|
||||
#endif
|
||||
|
||||
// If image matches
|
||||
// (Block must run, even if full already selected, to store hash for next time)
|
||||
if (newImageMatchesOld()) {
|
||||
// If low priority: limit rate
|
||||
// otherwise, every loop() will run the hash method
|
||||
@ -450,27 +510,29 @@ bool EInkDisplay::determineRefreshMode()
|
||||
|
||||
// If options require a full refresh
|
||||
if (!isHighPriority || needsFull) {
|
||||
if (partialRefreshCount > 0)
|
||||
if (fastRefreshCount > 0)
|
||||
configForFullRefresh();
|
||||
|
||||
LOG_DEBUG("Conditions met for full-refresh\n");
|
||||
partialRefreshCount = 0;
|
||||
LOG_DEBUG("Dynamic Refresh: conditions met for full-refresh\n");
|
||||
fastRefreshCount = 0;
|
||||
needsFull = false;
|
||||
demandingFull = false;
|
||||
erasedSinceFull = 0; // Reset the count for EINK_FASTREFRESH_ERASURE_LIMIT - tracks ghosting buildup
|
||||
}
|
||||
|
||||
// If options allow a partial refresh
|
||||
// If options allow a fast-refresh
|
||||
else {
|
||||
if (partialRefreshCount == 0)
|
||||
configForPartialRefresh();
|
||||
if (fastRefreshCount == 0)
|
||||
configForFastRefresh();
|
||||
|
||||
LOG_DEBUG("Conditions met for partial-refresh\n");
|
||||
partialRefreshCount++;
|
||||
LOG_DEBUG("Dynamic Refresh: conditions met for fast-refresh\n");
|
||||
fastRefreshCount++;
|
||||
}
|
||||
|
||||
lastUpdateMsec = now; // Mark time for rate limiting
|
||||
return true; // Instruct calling method to continue with update
|
||||
}
|
||||
|
||||
#endif // End USE_EINK_DYNAMIC_PARTIAL
|
||||
#endif // End USE_EINK_DYNAMIC_REFRESH
|
||||
|
||||
#endif
|
||||
|
@ -55,67 +55,80 @@ class EInkDisplay : public OLEDDisplay
|
||||
// Connect to the display
|
||||
virtual bool connect() override;
|
||||
|
||||
#if defined(USE_EINK_DYNAMIC_PARTIAL)
|
||||
// Full, partial, or skip: balance urgency with display health
|
||||
#if defined(USE_EINK_DYNAMIC_REFRESH)
|
||||
// Full, fast, or skip: balance urgency with display health
|
||||
|
||||
// Use partial refresh if EITHER:
|
||||
// Use fast refresh if EITHER:
|
||||
// * highPriority() was set
|
||||
// * a highPriority() update was previously skipped, for rate-limiting - (EINK_HIGHPRIORITY_LIMIT_SECONDS)
|
||||
|
||||
// Use full refresh if EITHER:
|
||||
// * lowPriority() was set
|
||||
// * too many partial updates in a row: protect display - (EINK_PARTIAL_REPEAT_LIMIT)
|
||||
// * no recent updates, and last update was partial: redraw for image quality (EINK_LOWPRIORITY_LIMIT_SECONDS)
|
||||
// * demandFullRefresh() was called - (single shot)
|
||||
// * too many fast updates in a row: protect display - (EINK_FASTREFRESH_REPEAT_LIMIT)
|
||||
// * no recent updates, and last update was fast: redraw for image quality (EINK_LOWPRIORITY_LIMIT_SECONDS)
|
||||
// * (optional) too many "erasures" since full-refresh (black pixels cleared to white)
|
||||
|
||||
// Rate limit if:
|
||||
// * lowPriority() - (EINK_LOWPRIORITY_LIMIT_SECONDS)
|
||||
// * highPriority(), if multiple partials have run back-to-back - (EINK_HIGHPRIORITY_LIMIT_SECONDS)
|
||||
// * highPriority(), if multiple fast updates have run back-to-back - (EINK_HIGHPRIORITY_LIMIT_SECONDS)
|
||||
|
||||
// Skip update entirely if ALL criteria met:
|
||||
// * new image matches old image
|
||||
// * lowPriority()
|
||||
// * no call to demandFullRefresh()
|
||||
// * not redrawing for image quality
|
||||
// * not refreshing for display health
|
||||
|
||||
// ------------------------------------
|
||||
|
||||
// To implement for your E-Ink display:
|
||||
// * edit configForPartialRefresh()
|
||||
// * edit configForFastRefresh()
|
||||
// * edit configForFullRefresh()
|
||||
// * add macros to variant.h, and adjust to taste:
|
||||
|
||||
/*
|
||||
#define USE_EINK_DYNAMIC_PARTIAL
|
||||
#define USE_EINK_DYNAMIC_REFRESH
|
||||
#define EINK_LOWPRIORITY_LIMIT_SECONDS 30
|
||||
#define EINK_HIGHPRIORITY_LIMIT_SECONDS 1
|
||||
#define EINK_PARTIAL_REPEAT_LIMIT 5
|
||||
#define EINK_FASTREFRESH_REPEAT_LIMIT 5
|
||||
#define EINK_FASTREFRESH_ERASURE_LIMIT 300 // optional
|
||||
*/
|
||||
|
||||
public:
|
||||
void highPriority(); // Suggest partial refresh
|
||||
void lowPriority(); // Suggest full refresh
|
||||
void highPriority(); // Suggest fast refresh
|
||||
void lowPriority(); // Suggest full refresh
|
||||
void demandFullRefresh(); // For next update: explicitly request full refresh
|
||||
|
||||
protected:
|
||||
void configForPartialRefresh(); // Display specific code to select partial refresh mode
|
||||
void configForFullRefresh(); // Display specific code to return to full refresh mode
|
||||
bool newImageMatchesOld(); // Is the new update actually different to the last image?
|
||||
bool determineRefreshMode(); // Called immediately before data written to display - choose refresh mode, or abort update
|
||||
void configForFastRefresh(); // Display specific code to select fast refresh mode
|
||||
void configForFullRefresh(); // Display specific code to return to full refresh mode
|
||||
bool newImageMatchesOld(); // Is the new update actually different to the last image?
|
||||
bool determineRefreshMode(); // Called immediately before data written to display - choose refresh mode, or abort update
|
||||
#ifdef EINK_FASTREFRESH_ERASURE_LIMIT
|
||||
int32_t countBlackPixels(); // Calculate the number of black pixels in the new image
|
||||
bool tooManyErasures(); // Has too much "ghosting" (black pixels erased to white) accumulated since last full-refresh?
|
||||
#endif
|
||||
|
||||
bool isHighPriority = true; // Does the method calling update believe that this is urgent?
|
||||
bool needsFull = false; // Is a full refresh forced? (display health)
|
||||
bool demandingFull = false; // Was full refresh specifically requested? (splash screens, etc)
|
||||
bool missedHighPriorityUpdate = false; // Was a high priority update skipped for rate-limiting?
|
||||
uint16_t partialRefreshCount = 0; // How many partials have occurred since last full refresh?
|
||||
uint16_t fastRefreshCount = 0; // How many fast updates have occurred since last full refresh?
|
||||
uint32_t lastUpdateMsec = 0; // When did the last update occur?
|
||||
uint32_t prevImageHash = 0; // Used to check if update will change screen image (skippable or not)
|
||||
int32_t prevBlackCount = 0; // How many black pixels were in the previous image
|
||||
uint32_t erasedSinceFull = 0; // How many black pixels have been set back to white since last full-refresh? (roughly)
|
||||
|
||||
// Set in variant.h
|
||||
const uint32_t lowPriorityLimitMsec = (uint32_t)1000 * EINK_LOWPRIORITY_LIMIT_SECONDS; // Max rate for partial refreshes
|
||||
const uint32_t lowPriorityLimitMsec = (uint32_t)1000 * EINK_LOWPRIORITY_LIMIT_SECONDS; // Max rate for fast refreshes
|
||||
const uint32_t highPriorityLimitMsec = (uint32_t)1000 * EINK_HIGHPRIORITY_LIMIT_SECONDS; // Max rate for full refreshes
|
||||
const uint32_t partialRefreshLimit = EINK_PARTIAL_REPEAT_LIMIT; // Max consecutive partials, before full is triggered
|
||||
const uint32_t fastRefreshLimit = EINK_FASTREFRESH_REPEAT_LIMIT; // Max consecutive fast updates, before full is triggered
|
||||
|
||||
#else // !USE_EINK_DYNAMIC_PARTIAL
|
||||
#else // !USE_EINK_DYNAMIC_REFRESH
|
||||
// Tolerate calls to these methods anywhere, just to be safe
|
||||
void highPriority() {}
|
||||
void lowPriority() {}
|
||||
void demandFullRefresh() {}
|
||||
#endif
|
||||
};
|
||||
|
@ -87,6 +87,7 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
||||
channelSettings.psk.bytes[0] = defaultpskIndex;
|
||||
channelSettings.psk.size = 1;
|
||||
strncpy(channelSettings.name, "", sizeof(channelSettings.name));
|
||||
channelSettings.module_settings.position_precision = 32; // default to sending location on the primary channel
|
||||
|
||||
ch.has_settings = true;
|
||||
ch.role = meshtastic_Channel_Role_PRIMARY;
|
||||
|
@ -21,7 +21,7 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p)
|
||||
{
|
||||
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
|
||||
printPacket("Ignoring incoming msg, because we've already seen it", p);
|
||||
if (!moduleConfig.mqtt.enabled && config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT &&
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
|
||||
// cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater!
|
||||
|
@ -257,10 +257,9 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
|
||||
return encodeResult; // FIXME - this isn't a valid ErrorCode
|
||||
}
|
||||
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
LOG_INFO("Should encrypt MQTT?: %d\n", moduleConfig.mqtt.encryption_enabled);
|
||||
if (mqtt)
|
||||
mqtt->onSend(*p, *p_decoded, chIndex);
|
||||
// Only publish to MQTT if we're the original transmitter of the packet
|
||||
if (moduleConfig.mqtt.enabled && p->from == nodeDB.getNodeNum() && mqtt) {
|
||||
mqtt->onSend(*p, *p_decoded, chIndex);
|
||||
}
|
||||
packetPool.release(p_decoded);
|
||||
}
|
||||
@ -438,6 +437,8 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
{
|
||||
// Also, we should set the time from the ISR and it should have msec level resolution
|
||||
p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone
|
||||
// Store a copy of encrypted packet for MQTT
|
||||
meshtastic_MeshPacket *p_encrypted = packetPool.allocCopy(*p);
|
||||
|
||||
// Take those raw bytes and convert them back into a well structured protobuf we can understand
|
||||
bool decoded = perhapsDecode(p);
|
||||
@ -449,10 +450,16 @@ void Router::handleReceived(meshtastic_MeshPacket *p, RxSource src)
|
||||
printPacket("handleReceived(USER)", p);
|
||||
else
|
||||
printPacket("handleReceived(REMOTE)", p);
|
||||
|
||||
// Publish received message to MQTT if we're not the original transmitter of the packet
|
||||
if (moduleConfig.mqtt.enabled && getFrom(p) != nodeDB.getNodeNum() && mqtt)
|
||||
mqtt->onSend(*p_encrypted, *p, p->channel);
|
||||
} else {
|
||||
printPacket("packet decoding failed or skipped (no PSK?)", p);
|
||||
}
|
||||
|
||||
packetPool.release(p_encrypted); // Release the encrypted packet
|
||||
|
||||
// call modules here
|
||||
MeshModule::callPlugins(*p, src);
|
||||
}
|
||||
@ -474,4 +481,4 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
|
||||
handleReceived(p);
|
||||
|
||||
packetPool.release(p);
|
||||
}
|
||||
}
|
@ -54,7 +54,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg;
|
||||
#define meshtastic_ChannelSet_fields &meshtastic_ChannelSet_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_ChannelSet_size 594
|
||||
#define meshtastic_ChannelSet_size 658
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -110,7 +110,7 @@ typedef struct _meshtastic_PLI {
|
||||
in floating point */
|
||||
int32_t longitude_i;
|
||||
/* Altitude (ATAK prefers HAE) */
|
||||
uint32_t altitude;
|
||||
int32_t altitude;
|
||||
/* Speed */
|
||||
uint32_t speed;
|
||||
/* Course in degrees */
|
||||
@ -238,7 +238,7 @@ X(a, STATIC, SINGULAR, STRING, device_callsign, 2)
|
||||
#define meshtastic_PLI_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 1) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 2) \
|
||||
X(a, STATIC, SINGULAR, UINT32, altitude, 3) \
|
||||
X(a, STATIC, SINGULAR, INT32, altitude, 3) \
|
||||
X(a, STATIC, SINGULAR, UINT32, speed, 4) \
|
||||
X(a, STATIC, SINGULAR, UINT32, course, 5)
|
||||
#define meshtastic_PLI_CALLBACK NULL
|
||||
@ -263,7 +263,7 @@ extern const pb_msgdesc_t meshtastic_PLI_msg;
|
||||
#define meshtastic_Contact_size 242
|
||||
#define meshtastic_GeoChat_size 323
|
||||
#define meshtastic_Group_size 4
|
||||
#define meshtastic_PLI_size 26
|
||||
#define meshtastic_PLI_size 31
|
||||
#define meshtastic_Status_size 3
|
||||
#define meshtastic_TAKPacket_size 584
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
PB_BIND(meshtastic_ChannelSettings, meshtastic_ChannelSettings, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ModuleSettings, meshtastic_ModuleSettings, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_Channel, meshtastic_Channel, AUTO)
|
||||
|
||||
|
||||
|
@ -30,6 +30,12 @@ typedef enum _meshtastic_Channel_Role {
|
||||
} meshtastic_Channel_Role;
|
||||
|
||||
/* Struct definitions */
|
||||
/* This message is specifically for modules to store per-channel configuration data. */
|
||||
typedef struct _meshtastic_ModuleSettings {
|
||||
/* Bits of precision for the location sent in position packets. */
|
||||
uint32_t position_precision;
|
||||
} meshtastic_ModuleSettings;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(32) meshtastic_ChannelSettings_psk_t;
|
||||
/* This information can be encoded as a QRcode/url so that other users can configure
|
||||
their radio to join the same channel.
|
||||
@ -85,6 +91,9 @@ typedef struct _meshtastic_ChannelSettings {
|
||||
bool uplink_enabled;
|
||||
/* If true, messages seen on the internet will be forwarded to the local mesh. */
|
||||
bool downlink_enabled;
|
||||
/* Per-channel module settings. */
|
||||
bool has_module_settings;
|
||||
meshtastic_ModuleSettings module_settings;
|
||||
} meshtastic_ChannelSettings;
|
||||
|
||||
/* A pair of a channel number, mode and the (sharable) settings for that channel */
|
||||
@ -111,22 +120,27 @@ extern "C" {
|
||||
#define _meshtastic_Channel_Role_ARRAYSIZE ((meshtastic_Channel_Role)(meshtastic_Channel_Role_SECONDARY+1))
|
||||
|
||||
|
||||
|
||||
#define meshtastic_Channel_role_ENUMTYPE meshtastic_Channel_Role
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0}
|
||||
#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default}
|
||||
#define meshtastic_ModuleSettings_init_default {0}
|
||||
#define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN}
|
||||
#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0}
|
||||
#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero}
|
||||
#define meshtastic_ModuleSettings_init_zero {0}
|
||||
#define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_ModuleSettings_position_precision_tag 1
|
||||
#define meshtastic_ChannelSettings_channel_num_tag 1
|
||||
#define meshtastic_ChannelSettings_psk_tag 2
|
||||
#define meshtastic_ChannelSettings_name_tag 3
|
||||
#define meshtastic_ChannelSettings_id_tag 4
|
||||
#define meshtastic_ChannelSettings_uplink_enabled_tag 5
|
||||
#define meshtastic_ChannelSettings_downlink_enabled_tag 6
|
||||
#define meshtastic_ChannelSettings_module_settings_tag 7
|
||||
#define meshtastic_Channel_index_tag 1
|
||||
#define meshtastic_Channel_settings_tag 2
|
||||
#define meshtastic_Channel_role_tag 3
|
||||
@ -138,9 +152,16 @@ X(a, STATIC, SINGULAR, BYTES, psk, 2) \
|
||||
X(a, STATIC, SINGULAR, STRING, name, 3) \
|
||||
X(a, STATIC, SINGULAR, FIXED32, id, 4) \
|
||||
X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6)
|
||||
X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7)
|
||||
#define meshtastic_ChannelSettings_CALLBACK NULL
|
||||
#define meshtastic_ChannelSettings_DEFAULT NULL
|
||||
#define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings
|
||||
|
||||
#define meshtastic_ModuleSettings_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_precision, 1)
|
||||
#define meshtastic_ModuleSettings_CALLBACK NULL
|
||||
#define meshtastic_ModuleSettings_DEFAULT NULL
|
||||
|
||||
#define meshtastic_Channel_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, INT32, index, 1) \
|
||||
@ -151,15 +172,18 @@ X(a, STATIC, SINGULAR, UENUM, role, 3)
|
||||
#define meshtastic_Channel_settings_MSGTYPE meshtastic_ChannelSettings
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_ChannelSettings_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleSettings_msg;
|
||||
extern const pb_msgdesc_t meshtastic_Channel_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_ChannelSettings_fields &meshtastic_ChannelSettings_msg
|
||||
#define meshtastic_ModuleSettings_fields &meshtastic_ModuleSettings_msg
|
||||
#define meshtastic_Channel_fields &meshtastic_Channel_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_ChannelSettings_size 62
|
||||
#define meshtastic_Channel_size 77
|
||||
#define meshtastic_ChannelSettings_size 70
|
||||
#define meshtastic_Channel_size 85
|
||||
#define meshtastic_ModuleSettings_size 6
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -317,9 +317,6 @@ typedef struct _meshtastic_Config_PositionConfig {
|
||||
uint32_t gps_en_gpio;
|
||||
/* Set where GPS is enabled, disabled, or not present */
|
||||
meshtastic_Config_PositionConfig_GpsMode gps_mode;
|
||||
/* Set GPS precision in bits per channel, or 0 for disabled */
|
||||
pb_size_t channel_precision_count;
|
||||
uint32_t channel_precision[8];
|
||||
} meshtastic_Config_PositionConfig;
|
||||
|
||||
/* Power Config\
|
||||
@ -587,7 +584,7 @@ extern "C" {
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Config_init_default {0, {meshtastic_Config_DeviceConfig_init_default}}
|
||||
#define meshtastic_Config_DeviceConfig_init_default {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define meshtastic_Config_PositionConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0}
|
||||
@ -596,7 +593,7 @@ extern "C" {
|
||||
#define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0}
|
||||
#define meshtastic_Config_init_zero {0, {meshtastic_Config_DeviceConfig_init_zero}}
|
||||
#define meshtastic_Config_DeviceConfig_init_zero {_meshtastic_Config_DeviceConfig_Role_MIN, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_RebroadcastMode_MIN, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define meshtastic_Config_PositionConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _meshtastic_Config_PositionConfig_GpsMode_MIN}
|
||||
#define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, ""}
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0}
|
||||
@ -628,7 +625,6 @@ extern "C" {
|
||||
#define meshtastic_Config_PositionConfig_broadcast_smart_minimum_interval_secs_tag 11
|
||||
#define meshtastic_Config_PositionConfig_gps_en_gpio_tag 12
|
||||
#define meshtastic_Config_PositionConfig_gps_mode_tag 13
|
||||
#define meshtastic_Config_PositionConfig_channel_precision_tag 14
|
||||
#define meshtastic_Config_PowerConfig_is_power_saving_tag 1
|
||||
#define meshtastic_Config_PowerConfig_on_battery_shutdown_after_secs_tag 2
|
||||
#define meshtastic_Config_PowerConfig_adc_multiplier_override_tag 3
|
||||
@ -732,8 +728,7 @@ X(a, STATIC, SINGULAR, UINT32, tx_gpio, 9) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_distance, 10) \
|
||||
X(a, STATIC, SINGULAR, UINT32, broadcast_smart_minimum_interval_secs, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, gps_en_gpio, 12) \
|
||||
X(a, STATIC, SINGULAR, UENUM, gps_mode, 13) \
|
||||
X(a, STATIC, REPEATED, UINT32, channel_precision, 14)
|
||||
X(a, STATIC, SINGULAR, UENUM, gps_mode, 13)
|
||||
#define meshtastic_Config_PositionConfig_CALLBACK NULL
|
||||
#define meshtastic_Config_PositionConfig_DEFAULT NULL
|
||||
|
||||
@ -839,7 +834,7 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg;
|
||||
#define meshtastic_Config_LoRaConfig_size 80
|
||||
#define meshtastic_Config_NetworkConfig_IpV4Config_size 20
|
||||
#define meshtastic_Config_NetworkConfig_size 196
|
||||
#define meshtastic_Config_PositionConfig_size 110
|
||||
#define meshtastic_Config_PositionConfig_size 62
|
||||
#define meshtastic_Config_PowerConfig_size 40
|
||||
#define meshtastic_Config_size 199
|
||||
|
||||
|
@ -312,11 +312,11 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
|
||||
#define meshtastic_NodeRemoteHardwarePin_fields &meshtastic_NodeRemoteHardwarePin_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_ChannelFile_size 638
|
||||
#define meshtastic_ChannelFile_size 702
|
||||
#define meshtastic_DeviceState_size 17062
|
||||
#define meshtastic_NodeInfoLite_size 153
|
||||
#define meshtastic_NodeRemoteHardwarePin_size 29
|
||||
#define meshtastic_OEMStore_size 3294
|
||||
#define meshtastic_OEMStore_size 3246
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -180,7 +180,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
#define meshtastic_LocalModuleConfig_fields &meshtastic_LocalModuleConfig_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_LocalConfig_size 517
|
||||
#define meshtastic_LocalConfig_size 469
|
||||
#define meshtastic_LocalModuleConfig_size 631
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -380,6 +380,8 @@ typedef struct _meshtastic_Position {
|
||||
/* A sequence number, incremented with each Position message to help
|
||||
detect lost updates if needed */
|
||||
uint32_t seq_number;
|
||||
/* Indicates the bits of precision set by the sending node */
|
||||
uint32_t precision_bits;
|
||||
} meshtastic_Position;
|
||||
|
||||
/* Broadcast when a newly powered mesh node wants to find a node num it can use
|
||||
@ -882,7 +884,7 @@ extern "C" {
|
||||
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Position_init_default {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_default {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
|
||||
#define meshtastic_RouteDiscovery_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define meshtastic_Routing_init_default {0, {meshtastic_RouteDiscovery_init_default}}
|
||||
@ -900,7 +902,7 @@ extern "C" {
|
||||
#define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
|
||||
#define meshtastic_Neighbor_init_default {0, 0, 0, 0}
|
||||
#define meshtastic_DeviceMetadata_init_default {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
|
||||
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_Position_init_zero {0, 0, 0, 0, _meshtastic_Position_LocSource_MIN, _meshtastic_Position_AltSource_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0, _meshtastic_Config_DeviceConfig_Role_MIN}
|
||||
#define meshtastic_RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}}
|
||||
#define meshtastic_Routing_init_zero {0, {meshtastic_RouteDiscovery_init_zero}}
|
||||
@ -942,6 +944,7 @@ extern "C" {
|
||||
#define meshtastic_Position_sensor_id_tag 20
|
||||
#define meshtastic_Position_next_update_tag 21
|
||||
#define meshtastic_Position_seq_number_tag 22
|
||||
#define meshtastic_Position_precision_bits_tag 23
|
||||
#define meshtastic_User_id_tag 1
|
||||
#define meshtastic_User_long_name_tag 2
|
||||
#define meshtastic_User_short_name_tag 3
|
||||
@ -1068,7 +1071,8 @@ X(a, STATIC, SINGULAR, UINT32, fix_type, 18) \
|
||||
X(a, STATIC, SINGULAR, UINT32, sats_in_view, 19) \
|
||||
X(a, STATIC, SINGULAR, UINT32, sensor_id, 20) \
|
||||
X(a, STATIC, SINGULAR, UINT32, next_update, 21) \
|
||||
X(a, STATIC, SINGULAR, UINT32, seq_number, 22)
|
||||
X(a, STATIC, SINGULAR, UINT32, seq_number, 22) \
|
||||
X(a, STATIC, SINGULAR, UINT32, precision_bits, 23)
|
||||
#define meshtastic_Position_CALLBACK NULL
|
||||
#define meshtastic_Position_DEFAULT NULL
|
||||
|
||||
@ -1313,8 +1317,8 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
|
||||
#define meshtastic_MyNodeInfo_size 18
|
||||
#define meshtastic_NeighborInfo_size 258
|
||||
#define meshtastic_Neighbor_size 22
|
||||
#define meshtastic_NodeInfo_size 263
|
||||
#define meshtastic_Position_size 137
|
||||
#define meshtastic_NodeInfo_size 270
|
||||
#define meshtastic_Position_size 144
|
||||
#define meshtastic_QueueStatus_size 23
|
||||
#define meshtastic_RouteDiscovery_size 40
|
||||
#define meshtastic_Routing_size 42
|
||||
|
@ -23,6 +23,7 @@ PositionModule::PositionModule()
|
||||
: ProtobufModule("position", meshtastic_PortNum_POSITION_APP, &meshtastic_Position_msg),
|
||||
concurrency::OSThread("PositionModule")
|
||||
{
|
||||
precision = 0; // safe starting value
|
||||
isPromiscuous = true; // We always want to update our nodedb, even if we are sniffing on others
|
||||
if (config.device.role != meshtastic_Config_DeviceConfig_Role_TRACKER &&
|
||||
config.device.role != meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)
|
||||
@ -82,21 +83,15 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
||||
}
|
||||
|
||||
nodeDB.updatePosition(getFrom(&mp), p);
|
||||
|
||||
// Only respond to location requests on the channel where we broadcast location.
|
||||
if (channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) {
|
||||
ignoreRequest = false;
|
||||
} else {
|
||||
ignoreRequest = true;
|
||||
}
|
||||
precision = channels.getByIndex(mp.channel).settings.module_settings.position_precision;
|
||||
|
||||
return false; // Let others look at this message also if they want
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
{
|
||||
if (ignoreRequest) {
|
||||
ignoreRequest = false; // Reset for next request
|
||||
if (precision == 0) {
|
||||
LOG_DEBUG("Skipping location send because precision is set to 0!\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -116,8 +111,16 @@ meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
localPosition.seq_number++;
|
||||
|
||||
// lat/lon are unconditionally included - IF AVAILABLE!
|
||||
p.latitude_i = localPosition.latitude_i;
|
||||
p.longitude_i = localPosition.longitude_i;
|
||||
LOG_DEBUG("Sending location with precision %i\n", precision);
|
||||
p.latitude_i = localPosition.latitude_i & (INT32_MAX << (32 - precision));
|
||||
p.longitude_i = localPosition.longitude_i & (INT32_MAX << (32 - precision));
|
||||
|
||||
// We want the imprecise position to be the middle of the possible location, not
|
||||
if (precision < 31 && precision > 1) {
|
||||
p.latitude_i += (1 << 31 - precision);
|
||||
p.longitude_i += (1 << 31 - precision);
|
||||
}
|
||||
p.precision_bits = precision;
|
||||
p.time = localPosition.time;
|
||||
|
||||
if (pos_flags & meshtastic_Config_PositionConfig_PositionFlags_ALTITUDE) {
|
||||
@ -164,7 +167,7 @@ meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
LOG_INFO("Providing time to mesh %u\n", p.time);
|
||||
}
|
||||
|
||||
LOG_INFO("Position reply: time=%i, latI=%i, lonI=-%i\n", p.time, p.latitude_i, p.longitude_i);
|
||||
LOG_INFO("Position reply: time=%i, latI=%i, lonI=%i\n", p.time, p.latitude_i, p.longitude_i);
|
||||
|
||||
// TAK Tracker devices should send their position in a TAK packet over the ATAK port
|
||||
if (config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)
|
||||
@ -193,7 +196,7 @@ meshtastic_MeshPacket *PositionModule::allocAtakPli()
|
||||
{.pli = {
|
||||
.latitude_i = localPosition.latitude_i,
|
||||
.longitude_i = localPosition.longitude_i,
|
||||
.altitude = localPosition.altitude_hae > 0 ? localPosition.altitude_hae : 0,
|
||||
.altitude = localPosition.altitude_hae,
|
||||
.speed = localPosition.ground_speed,
|
||||
.course = static_cast<uint16_t>(localPosition.ground_track),
|
||||
}}};
|
||||
@ -213,9 +216,12 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
|
||||
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
|
||||
service.cancelSending(prevPacketId);
|
||||
|
||||
// Set's the class precision value for this particular packet
|
||||
precision = channels.getByIndex(channel).settings.module_settings.position_precision;
|
||||
|
||||
meshtastic_MeshPacket *p = allocReply();
|
||||
if (p == nullptr) {
|
||||
LOG_WARN("allocReply returned a nullptr\n");
|
||||
LOG_DEBUG("allocReply returned a nullptr\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ class PositionModule : public ProtobufModule<meshtastic_Position>, private concu
|
||||
private:
|
||||
struct SmartPosition getDistanceTraveledSinceLastSend(meshtastic_PositionLite currentPosition);
|
||||
meshtastic_MeshPacket *allocAtakPli();
|
||||
uint32_t precision;
|
||||
|
||||
/** Only used in power saving trackers for now */
|
||||
void clearPosition();
|
||||
|
@ -485,14 +485,15 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket &
|
||||
env->channel_id = (char *)channelId;
|
||||
env->gateway_id = owner.id;
|
||||
|
||||
LOG_DEBUG("MQTT onSend - Publishing ");
|
||||
if (moduleConfig.mqtt.encryption_enabled) {
|
||||
env->packet = (meshtastic_MeshPacket *)∓
|
||||
LOG_DEBUG("encrypted message\n");
|
||||
} else {
|
||||
env->packet = (meshtastic_MeshPacket *)&mp_decoded;
|
||||
LOG_DEBUG("portnum %i message\n", env->packet->decoded.portnum);
|
||||
}
|
||||
|
||||
LOG_DEBUG("MQTT onSend - Publishing portnum %i message\n", env->packet->decoded.portnum);
|
||||
|
||||
if (moduleConfig.mqtt.proxy_to_client_enabled || this->isConnectedDirectly()) {
|
||||
// FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets
|
||||
static uint8_t bytes[meshtastic_MeshPacket_size + 64];
|
||||
|
@ -50,7 +50,8 @@ class MQTT : private concurrency::OSThread
|
||||
|
||||
/**
|
||||
* Publish a packet on the global MQTT server.
|
||||
* This hook must be called **after** the packet is encrypted (including the channel being changed to a hash).
|
||||
* @param mp the encrypted packet to publish
|
||||
* @param mp_decoded the decrypted packet to publish
|
||||
* @param chIndex the index of the channel for this message
|
||||
*
|
||||
* Note: for messages we are forwarding on the mesh that we can't find the channel for (because we don't have the keys), we
|
||||
|
@ -6,12 +6,12 @@
|
||||
|
||||
#define USE_EINK
|
||||
|
||||
// Settings for Dynamic Partial mode
|
||||
// Change between partial and full refresh config, or skip update, balancing urgency and display health.
|
||||
#define USE_EINK_DYNAMIC_PARTIAL
|
||||
// Settings for Dynamic Refresh mode
|
||||
// Change between full-refresh, fast-refresh, or update-skipping, to balance urgency and display health.
|
||||
#define USE_EINK_DYNAMIC_REFRESH
|
||||
#define EINK_LOWPRIORITY_LIMIT_SECONDS 30
|
||||
#define EINK_HIGHPRIORITY_LIMIT_SECONDS 1
|
||||
#define EINK_PARTIAL_REPEAT_LIMIT 5
|
||||
#define EINK_FASTREFRESH_REPEAT_LIMIT 5
|
||||
|
||||
/*
|
||||
* eink display pins
|
||||
|
Loading…
Reference in New Issue
Block a user