Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/esp32/esp32.ini
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ build_flags =
-DLIBPAX_ARDUINO
-DLIBPAX_WIFI
-DLIBPAX_BLE
-DHAS_UDP_MULTICAST=1
;-DDEBUG_HEAP

lib_deps =
Expand Down
12 changes: 11 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ AccelerometerThread *accelerometerThread = nullptr;
AudioThread *audioThread = nullptr;
#endif

#ifdef HAS_UDP_MULTICAST
#include "mesh/udp/UdpMulticastThread.h"
UdpMulticastThread *udpThread = nullptr;
#endif

#if defined(TCXO_OPTIONAL)
float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; // if TCXO is optional, put this here so it can be changed further down.
#endif
Expand Down Expand Up @@ -783,6 +788,11 @@ void setup()
LOG_DEBUG("Start audio thread");
audioThread = new AudioThread();
#endif

#ifdef HAS_UDP_MULTICAST
LOG_DEBUG("Start multicast thread");
udpThread = new UdpMulticastThread();
#endif
service = new MeshService();
service->init();

Expand Down Expand Up @@ -1278,4 +1288,4 @@ void loop()
mainDelay.delay(delayMsec);
}
}
#endif
#endif
5 changes: 5 additions & 0 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ extern Adafruit_DRV2605 drv;
extern AudioThread *audioThread;
#endif

#ifdef HAS_UDP_MULTICAST
#include "mesh/udp/UdpMulticastThread.h"
extern UdpMulticastThread *udpThread;
#endif

// Global Screen singleton.
extern graphics::Screen *screen;

Expand Down
3 changes: 3 additions & 0 deletions src/mesh/NodeDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,9 @@ NodeDB::NodeDB()
resetRadioConfig(); // If bogus settings got saved, then fix them
// nodeDB->LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d", config.lora.region, myNodeInfo.my_node_num, numMeshNodes);

// Uncomment below to always enable UDP broadcasts
// config.network.enabled_protocols = meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST;

// If we are setup to broadcast on the default channel, ensure that the telemetry intervals are coerced to the minimum value
// of 30 minutes or more
if (channels.isDefaultChannel(channels.getPrimaryIndex())) {
Expand Down
5 changes: 5 additions & 0 deletions src/mesh/Router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,11 @@ ErrorCode Router::send(meshtastic_MeshPacket *p)
abortSendAndNak(encodeResult, p);
return encodeResult; // FIXME - this isn't a valid ErrorCode
}
#if HAS_UDP_MULTICAST
if (udpThread && config.network.enabled_protocols & meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST) {
udpThread->onSend(const_cast<meshtastic_MeshPacket *>(p));
}
#endif
#if !MESHTASTIC_EXCLUDE_MQTT
// Only publish to MQTT if we're the original transmitter of the packet
if (moduleConfig.mqtt.enabled && isFromUs(p) && mqtt) {
Expand Down
70 changes: 70 additions & 0 deletions src/mesh/udp/UdpMulticastThread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#pragma once
#if HAS_UDP_MULTICAST
#include "configuration.h"
#include "main.h"
#include "mesh/Router.h"

#include <AsyncUDP.h>
#include <WiFi.h>

#define UDP_MULTICAST_DEFAUL_PORT 4403 // Default port for UDP multicast is same as TCP api server
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UDP_MULTICAST_DEFAULT_PORT, maybe

#define UDP_MULTICAST_THREAD_INTERVAL_MS 15000

class UdpMulticastThread : public concurrency::OSThread
{
public:
UdpMulticastThread() : OSThread("UdpMulticast") { udpIpAddress = IPAddress(224, 0, 0, 69); }

void start()
{
if (udp.listenMulticast(udpIpAddress, UDP_MULTICAST_DEFAUL_PORT)) {
LOG_DEBUG("UDP Listening on IP: %s", WiFi.localIP().toString().c_str());
udp.onPacket([this](AsyncUDPPacket packet) { onReceive(packet); });
} else {
LOG_DEBUG("Failed to listen on UDP");
}
}

void onReceive(AsyncUDPPacket packet)
{
size_t packetLength = packet.length();
LOG_DEBUG("UDP broadcast from: %s, len=%u", packet.remoteIP().toString().c_str(), packetLength);
meshtastic_MeshPacket mp;
uint8_t bytes[meshtastic_MeshPacket_size]; // Allocate buffer for the data
size_t packetSize = packet.readBytes(bytes, packet.length());
LOG_DEBUG("Decoding MeshPacket from UDP len=%u", packetSize);
bool isPacketDecoded = pb_decode_from_bytes(bytes, packetLength, &meshtastic_MeshPacket_msg, &mp);
if (isPacketDecoded && router) {
UniquePacketPoolPacket p = packetPool.allocUniqueCopy(mp);
// Unset received SNR/RSSI
p->rx_snr = 0;
p->rx_rssi = 0;
router->enqueueReceivedMessage(p.release());
}
}

bool onSend(const meshtastic_MeshPacket *mp)
{
if (!mp || WiFi.status() != WL_CONNECTED) {
return false;
}
LOG_DEBUG("Broadcasting packet over UDP (id=%u)", mp->id);
uint8_t buffer[meshtastic_MeshPacket_size];
size_t encodedLength = pb_encode_to_bytes(buffer, sizeof(buffer), &meshtastic_MeshPacket_msg, mp);
udp.broadcastTo(buffer, encodedLength, UDP_MULTICAST_DEFAUL_PORT);
return true;
}

protected:
int32_t runOnce() override
{
canSleep = true;
// TODO: Implement nodeinfo broadcast
return UDP_MULTICAST_THREAD_INTERVAL_MS;
}

private:
IPAddress udpIpAddress;
AsyncUDP udp;
};
#endif // ARCH_ESP32
8 changes: 7 additions & 1 deletion src/mesh/wifi/WiFiAPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ static void onNetworkConnected()
APStartupComplete = true;
}

#if HAS_UDP_MULTICAST
if (udpThread) {
udpThread->start();
}
#endif

// FIXME this is kinda yucky, instead we should just have an observable for 'wifireconnected'
#ifndef MESHTASTIC_EXCLUDE_MQTT
if (mqtt)
Expand Down Expand Up @@ -437,4 +443,4 @@ uint8_t getWifiDisconnectReason()
{
return wifiDisconnectReason;
}
#endif
#endif
Loading