Make SPI frequency and TOPHONE queue size configurable on Native (#4369)

* Make SPI frequency configurable on Native

* Make the tophone queue size configurable for Portduino

* The modified SPISettings must be configured in setup(), after config.yaml is processed

* make MeshService a pointer, so we can configure MAX_RX_TOPHONE at run time

* Got a little over excited with refactoring

* Silence a warning
This commit is contained in:
Jonathan Bennett 2024-08-01 19:29:49 -05:00 committed by GitHub
parent 4c1c5b070e
commit d2ea430a3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 110 additions and 83 deletions

View File

@ -54,6 +54,8 @@ Lora:
# ch341_quirk: true # Uncomment this to use the chunked SPI transfer that seems to fix the ch341 # ch341_quirk: true # Uncomment this to use the chunked SPI transfer that seems to fix the ch341
# spiSpeed: 2000000
### Set gpio chip to use in /dev/. Defaults to 0. ### Set gpio chip to use in /dev/. Defaults to 0.
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4 ### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
# gpiochip: 4 # gpiochip: 4
@ -111,6 +113,9 @@ Display:
# Height: 320 # Height: 320
# Rotate: true # Rotate: true
### You can also specify the spi device for the display to use
# spidev: spidev0.0
Touchscreen: Touchscreen:
### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching. ### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching.
@ -126,9 +131,13 @@ Touchscreen:
# CS: 7 # CS: 7
# IRQ: 17 # IRQ: 17
### Configure device for direct keyboard input ### You can also specify the spi device for the touchscreen to use
# spidev: spidev0.0
Input: Input:
### Configure device for direct keyboard input
# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd # KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd
### ###
@ -143,3 +152,4 @@ Webserver:
General: General:
MaxNodes: 200 MaxNodes: 200
MaxMessageQueue: 100

View File

@ -144,8 +144,8 @@ int32_t ButtonThread::runOnce()
case BUTTON_EVENT_DOUBLE_PRESSED: { case BUTTON_EVENT_DOUBLE_PRESSED: {
LOG_BUTTON("Double press!\n"); LOG_BUTTON("Double press!\n");
service.refreshLocalMeshNode(); service->refreshLocalMeshNode();
auto sentPosition = service.trySendPosition(NODENUM_BROADCAST, true); auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true);
if (screen) { if (screen) {
if (sentPosition) if (sentPosition)
screen->print("Sent ad-hoc position\n"); screen->print("Sent ad-hoc position\n");

View File

@ -208,7 +208,6 @@ uint32_t timeLastPowered = 0;
static Periodic *ledPeriodic; static Periodic *ledPeriodic;
static OSThread *powerFSMthread; static OSThread *powerFSMthread;
static OSThread *ambientLightingThread; static OSThread *ambientLightingThread;
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
RadioInterface *rIf = NULL; RadioInterface *rIf = NULL;
@ -231,6 +230,12 @@ void printInfo()
void setup() void setup()
{ {
concurrency::hasBeenSetup = true; concurrency::hasBeenSetup = true;
#if ARCH_PORTDUINO
SPISettings spiSettings(settingsMap[spiSpeed], MSBFIRST, SPI_MODE0);
#else
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
#endif
meshtastic_Config_DisplayConfig_OledType screen_model = meshtastic_Config_DisplayConfig_OledType screen_model =
meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO; meshtastic_Config_DisplayConfig_OledType::meshtastic_Config_DisplayConfig_OledType_OLED_AUTO;
OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64; OLEDDISPLAY_GEOMETRY screen_geometry = GEOMETRY_128_64;
@ -714,8 +719,8 @@ void setup()
LOG_DEBUG("Starting audio thread\n"); LOG_DEBUG("Starting audio thread\n");
audioThread = new AudioThread(); audioThread = new AudioThread();
#endif #endif
service = new MeshService();
service.init(); service->init();
// Now that the mesh service is created, create any modules // Now that the mesh service is created, create any modules
setupModules(); setupModules();
@ -1080,7 +1085,7 @@ void loop()
// TODO: This should go into a thread handled by FreeRTOS. // TODO: This should go into a thread handled by FreeRTOS.
// handleWebResponse(); // handleWebResponse();
service.loop(); service->loop();
long delayMsec = mainController.runOrDelay(); long delayMsec = mainController.runOrDelay();

View File

@ -170,7 +170,7 @@ void MeshModule::callModules(meshtastic_MeshPacket &mp, RxSource src)
if (isDecoded && mp.decoded.want_response && toUs) { if (isDecoded && mp.decoded.want_response && toUs) {
if (currentReply) { if (currentReply) {
printPacket("Sending response", currentReply); printPacket("Sending response", currentReply);
service.sendToMesh(currentReply); service->sendToMesh(currentReply);
currentReply = NULL; currentReply = NULL;
} else if (mp.from != ourNodeNum && !ignoreRequest) { } else if (mp.from != ourNodeNum && !ignoreRequest) {
// Note: if the message started with the local node or a module asked to ignore the request, we don't want to send a // Note: if the message started with the local node or a module asked to ignore the request, we don't want to send a

View File

@ -23,6 +23,10 @@
#include "nimble/NimbleBluetooth.h" #include "nimble/NimbleBluetooth.h"
#endif #endif
#if ARCH_PORTDUINO
#include "PortduinoGlue.h"
#endif
/* /*
receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone. receivedPacketQueue - this is a queue of messages we've received from the mesh, which we are keeping to deliver to the phone.
It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were It is implemented with a FreeRTos queue (wrapped with a little RTQueue class) of pointers to MeshPacket protobufs (which were
@ -53,7 +57,7 @@ nodenum (filtering against whatever it knows about the nodedb) and rebroadcast t
FIXME in the initial proof of concept we just skip the entire want/deny flow and just hand pick node numbers at first. FIXME in the initial proof of concept we just skip the entire want/deny flow and just hand pick node numbers at first.
*/ */
MeshService service; MeshService *service;
static MemoryDynamic<meshtastic_MqttClientProxyMessage> staticMqttClientProxyMessagePool; static MemoryDynamic<meshtastic_MqttClientProxyMessage> staticMqttClientProxyMessagePool;

View File

@ -150,4 +150,4 @@ class MeshService
friend class RoutingModule; friend class RoutingModule;
}; };
extern MeshService service; extern MeshService *service;

View File

@ -41,7 +41,7 @@ void PhoneAPI::handleStartConfig()
// Must be before setting state (because state is how we know !connected) // Must be before setting state (because state is how we know !connected)
if (!isConnected()) { if (!isConnected()) {
onConnectionChanged(true); onConnectionChanged(true);
observe(&service.fromNumChanged); observe(&service->fromNumChanged);
#ifdef FSCom #ifdef FSCom
observe(&xModem.packetReady); observe(&xModem.packetReady);
#endif #endif
@ -63,7 +63,7 @@ void PhoneAPI::close()
if (state != STATE_SEND_NOTHING) { if (state != STATE_SEND_NOTHING) {
state = STATE_SEND_NOTHING; state = STATE_SEND_NOTHING;
unobserve(&service.fromNumChanged); unobserve(&service->fromNumChanged);
#ifdef FSCom #ifdef FSCom
unobserve(&xModem.packetReady); unobserve(&xModem.packetReady);
#endif #endif
@ -186,7 +186,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.my_info = myNodeInfo; fromRadioScratch.my_info = myNodeInfo;
state = STATE_SEND_OWN_NODEINFO; state = STATE_SEND_OWN_NODEINFO;
service.refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon. service->refreshLocalMeshNode(); // Update my NodeInfo because the client will be asking for it soon.
break; break;
case STATE_SEND_OWN_NODEINFO: { case STATE_SEND_OWN_NODEINFO: {
@ -443,7 +443,7 @@ void PhoneAPI::handleDisconnect()
void PhoneAPI::releasePhonePacket() void PhoneAPI::releasePhonePacket()
{ {
if (packetForPhone) { if (packetForPhone) {
service.releaseToPool(packetForPhone); // we just copied the bytes, so don't need this buffer anymore service->releaseToPool(packetForPhone); // we just copied the bytes, so don't need this buffer anymore
packetForPhone = NULL; packetForPhone = NULL;
} }
} }
@ -451,7 +451,7 @@ void PhoneAPI::releasePhonePacket()
void PhoneAPI::releaseQueueStatusPhonePacket() void PhoneAPI::releaseQueueStatusPhonePacket()
{ {
if (queueStatusPacketForPhone) { if (queueStatusPacketForPhone) {
service.releaseQueueStatusToPool(queueStatusPacketForPhone); service->releaseQueueStatusToPool(queueStatusPacketForPhone);
queueStatusPacketForPhone = NULL; queueStatusPacketForPhone = NULL;
} }
} }
@ -459,7 +459,7 @@ void PhoneAPI::releaseQueueStatusPhonePacket()
void PhoneAPI::releaseMqttClientProxyPhonePacket() void PhoneAPI::releaseMqttClientProxyPhonePacket()
{ {
if (mqttClientProxyMessageForPhone) { if (mqttClientProxyMessageForPhone) {
service.releaseMqttClientProxyMessageToPool(mqttClientProxyMessageForPhone); service->releaseMqttClientProxyMessageToPool(mqttClientProxyMessageForPhone);
mqttClientProxyMessageForPhone = NULL; mqttClientProxyMessageForPhone = NULL;
} }
} }
@ -495,9 +495,9 @@ bool PhoneAPI::available()
return true; // Always say we have something, because we might need to advance our state machine return true; // Always say we have something, because we might need to advance our state machine
case STATE_SEND_PACKETS: { case STATE_SEND_PACKETS: {
if (!queueStatusPacketForPhone) if (!queueStatusPacketForPhone)
queueStatusPacketForPhone = service.getQueueStatusForPhone(); queueStatusPacketForPhone = service->getQueueStatusForPhone();
if (!mqttClientProxyMessageForPhone) if (!mqttClientProxyMessageForPhone)
mqttClientProxyMessageForPhone = service.getMqttClientProxyMessageForPhone(); mqttClientProxyMessageForPhone = service->getMqttClientProxyMessageForPhone();
bool hasPacket = !!queueStatusPacketForPhone || !!mqttClientProxyMessageForPhone; bool hasPacket = !!queueStatusPacketForPhone || !!mqttClientProxyMessageForPhone;
if (hasPacket) if (hasPacket)
return true; return true;
@ -520,7 +520,7 @@ bool PhoneAPI::available()
#endif #endif
if (!packetForPhone) if (!packetForPhone)
packetForPhone = service.getForPhone(); packetForPhone = service->getForPhone();
hasPacket = !!packetForPhone; hasPacket = !!packetForPhone;
// LOG_DEBUG("available hasPacket=%d\n", hasPacket); // LOG_DEBUG("available hasPacket=%d\n", hasPacket);
return hasPacket; return hasPacket;
@ -538,7 +538,7 @@ bool PhoneAPI::available()
bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p) bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p)
{ {
printPacket("PACKET FROM PHONE", &p); printPacket("PACKET FROM PHONE", &p);
service.handleToRadio(p); service->handleToRadio(p);
return true; return true;
} }

View File

@ -38,7 +38,7 @@ template <class T> class ProtobufModule : protected SinglePortModule
/** /**
* Return a mesh packet which has been preinited with a particular protobuf data payload and port number. * Return a mesh packet which has been preinited with a particular protobuf data payload and port number.
* You can then send this packet (after customizing any of the payload fields you might need) with * You can then send this packet (after customizing any of the payload fields you might need) with
* service.sendToMesh() * service->sendToMesh()
*/ */
meshtastic_MeshPacket *allocDataProtobuf(const T &payload) meshtastic_MeshPacket *allocDataProtobuf(const T &payload)
{ {

View File

@ -334,7 +334,7 @@ bool RadioInterface::init()
{ {
LOG_INFO("Starting meshradio init...\n"); LOG_INFO("Starting meshradio init...\n");
configChangedObserver.observe(&service.configChanged); configChangedObserver.observe(&service->configChanged);
preflightSleepObserver.observe(&preflightSleep); preflightSleepObserver.observe(&preflightSleep);
notifyDeepSleepObserver.observe(&notifyDeepSleep); notifyDeepSleepObserver.observe(&notifyDeepSleep);

View File

@ -26,7 +26,7 @@ class SinglePortModule : public MeshModule
/** /**
* Return a mesh packet which has been preinited as a data packet with a particular port number. * Return a mesh packet which has been preinited as a data packet with a particular port number.
* You can then send this packet (after customizing any of the payload fields you might need) with * You can then send this packet (after customizing any of the payload fields you might need) with
* service.sendToMesh() * service->sendToMesh()
*/ */
meshtastic_MeshPacket *allocDataPacket() meshtastic_MeshPacket *allocDataPacket()
{ {

View File

@ -14,7 +14,9 @@
/// max number of packets which can be waiting for delivery to android - note, this value comes from mesh.options protobuf /// max number of packets which can be waiting for delivery to android - note, this value comes from mesh.options protobuf
// FIXME - max_count is actually 32 but we save/load this as one long string of preencoded MeshPacket bytes - not a big array in // FIXME - max_count is actually 32 but we save/load this as one long string of preencoded MeshPacket bytes - not a big array in
// RAM #define MAX_RX_TOPHONE (member_size(DeviceState, receive_queue) / member_size(DeviceState, receive_queue[0])) // RAM #define MAX_RX_TOPHONE (member_size(DeviceState, receive_queue) / member_size(DeviceState, receive_queue[0]))
#ifndef MAX_RX_TOPHONE
#define MAX_RX_TOPHONE 32 #define MAX_RX_TOPHONE 32
#endif
/// max number of nodes allowed in the mesh /// max number of nodes allowed in the mesh
#ifndef MAX_NUM_NODES #ifndef MAX_NUM_NODES

View File

@ -348,7 +348,7 @@ void AdminModule::handleSetOwner(const meshtastic_User &o)
} }
if (changed) { // If nothing really changed, don't broadcast on the network or write to flash if (changed) { // If nothing really changed, don't broadcast on the network or write to flash
service.reloadOwner(!hasOpenEditTransaction); service->reloadOwner(!hasOpenEditTransaction);
saveChanges(SEGMENT_DEVICESTATE); saveChanges(SEGMENT_DEVICESTATE);
} }
} }
@ -848,7 +848,7 @@ void AdminModule::saveChanges(int saveWhat, bool shouldReboot)
{ {
if (!hasOpenEditTransaction) { if (!hasOpenEditTransaction) {
LOG_INFO("Saving changes to disk\n"); LOG_INFO("Saving changes to disk\n");
service.reloadConfig(saveWhat); // Calls saveToDisk among other things service->reloadConfig(saveWhat); // Calls saveToDisk among other things
} else { } else {
LOG_INFO("Delaying save of changes to disk until the open transaction is committed\n"); LOG_INFO("Delaying save of changes to disk until the open transaction is committed\n");
} }
@ -879,7 +879,7 @@ void AdminModule::handleSetHamMode(const meshtastic_HamParameters &p)
channels.setChannel(primaryChannel); channels.setChannel(primaryChannel);
channels.onConfigChanged(); channels.onConfigChanged();
service.reloadOwner(false); service->reloadOwner(false);
saveChanges(SEGMENT_CONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS); saveChanges(SEGMENT_CONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
} }

View File

@ -188,7 +188,7 @@ void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtast
pb_encode_to_bytes(decompressedCopy->decoded.payload.bytes, sizeof(decompressedCopy->decoded.payload), pb_encode_to_bytes(decompressedCopy->decoded.payload.bytes, sizeof(decompressedCopy->decoded.payload),
meshtastic_TAKPacket_fields, &uncompressed); meshtastic_TAKPacket_fields, &uncompressed);
service.sendToPhone(decompressedCopy); service->sendToPhone(decompressedCopy);
} }
return; return;
} }

View File

@ -264,8 +264,8 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
#endif #endif
break; break;
case 0xaf: // fn+space send network ping like double press does case 0xaf: // fn+space send network ping like double press does
service.refreshLocalMeshNode(); service->refreshLocalMeshNode();
if (service.trySendPosition(NODENUM_BROADCAST, true)) { if (service->trySendPosition(NODENUM_BROADCAST, true)) {
showTemporaryMessage("Position \nUpdate Sent"); showTemporaryMessage("Position \nUpdate Sent");
} else { } else {
showTemporaryMessage("Node Info \nUpdate Sent"); showTemporaryMessage("Node Info \nUpdate Sent");
@ -388,7 +388,7 @@ void CannedMessageModule::sendText(NodeNum dest, ChannelIndex channel, const cha
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes); LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
service.sendToMesh( service->sendToMesh(
p, RX_SRC_LOCAL, p, RX_SRC_LOCAL,
true); // send to mesh, cc to phone. Even if there's no phone connected, this stores the message to match ACKs true); // send to mesh, cc to phone. Even if there's no phone connected, this stores the message to match ACKs
} }
@ -1048,7 +1048,7 @@ ProcessMessage CannedMessageModule::handleReceived(const meshtastic_MeshPacket &
e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; // We want to change the list of frames shown on-screen
requestFocus(); // Tell Screen::setFrames that our module's frame should be shown, even if not "first" in the frameset requestFocus(); // Tell Screen::setFrames that our module's frame should be shown, even if not "first" in the frameset
this->runState = CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED; this->runState = CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED;
this->incoming = service.getNodenumFromRequestId(mp.decoded.request_id); this->incoming = service->getNodenumFromRequestId(mp.decoded.request_id);
meshtastic_Routing decoded = meshtastic_Routing_init_default; meshtastic_Routing decoded = meshtastic_Routing_init_default;
pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_Routing_fields, &decoded); pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, meshtastic_Routing_fields, &decoded);
this->ack = decoded.error_reason == meshtastic_Routing_Error_NONE; this->ack = decoded.error_reason == meshtastic_Routing_Error_NONE;

View File

@ -82,7 +82,7 @@ void DetectionSensorModule::sendDetectionMessage()
} }
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes); LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
lastSentToMesh = millis(); lastSentToMesh = millis();
service.sendToMesh(p); service->sendToMesh(p);
delete[] message; delete[] message;
} }
@ -97,7 +97,7 @@ void DetectionSensorModule::sendCurrentStateMessage()
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size); memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes); LOG_INFO("Sending message id=%d, dest=%x, msg=%.*s\n", p->id, p->to, p->decoded.payload.size, p->decoded.payload.bytes);
lastSentToMesh = millis(); lastSentToMesh = millis();
service.sendToMesh(p); service->sendToMesh(p);
delete[] message; delete[] message;
} }

View File

@ -1,7 +1,7 @@
#if !MESHTASTIC_EXCLUDE_DROPZONE #if !MESHTASTIC_EXCLUDE_DROPZONE
#include "DropzoneModule.h" #include "DropzoneModule.h"
#include "MeshService.h" #include "Meshservice->h"
#include "configuration.h" #include "configuration.h"
#include "gps/GeoCoord.h" #include "gps/GeoCoord.h"
#include "gps/RTC.h" #include "gps/RTC.h"
@ -20,7 +20,7 @@ int32_t DropzoneModule::runOnce()
{ {
// Send on a 5 second delay from receiving the matching request // Send on a 5 second delay from receiving the matching request
if (startSendConditions != 0 && (startSendConditions + 5000U) < millis()) { if (startSendConditions != 0 && (startSendConditions + 5000U) < millis()) {
service.sendToMesh(sendConditions(), RX_SRC_LOCAL); service->sendToMesh(sendConditions(), RX_SRC_LOCAL);
startSendConditions = 0; startSendConditions = 0;
} }
// Run every second to check if we need to send conditions // Run every second to check if we need to send conditions

View File

@ -108,7 +108,7 @@ void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
p->to = dest; p->to = dest;
p->decoded.want_response = wantReplies; p->decoded.want_response = wantReplies;
printNeighborInfo("SENDING", &neighborInfo); printNeighborInfo("SENDING", &neighborInfo);
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
} }
/* /*

View File

@ -26,7 +26,7 @@ bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
// if user has changed while packet was not for us, inform phone // if user has changed while packet was not for us, inform phone
if (hasChanged && !wasBroadcast && mp.to != nodeDB->getNodeNum()) if (hasChanged && !wasBroadcast && mp.to != nodeDB->getNodeNum())
service.sendToPhone(packetPool.allocCopy(mp)); service->sendToPhone(packetPool.allocCopy(mp));
// LOG_DEBUG("did handleReceived\n"); // LOG_DEBUG("did handleReceived\n");
return false; // Let others look at this message also if they want return false; // Let others look at this message also if they want
@ -36,7 +36,7 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
{ {
// cancel any not yet sent (now stale) position packets // cancel any not yet sent (now stale) position packets
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal) if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
service.cancelSending(prevPacketId); service->cancelSending(prevPacketId);
meshtastic_MeshPacket *p = allocReply(); meshtastic_MeshPacket *p = allocReply();
if (p) { // Check whether we didn't ignore it if (p) { // Check whether we didn't ignore it
@ -52,7 +52,7 @@ void NodeInfoModule::sendOurNodeInfo(NodeNum dest, bool wantReplies, uint8_t cha
prevPacketId = p->id; prevPacketId = p->id;
service.sendToMesh(p); service->sendToMesh(p);
} }
} }

View File

@ -141,7 +141,7 @@ meshtastic_MeshPacket *PositionModule::allocReply()
return nullptr; return nullptr;
} }
meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position meshtastic_NodeInfoLite *node = service->refreshLocalMeshNode(); // should guarantee there is now a position
assert(node->has_position); assert(node->has_position);
// configuration of POSITION packet // configuration of POSITION packet
@ -280,7 +280,7 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
{ {
// cancel any not yet sent (now stale) position packets // cancel any not yet sent (now stale) position packets
if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal) if (prevPacketId) // if we wrap around to zero, we'll simply fail to cancel in that rare case (no big deal)
service.cancelSending(prevPacketId); service->cancelSending(prevPacketId);
// Set's the class precision value for this particular packet // Set's the class precision value for this particular packet
if (channels.getByIndex(channel).settings.has_module_settings) { if (channels.getByIndex(channel).settings.has_module_settings) {
@ -309,7 +309,7 @@ void PositionModule::sendOurPosition(NodeNum dest, bool wantReplies, uint8_t cha
if (channel > 0) if (channel > 0)
p->channel = channel; p->channel = channel;
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
if ((config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER || if ((config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) && config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER) &&
@ -359,7 +359,7 @@ int32_t PositionModule::runOnce()
} }
} }
} else if (config.position.position_broadcast_smart_enabled) { } else if (config.position.position_broadcast_smart_enabled) {
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position const meshtastic_NodeInfoLite *node2 = service->refreshLocalMeshNode(); // should guarantee there is now a position
if (hasValidPosition(node2)) { if (hasValidPosition(node2)) {
// The minimum time (in seconds) that would pass before we are able to send a new position packet. // The minimum time (in seconds) that would pass before we are able to send a new position packet.
@ -398,7 +398,7 @@ void PositionModule::sendLostAndFoundText()
p->decoded.payload.size = strlen(message); p->decoded.payload.size = strlen(message);
memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size); memcpy(p->decoded.payload.bytes, message, p->decoded.payload.size);
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
delete[] message; delete[] message;
} }
@ -437,7 +437,7 @@ struct SmartPosition PositionModule::getDistanceTraveledSinceLastSend(meshtastic
void PositionModule::handleNewPosition() void PositionModule::handleNewPosition()
{ {
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum()); meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
const meshtastic_NodeInfoLite *node2 = service.refreshLocalMeshNode(); // should guarantee there is now a position const meshtastic_NodeInfoLite *node2 = service->refreshLocalMeshNode(); // should guarantee there is now a position
// We limit our GPS broadcasts to a max rate // We limit our GPS broadcasts to a max rate
if (hasValidPosition(node2)) { if (hasValidPosition(node2)) {
auto smartPosition = getDistanceTraveledSinceLastSend(node->position); auto smartPosition = getDistanceTraveledSinceLastSend(node->position);

View File

@ -120,7 +120,7 @@ void RangeTestModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply p->decoded.payload.size = strlen(heartbeatString); // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, heartbeatString, p->decoded.payload.size); memcpy(p->decoded.payload.bytes, heartbeatString, p->decoded.payload.size);
service.sendToMesh(p); service->sendToMesh(p);
// TODO: Handle this better. We want to keep the phone awake otherwise it stops sending. // TODO: Handle this better. We want to keep the phone awake otherwise it stops sending.
powerFSM.trigger(EVENT_CONTACT_FROM_PHONE); powerFSM.trigger(EVENT_CONTACT_FROM_PHONE);

View File

@ -131,7 +131,7 @@ int32_t RemoteHardwareModule::runOnce()
r.type = meshtastic_HardwareMessage_Type_GPIOS_CHANGED; r.type = meshtastic_HardwareMessage_Type_GPIOS_CHANGED;
r.gpio_value = curVal; r.gpio_value = curVal;
meshtastic_MeshPacket *p = allocDataProtobuf(r); meshtastic_MeshPacket *p = allocDataProtobuf(r);
service.sendToMesh(p); service->sendToMesh(p);
} }
} }
} else { } else {

View File

@ -17,7 +17,7 @@ bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mesh
// Note: we are careful not to send back packets that started with the phone back to the phone // Note: we are careful not to send back packets that started with the phone back to the phone
if ((mp.to == NODENUM_BROADCAST || mp.to == nodeDB->getNodeNum()) && (mp.from != 0)) { if ((mp.to == NODENUM_BROADCAST || mp.to == nodeDB->getNodeNum()) && (mp.from != 0)) {
printPacket("Delivering rx packet", &mp); printPacket("Delivering rx packet", &mp);
service.handleFromRadio(&mp); service->handleFromRadio(&mp);
} }
return false; // Let others look at this message also if they want return false; // Let others look at this message also if they want

View File

@ -236,7 +236,7 @@ void SerialModule::sendTelemetry(meshtastic_Telemetry m)
p->to = NODENUM_BROADCAST; p->to = NODENUM_BROADCAST;
p->decoded.want_response = false; p->decoded.want_response = false;
p->priority = meshtastic_MeshPacket_Priority_RELIABLE; p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
} }
/** /**
@ -272,7 +272,7 @@ void SerialModuleRadio::sendPayload(NodeNum dest, bool wantReplies)
p->decoded.payload.size = serialPayloadSize; // You must specify how many bytes are in the reply p->decoded.payload.size = serialPayloadSize; // You must specify how many bytes are in the reply
memcpy(p->decoded.payload.bytes, serialBytes, p->decoded.payload.size); memcpy(p->decoded.payload.bytes, serialBytes, p->decoded.payload.size);
service.sendToMesh(p); service->sendToMesh(p);
} }
/** /**

View File

@ -54,7 +54,7 @@ int32_t AirQualityTelemetryModule::runOnce()
airTime->isTxAllowedAirUtil()) { airTime->isTxAllowedAirUtil()) {
sendTelemetry(); sendTelemetry();
lastSentToMesh = now; lastSentToMesh = now;
} else if (service.isToPhoneQueueEmpty()) { } else if (service->isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet // Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected) // Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true); sendTelemetry(NODENUM_BROADCAST, true);
@ -162,10 +162,10 @@ bool AirQualityTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
lastMeasurementPacket = packetPool.allocCopy(*p); lastMeasurementPacket = packetPool.allocCopy(*p);
if (phoneOnly) { if (phoneOnly) {
LOG_INFO("Sending packet to phone\n"); LOG_INFO("Sending packet to phone\n");
service.sendToPhone(p); service->sendToPhone(p);
} else { } else {
LOG_INFO("Sending packet to mesh\n"); LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
} }
return true; return true;
} }

View File

@ -25,7 +25,7 @@ int32_t DeviceTelemetryModule::runOnce()
config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) { config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) {
sendTelemetry(); sendTelemetry();
lastSentToMesh = uptimeLastMs; lastSentToMesh = uptimeLastMs;
} else if (service.isToPhoneQueueEmpty()) { } else if (service->isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet // Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected) // Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true); sendTelemetry(NODENUM_BROADCAST, true);
@ -113,10 +113,10 @@ bool DeviceTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
nodeDB->updateTelemetry(nodeDB->getNodeNum(), telemetry, RX_SRC_LOCAL); nodeDB->updateTelemetry(nodeDB->getNodeNum(), telemetry, RX_SRC_LOCAL);
if (phoneOnly) { if (phoneOnly) {
LOG_INFO("Sending packet to phone\n"); LOG_INFO("Sending packet to phone\n");
service.sendToPhone(p); service->sendToPhone(p);
} else { } else {
LOG_INFO("Sending packet to mesh\n"); LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
} }
return true; return true;
} }

View File

@ -161,7 +161,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
sendTelemetry(); sendTelemetry();
lastSentToMesh = now; lastSentToMesh = now;
} else if (((lastSentToPhone == 0) || ((now - lastSentToPhone) >= sendToPhoneIntervalMs)) && } else if (((lastSentToPhone == 0) || ((now - lastSentToPhone) >= sendToPhoneIntervalMs)) &&
(service.isToPhoneQueueEmpty())) { (service->isToPhoneQueueEmpty())) {
// Just send to phone when it's not our time to send to mesh yet // Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected) // Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true); sendTelemetry(NODENUM_BROADCAST, true);
@ -449,10 +449,10 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
lastMeasurementPacket = packetPool.allocCopy(*p); lastMeasurementPacket = packetPool.allocCopy(*p);
if (phoneOnly) { if (phoneOnly) {
LOG_INFO("Sending packet to phone\n"); LOG_INFO("Sending packet to phone\n");
service.sendToPhone(p); service->sendToPhone(p);
} else { } else {
LOG_INFO("Sending packet to mesh\n"); LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving) { if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving) {
LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n"); LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n");

View File

@ -78,7 +78,7 @@ int32_t PowerTelemetryModule::runOnce()
sendTelemetry(); sendTelemetry();
lastSentToMesh = now; lastSentToMesh = now;
} else if (((lastSentToPhone == 0) || ((now - lastSentToPhone) >= sendToPhoneIntervalMs)) && } else if (((lastSentToPhone == 0) || ((now - lastSentToPhone) >= sendToPhoneIntervalMs)) &&
(service.isToPhoneQueueEmpty())) { (service->isToPhoneQueueEmpty())) {
// Just send to phone when it's not our time to send to mesh yet // Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected) // Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true); sendTelemetry(NODENUM_BROADCAST, true);
@ -244,10 +244,10 @@ bool PowerTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
lastMeasurementPacket = packetPool.allocCopy(*p); lastMeasurementPacket = packetPool.allocCopy(*p);
if (phoneOnly) { if (phoneOnly) {
LOG_INFO("Sending packet to phone\n"); LOG_INFO("Sending packet to phone\n");
service.sendToPhone(p); service->sendToPhone(p);
} else { } else {
LOG_INFO("Sending packet to mesh\n"); LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving) { if (config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR && config.power.is_power_saving) {
LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n"); LOG_DEBUG("Starting next execution in 5 seconds and then going to sleep.\n");

View File

@ -266,7 +266,7 @@ void AudioModule::sendPayload(NodeNum dest, bool wantReplies)
p->decoded.payload.size = tx_encode_frame_index; p->decoded.payload.size = tx_encode_frame_index;
memcpy(p->decoded.payload.bytes, tx_encode_frame, p->decoded.payload.size); memcpy(p->decoded.payload.bytes, tx_encode_frame, p->decoded.payload.size);
service.sendToMesh(p); service->sendToMesh(p);
} }
ProcessMessage AudioModule::handleReceived(const meshtastic_MeshPacket &mp) ProcessMessage AudioModule::handleReceived(const meshtastic_MeshPacket &mp)

View File

@ -52,7 +52,7 @@ bool PaxcounterModule::sendInfo(NodeNum dest)
p->decoded.want_response = false; p->decoded.want_response = false;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND; p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
service.sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
paxcounterModule->reportedDataSent = true; paxcounterModule->reportedDataSent = true;

View File

@ -211,7 +211,7 @@ bool StoreForwardModule::sendPayload(NodeNum dest, uint32_t last_time)
meshtastic_MeshPacket *p = preparePayload(dest, last_time); meshtastic_MeshPacket *p = preparePayload(dest, last_time);
if (p) { if (p) {
LOG_INFO("*** Sending S&F Payload\n"); LOG_INFO("*** Sending S&F Payload\n");
service.sendToMesh(p); service->sendToMesh(p);
this->requestCount++; this->requestCount++;
return true; return true;
} }
@ -293,7 +293,7 @@ void StoreForwardModule::sendMessage(NodeNum dest, const meshtastic_StoreAndForw
p->want_ack = false; p->want_ack = false;
p->decoded.want_response = false; p->decoded.want_response = false;
service.sendToMesh(p); service->sendToMesh(p);
} }
/** /**
@ -336,7 +336,7 @@ void StoreForwardModule::sendErrorTextMessage(NodeNum dest, bool want_response)
if (want_response) { if (want_response) {
ignoreRequest = true; // This text message counts as response. ignoreRequest = true; // This text message counts as response.
} }
service.sendToMesh(pr); service->sendToMesh(pr);
} }
/** /**

View File

@ -83,7 +83,7 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length)
if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) { if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length()); memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
p->decoded.payload.size = jsonPayloadStr.length(); p->decoded.payload.size = jsonPayloadStr.length();
service.sendToMesh(p, RX_SRC_LOCAL); service->sendToMesh(p, RX_SRC_LOCAL);
} else { } else {
LOG_WARN("Received MQTT json payload too long, dropping\n"); LOG_WARN("Received MQTT json payload too long, dropping\n");
} }
@ -114,7 +114,7 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length)
p->decoded.payload.size = p->decoded.payload.size =
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes),
&meshtastic_Position_msg, &pos); // make the Data protobuf from position &meshtastic_Position_msg, &pos); // make the Data protobuf from position
service.sendToMesh(p, RX_SRC_LOCAL); service->sendToMesh(p, RX_SRC_LOCAL);
} else { } else {
LOG_DEBUG("JSON Ignoring downlink message with unsupported type.\n"); LOG_DEBUG("JSON Ignoring downlink message with unsupported type.\n");
} }
@ -245,7 +245,7 @@ bool MQTT::publish(const char *topic, const char *payload, bool retained)
strcpy(msg->topic, topic); strcpy(msg->topic, topic);
strcpy(msg->payload_variant.text, payload); strcpy(msg->payload_variant.text, payload);
msg->retained = retained; msg->retained = retained;
service.sendMqttMessageToClientProxy(msg); service->sendMqttMessageToClientProxy(msg);
return true; return true;
} }
#if HAS_NETWORKING #if HAS_NETWORKING
@ -265,7 +265,7 @@ bool MQTT::publish(const char *topic, const uint8_t *payload, size_t length, boo
msg->payload_variant.data.size = length; msg->payload_variant.data.size = length;
memcpy(msg->payload_variant.data.bytes, payload, length); memcpy(msg->payload_variant.data.bytes, payload, length);
msg->retained = retained; msg->retained = retained;
service.sendMqttMessageToClientProxy(msg); service->sendMqttMessageToClientProxy(msg);
return true; return true;
} }
#if HAS_NETWORKING #if HAS_NETWORKING

View File

@ -97,6 +97,7 @@ void portduinoSetup()
settingsStrings[webserverrootpath] = ""; settingsStrings[webserverrootpath] = "";
settingsStrings[spidev] = ""; settingsStrings[spidev] = "";
settingsStrings[displayspidev] = ""; settingsStrings[displayspidev] = "";
settingsMap[spiSpeed] = 2000000;
YAML::Node yamlConfig; YAML::Node yamlConfig;
@ -173,6 +174,7 @@ void portduinoSetup()
settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as<int>(RADIOLIB_NC); settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as<int>(RADIOLIB_NC);
settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0); settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
settingsMap[ch341Quirk] = yamlConfig["Lora"]["ch341_quirk"].as<bool>(false); settingsMap[ch341Quirk] = yamlConfig["Lora"]["ch341_quirk"].as<bool>(false);
settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
gpioChipName += std::to_string(settingsMap[gpiochip]); gpioChipName += std::to_string(settingsMap[gpiochip]);
settingsStrings[spidev] = "/dev/" + yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0"); settingsStrings[spidev] = "/dev/" + yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0");
@ -280,6 +282,7 @@ void portduinoSetup()
} }
settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as<int>(200); settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
} catch (YAML::Exception &e) { } catch (YAML::Exception &e) {
std::cout << "*** Exception " << e.what() << std::endl; std::cout << "*** Exception " << e.what() << std::endl;

View File

@ -19,6 +19,7 @@ enum configNames {
user, user,
gpiochip, gpiochip,
spidev, spidev,
spiSpeed,
i2cdev, i2cdev,
has_gps, has_gps,
touchscreenModule, touchscreenModule,
@ -51,6 +52,7 @@ enum configNames {
webserver, webserver,
webserverport, webserverport,
webserverrootpath, webserverrootpath,
maxtophone,
maxnodes maxnodes
}; };
enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d }; enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9488, hx8357d };

View File

@ -199,8 +199,8 @@ void SimRadio::startSend(meshtastic_MeshPacket *txp)
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_Compressed_msg, &c); pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_Compressed_msg, &c);
p->decoded.portnum = meshtastic_PortNum_SIMULATOR_APP; p->decoded.portnum = meshtastic_PortNum_SIMULATOR_APP;
service.sendQueueStatusToPhone(router->getQueueStatus(), 0, p->id); service->sendQueueStatusToPhone(router->getQueueStatus(), 0, p->id);
service.sendToPhone(p); // Sending back to simulator service->sendToPhone(p); // Sending back to simulator
} }
void SimRadio::startReceive(meshtastic_MeshPacket *p) void SimRadio::startReceive(meshtastic_MeshPacket *p)

View File

@ -126,8 +126,8 @@ No longer populated on PCB
#define LORA_CS (0 + 24) #define LORA_CS (0 + 24)
#define SX126X_DIO1 (0 + 20) #define SX126X_DIO1 (0 + 20)
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching // Note DIO2 is attached internally to the module to an analog switch for TX/RX switching
// #define SX1262_DIO3 \ // #define SX1262_DIO3 (0 + 21)
// (0 + 21) // This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the // This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the
// main // main
// CPU? // CPU?
#define SX126X_BUSY (0 + 17) #define SX126X_BUSY (0 + 17)

View File

@ -1,5 +1,6 @@
#define HAS_SCREEN 1 #define HAS_SCREEN 1
#define CANNED_MESSAGE_MODULE_ENABLE 1 #define CANNED_MESSAGE_MODULE_ENABLE 1
#define HAS_GPS 1 #define HAS_GPS 1
#define MAX_RX_TOPHONE settingsMap[maxtophone]
#define MAX_NUM_NODES settingsMap[maxnodes] #define MAX_NUM_NODES settingsMap[maxnodes]
#define RADIOLIB_GODMODE 1 #define RADIOLIB_GODMODE 1