Skip to content

Commit

Permalink
Merge branch 'meshtastic:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Mictronics authored Feb 10, 2024
2 parents 5ec5b45 + 1085b54 commit abf75d9
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 33 deletions.
1 change: 1 addition & 0 deletions boards/t-echo.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "TTGO_eink",
Expand Down
2 changes: 1 addition & 1 deletion protobufs
22 changes: 17 additions & 5 deletions src/ButtonThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,18 @@ class ButtonThread : public concurrency::OSThread
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
userButton = OneButton(settingsMap[user], true, true);
#elif defined(BUTTON_PIN)

userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN;
userButton = OneButton(pin, true, true);
#endif

#ifdef INPUT_PULLUP_SENSE
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
pinMode(pin, INPUT_PULLUP_SENSE);
#endif
userButton.attachClick(userButtonPressed);
userButton.setClickMs(300);
userButton.setClickMs(400);
userButton.setPressMs(1000);
userButton.setDebounceMs(10);
userButton.attachDuringLongPress(userButtonPressedLong);
userButton.attachDoubleClick(userButtonDoublePressed);
userButton.attachMultiClick(userButtonMultiPressed);
Expand All @@ -72,7 +75,15 @@ class ButtonThread : public concurrency::OSThread
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
wakeOnIrq(settingsMap[user], FALLING);
#else
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
static OneButton *pBtn = &userButton; // only one instance of ButtonThread is created, so static is safe
attachInterrupt(
pin,
[]() {
BaseType_t higherWake = 0;
mainDelay.interruptFromISR(&higherWake);
pBtn->tick();
},
CHANGE);
#endif
#endif
#ifdef BUTTON_PIN_ALT
Expand Down Expand Up @@ -194,6 +205,7 @@ class ButtonThread : public concurrency::OSThread
{
if (!config.device.disable_triple_click && (gps != nullptr)) {
gps->toggleGpsMode();
screen->forceDisplay();
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/mesh/MeshModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ meshtastic_MeshPacket *MeshModule::allocErrorResponse(meshtastic_Routing_Error e
return r;
}

void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src)
void MeshModule::callPlugins(meshtastic_MeshPacket &mp, RxSource src)
{
// LOG_DEBUG("In call modules\n");
bool moduleFound = false;
Expand Down Expand Up @@ -124,9 +124,10 @@ void MeshModule::callPlugins(const meshtastic_MeshPacket &mp, RxSource src)
} else
printPacket("packet on wrong channel, but can't respond", &mp);
} else {

ProcessMessage handled = pi.handleReceived(mp);

pi.alterReceived(mp);

// Possibly send replies (but only if the message was directed to us specifically, i.e. not for promiscious
// sniffing) also: we only let the one module send a reply, once that happens, remaining modules are not
// considered
Expand Down
27 changes: 10 additions & 17 deletions src/mesh/MeshModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,15 @@ class MeshModule

/** For use only by MeshService
*/
static void callPlugins(const meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);
static void callPlugins(meshtastic_MeshPacket &mp, RxSource src = RX_SRC_RADIO);

static std::vector<MeshModule *> GetMeshModulesWithUIFrames();
static void observeUIEvents(Observer<const UIFrameEvent *> *observer);
static AdminMessageHandleResult handleAdminMessageForAllPlugins(const meshtastic_MeshPacket &mp,
meshtastic_AdminMessage *request,
meshtastic_AdminMessage *response);
#if HAS_SCREEN
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
return;
}
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { return; }
#endif
protected:
const char *name;
Expand Down Expand Up @@ -135,10 +132,12 @@ class MeshModule
@return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered for
it
*/
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp)
{
return ProcessMessage::CONTINUE;
}
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) { return ProcessMessage::CONTINUE; }

/** Called to change a particular incoming message
This allows the module to change the message before it is passed through the rest of the call-chain.
*/
virtual void alterReceived(meshtastic_MeshPacket &mp) {}

/** Messages can be received that have the want_response bit set. If set, this callback will be invoked
* so that subclasses can (optionally) send a response back to the original sender.
Expand All @@ -151,14 +150,8 @@ class MeshModule
/***
* @return true if you want to be alloced a UI screen frame
*/
virtual bool wantUIFrame()
{
return false;
}
virtual Observable<const UIFrameEvent *> *getUIFrameObservable()
{
return NULL;
}
virtual bool wantUIFrame() { return false; }
virtual Observable<const UIFrameEvent *> *getUIFrameObservable() { return NULL; }

meshtastic_MeshPacket *allocAckNak(meshtastic_Routing_Error err, NodeNum to, PacketId idFrom, ChannelIndex chIndex);

Expand Down
26 changes: 26 additions & 0 deletions src/mesh/ProtobufModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ template <class T> class ProtobufModule : protected SinglePortModule
*/
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, T *decoded) = 0;

/** Called to make changes to a particular incoming message
*/
virtual void alterReceivedProtobuf(meshtastic_MeshPacket &mp, T *decoded){};

/**
* 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
Expand Down Expand Up @@ -86,4 +90,26 @@ template <class T> class ProtobufModule : protected SinglePortModule

return handleReceivedProtobuf(mp, decoded) ? ProcessMessage::STOP : ProcessMessage::CONTINUE;
}

/** Called to alter a particular incoming message
*/
virtual void alterReceived(meshtastic_MeshPacket &mp) override
{
auto &p = mp.decoded;

T scratch;
T *decoded = NULL;
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.decoded.portnum == ourPortNum) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(p.payload.bytes, p.payload.size, fields, &scratch)) {
decoded = &scratch;
} else {
LOG_ERROR("Error decoding protobuf module!\n");
// if we can't decode it, nobody can process it!
return;
}
}

return alterReceivedProtobuf(mp, decoded);
}
};
7 changes: 7 additions & 0 deletions src/mesh/RadioInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ const RegionInfo regions[] = {
*/
RDEF(MY_919, 919.0f, 924.0f, 100, 0, 27, true, true, false),

/*
Singapore
SG_923 Band 30d: 917 - 925 MHz at 100mW, no restrictions.
https://www.imda.gov.sg/-/media/imda/files/regulation-licensing-and-consultations/ict-standards/telecommunication-standards/radio-comms/imdatssrd.pdf
*/
RDEF(SG_923, 917.0f, 925.0f, 100, 0, 20, true, false, false),

/*
2.4 GHZ WLAN Band equivalent. Only for SX128x chips.
*/
Expand Down
12 changes: 8 additions & 4 deletions src/mesh/ReliableRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,14 @@ bool ReliableRouter::stopRetransmission(GlobalPacketId key)
auto p = old->packet;
auto numErased = pending.erase(key);
assert(numErased == 1);
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
cancelSending(getFrom(p), p->id);
// now free the pooled copy for retransmission too
packetPool.release(p);
/* Only when we already transmitted a packet via LoRa, we will cancel the packet in the Tx queue
to avoid canceling a transmission if it was ACKed super fast via MQTT */
if (old->numRetransmissions < NUM_RETRANSMISSIONS - 1) {
// remove the 'original' (identified by originator and packet->id) from the txqueue and free it
cancelSending(getFrom(p), p->id);
// now free the pooled copy for retransmission too
packetPool.release(p);
}
return true;
} else
return false;
Expand Down
8 changes: 5 additions & 3 deletions src/mesh/generated/meshtastic/config.pb.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,9 @@ typedef enum _meshtastic_Config_LoRaConfig_RegionCode {
/* Malaysia 433mhz */
meshtastic_Config_LoRaConfig_RegionCode_MY_433 = 16,
/* Malaysia 919mhz */
meshtastic_Config_LoRaConfig_RegionCode_MY_919 = 17
meshtastic_Config_LoRaConfig_RegionCode_MY_919 = 17,
/* Singapore 923mhz */
meshtastic_Config_LoRaConfig_RegionCode_SG_923 = 18
} meshtastic_Config_LoRaConfig_RegionCode;

/* Standard predefined channel settings
Expand Down Expand Up @@ -543,8 +545,8 @@ extern "C" {
#define _meshtastic_Config_DisplayConfig_DisplayMode_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayMode)(meshtastic_Config_DisplayConfig_DisplayMode_COLOR+1))

#define _meshtastic_Config_LoRaConfig_RegionCode_MIN meshtastic_Config_LoRaConfig_RegionCode_UNSET
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_MY_919
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_MY_919+1))
#define _meshtastic_Config_LoRaConfig_RegionCode_MAX meshtastic_Config_LoRaConfig_RegionCode_SG_923
#define _meshtastic_Config_LoRaConfig_RegionCode_ARRAYSIZE ((meshtastic_Config_LoRaConfig_RegionCode)(meshtastic_Config_LoRaConfig_RegionCode_SG_923+1))

#define _meshtastic_Config_LoRaConfig_ModemPreset_MIN meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST
#define _meshtastic_Config_LoRaConfig_ModemPreset_MAX meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE
Expand Down
128 changes: 128 additions & 0 deletions src/modules/AtakPluginModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "AtakPluginModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "configuration.h"
#include "main.h"
#include "meshtastic/atak.pb.h"

extern "C" {
#include "mesh/compression/unishox2.h"
}

AtakPluginModule *atakPluginModule;

AtakPluginModule::AtakPluginModule()
: ProtobufModule("atak", meshtastic_PortNum_ATAK_PLUGIN, &meshtastic_TAKPacket_msg), concurrency::OSThread("AtakPluginModule")
{
ourPortNum = meshtastic_PortNum_ATAK_PLUGIN;
}

/*
Encompasses the full construction and sending packet to mesh
Will be used for broadcast.
*/
int32_t AtakPluginModule::runOnce()
{
return default_broadcast_interval_secs;
}

bool AtakPluginModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_TAKPacket *r)
{
return false;
}

meshtastic_TAKPacket AtakPluginModule::cloneTAKPacketData(meshtastic_TAKPacket *t)
{
meshtastic_TAKPacket clone = meshtastic_TAKPacket_init_zero;
if (t->has_group) {
clone.has_group = true;
clone.group = t->group;
}
if (t->has_status) {
clone.has_status = true;
clone.status = t->status;
}
if (t->has_contact) {
clone.has_contact = true;
clone.contact = {0};
}

if (t->which_payload_variant == meshtastic_TAKPacket_pli_tag) {
clone.which_payload_variant = meshtastic_TAKPacket_pli_tag;
clone.payload_variant.pli = t->payload_variant.pli;
} else if (t->which_payload_variant == meshtastic_TAKPacket_chat_tag) {
clone.which_payload_variant = meshtastic_TAKPacket_chat_tag;
clone.payload_variant.chat = {0};
}

return clone;
}

void AtakPluginModule::alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_TAKPacket *t)
{
// From Phone (EUD)
if (mp.from == 0) {
LOG_DEBUG("Received uncompressed TAK payload from phone with %d bytes\n", mp.decoded.payload.size);
// Compress for LoRA transport
auto compressed = cloneTAKPacketData(t);
compressed.is_compressed = true;
if (t->has_contact) {
auto length = unishox2_compress_simple(t->contact.callsign, strlen(t->contact.callsign), compressed.contact.callsign);
LOG_DEBUG("Uncompressed callsign '%s' - %d bytes\n", t->contact.callsign, strlen(t->contact.callsign));
LOG_DEBUG("Compressed callsign '%s' - %d bytes\n", t->contact.callsign, length);

length = unishox2_compress_simple(t->contact.device_callsign, strlen(t->contact.device_callsign),
compressed.contact.device_callsign);
LOG_DEBUG("Uncompressed device_callsign '%s' - %d bytes\n", t->contact.device_callsign,
strlen(t->contact.device_callsign));
LOG_DEBUG("Compressed device_callsign '%s' - %d bytes\n", compressed.contact.device_callsign, length);
}
if (t->which_payload_variant == meshtastic_TAKPacket_chat_tag) {
auto length = unishox2_compress_simple(t->payload_variant.chat.message, strlen(t->payload_variant.chat.message),
compressed.payload_variant.chat.message);
LOG_DEBUG("Uncompressed chat message '%s' - %d bytes\n", t->payload_variant.chat.message,
strlen(t->payload_variant.chat.message));
LOG_DEBUG("Compressed chat message '%s' - %d bytes\n", compressed.payload_variant.chat.message, length);
}
mp.decoded.payload.size = pb_encode_to_bytes(mp.decoded.payload.bytes, sizeof(mp.decoded.payload.bytes),
meshtastic_TAKPacket_fields, &compressed);
LOG_DEBUG("Final payload size of %d bytes\n", mp.decoded.payload.size);
} else {
if (!t->is_compressed) {
// Not compressed. Something is wrong
LOG_ERROR("Received uncompressed TAKPacket over radio!\n");
return;
}

// Decompress for Phone (EUD)
auto decompressedCopy = packetPool.allocCopy(mp);
auto uncompressed = cloneTAKPacketData(t);
uncompressed.is_compressed = false;
if (t->has_contact) {
auto length =
unishox2_decompress_simple(t->contact.callsign, strlen(t->contact.callsign), uncompressed.contact.callsign);

LOG_DEBUG("Compressed callsign: %d bytes\n", strlen(t->contact.callsign));
LOG_DEBUG("Decompressed callsign: '%s' @ %d bytes\n", uncompressed.contact.callsign, length);

length = unishox2_decompress_simple(t->contact.device_callsign, strlen(t->contact.device_callsign),
uncompressed.contact.device_callsign);

LOG_DEBUG("Compressed device_callsign: %d bytes\n", strlen(t->contact.device_callsign));
LOG_DEBUG("Decompressed device_callsign: '%s' @ %d bytes\n", uncompressed.contact.device_callsign, length);
}
if (uncompressed.which_payload_variant == meshtastic_TAKPacket_chat_tag) {
auto length = unishox2_decompress_simple(t->payload_variant.chat.message, strlen(t->payload_variant.chat.message),
uncompressed.payload_variant.chat.message);
LOG_DEBUG("Compressed chat message: %d bytes\n", strlen(t->payload_variant.chat.message));
LOG_DEBUG("Decompressed chat message: '%s' @ %d bytes\n", uncompressed.payload_variant.chat.message, length);
}
decompressedCopy->decoded.payload.size =
pb_encode_to_bytes(decompressedCopy->decoded.payload.bytes, sizeof(decompressedCopy->decoded.payload),
meshtastic_TAKPacket_fields, &uncompressed);

service.sendToPhone(decompressedCopy);
}
return;
}
26 changes: 26 additions & 0 deletions src/modules/AtakPluginModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once
#include "ProtobufModule.h"
#include "meshtastic/atak.pb.h"

/**
* Waypoint message handling for meshtastic
*/
class AtakPluginModule : public ProtobufModule<meshtastic_TAKPacket>, private concurrency::OSThread
{
public:
/** Constructor
* name is for debugging output
*/
AtakPluginModule();

protected:
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_TAKPacket *t) override;
virtual void alterReceivedProtobuf(meshtastic_MeshPacket &mp, meshtastic_TAKPacket *t) override;
/* Does our periodic broadcast */
int32_t runOnce() override;

private:
meshtastic_TAKPacket cloneTAKPacketData(meshtastic_TAKPacket *t);
};

extern AtakPluginModule *atakPluginModule;
Loading

0 comments on commit abf75d9

Please sign in to comment.