Merge branch 'master' into t-watch-fixes

pull/2694/head
Manuel 2023-08-08 18:21:57 +02:00 zatwierdzone przez GitHub
commit 9a7777dbdb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
38 zmienionych plików z 909 dodań i 293 usunięć

Wyświetl plik

@ -95,6 +95,7 @@ jobs:
- board: tlora-t3s3-v1
- board: t-watch-s3
- board: t-deck
- board: picomputer-s3
uses: ./.github/workflows/build_esp32_s3.yml
with:
board: ${{ matrix.board }}

Wyświetl plik

@ -1,6 +1,6 @@
version: 0.1
cli:
version: 1.9.1
version: 1.10.0
plugins:
sources:
- id: trunk
@ -10,7 +10,7 @@ lint:
enabled:
- taplo@0.7.0
- ruff@0.0.265
- yamllint@1.31.0
- yamllint@1.32.0
- isort@5.12.0
- markdownlint@0.34.0
- oxipng@8.0.0

Wyświetl plik

@ -28,8 +28,6 @@
"flash_size": "8MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 921600
},

@ -1 +1 @@
Subproject commit c5fa71fbb68b8d4044cb6a6d72f06257ac29dd9c
Subproject commit d47300965904a8d55d109327568e19a2eb9a12c0

Wyświetl plik

@ -108,10 +108,12 @@ class LGFX : public lgfx::LGFX_Device
lgfx::Panel_ST7789 _panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
#if HAS_TOUCHSCREEN
#ifdef T_WATCH_S3
lgfx::Touch_FT5x06 _touch_instance;
#else
lgfx::Touch_GT911 _touch_instance;
#endif
#endif
public:
@ -126,13 +128,14 @@ class LGFX : public lgfx::LGFX_Device
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number
cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number
cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = ST7789_RS; // Set SPI DC pin number (-1 = disable)
cfg.spi_3wire = false;
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number
cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number
cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = ST7789_RS; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(cfg); // applies the set value to the bus.
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
@ -181,6 +184,7 @@ class LGFX : public lgfx::LGFX_Device
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
}
#if HAS_TOUCHSCREEN
// Configure settings for touch screen control.
{
auto cfg = _touch_instance.config();
@ -210,6 +214,7 @@ class LGFX : public lgfx::LGFX_Device
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
#endif
setPanel(&_panel_instance); // Sets the panel to use.
}
@ -434,7 +439,7 @@ bool TFTDisplay::connect()
tft.init();
#if defined(M5STACK)
tft.setRotation(0);
#elif defined(T_DECK)
#elif defined(T_DECK) || defined(PICOMPUTER_S3)
tft.setRotation(1); // T-Deck has the TFT in landscape
#elif defined(T_WATCH_S3)
tft.setRotation(2); // T-Watch S3 left-handed orientation

Wyświetl plik

@ -28,17 +28,6 @@ uint8_t read_from_14004(TwoWire *i2cBus, uint8_t reg, uint8_t *data, uint8_t len
return readflag;
}
// Unused for now - flagging it off
#if 0
void write_to_14004(const TwoWire * i2cBus, uint8_t reg, uint8_t data)
{
i2cBus->beginTransmission(CARDKB_ADDR);
i2cBus->write(reg);
i2cBus->write(data);
i2cBus->endTransmission(); // stop transmitting
}
#endif
int32_t KbI2cBase::runOnce()
{
if (cardkb_found.address != CARDKB_ADDR && cardkb_found.address != TDECK_KB_ADDR) {

Wyświetl plik

@ -0,0 +1,131 @@
#include "kbMatrixBase.h"
#include "configuration.h"
#ifdef INPUTBROKER_MATRIX_TYPE
const byte keys_cols[] = KEYS_COLS;
const byte keys_rows[] = KEYS_ROWS;
#if INPUTBROKER_MATRIX_TYPE == 1
unsigned char KeyMap[3][sizeof(keys_rows)][sizeof(keys_cols)] = {{{' ', '.', 'm', 'n', 'b', 0xb6},
{0x0d, 'l', 'k', 'j', 'h', 0xb4},
{'p', 'o', 'i', 'u', 'y', 0xb5},
{0x08, 'z', 'x', 'c', 'v', 0xb7},
{'a', 's', 'd', 'f', 'g', 0x09},
{'q', 'w', 'e', 'r', 't', 0x1a}},
{// SHIFT
{':', ';', 'M', 'N', 'B', 0xb6},
{0x0d, 'L', 'K', 'J', 'H', 0xb4},
{'P', 'O', 'I', 'U', 'Y', 0xb5},
{0x08, 'Z', 'X', 'C', 'V', 0xb7},
{'A', 'S', 'D', 'F', 'G', 0x09},
{'Q', 'W', 'E', 'R', 'T', 0x1a}},
{// SHIFT-SHIFT
{'_', ',', '>', '<', '"', '{'},
{'~', '-', '*', '&', '+', '['},
{'0', '9', '8', '7', '6', '}'},
{'=', '(', ')', '?', '/', ']'},
{'!', '@', '#', '$', '%', '\\'},
{'1', '2', '3', '4', '5', 0x1a}}};
#endif
KbMatrixBase::KbMatrixBase(const char *name) : concurrency::OSThread(name)
{
this->_originName = name;
}
int32_t KbMatrixBase::runOnce()
{
if (!INPUTBROKER_MATRIX_TYPE) {
// Input device is not requested.
return disable();
}
if (firstTime) {
// This is the first time the OSThread library has called this function, so do port setup
firstTime = 0;
for (byte i = 0; i < sizeof(keys_rows); i++) {
pinMode(keys_rows[i], OUTPUT);
digitalWrite(keys_rows[i], HIGH);
}
for (byte i = 0; i < sizeof(keys_cols); i++) {
pinMode(keys_cols[i], INPUT_PULLUP);
}
}
key = 0;
if (INPUTBROKER_MATRIX_TYPE == 1) {
// scan for keypresses
for (byte i = 0; i < sizeof(keys_rows); i++) {
digitalWrite(keys_rows[i], LOW);
for (byte j = 0; j < sizeof(keys_cols); j++) {
if (digitalRead(keys_cols[j]) == LOW) {
key = KeyMap[shift][i][j];
}
}
digitalWrite(keys_rows[i], HIGH);
}
// debounce
if (key != prevkey) {
if (key != 0) {
LOG_DEBUG("Key 0x%x pressed\n", key);
// reset shift now that we have a keypress
InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
e.source = this->_originName;
switch (key) {
case 0x1b: // ESC
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL;
break;
case 0x08: // Back
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK;
e.kbchar = key;
break;
case 0xb5: // Up
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP;
break;
case 0xb6: // Down
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN;
break;
case 0xb4: // Left
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT;
e.kbchar = key;
break;
case 0xb7: // Right
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT;
e.kbchar = key;
break;
case 0x0d: // Enter
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT;
break;
case 0x00: // nopress
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break;
case 0x1a: // Shift
shift++;
if (shift > 2) {
shift = 0;
}
break;
default: // all other keys
e.inputEvent = ANYKEY;
e.kbchar = key;
break;
}
if (e.inputEvent != meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE) {
this->notifyObservers(&e);
}
}
prevkey = key;
}
} else {
LOG_WARN("Unknown kb_model 0x%02x\n", INPUTBROKER_MATRIX_TYPE);
return disable();
}
return 50; // Keyscan every 50msec to avoid key bounce
}
#endif // INPUTBROKER_MATRIX_TYPE

Wyświetl plik

@ -0,0 +1,20 @@
#pragma once
#include "InputBroker.h"
#include "concurrency/OSThread.h"
class KbMatrixBase : public Observable<const InputEvent *>, public concurrency::OSThread
{
public:
explicit KbMatrixBase(const char *name);
protected:
virtual int32_t runOnce() override;
private:
const char *_originName;
bool firstTime = 1;
int shift = 0;
char key = 0;
char prevkey = 0;
};

Wyświetl plik

@ -0,0 +1,20 @@
#include "kbMatrixImpl.h"
#include "InputBroker.h"
#ifdef INPUTBROKER_MATRIX_TYPE
KbMatrixImpl *kbMatrixImpl;
KbMatrixImpl::KbMatrixImpl() : KbMatrixBase("matrixKB") {}
void KbMatrixImpl::init()
{
if (!INPUTBROKER_MATRIX_TYPE) {
disable();
return;
}
inputBroker->registerSource(this);
}
#endif // INPUTBROKER_MATRIX_TYPE

Wyświetl plik

@ -0,0 +1,19 @@
#pragma once
#include "kbMatrixBase.h"
#include "main.h"
/**
* @brief The idea behind this class to have static methods for the event handlers.
* Check attachInterrupt() at RotaryEncoderInteruptBase.cpp
* Technically you can have as many rotary encoders hardver attached
* to your device as you wish, but you always need to have separate event
* handlers, thus you need to have a RotaryEncoderInterrupt implementation.
*/
class KbMatrixImpl : public KbMatrixBase
{
public:
KbMatrixImpl();
void init();
};
extern KbMatrixImpl *kbMatrixImpl;

Wyświetl plik

@ -480,7 +480,7 @@ void setup()
#endif
// We do this as early as possible because this loads preferences from flash
// but we need to do this after main cpu iniot (esp32setup), because we need the random seed set
// but we need to do this after main cpu init (esp32setup), because we need the random seed set
nodeDB.init();
// If we're taking on the repeater role, use flood router
@ -545,6 +545,7 @@ void setup()
#else
// ESP32
SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
LOG_WARN("SPI.begin(SCK=%d, MISO=%d, MOSI=%d, NSS=%d)\n", RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS);
SPI.setFrequency(4000000);
#endif

Wyświetl plik

@ -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 (config.device.role != meshtastic_Config_DeviceConfig_Role_ROUTER &&
if (!moduleConfig.mqtt.enabled && 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!
@ -49,10 +49,13 @@ void FloodingRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtas
tosend->hop_limit--; // bump down the hop count
// If it is a traceRoute request, update the route that it went via me
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag && traceRouteModule &&
traceRouteModule->wantPacket(p)) {
traceRouteModule->updateRoute(tosend);
if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
// If it is a traceRoute request, update the route that it went via me
if (traceRouteModule && traceRouteModule->wantPacket(p))
traceRouteModule->updateRoute(tosend);
// If it is a neighborInfo packet, update last_sent_by_id
if (neighborInfoModule && neighborInfoModule->wantPacket(p))
neighborInfoModule->updateLastSentById(tosend);
}
LOG_INFO("Rebroadcasting received floodmsg to neighbors\n");

Wyświetl plik

@ -2,6 +2,7 @@
#include "PacketHistory.h"
#include "Router.h"
#include "modules/NeighborInfoModule.h"
#include "modules/TraceRouteModule.h"
/**
@ -57,4 +58,4 @@ class FloodingRouter : public Router, protected PacketHistory
* Look for broadcasts we need to rebroadcast
*/
virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override;
};
};

Wyświetl plik

@ -15,6 +15,7 @@
#include "error.h"
#include "main.h"
#include "mesh-pb-constants.h"
#include "modules/NeighborInfoModule.h"
#include <ErriezCRC32.h>
#include <pb_decode.h>
#include <pb_encode.h>
@ -63,11 +64,7 @@ uint32_t error_address = 0;
static uint8_t ourMacAddr[6];
NodeDB::NodeDB()
: nodes(devicestate.node_db), numNodes(&devicestate.node_db_count), meshNodes(devicestate.node_db_lite),
numMeshNodes(&devicestate.node_db_lite_count)
{
}
NodeDB::NodeDB() : meshNodes(devicestate.node_db_lite), numMeshNodes(&devicestate.node_db_lite_count) {}
/**
* Most (but not always) of the time we want to treat packets 'from' the local phone (where from == 0), as if they originated on
@ -248,6 +245,9 @@ void NodeDB::installDefaultModuleConfig()
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username));
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password));
moduleConfig.has_neighbor_info = true;
moduleConfig.neighbor_info.enabled = false;
initModuleConfigIntervals();
}
@ -271,6 +271,7 @@ void NodeDB::initModuleConfigIntervals()
moduleConfig.telemetry.device_update_interval = default_broadcast_interval_secs;
moduleConfig.telemetry.environment_update_interval = default_broadcast_interval_secs;
moduleConfig.telemetry.air_quality_interval = default_broadcast_interval_secs;
moduleConfig.neighbor_info.update_interval = default_broadcast_interval_secs;
}
void NodeDB::installDefaultChannels()
@ -282,12 +283,11 @@ void NodeDB::installDefaultChannels()
void NodeDB::resetNodes()
{
devicestate.node_db_count = 0;
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
devicestate.node_db_lite_count = 0;
memset(devicestate.node_db_lite, 0, sizeof(devicestate.node_db_lite));
saveDeviceStateToDisk();
if (neighborInfoModule && moduleConfig.neighbor_info.enabled)
neighborInfoModule->resetNeighbors();
}
void NodeDB::installDefaultDeviceState()
@ -295,12 +295,11 @@ void NodeDB::installDefaultDeviceState()
LOG_INFO("Installing default DeviceState\n");
memset(&devicestate, 0, sizeof(meshtastic_DeviceState));
*numNodes = 0;
*numMeshNodes = 0;
// init our devicestate with valid flags so protobuf writing/reading will work
devicestate.has_my_node = true;
devicestate.has_owner = true;
devicestate.node_db_count = 0;
devicestate.node_db_lite_count = 0;
devicestate.version = DEVICESTATE_CUR_VER;
devicestate.receive_queue_count = 0; // Not yet implemented FIXME
@ -328,11 +327,9 @@ void NodeDB::init()
int saveWhat = 0;
// likewise - we always want the app requirements to come from the running appload
myNodeInfo.min_app_version = 20300; // format is Mmmss (where M is 1+the numeric major number. i.e. 20120 means 1.1.20
myNodeInfo.max_channels = MAX_NUM_CHANNELS; // tell others the max # of channels we can understand
myNodeInfo.min_app_version = 30200; // format is Mmmss (where M is 1+the numeric major number. i.e. 30200 means 2.2.00
// Note! We do this after loading saved settings, so that if somehow an invalid nodenum was stored in preferences we won't
// keep using that nodenum forever. Crummy guess at our nodenum (but we will check against the nodedb to avoid conflicts)
strncpy(myNodeInfo.firmware_version, optstr(APP_VERSION), sizeof(myNodeInfo.firmware_version));
pickNewNodeNum();
// Set our board type so we can share it with others
@ -343,19 +340,6 @@ void NodeDB::init()
info->user = owner;
info->has_user = true;
if (*numNodes > 0) {
LOG_DEBUG("Legacy NodeDB detected... Migrating to NodeDBLite\n");
uint32_t readIndex = 0;
const meshtastic_NodeInfo *oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
while (oldNodeInfo != NULL) {
migrateToNodeInfoLite(oldNodeInfo);
oldNodeInfo = nodeDB.readNextNodeInfo(readIndex);
}
LOG_DEBUG("Migration complete! Clearing out legacy NodeDB...\n");
devicestate.node_db_count = 0;
memset(devicestate.node_db, 0, sizeof(devicestate.node_db));
}
#ifdef ARCH_ESP32
Preferences preferences;
preferences.begin("meshtastic", false);
@ -365,7 +349,7 @@ void NodeDB::init()
#endif
resetRadioConfig(); // If bogus settings got saved, then fix them
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numMeshNodes);
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
saveWhat |= SEGMENT_DEVICESTATE;
@ -611,14 +595,6 @@ void NodeDB::saveToDisk(int saveWhat)
}
}
const meshtastic_NodeInfo *NodeDB::readNextNodeInfo(uint32_t &readIndex)
{
if (readIndex < *numNodes)
return &nodes[readIndex++];
else
return NULL;
}
const meshtastic_NodeInfoLite *NodeDB::readNextMeshNode(uint32_t &readIndex)
{
if (readIndex < *numMeshNodes)
@ -796,17 +772,6 @@ uint8_t NodeDB::getMeshNodeChannel(NodeNum n)
return info->channel;
}
/// Find a node in our DB, return null for missing
/// NOTE: This function might be called from an ISR
meshtastic_NodeInfo *NodeDB::getNodeInfo(NodeNum n)
{
for (int i = 0; i < *numNodes; i++)
if (nodes[i].num == n)
return &nodes[i];
return NULL;
}
/// Find a node in our DB, return null for missing
/// NOTE: This function might be called from an ISR
meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n)
@ -852,57 +817,6 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
return lite;
}
void NodeDB::migrateToNodeInfoLite(const meshtastic_NodeInfo *node)
{
meshtastic_NodeInfoLite *lite = getMeshNode(node->num);
if (!lite) {
if ((*numMeshNodes >= MAX_NUM_NODES) || (memGet.getFreeHeap() < meshtastic_NodeInfoLite_size * 3)) {
screen->print("warning: node_db_lite full! erasing oldest entry\n");
// look for oldest node and erase it
uint32_t oldest = UINT32_MAX;
int oldestIndex = -1;
for (int i = 0; i < *numMeshNodes; i++) {
if (meshNodes[i].last_heard < oldest) {
oldest = meshNodes[i].last_heard;
oldestIndex = i;
}
}
// Shove the remaining nodes down the chain
for (int i = oldestIndex; i < *numMeshNodes - 1; i++) {
meshNodes[i] = meshNodes[i + 1];
}
(*numMeshNodes)--;
}
// add the node at the end
lite = &meshNodes[(*numMeshNodes)++];
// everything is missing except the nodenum
memset(lite, 0, sizeof(*lite));
lite->num = node->num;
lite->snr = node->snr;
lite->last_heard = node->last_heard;
lite->channel = node->channel;
if (node->has_position) {
lite->has_position = true;
lite->position.latitude_i = node->position.latitude_i;
lite->position.longitude_i = node->position.longitude_i;
lite->position.altitude = node->position.altitude;
lite->position.location_source = node->position.location_source;
lite->position.time = node->position.time;
}
if (node->has_user) {
lite->has_user = true;
lite->user = node->user;
}
if (node->has_device_metrics) {
lite->has_device_metrics = true;
lite->device_metrics = node->device_metrics;
}
}
}
/// Record an error that should be reported via analytics
void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename)
{

Wyświetl plik

@ -19,7 +19,7 @@ DeviceState versions used to be defined in the .proto file but really only this
#define SEGMENT_DEVICESTATE 4
#define SEGMENT_CHANNELS 8
#define DEVICESTATE_CUR_VER 20
#define DEVICESTATE_CUR_VER 22
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
extern meshtastic_DeviceState devicestate;
@ -45,9 +45,6 @@ class NodeDB
// Eventually use a smarter datastructure
// HashMap<NodeNum, NodeInfo> nodes;
// Note: these two references just point into our static array we serialize to/from disk
meshtastic_NodeInfo *nodes;
pb_size_t *numNodes;
meshtastic_NodeInfoLite *meshNodes;
pb_size_t *numMeshNodes;
@ -137,18 +134,6 @@ class NodeDB
private:
/// Find a node in our DB, create an empty NodeInfoLite if missing
meshtastic_NodeInfoLite *getOrCreateMeshNode(NodeNum n);
void migrateToNodeInfoLite(const meshtastic_NodeInfo *node);
/// Find a node in our DB, return null for missing
meshtastic_NodeInfo *getNodeInfo(NodeNum n);
/// Allow the bluetooth layer to read our next nodeinfo record, or NULL if done reading
const meshtastic_NodeInfo *readNextNodeInfo(uint32_t &readIndex);
size_t getNumNodes() { return *numNodes; }
meshtastic_NodeInfo *getNodeByIndex(size_t x)
{
assert(x < *numNodes);
return &nodes[x];
}
/// Notify observers of changes to the DB
void notifyObservers(bool forceUpdate = false)
@ -226,10 +211,6 @@ inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t d
/// Sometimes we will have Position objects that only have a time, so check for
/// valid lat/lon
static inline bool hasValidPosition(const meshtastic_NodeInfo *n)
{
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);
}
static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n)
{
return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0);

Wyświetl plik

@ -279,6 +279,10 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
fromRadioScratch.moduleConfig.payload_variant.remote_hardware = moduleConfig.remote_hardware;
break;
case meshtastic_ModuleConfig_neighbor_info_tag:
fromRadioScratch.moduleConfig.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
fromRadioScratch.moduleConfig.payload_variant.neighbor_info = moduleConfig.neighbor_info;
break;
default:
LOG_ERROR("Unknown module config type %d\n", config_state);
}

Wyświetl plik

@ -55,6 +55,8 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
/* TODO: REPLACE */
meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG = 8,
/* TODO: REPLACE */
meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG = 9,
/* TODO: REPLACE */
meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG = 10
} meshtastic_AdminMessage_ModuleConfigType;

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -103,10 +103,12 @@ typedef enum _meshtastic_HardwareModel {
meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER = 48,
/* Heltec Wireless Paper with ESP32-S3 CPU and E-Ink display */
meshtastic_HardwareModel_HELTEC_WIRELESS_PAPER = 49,
/* LilyGo T-Deck with ESP32-S3 CPU, Keyboard, and IPS display */
/* LilyGo T-Deck with ESP32-S3 CPU, Keyboard and IPS display */
meshtastic_HardwareModel_T_DECK = 50,
/* LilyGo T-Watch S3 with ESP32-S3 CPU and IPS display */
meshtastic_HardwareModel_T_WATCH_S3 = 51,
/* Bobricius Picomputer with ESP32-S3 CPU, Keyboard and IPS display */
meshtastic_HardwareModel_PICOMPUTER_S3 = 52,
/* ------------------------------------------------------------------------------------------------------------------------------------------
Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits.
------------------------------------------------------------------------------------------------------------------------------------------ */
@ -605,60 +607,12 @@ typedef struct _meshtastic_MyNodeInfo {
/* Tells the phone what our node number is, default starting value is
lowbyte of macaddr, but it will be fixed if that is already in use */
uint32_t my_node_num;
/* Deprecated in 2.1.x (Source from device_metadata)
Note: This flag merely means we detected a hardware GPS in our node.
Not the same as UserPreferences.location_sharing */
bool has_gps;
/* Deprecated in 2.1.x
The maximum number of 'software' channels that can be set on this node. */
uint32_t max_channels;
/* Deprecated in 2.1.x (Source from device_metadata)
0.0.5 etc... */
char firmware_version[18];
/* An error message we'd like to report back to the mothership through analytics.
It indicates a serious bug occurred on the device, the device coped with it,
but we still want to tell the devs about the bug.
This field will be cleared after the phone reads MyNodeInfo
(i.e. it will only be reported once)
a numeric error code to go with error message, zero means no error */
meshtastic_CriticalErrorCode error_code;
/* A numeric error address (nonzero if available) */
uint32_t error_address;
/* The total number of errors this node has ever encountered
(well - since the last time we discarded preferences) */
uint32_t error_count;
/* The total number of reboots this node has ever encountered
(well - since the last time we discarded preferences) */
uint32_t reboot_count;
/* Deprecated in 2.1.x
Calculated bitrate of the current channel (in Bytes Per Second) */
float bitrate;
/* Deprecated in 2.1.x
How long before we consider a message abandoned and we can clear our
caches of any messages in flight Normally quite large to handle the worst case
message delivery time, 5 minutes.
Formerly called FLOOD_EXPIRE_TIME in the device code */
uint32_t message_timeout_msec;
/* The minimum app version that can talk to this device.
Phone/PC apps should compare this to their build number and if too low tell the user they must update their app */
uint32_t min_app_version;
/* Deprecated in 2.1.x (Only used on device to keep track of utilization)
24 time windows of 1hr each with the airtime transmitted out of the device per hour. */
pb_size_t air_period_tx_count;
uint32_t air_period_tx[8];
/* Deprecated in 2.1.x (Only used on device to keep track of utilization)
24 time windows of 1hr each with the airtime of valid packets for your mesh. */
pb_size_t air_period_rx_count;
uint32_t air_period_rx[8];
/* Deprecated in 2.1.x (Source from DeviceMetadata instead)
Is the device wifi capable? */
bool has_wifi;
/* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads)
Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise). */
float channel_utilization;
/* Deprecated in 2.1.x (Source from DeviceMetrics telemetry payloads)
Percent of airtime for transmission used within the last hour. */
float air_util_tx;
} meshtastic_MyNodeInfo;
/* Debug output from the device.
@ -729,6 +683,12 @@ typedef struct _meshtastic_Neighbor {
uint32_t node_id;
/* SNR of last heard message */
float snr;
/* Reception time (in secs since 1970) of last message that was last sent by this ID.
Note: this is for local storage only and will not be sent out over the mesh. */
uint32_t last_rx_time;
/* Broadcast interval of this neighbor (in seconds).
Note: this is for local storage only and will not be sent out over the mesh. */
uint32_t node_broadcast_interval_secs;
} meshtastic_Neighbor;
/* Full info on edges for a single node */
@ -737,6 +697,8 @@ typedef struct _meshtastic_NeighborInfo {
uint32_t node_id;
/* Field to pass neighbor info for the next sending cycle */
uint32_t last_sent_by_id;
/* Broadcast interval of the represented node (in seconds) */
uint32_t node_broadcast_interval_secs;
/* The list of out edges from this node */
pb_size_t neighbors_count;
meshtastic_Neighbor neighbors[10];
@ -871,7 +833,6 @@ extern "C" {
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
#define meshtastic_MyNodeInfo_error_code_ENUMTYPE meshtastic_CriticalErrorCode
#define meshtastic_LogRecord_level_ENUMTYPE meshtastic_LogRecord_Level
@ -896,14 +857,14 @@ extern "C" {
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0}
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
#define meshtastic_MyNodeInfo_init_default {0, 0, 0}
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_default {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}
#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_User_init_zero {"", "", "", {0}, _meshtastic_HardwareModel_MIN, 0}
@ -914,14 +875,14 @@ extern "C" {
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN}
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0}
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, "", _meshtastic_CriticalErrorCode_MIN, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, {0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0}
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0}
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
#define meshtastic_Neighbor_init_zero {0, 0}
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
#define meshtastic_Neighbor_init_zero {0, 0, 0, 0}
#define meshtastic_DeviceMetadata_init_zero {"", 0, 0, 0, 0, 0, _meshtastic_Config_DeviceConfig_Role_MIN, 0, _meshtastic_HardwareModel_MIN, 0}
/* Field tags (for use in manual encoding/decoding) */
@ -998,21 +959,8 @@ extern "C" {
#define meshtastic_NodeInfo_device_metrics_tag 6
#define meshtastic_NodeInfo_channel_tag 7
#define meshtastic_MyNodeInfo_my_node_num_tag 1
#define meshtastic_MyNodeInfo_has_gps_tag 2
#define meshtastic_MyNodeInfo_max_channels_tag 3
#define meshtastic_MyNodeInfo_firmware_version_tag 4
#define meshtastic_MyNodeInfo_error_code_tag 5
#define meshtastic_MyNodeInfo_error_address_tag 6
#define meshtastic_MyNodeInfo_error_count_tag 7
#define meshtastic_MyNodeInfo_reboot_count_tag 8
#define meshtastic_MyNodeInfo_bitrate_tag 9
#define meshtastic_MyNodeInfo_message_timeout_msec_tag 10
#define meshtastic_MyNodeInfo_min_app_version_tag 11
#define meshtastic_MyNodeInfo_air_period_tx_tag 12
#define meshtastic_MyNodeInfo_air_period_rx_tag 13
#define meshtastic_MyNodeInfo_has_wifi_tag 14
#define meshtastic_MyNodeInfo_channel_utilization_tag 15
#define meshtastic_MyNodeInfo_air_util_tx_tag 16
#define meshtastic_LogRecord_message_tag 1
#define meshtastic_LogRecord_time_tag 2
#define meshtastic_LogRecord_source_tag 3
@ -1030,9 +978,12 @@ extern "C" {
#define meshtastic_Compressed_data_tag 2
#define meshtastic_Neighbor_node_id_tag 1
#define meshtastic_Neighbor_snr_tag 2
#define meshtastic_Neighbor_last_rx_time_tag 3
#define meshtastic_Neighbor_node_broadcast_interval_secs_tag 4
#define meshtastic_NeighborInfo_node_id_tag 1
#define meshtastic_NeighborInfo_last_sent_by_id_tag 2
#define meshtastic_NeighborInfo_neighbors_tag 3
#define meshtastic_NeighborInfo_node_broadcast_interval_secs_tag 3
#define meshtastic_NeighborInfo_neighbors_tag 4
#define meshtastic_DeviceMetadata_firmware_version_tag 1
#define meshtastic_DeviceMetadata_device_state_version_tag 2
#define meshtastic_DeviceMetadata_canShutdown_tag 3
@ -1175,21 +1126,8 @@ X(a, STATIC, SINGULAR, UINT32, channel, 7)
#define meshtastic_MyNodeInfo_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, my_node_num, 1) \
X(a, STATIC, SINGULAR, BOOL, has_gps, 2) \
X(a, STATIC, SINGULAR, UINT32, max_channels, 3) \
X(a, STATIC, SINGULAR, STRING, firmware_version, 4) \
X(a, STATIC, SINGULAR, UENUM, error_code, 5) \
X(a, STATIC, SINGULAR, UINT32, error_address, 6) \
X(a, STATIC, SINGULAR, UINT32, error_count, 7) \
X(a, STATIC, SINGULAR, UINT32, reboot_count, 8) \
X(a, STATIC, SINGULAR, FLOAT, bitrate, 9) \
X(a, STATIC, SINGULAR, UINT32, message_timeout_msec, 10) \
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11) \
X(a, STATIC, REPEATED, UINT32, air_period_tx, 12) \
X(a, STATIC, REPEATED, UINT32, air_period_rx, 13) \
X(a, STATIC, SINGULAR, BOOL, has_wifi, 14) \
X(a, STATIC, SINGULAR, FLOAT, channel_utilization, 15) \
X(a, STATIC, SINGULAR, FLOAT, air_util_tx, 16)
X(a, STATIC, SINGULAR, UINT32, min_app_version, 11)
#define meshtastic_MyNodeInfo_CALLBACK NULL
#define meshtastic_MyNodeInfo_DEFAULT NULL
@ -1259,14 +1197,17 @@ X(a, STATIC, SINGULAR, BYTES, data, 2)
#define meshtastic_NeighborInfo_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
X(a, STATIC, SINGULAR, UINT32, last_sent_by_id, 2) \
X(a, STATIC, REPEATED, MESSAGE, neighbors, 3)
X(a, STATIC, SINGULAR, UINT32, node_broadcast_interval_secs, 3) \
X(a, STATIC, REPEATED, MESSAGE, neighbors, 4)
#define meshtastic_NeighborInfo_CALLBACK NULL
#define meshtastic_NeighborInfo_DEFAULT NULL
#define meshtastic_NeighborInfo_neighbors_MSGTYPE meshtastic_Neighbor
#define meshtastic_Neighbor_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, node_id, 1) \
X(a, STATIC, SINGULAR, FLOAT, snr, 2)
X(a, STATIC, SINGULAR, FLOAT, snr, 2) \
X(a, STATIC, SINGULAR, FIXED32, last_rx_time, 3) \
X(a, STATIC, SINGULAR, UINT32, node_broadcast_interval_secs, 4)
#define meshtastic_Neighbor_CALLBACK NULL
#define meshtastic_Neighbor_DEFAULT NULL
@ -1331,9 +1272,9 @@ extern const pb_msgdesc_t meshtastic_DeviceMetadata_msg;
#define meshtastic_LogRecord_size 81
#define meshtastic_MeshPacket_size 321
#define meshtastic_MqttClientProxyMessage_size 501
#define meshtastic_MyNodeInfo_size 179
#define meshtastic_NeighborInfo_size 142
#define meshtastic_Neighbor_size 11
#define meshtastic_MyNodeInfo_size 18
#define meshtastic_NeighborInfo_size 258
#define meshtastic_Neighbor_size 22
#define meshtastic_NodeInfo_size 261
#define meshtastic_Position_size 137
#define meshtastic_QueueStatus_size 23

Wyświetl plik

@ -25,73 +25,99 @@
typedef enum _meshtastic_PortNum {
/* Deprecated: do not use in new code (formerly called OPAQUE)
A message sent from a device outside of the mesh, in a form the mesh does not understand
NOTE: This must be 0, because it is documented in IMeshService.aidl to be so */
NOTE: This must be 0, because it is documented in IMeshService.aidl to be so
ENCODING: binary undefined */
meshtastic_PortNum_UNKNOWN_APP = 0,
/* A simple UTF-8 text message, which even the little micros in the mesh
can understand and show on their screen eventually in some circumstances
even signal might send messages in this form (see below) */
even signal might send messages in this form (see below)
ENCODING: UTF-8 Plaintext (?) */
meshtastic_PortNum_TEXT_MESSAGE_APP = 1,
/* Reserved for built-in GPIO/example app.
See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number */
See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number
ENCODING: Protobuf */
meshtastic_PortNum_REMOTE_HARDWARE_APP = 2,
/* The built-in position messaging app.
Payload is a [Position](/docs/developers/protobufs/api#position) message */
Payload is a [Position](/docs/developers/protobufs/api#position) message
ENCODING: Protobuf */
meshtastic_PortNum_POSITION_APP = 3,
/* The built-in user info app.
Payload is a [User](/docs/developers/protobufs/api#user) message */
Payload is a [User](/docs/developers/protobufs/api#user) message
ENCODING: Protobuf */
meshtastic_PortNum_NODEINFO_APP = 4,
/* Protocol control packets for mesh protocol use.
Payload is a [Routing](/docs/developers/protobufs/api#routing) message */
Payload is a [Routing](/docs/developers/protobufs/api#routing) message
ENCODING: Protobuf */
meshtastic_PortNum_ROUTING_APP = 5,
/* Admin control packets.
Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message */
Payload is a [AdminMessage](/docs/developers/protobufs/api#adminmessage) message
ENCODING: Protobuf */
meshtastic_PortNum_ADMIN_APP = 6,
/* Compressed TEXT_MESSAGE payloads. */
/* Compressed TEXT_MESSAGE payloads.
ENCODING: UTF-8 Plaintext (?) with Unishox2 Compression
NOTE: The Device Firmware converts a TEXT_MESSAGE_APP to TEXT_MESSAGE_COMPRESSED_APP if the compressed
payload is shorter. There's no need for app developers to do this themselves. Also the firmware will decompress
any incoming TEXT_MESSAGE_COMPRESSED_APP payload and convert to TEXT_MESSAGE_APP. */
meshtastic_PortNum_TEXT_MESSAGE_COMPRESSED_APP = 7,
/* Waypoint payloads.
Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message */
Payload is a [Waypoint](/docs/developers/protobufs/api#waypoint) message
ENCODING: Protobuf */
meshtastic_PortNum_WAYPOINT_APP = 8,
/* Audio Payloads.
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now */
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now
ENCODING: codec2 audio frames
NOTE: audio frames contain a 3 byte header (0xc0 0xde 0xc2) and a one byte marker for the decompressed bitrate.
This marker comes from the 'moduleConfig.audio.bitrate' enum minus one. */
meshtastic_PortNum_AUDIO_APP = 9,
/* Provides a 'ping' service that replies to any packet it receives.
Also serves as a small example module. */
Also serves as a small example module.
ENCODING: ASCII Plaintext */
meshtastic_PortNum_REPLY_APP = 32,
/* Used for the python IP tunnel feature */
/* Used for the python IP tunnel feature
ENCODING: IP Packet. Handled by the python API, firmware ignores this one and pases on. */
meshtastic_PortNum_IP_TUNNEL_APP = 33,
/* Provides a hardware serial interface to send and receive from the Meshtastic network.
Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic
network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network.
Maximum packet size of 240 bytes.
Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp. */
Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp.
ENCODING: binary undefined */
meshtastic_PortNum_SERIAL_APP = 64,
/* STORE_FORWARD_APP (Work in Progress)
Maintained by Jm Casler (MC Hamster) : jm@casler.org */
Maintained by Jm Casler (MC Hamster) : jm@casler.org
ENCODING: Protobuf */
meshtastic_PortNum_STORE_FORWARD_APP = 65,
/* Optional port for messages for the range test module. */
/* Optional port for messages for the range test module.
ENCODING: ASCII Plaintext */
meshtastic_PortNum_RANGE_TEST_APP = 66,
/* Provides a format to send and receive telemetry data from the Meshtastic network.
Maintained by Charles Crossan (crossan007) : crossan007@gmail.com */
Maintained by Charles Crossan (crossan007) : crossan007@gmail.com
ENCODING: Protobuf */
meshtastic_PortNum_TELEMETRY_APP = 67,
/* Experimental tools for estimating node position without a GPS
Maintained by Github user a-f-G-U-C (a Meshtastic contributor)
Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS */
Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS
ENCODING: arrays of int64 fields */
meshtastic_PortNum_ZPS_APP = 68,
/* Used to let multiple instances of Linux native applications communicate
as if they did using their LoRa chip.
Maintained by GitHub user GUVWAF.
Project files at https://github.com/GUVWAF/Meshtasticator */
Project files at https://github.com/GUVWAF/Meshtasticator
ENCODING: Protobuf (?) */
meshtastic_PortNum_SIMULATOR_APP = 69,
/* Provides a traceroute functionality to show the route a packet towards
a certain destination would take on the mesh. */
a certain destination would take on the mesh.
ENCODING: Protobuf */
meshtastic_PortNum_TRACEROUTE_APP = 70,
/* Aggregates edge info for the network by sending out a list of each node's neighbors */
/* Aggregates edge info for the network by sending out a list of each node's neighbors
ENCODING: Protobuf */
meshtastic_PortNum_NEIGHBORINFO_APP = 71,
/* Private applications should use portnums >= 256.
To simplify initial development and testing you can use "PRIVATE_APP"
in your code without needing to rebuild protobuf files (via [regen-protos.sh](https://github.com/meshtastic/firmware/blob/master/bin/regen-protos.sh)) */
meshtastic_PortNum_PRIVATE_APP = 256,
/* ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder */
/* ATAK Forwarder Module https://github.com/paulmandal/atak-forwarder
ENCODING: libcotshrink */
meshtastic_PortNum_ATAK_FORWARDER = 257,
/* Currently we limit port nums to no higher than this value */
meshtastic_PortNum_MAX = 511

Wyświetl plik

@ -16,7 +16,7 @@
#define MAX_RX_TOPHONE 32
/// max number of nodes allowed in the mesh
#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db) / member_size(meshtastic_DeviceState, node_db[0]))
#define MAX_NUM_NODES (member_size(meshtastic_DeviceState, node_db_lite) / member_size(meshtastic_DeviceState, node_db_lite[0]))
/// Max number of channels allowed
#define MAX_NUM_CHANNELS (member_size(meshtastic_ChannelFile, channels) / member_size(meshtastic_ChannelFile, channels[0]))

Wyświetl plik

@ -368,6 +368,11 @@ void AdminModule::handleSetModuleConfig(const meshtastic_ModuleConfig &c)
moduleConfig.has_remote_hardware = true;
moduleConfig.remote_hardware = c.payload_variant.remote_hardware;
break;
case meshtastic_ModuleConfig_neighbor_info_tag:
LOG_INFO("Setting module config: Neighbor Info\n");
moduleConfig.has_neighbor_info = true;
moduleConfig.neighbor_info = c.payload_variant.neighbor_info;
break;
}
saveChanges(SEGMENT_MODULECONFIG);
@ -503,6 +508,11 @@ void AdminModule::handleGetModuleConfig(const meshtastic_MeshPacket &req, const
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_remote_hardware_tag;
res.get_module_config_response.payload_variant.remote_hardware = moduleConfig.remote_hardware;
break;
case meshtastic_AdminMessage_ModuleConfigType_NEIGHBORINFO_CONFIG:
LOG_INFO("Getting module config: Neighbor Info\n");
res.get_module_config_response.which_payload_variant = meshtastic_ModuleConfig_neighbor_info_tag;
res.get_module_config_response.payload_variant.neighbor_info = moduleConfig.neighbor_info;
break;
}
// NOTE: The phone app needs to know the ls_secsvalue so it can properly expect sleep behavior.
@ -663,4 +673,4 @@ AdminModule::AdminModule() : ProtobufModule("Admin", meshtastic_PortNum_ADMIN_AP
{
// restrict to the admin channel for rx
boundChannel = Channels::adminChannel;
}
}

Wyświetl plik

@ -10,6 +10,10 @@
#include "main.h" // for cardkb_found
#ifndef INPUTBROKER_MATRIX_TYPE
#define INPUTBROKER_MATRIX_TYPE 0
#endif
#ifdef OLED_RU
#include "graphics/fonts/OLEDDisplayFontsRU.h"
#endif
@ -62,7 +66,7 @@ CannedMessageModule::CannedMessageModule()
if (moduleConfig.canned_message.enabled) {
this->loadProtoForModule();
if ((this->splitConfiguredMessages() <= 0) && (cardkb_found.address != CARDKB_ADDR) &&
(cardkb_found.address != TDECK_KB_ADDR)) {
(cardkb_found.address != TDECK_KB_ADDR) && !INPUTBROKER_MATRIX_TYPE) {
LOG_INFO("CannedMessageModule: No messages are configured. Module is disabled\n");
this->runState = CANNED_MESSAGE_RUN_STATE_DISABLED;
disable();

Wyświetl plik

@ -4,8 +4,10 @@
#include "input/TrackballInterruptImpl1.h"
#include "input/UpDownInterruptImpl1.h"
#include "input/cardKbI2cImpl.h"
#include "input/kbMatrixImpl.h"
#include "modules/AdminModule.h"
#include "modules/CannedMessageModule.h"
#include "modules/NeighborInfoModule.h"
#include "modules/NodeInfoModule.h"
#include "modules/PositionModule.h"
#include "modules/RemoteHardwareModule.h"
@ -47,6 +49,7 @@ void setupModules()
waypointModule = new WaypointModule();
textMessageModule = new TextMessageModule();
traceRouteModule = new TraceRouteModule();
neighborInfoModule = new NeighborInfoModule();
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
// to a global variable.
@ -60,7 +63,11 @@ void setupModules()
upDownInterruptImpl1->init();
cardKbI2cImpl = new CardKbI2cImpl();
cardKbI2cImpl->init();
#endif
#ifdef INPUTBROKER_MATRIX_TYPE
kbMatrixImpl = new KbMatrixImpl();
kbMatrixImpl->init();
#endif // INPUTBROKER_MATRIX_TYPE
#endif // HAS_BUTTON
#if HAS_TRACKBALL
trackballInterruptImpl1 = new TrackballInterruptImpl1();
trackballInterruptImpl1->init();

Wyświetl plik

@ -0,0 +1,319 @@
#include "NeighborInfoModule.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "RTC.h"
#define MAX_NUM_NEIGHBORS 10 // also defined in NeighborInfo protobuf options
NeighborInfoModule *neighborInfoModule;
static const char *neighborInfoConfigFile = "/prefs/neighbors.proto";
/*
Prints a single neighbor info packet and associated neighbors
Uses LOG_DEBUG, which equates to Console.log
NOTE: For debugging only
*/
void NeighborInfoModule::printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np)
{
LOG_DEBUG("%s NEIGHBORINFO PACKET from Node %d to Node %d (last sent by %d)\n", header, np->node_id, nodeDB.getNodeNum(),
np->last_sent_by_id);
LOG_DEBUG("----------------\n");
LOG_DEBUG("Packet contains %d neighbors\n", np->neighbors_count);
for (int i = 0; i < np->neighbors_count; i++) {
LOG_DEBUG("Neighbor %d: node_id=%d, snr=%.2f\n", i, np->neighbors[i].node_id, np->neighbors[i].snr);
}
LOG_DEBUG("----------------\n");
}
/*
Prints the nodeDB nodes so we can see whose nodeInfo we have
NOTE: for debugging only
*/
void NeighborInfoModule::printNodeDBNodes(const char *header)
{
int num_nodes = nodeDB.getNumMeshNodes();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n");
LOG_DEBUG("DB contains %d nodes\n", num_nodes);
for (int i = 0; i < num_nodes; i++) {
meshtastic_NodeInfoLite *dbEntry = nodeDB.getMeshNodeByIndex(i);
LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->num, dbEntry->snr);
}
LOG_DEBUG("----------------\n");
}
/*
Prints the nodeDB neighbors
NOTE: for debugging only
*/
void NeighborInfoModule::printNodeDBNeighbors(const char *header)
{
int num_neighbors = getNumNeighbors();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n");
LOG_DEBUG("DB contains %d neighbors\n", num_neighbors);
for (int i = 0; i < num_neighbors; i++) {
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
LOG_DEBUG(" Node %d: node_id=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
}
LOG_DEBUG("----------------\n");
}
/*
Prints the nodeDB with selectors for the neighbors we've chosen to send (inefficiently)
Uses LOG_DEBUG, which equates to Console.log
NOTE: For debugging only
*/
void NeighborInfoModule::printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np)
{
int num_neighbors = getNumNeighbors();
LOG_DEBUG("%s NODEDB SELECTION from Node %d:\n", header, nodeDB.getNodeNum());
LOG_DEBUG("----------------\n");
LOG_DEBUG("Selected %d neighbors of %d DB neighbors\n", np->neighbors_count, num_neighbors);
for (int i = 0; i < num_neighbors; i++) {
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
bool chosen = false;
for (int j = 0; j < np->neighbors_count; j++) {
if (np->neighbors[j].node_id == dbEntry->node_id) {
chosen = true;
}
}
if (!chosen) {
LOG_DEBUG(" Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
} else {
LOG_DEBUG("---> Node %d: neighbor=%d, snr=%.2f\n", i, dbEntry->node_id, dbEntry->snr);
}
}
LOG_DEBUG("----------------\n");
}
/* Send our initial owner announcement 35 seconds after we start (to give network time to setup) */
NeighborInfoModule::NeighborInfoModule()
: neighbors(neighborState.neighbors), numNeighbors(&neighborState.neighbors_count),
ProtobufModule("neighborinfo", meshtastic_PortNum_NEIGHBORINFO_APP, &meshtastic_NeighborInfo_msg), concurrency::OSThread(
"NeighborInfoModule")
{
ourPortNum = meshtastic_PortNum_NEIGHBORINFO_APP;
if (moduleConfig.neighbor_info.enabled) {
this->loadProtoForModule();
setIntervalFromNow(35 * 1000);
} else {
LOG_DEBUG("NeighborInfoModule is disabled\n");
disable();
}
}
/*
Allocate a zeroed neighbor info packet
*/
meshtastic_NeighborInfo *NeighborInfoModule::allocateNeighborInfoPacket()
{
meshtastic_NeighborInfo *neighborInfo = (meshtastic_NeighborInfo *)malloc(sizeof(meshtastic_NeighborInfo));
memset(neighborInfo, 0, sizeof(meshtastic_NeighborInfo));
return neighborInfo;
}
/*
Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
Assumes that the neighborInfo packet has been allocated
@returns the number of entries collected
*/
uint32_t NeighborInfoModule::collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo)
{
int my_node_id = nodeDB.getNodeNum();
neighborInfo->node_id = my_node_id;
neighborInfo->last_sent_by_id = my_node_id;
neighborInfo->node_broadcast_interval_secs = moduleConfig.neighbor_info.update_interval;
int num_neighbors = cleanUpNeighbors();
for (int i = 0; i < num_neighbors; i++) {
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
if ((neighborInfo->neighbors_count < MAX_NUM_NEIGHBORS) && (dbEntry->node_id != my_node_id)) {
neighborInfo->neighbors[neighborInfo->neighbors_count].node_id = dbEntry->node_id;
neighborInfo->neighbors[neighborInfo->neighbors_count].snr = dbEntry->snr;
// Note: we don't set the last_rx_time and node_broadcast_intervals_secs here, because we don't want to send this over
// the mesh
neighborInfo->neighbors_count++;
}
}
printNodeDBNodes("DBSTATE");
printNodeDBNeighbors("NEIGHBORS");
printNodeDBSelection("COLLECTED", neighborInfo);
return neighborInfo->neighbors_count;
}
/*
Remove neighbors from the database that we haven't heard from in a while
@returns new number of neighbors
*/
size_t NeighborInfoModule::cleanUpNeighbors()
{
uint32_t now = getTime();
int num_neighbors = getNumNeighbors();
NodeNum my_node_id = nodeDB.getNodeNum();
// Find neighbors to remove
std::vector<int> indices_to_remove;
for (int i = 0; i < num_neighbors; i++) {
meshtastic_Neighbor *dbEntry = getNeighborByIndex(i);
// We will remove a neighbor if we haven't heard from them in twice the broadcast interval
if ((now - dbEntry->last_rx_time > dbEntry->node_broadcast_interval_secs * 2) && (dbEntry->node_id != my_node_id)) {
indices_to_remove.push_back(i);
}
}
// Update the neighbor list
for (int i = 0; i < indices_to_remove.size(); i++) {
int index = indices_to_remove[i];
LOG_DEBUG("Removing neighbor with node ID 0x%x\n", neighbors[index].node_id);
for (int j = index; j < num_neighbors - 1; j++) {
neighbors[j] = neighbors[j + 1];
}
(*numNeighbors)--;
}
// Save the neighbor list if we removed any neighbors
if (indices_to_remove.size() > 0) {
saveProtoForModule();
}
return *numNeighbors;
}
/* Send neighbor info to the mesh */
void NeighborInfoModule::sendNeighborInfo(NodeNum dest, bool wantReplies)
{
meshtastic_NeighborInfo *neighborInfo = allocateNeighborInfoPacket();
collectNeighborInfo(neighborInfo);
meshtastic_MeshPacket *p = allocDataProtobuf(*neighborInfo);
// send regardless of whether or not we have neighbors in our DB,
// because we want to get neighbors for the next cycle
p->to = dest;
p->decoded.want_response = wantReplies;
printNeighborInfo("SENDING", neighborInfo);
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
/*
Encompasses the full construction and sending packet to mesh
Will be used for broadcast.
*/
int32_t NeighborInfoModule::runOnce()
{
bool requestReplies = false;
sendNeighborInfo(NODENUM_BROADCAST, requestReplies);
return getConfiguredOrDefaultMs(moduleConfig.neighbor_info.update_interval, default_broadcast_interval_secs);
}
/*
Collect a recieved neighbor info packet from another node
Pass it to an upper client; do not persist this data on the mesh
*/
bool NeighborInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
{
printNeighborInfo("RECEIVED", np);
updateNeighbors(mp, np);
// Allow others to handle this packet
return false;
}
/*
Copy the content of a current NeighborInfo packet into a new one and update the last_sent_by_id to our NodeNum
*/
void NeighborInfoModule::updateLastSentById(meshtastic_MeshPacket *p)
{
auto &incoming = p->decoded;
meshtastic_NeighborInfo scratch;
meshtastic_NeighborInfo *updated = NULL;
memset(&scratch, 0, sizeof(scratch));
pb_decode_from_bytes(incoming.payload.bytes, incoming.payload.size, &meshtastic_NeighborInfo_msg, &scratch);
updated = &scratch;
updated->last_sent_by_id = nodeDB.getNodeNum();
// Set updated last_sent_by_id to the payload of the to be flooded packet
p->decoded.payload.size =
pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &meshtastic_NeighborInfo_msg, updated);
}
void NeighborInfoModule::resetNeighbors()
{
*numNeighbors = 0;
neighborState.neighbors_count = 0;
memset(neighborState.neighbors, 0, sizeof(neighborState.neighbors));
saveProtoForModule();
}
void NeighborInfoModule::updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np)
{
// The last sent ID will be 0 if the packet is from the phone, which we don't count as
// an edge. So we assume that if it's zero, then this packet is from our node.
if (mp.which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp.from) {
getOrCreateNeighbor(mp.from, np->last_sent_by_id, np->node_broadcast_interval_secs, mp.rx_snr);
}
}
meshtastic_Neighbor *NeighborInfoModule::getOrCreateNeighbor(NodeNum originalSender, NodeNum n,
uint32_t node_broadcast_interval_secs, int snr)
{
// our node and the phone are the same node (not neighbors)
if (n == 0) {
n = nodeDB.getNodeNum();
}
// look for one in the existing list
for (int i = 0; i < (*numNeighbors); i++) {
meshtastic_Neighbor *nbr = &neighbors[i];
if (nbr->node_id == n) {
// if found, update it
nbr->snr = snr;
nbr->last_rx_time = getTime();
// Only if this is the original sender, the broadcast interval corresponds to it
if (originalSender == n)
nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
saveProtoForModule(); // Save the updated neighbor
return nbr;
}
}
// otherwise, allocate one and assign data to it
// TODO: max memory for the database should take neighbors into account, but currently doesn't
if (*numNeighbors < MAX_NUM_NODES) {
(*numNeighbors)++;
}
meshtastic_Neighbor *new_nbr = &neighbors[((*numNeighbors) - 1)];
new_nbr->node_id = n;
new_nbr->snr = snr;
new_nbr->last_rx_time = getTime();
// Only if this is the original sender, the broadcast interval corresponds to it
if (originalSender == n)
new_nbr->node_broadcast_interval_secs = node_broadcast_interval_secs;
saveProtoForModule(); // Save the new neighbor
return new_nbr;
}
void NeighborInfoModule::loadProtoForModule()
{
if (!nodeDB.loadProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, sizeof(meshtastic_NeighborInfo),
&meshtastic_NeighborInfo_msg, &neighborState)) {
neighborState = meshtastic_NeighborInfo_init_zero;
}
}
/**
* @brief Save the module config to file.
*
* @return true On success.
* @return false On error.
*/
bool NeighborInfoModule::saveProtoForModule()
{
bool okay = true;
#ifdef FS
FS.mkdir("/prefs");
#endif
okay &= nodeDB.saveProto(neighborInfoConfigFile, meshtastic_NeighborInfo_size, &meshtastic_NeighborInfo_msg, &neighborState);
return okay;
}

Wyświetl plik

@ -0,0 +1,84 @@
#pragma once
#include "ProtobufModule.h"
/*
* Neighborinfo module for sending info on each node's 0-hop neighbors to the mesh
*/
class NeighborInfoModule : public ProtobufModule<meshtastic_NeighborInfo>, private concurrency::OSThread
{
meshtastic_Neighbor *neighbors;
pb_size_t *numNeighbors;
public:
/*
* Expose the constructor
*/
NeighborInfoModule();
/* Reset neighbor info after clearing nodeDB*/
void resetNeighbors();
bool saveProtoForModule();
// Let FloodingRouter call updateLastSentById upon rebroadcasting a NeighborInfo packet
friend class FloodingRouter;
protected:
// Note: this holds our local info.
meshtastic_NeighborInfo neighborState;
/*
* Called to handle a particular incoming message
* @return true if you've guaranteed you've handled this message and no other handlers should be considered for it
*/
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *nb) override;
/*
* Collect neighbor info from the nodeDB's history, capping at a maximum number of entries and max time
* @return the number of entries collected
*/
uint32_t collectNeighborInfo(meshtastic_NeighborInfo *neighborInfo);
/*
Remove neighbors from the database that we haven't heard from in a while
@returns new number of neighbors
*/
size_t cleanUpNeighbors();
/* Allocate a new NeighborInfo packet */
meshtastic_NeighborInfo *allocateNeighborInfoPacket();
// Find a neighbor in our DB, create an empty neighbor if missing
meshtastic_Neighbor *getOrCreateNeighbor(NodeNum originalSender, NodeNum n, uint32_t node_broadcast_interval_secs, int snr);
/*
* Send info on our node's neighbors into the mesh
*/
void sendNeighborInfo(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
size_t getNumNeighbors() { return *numNeighbors; }
meshtastic_Neighbor *getNeighborByIndex(size_t x)
{
assert(x < *numNeighbors);
return &neighbors[x];
}
/* update neighbors with subpacket sniffed from network */
void updateNeighbors(const meshtastic_MeshPacket &mp, meshtastic_NeighborInfo *np);
/* update a NeighborInfo packet with our NodeNum as last_sent_by_id */
void updateLastSentById(meshtastic_MeshPacket *p);
void loadProtoForModule();
/* Does our periodic broadcast */
int32_t runOnce() override;
/* These are for debugging only */
void printNeighborInfo(const char *header, const meshtastic_NeighborInfo *np);
void printNodeDBNodes(const char *header);
void printNodeDBNeighbors(const char *header);
void printNodeDBSelection(const char *header, const meshtastic_NeighborInfo *np);
};
extern NeighborInfoModule *neighborInfoModule;

Wyświetl plik

@ -363,6 +363,19 @@ JSONValue::JSONValue(int m_integer_value)
number_value = (double)m_integer_value;
}
/**
* Basic constructor for creating a JSON Value of type Number
*
* @access public
*
* @param uint m_integer_value The number to use as the value
*/
JSONValue::JSONValue(uint m_integer_value)
{
type = JSONType_Number;
number_value = (double)m_integer_value;
}
/**
* Basic constructor for creating a JSON Value of type Array
*
@ -874,4 +887,4 @@ std::string JSONValue::Indent(size_t depth)
depth ? --depth : 0;
std::string indentStr(depth * indent_step, ' ');
return indentStr;
}
}

Wyświetl plik

@ -45,6 +45,7 @@ class JSONValue
JSONValue(bool m_bool_value);
JSONValue(double m_number_value);
JSONValue(int m_integer_value);
JSONValue(uint m_integer_value);
JSONValue(const JSONArray &m_array_value);
JSONValue(const JSONObject &m_object_value);
JSONValue(const JSONValue &m_source);
@ -91,4 +92,4 @@ class JSONValue
};
};
#endif
#endif

Wyświetl plik

@ -541,7 +541,7 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Telemetry_msg, &scratch)) {
decoded = &scratch;
if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) {
msgPayload["battery_level"] = new JSONValue((int)decoded->variant.device_metrics.battery_level);
msgPayload["battery_level"] = new JSONValue((uint)decoded->variant.device_metrics.battery_level);
msgPayload["voltage"] = new JSONValue(decoded->variant.device_metrics.voltage);
msgPayload["channel_utilization"] = new JSONValue(decoded->variant.device_metrics.channel_utilization);
msgPayload["air_util_tx"] = new JSONValue(decoded->variant.device_metrics.air_util_tx);
@ -588,10 +588,10 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Position_msg, &scratch)) {
decoded = &scratch;
if ((int)decoded->time) {
msgPayload["time"] = new JSONValue((int)decoded->time);
msgPayload["time"] = new JSONValue((uint)decoded->time);
}
if ((int)decoded->timestamp) {
msgPayload["timestamp"] = new JSONValue((int)decoded->timestamp);
msgPayload["timestamp"] = new JSONValue((uint)decoded->timestamp);
}
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
@ -599,13 +599,13 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
msgPayload["altitude"] = new JSONValue((int)decoded->altitude);
}
if ((int)decoded->ground_speed) {
msgPayload["ground_speed"] = new JSONValue((int)decoded->ground_speed);
msgPayload["ground_speed"] = new JSONValue((uint)decoded->ground_speed);
}
if (int(decoded->ground_track)) {
msgPayload["ground_track"] = new JSONValue((int)decoded->ground_track);
msgPayload["ground_track"] = new JSONValue((uint)decoded->ground_track);
}
if (int(decoded->sats_in_view)) {
msgPayload["sats_in_view"] = new JSONValue((int)decoded->sats_in_view);
msgPayload["sats_in_view"] = new JSONValue((uint)decoded->sats_in_view);
}
if ((int)decoded->PDOP) {
msgPayload["PDOP"] = new JSONValue((int)decoded->PDOP);
@ -632,11 +632,11 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) {
decoded = &scratch;
msgPayload["id"] = new JSONValue((int)decoded->id);
msgPayload["id"] = new JSONValue((uint)decoded->id);
msgPayload["name"] = new JSONValue(decoded->name);
msgPayload["description"] = new JSONValue(decoded->description);
msgPayload["expire"] = new JSONValue((int)decoded->expire);
msgPayload["locked_to"] = new JSONValue((int)decoded->locked_to);
msgPayload["expire"] = new JSONValue((uint)decoded->expire);
msgPayload["locked_to"] = new JSONValue((uint)decoded->locked_to);
msgPayload["latitude_i"] = new JSONValue((int)decoded->latitude_i);
msgPayload["longitude_i"] = new JSONValue((int)decoded->longitude_i);
jsonObj["payload"] = new JSONValue(msgPayload);
@ -646,16 +646,34 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
};
break;
}
case meshtastic_PortNum_NEIGHBORINFO_APP: {
msgType = "neighborinfo";
meshtastic_NeighborInfo scratch;
meshtastic_NeighborInfo *decoded = NULL;
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
memset(&scratch, 0, sizeof(scratch));
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_NeighborInfo_msg,
&scratch)) {
decoded = &scratch;
msgPayload["node_id"] = new JSONValue((uint)decoded->node_id);
msgPayload["neighbors_count"] = new JSONValue(decoded->neighbors_count);
msgPayload["neighbors"] = new JSONValue(decoded->neighbors);
} else {
LOG_ERROR("Error decoding protobuf for neighborinfo message!\n");
}
};
break;
}
// add more packet types here if needed
default:
break;
}
jsonObj["id"] = new JSONValue((int)mp->id);
jsonObj["timestamp"] = new JSONValue((int)mp->rx_time);
jsonObj["to"] = new JSONValue((int)mp->to);
jsonObj["from"] = new JSONValue((int)mp->from);
jsonObj["channel"] = new JSONValue((int)mp->channel);
jsonObj["id"] = new JSONValue((uint)mp->id);
jsonObj["timestamp"] = new JSONValue((uint)mp->rx_time);
jsonObj["to"] = new JSONValue((uint)mp->to);
jsonObj["from"] = new JSONValue((uint)mp->from);
jsonObj["channel"] = new JSONValue((uint)mp->channel);
jsonObj["type"] = new JSONValue(msgType.c_str());
jsonObj["sender"] = new JSONValue(owner.id);

Wyświetl plik

@ -117,6 +117,8 @@
#define HW_VENDOR meshtastic_HardwareModel_NANO_G1_EXPLORER
#elif defined(BETAFPV_900_TX_NANO)
#define HW_VENDOR meshtastic_HardwareModel_BETAFPV_900_NANO_TX
#elif defined(PICOMPUTER_S3)
#define HW_VENDOR meshtastic_HardwareModel_PICOMPUTER_S3
#endif
//

Wyświetl plik

@ -16,7 +16,7 @@ void powerCommandsCheck()
rp2040.reboot();
#else
rebootAtMsec = -1;
LOG_WARN("FIXME implement reboot for this platform. Skipping for now.\n");
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied.\n");
#endif
}

Wyświetl plik

@ -4,6 +4,10 @@
#define I2C_SDA SDA_OLED // I2C pins for this board
#define I2C_SCL SCL_OLED
// Enable secondary bus for external periherals
#define I2C_SDA1 SDA
#define I2C_SCL1 SCL
#define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost
#define BUTTON_PIN 0

Wyświetl plik

@ -1,5 +1,9 @@
#define LED_PIN 18
// Enable bus for external periherals
#define I2C_SDA SDA
#define I2C_SCL SCL
#define USE_EINK
/*
* eink display pins

Wyświetl plik

@ -1,5 +1,5 @@
#define I2C_SCL 47
#define I2C_SDA 48
#define I2C_SCL SCL
#define I2C_SDA SDA
#define LED_PIN LED

Wyświetl plik

@ -0,0 +1,30 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#define USB_VID 0x303a
#define USB_PID 0x1001
#define EXTERNAL_NUM_INTERRUPTS 46
#define NUM_DIGITAL_PINS 48
#define NUM_ANALOG_INPUTS 20
#define analogInputToDigitalPin(p) (((p) < 20) ? (analogChannelToDigitalPin(p)) : -1)
#define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1)
#define digitalPinHasPWM(p) (p < 46)
static const uint8_t TX = 43;
static const uint8_t RX = 44;
// The default Wire will be mapped to PMU and RTC
static const uint8_t SDA = 8;
static const uint8_t SCL = 9;
// Default SPI
static const uint8_t MISO = 39;
static const uint8_t SCK = 21;
static const uint8_t MOSI = 38;
static const uint8_t SS = 40;
#endif /* Pins_Arduino_h */

Wyświetl plik

@ -0,0 +1,17 @@
[env:picomputer-s3]
extends = esp32s3_base
board = bpi_picow_esp32_s3
board_level = extra
;OpenOCD flash method
;upload_protocol = esp-builtin
;Normal method
upload_protocol = esptool
build_flags =
${esp32s3_base.build_flags}
-DPICOMPUTER_S3
-I variants/picomputer-s3
lib_deps =
${esp32s3_base.lib_deps}
lovyan03/LovyanGFX@^1.1.8

Wyświetl plik

@ -0,0 +1,54 @@
#undef GPS_RX_PIN
#undef GPS_TX_PIN
#define BUTTON_PIN 0
#define PIN_BUZZER 43
#define HAS_GPS 0
#define HAS_WIRE 0
#define USE_RF95 // RFM95/SX127x
#define RF95_SCK SCK // 21
#define RF95_MISO MISO // 39
#define RF95_MOSI MOSI // 38
#define RF95_NSS SS // 40
#define LORA_RESET RADIOLIB_NC
// per SX1276_Receive_Interrupt/utilities.h
#define LORA_DIO0 10
#define LORA_DIO1 RADIOLIB_NC
#define LORA_DIO2 RADIOLIB_NC
// Default SPI1 will be mapped to the display
#define ST7789_SDA 4
#define ST7789_SCK 3
#define ST7789_CS 6
#define ST7789_RS 1
#define ST7789_BL 5
#define ST7789_RESET -1
#define ST7789_MISO -1
#define ST7789_BUSY -1
#define ST7789_SPI_HOST SPI3_HOST
#define ST7789_BACKLIGHT_EN 5
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 16000000
#define TFT_HEIGHT 320
#define TFT_WIDTH 240
#define TFT_OFFSET_X 0
#define TFT_OFFSET_Y 0
#define SCREEN_ROTATE
#define SCREEN_TRANSITION_FRAMERATE 5
#define INPUTBROKER_MATRIX_TYPE 1
#define KEYS_COLS \
{ \
44, 47, 17, 15, 13, 41 \
}
#define KEYS_ROWS \
{ \
12, 16, 42, 18, 14, 7 \
}

Wyświetl plik

@ -1,4 +1,4 @@
[VERSION]
major = 2
minor = 1
build = 23
minor = 2
build = 0