mirror of
https://github.com/meshtastic/firmware.git
synced 2025-02-26 22:33:24 +00:00
Merge branch 'master' into tft-gui-work
This commit is contained in:
commit
de62cb847d
@ -1 +1 @@
|
||||
Subproject commit 5a97acb17543a10e114675a205e3274a83e721af
|
||||
Subproject commit 00332412b238fe559175a6e83fdf8d31fa5e209a
|
@ -103,12 +103,21 @@ class AccelerometerThread : public concurrency::OSThread
|
||||
#endif
|
||||
|
||||
struct bma423_axes_remap remap_data;
|
||||
#ifdef T_WATCH_S3
|
||||
remap_data.x_axis = 1;
|
||||
remap_data.x_axis_sign = 0;
|
||||
remap_data.y_axis = 0;
|
||||
remap_data.y_axis_sign = 0;
|
||||
remap_data.z_axis = 2;
|
||||
remap_data.z_axis_sign = 1;
|
||||
#else
|
||||
remap_data.x_axis = 0;
|
||||
remap_data.x_axis_sign = 1;
|
||||
remap_data.y_axis = 1;
|
||||
remap_data.y_axis_sign = 0;
|
||||
remap_data.z_axis = 2;
|
||||
remap_data.z_axis_sign = 1;
|
||||
#endif
|
||||
// Need to raise the wrist function, need to set the correct axis
|
||||
bmaSensor.setRemapAxes(&remap_data);
|
||||
// sensor.enableFeature(BMA423_STEP_CNTR, true);
|
||||
@ -171,4 +180,4 @@ class AccelerometerThread : public concurrency::OSThread
|
||||
Adafruit_LIS3DH lis;
|
||||
};
|
||||
|
||||
} // namespace concurrency
|
||||
} // namespace concurrency
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "CryptoEngine.h"
|
||||
#include "DisplayFormatters.h"
|
||||
#include "NodeDB.h"
|
||||
#include "RadioInterface.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include <assert.h>
|
||||
@ -254,6 +255,25 @@ const char *Channels::getName(size_t chIndex)
|
||||
return channelName;
|
||||
}
|
||||
|
||||
bool Channels::hasDefaultChannel()
|
||||
{
|
||||
// If we don't use a preset or the default frequency slot, or we override the frequency, we don't have a default channel
|
||||
if (!config.lora.use_preset || !RadioInterface::uses_default_frequency_slot || config.lora.override_frequency)
|
||||
return false;
|
||||
// Check if any of the channels are using the default name and PSK
|
||||
for (size_t i = 0; i < getNumChannels(); i++) {
|
||||
const auto &ch = getByIndex(i);
|
||||
if (ch.settings.psk.size == 1 && ch.settings.psk.bytes[0] == 1) {
|
||||
const char *name = getName(i);
|
||||
const char *presetName = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false);
|
||||
// Check if the name is the default derived from the modem preset
|
||||
if (strcmp(name, presetName) == 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a short suffix used to disambiguate channels that might have the same "name" entered by the human but different PSKs.
|
||||
* The ideas is that the PSK changing should be visible to the user so that they see they probably messed up and that's why they
|
||||
|
@ -102,6 +102,9 @@ class Channels
|
||||
*/
|
||||
int16_t setActiveByIndex(ChannelIndex channelIndex);
|
||||
|
||||
// Returns true if we can be reached via a channel with the default settings given a region and modem preset
|
||||
bool hasDefaultChannel();
|
||||
|
||||
private:
|
||||
/** Given a channel index, change to use the crypto key specified by that index
|
||||
*
|
||||
|
@ -744,14 +744,17 @@ uint32_t sinceReceived(const meshtastic_MeshPacket *p)
|
||||
|
||||
#define NUM_ONLINE_SECS (60 * 60 * 2) // 2 hrs to consider someone offline
|
||||
|
||||
size_t NodeDB::getNumOnlineMeshNodes()
|
||||
size_t NodeDB::getNumOnlineMeshNodes(bool localOnly)
|
||||
{
|
||||
size_t numseen = 0;
|
||||
|
||||
// FIXME this implementation is kinda expensive
|
||||
for (int i = 0; i < *numMeshNodes; i++)
|
||||
for (int i = 0; i < *numMeshNodes; i++) {
|
||||
if (localOnly && meshNodes[i].via_mqtt)
|
||||
continue;
|
||||
if (sinceLastSeen(&meshNodes[i]) < NUM_ONLINE_SECS)
|
||||
numseen++;
|
||||
}
|
||||
|
||||
return numseen;
|
||||
}
|
||||
|
@ -108,8 +108,10 @@ class NodeDB
|
||||
// get channel channel index we heard a nodeNum on, defaults to 0 if not found
|
||||
uint8_t getMeshNodeChannel(NodeNum n);
|
||||
|
||||
/// Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
||||
size_t getNumOnlineMeshNodes();
|
||||
/* Return the number of nodes we've heard from recently (within the last 2 hrs?)
|
||||
* @param localOnly if true, ignore nodes heard via MQTT
|
||||
*/
|
||||
size_t getNumOnlineMeshNodes(bool localOnly = false);
|
||||
|
||||
void initConfigIntervals(), initModuleConfigIntervals(), resetNodes(), removeNodeByNum(uint nodeNum);
|
||||
|
||||
@ -246,4 +248,4 @@ extern uint32_t error_address;
|
||||
#define Module_Config_size \
|
||||
(ModuleConfig_CannedMessageConfig_size + ModuleConfig_ExternalNotificationConfig_size + ModuleConfig_MQTTConfig_size + \
|
||||
ModuleConfig_RangeTestConfig_size + ModuleConfig_SerialConfig_size + ModuleConfig_StoreForwardConfig_size + \
|
||||
ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
|
||||
ModuleConfig_TelemetryConfig_size + ModuleConfig_size)
|
@ -1,5 +1,6 @@
|
||||
#include "RadioInterface.h"
|
||||
#include "Channels.h"
|
||||
#include "DisplayFormatters.h"
|
||||
#include "MeshRadio.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
@ -143,6 +144,7 @@ const RegionInfo regions[] = {
|
||||
};
|
||||
|
||||
const RegionInfo *myRegion;
|
||||
bool RadioInterface::uses_default_frequency_slot = true;
|
||||
|
||||
static uint8_t bytes[MAX_RHPACKETLEN];
|
||||
|
||||
@ -486,6 +488,10 @@ void RadioInterface::applyModemConfig()
|
||||
// channel_num is actually (channel_num - 1), since modulus (%) returns values from 0 to (numChannels - 1)
|
||||
int channel_num = (loraConfig.channel_num ? loraConfig.channel_num - 1 : hash(channelName)) % numChannels;
|
||||
|
||||
// Check if we use the default frequency slot
|
||||
RadioInterface::uses_default_frequency_slot =
|
||||
channel_num == hash(DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false)) % numChannels;
|
||||
|
||||
// Old frequency selection formula
|
||||
// float freq = myRegion->freqStart + ((((myRegion->freqEnd - myRegion->freqStart) / numChannels) / 2) * channel_num);
|
||||
|
||||
|
@ -175,6 +175,9 @@ class RadioInterface
|
||||
/// Some boards (1st gen Pinetab Lora module) have broken IRQ wires, so we need to poll via i2c registers
|
||||
virtual bool isIRQPending() { return false; }
|
||||
|
||||
// Whether we use the default frequency slot given our LoRa config (region and modem preset)
|
||||
static bool uses_default_frequency_slot;
|
||||
|
||||
protected:
|
||||
int8_t power = 17; // Set by applyModemConfig()
|
||||
|
||||
|
@ -324,7 +324,7 @@ extern const pb_msgdesc_t meshtastic_NodeRemoteHardwarePin_msg;
|
||||
#define meshtastic_DeviceState_size 17571
|
||||
#define meshtastic_NodeInfoLite_size 158
|
||||
#define meshtastic_NodeRemoteHardwarePin_size 29
|
||||
#define meshtastic_OEMStore_size 3246
|
||||
#define meshtastic_OEMStore_size 3262
|
||||
#define meshtastic_PositionLite_size 28
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -181,7 +181,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg;
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
#define meshtastic_LocalConfig_size 469
|
||||
#define meshtastic_LocalModuleConfig_size 631
|
||||
#define meshtastic_LocalModuleConfig_size 647
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -6,12 +6,15 @@
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(meshtastic_ModuleConfig, meshtastic_ModuleConfig, AUTO)
|
||||
PB_BIND(meshtastic_ModuleConfig, meshtastic_ModuleConfig, 2)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ModuleConfig_MQTTConfig, meshtastic_ModuleConfig_MQTTConfig, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ModuleConfig_MapReportSettings, meshtastic_ModuleConfig_MapReportSettings, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_ModuleConfig_RemoteHardwareConfig, meshtastic_ModuleConfig_RemoteHardwareConfig, AUTO)
|
||||
|
||||
|
||||
|
@ -84,6 +84,14 @@ typedef enum _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar {
|
||||
} meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar;
|
||||
|
||||
/* Struct definitions */
|
||||
/* Settings for reporting unencrypted information about our node to a map via MQTT */
|
||||
typedef struct _meshtastic_ModuleConfig_MapReportSettings {
|
||||
/* How often we should report our info to the map (in seconds) */
|
||||
uint32_t publish_interval_secs;
|
||||
/* Bits of precision for the location sent (default of 32 is full precision). */
|
||||
uint32_t position_precision;
|
||||
} meshtastic_ModuleConfig_MapReportSettings;
|
||||
|
||||
/* MQTT Client Config */
|
||||
typedef struct _meshtastic_ModuleConfig_MQTTConfig {
|
||||
/* If a meshtastic node is able to reach the internet it will normally attempt to gateway any channels that are marked as
|
||||
@ -114,6 +122,11 @@ typedef struct _meshtastic_ModuleConfig_MQTTConfig {
|
||||
char root[16];
|
||||
/* If true, we can use the connected phone / client to proxy messages to MQTT instead of a direct connection */
|
||||
bool proxy_to_client_enabled;
|
||||
/* If true, we will periodically report unencrypted information about our node to a map via MQTT */
|
||||
bool map_reporting_enabled;
|
||||
/* Settings for reporting information about our node to a map via MQTT */
|
||||
bool has_map_report_settings;
|
||||
meshtastic_ModuleConfig_MapReportSettings map_report_settings;
|
||||
} meshtastic_ModuleConfig_MQTTConfig;
|
||||
|
||||
/* NeighborInfoModule Config */
|
||||
@ -427,6 +440,7 @@ extern "C" {
|
||||
|
||||
|
||||
|
||||
|
||||
#define meshtastic_ModuleConfig_AudioConfig_bitrate_ENUMTYPE meshtastic_ModuleConfig_AudioConfig_Audio_Baud
|
||||
|
||||
|
||||
@ -447,7 +461,8 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_ModuleConfig_init_default {0, {meshtastic_ModuleConfig_MQTTConfig_init_default}}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_default {0, "", "", "", 0, 0, 0, "", 0, 0, false, meshtastic_ModuleConfig_MapReportSettings_init_default}
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_init_default {0, 0}
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_default {0, 0, 0, {meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default, meshtastic_RemoteHardwarePin_init_default}}
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_default {0, 0}
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_default {0, 0, 0, 0, "", 0, 0, 0}
|
||||
@ -462,7 +477,8 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0}
|
||||
#define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
||||
#define meshtastic_ModuleConfig_init_zero {0, {meshtastic_ModuleConfig_MQTTConfig_init_zero}}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0}
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_init_zero {0, "", "", "", 0, 0, 0, "", 0, 0, false, meshtastic_ModuleConfig_MapReportSettings_init_zero}
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_init_zero {0, 0}
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_init_zero {0, 0, 0, {meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero, meshtastic_RemoteHardwarePin_init_zero}}
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_init_zero {0, 0}
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_init_zero {0, 0, 0, 0, "", 0, 0, 0}
|
||||
@ -478,6 +494,8 @@ extern "C" {
|
||||
#define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_publish_interval_secs_tag 1
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_position_precision_tag 2
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_address_tag 2
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_username_tag 3
|
||||
@ -487,6 +505,8 @@ extern "C" {
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_tls_enabled_tag 7
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_root_tag 8
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_proxy_to_client_enabled_tag 9
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_map_reporting_enabled_tag 10
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_map_report_settings_tag 11
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_enabled_tag 1
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_update_interval_tag 2
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_enabled_tag 1
|
||||
@ -623,9 +643,18 @@ X(a, STATIC, SINGULAR, BOOL, encryption_enabled, 5) \
|
||||
X(a, STATIC, SINGULAR, BOOL, json_enabled, 6) \
|
||||
X(a, STATIC, SINGULAR, BOOL, tls_enabled, 7) \
|
||||
X(a, STATIC, SINGULAR, STRING, root, 8) \
|
||||
X(a, STATIC, SINGULAR, BOOL, proxy_to_client_enabled, 9)
|
||||
X(a, STATIC, SINGULAR, BOOL, proxy_to_client_enabled, 9) \
|
||||
X(a, STATIC, SINGULAR, BOOL, map_reporting_enabled, 10) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, map_report_settings, 11)
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_DEFAULT NULL
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_map_report_settings_MSGTYPE meshtastic_ModuleConfig_MapReportSettings
|
||||
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT32, publish_interval_secs, 1) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_precision, 2)
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_CALLBACK NULL
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_DEFAULT NULL
|
||||
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, BOOL, enabled, 1) \
|
||||
@ -764,6 +793,7 @@ X(a, STATIC, SINGULAR, UENUM, type, 3)
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_MQTTConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_MapReportSettings_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_RemoteHardwareConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_NeighborInfoConfig_msg;
|
||||
extern const pb_msgdesc_t meshtastic_ModuleConfig_DetectionSensorConfig_msg;
|
||||
@ -781,6 +811,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_ModuleConfig_fields &meshtastic_ModuleConfig_msg
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_fields &meshtastic_ModuleConfig_MQTTConfig_msg
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_fields &meshtastic_ModuleConfig_MapReportSettings_msg
|
||||
#define meshtastic_ModuleConfig_RemoteHardwareConfig_fields &meshtastic_ModuleConfig_RemoteHardwareConfig_msg
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_fields &meshtastic_ModuleConfig_NeighborInfoConfig_msg
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_fields &meshtastic_ModuleConfig_DetectionSensorConfig_msg
|
||||
@ -801,7 +832,8 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
||||
#define meshtastic_ModuleConfig_CannedMessageConfig_size 49
|
||||
#define meshtastic_ModuleConfig_DetectionSensorConfig_size 44
|
||||
#define meshtastic_ModuleConfig_ExternalNotificationConfig_size 42
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_size 222
|
||||
#define meshtastic_ModuleConfig_MQTTConfig_size 238
|
||||
#define meshtastic_ModuleConfig_MapReportSettings_size 12
|
||||
#define meshtastic_ModuleConfig_NeighborInfoConfig_size 8
|
||||
#define meshtastic_ModuleConfig_PaxcounterConfig_size 8
|
||||
#define meshtastic_ModuleConfig_RangeTestConfig_size 10
|
||||
@ -809,7 +841,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg;
|
||||
#define meshtastic_ModuleConfig_SerialConfig_size 28
|
||||
#define meshtastic_ModuleConfig_StoreForwardConfig_size 22
|
||||
#define meshtastic_ModuleConfig_TelemetryConfig_size 36
|
||||
#define meshtastic_ModuleConfig_size 225
|
||||
#define meshtastic_ModuleConfig_size 241
|
||||
#define meshtastic_RemoteHardwarePin_size 21
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -9,4 +9,7 @@
|
||||
PB_BIND(meshtastic_ServiceEnvelope, meshtastic_ServiceEnvelope, AUTO)
|
||||
|
||||
|
||||
PB_BIND(meshtastic_MapReport, meshtastic_MapReport, AUTO)
|
||||
|
||||
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#define PB_MESHTASTIC_MESHTASTIC_MQTT_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
#include "meshtastic/mesh.pb.h"
|
||||
#include "meshtastic/config.pb.h"
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
@ -23,6 +24,38 @@ typedef struct _meshtastic_ServiceEnvelope {
|
||||
char *gateway_id;
|
||||
} meshtastic_ServiceEnvelope;
|
||||
|
||||
/* Information about a node intended to be reported unencrypted to a map using MQTT. */
|
||||
typedef struct _meshtastic_MapReport {
|
||||
/* A full name for this user, i.e. "Kevin Hester" */
|
||||
char long_name[40];
|
||||
/* A VERY short name, ideally two characters.
|
||||
Suitable for a tiny OLED screen */
|
||||
char short_name[5];
|
||||
/* Role of the node that applies specific settings for a particular use-case */
|
||||
meshtastic_Config_DeviceConfig_Role role;
|
||||
/* Hardware model of the node, i.e. T-Beam, Heltec V3, etc... */
|
||||
meshtastic_HardwareModel hw_model;
|
||||
/* Device firmware version string */
|
||||
char firmware_version[18];
|
||||
/* The region code for the radio (US, CN, EU433, etc...) */
|
||||
meshtastic_Config_LoRaConfig_RegionCode region;
|
||||
/* Modem preset used by the radio (LongFast, MediumSlow, etc...) */
|
||||
meshtastic_Config_LoRaConfig_ModemPreset modem_preset;
|
||||
/* Whether the node has a channel with default PSK and name (LongFast, MediumSlow, etc...)
|
||||
and it uses the default frequency slot given the region and modem preset. */
|
||||
bool has_default_channel;
|
||||
/* Latitude: multiply by 1e-7 to get degrees in floating point */
|
||||
int32_t latitude_i;
|
||||
/* Longitude: multiply by 1e-7 to get degrees in floating point */
|
||||
int32_t longitude_i;
|
||||
/* Altitude in meters above MSL */
|
||||
int32_t altitude;
|
||||
/* Indicates the bits of precision for latitude and longitude set by the sending node */
|
||||
uint32_t position_precision;
|
||||
/* Number of online nodes (heard in the last 2 hours) this node has in its list that were received locally (not via MQTT) */
|
||||
uint16_t num_online_local_nodes;
|
||||
} meshtastic_MapReport;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -30,12 +63,27 @@ extern "C" {
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define meshtastic_ServiceEnvelope_init_default {NULL, NULL, NULL}
|
||||
#define meshtastic_MapReport_init_default {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0}
|
||||
#define meshtastic_ServiceEnvelope_init_zero {NULL, NULL, NULL}
|
||||
#define meshtastic_MapReport_init_zero {"", "", _meshtastic_Config_DeviceConfig_Role_MIN, _meshtastic_HardwareModel_MIN, "", _meshtastic_Config_LoRaConfig_RegionCode_MIN, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, 0, 0}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define meshtastic_ServiceEnvelope_packet_tag 1
|
||||
#define meshtastic_ServiceEnvelope_channel_id_tag 2
|
||||
#define meshtastic_ServiceEnvelope_gateway_id_tag 3
|
||||
#define meshtastic_MapReport_long_name_tag 1
|
||||
#define meshtastic_MapReport_short_name_tag 2
|
||||
#define meshtastic_MapReport_role_tag 3
|
||||
#define meshtastic_MapReport_hw_model_tag 4
|
||||
#define meshtastic_MapReport_firmware_version_tag 5
|
||||
#define meshtastic_MapReport_region_tag 6
|
||||
#define meshtastic_MapReport_modem_preset_tag 7
|
||||
#define meshtastic_MapReport_has_default_channel_tag 8
|
||||
#define meshtastic_MapReport_latitude_i_tag 9
|
||||
#define meshtastic_MapReport_longitude_i_tag 10
|
||||
#define meshtastic_MapReport_altitude_tag 11
|
||||
#define meshtastic_MapReport_position_precision_tag 12
|
||||
#define meshtastic_MapReport_num_online_local_nodes_tag 13
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define meshtastic_ServiceEnvelope_FIELDLIST(X, a) \
|
||||
@ -46,13 +94,33 @@ X(a, POINTER, SINGULAR, STRING, gateway_id, 3)
|
||||
#define meshtastic_ServiceEnvelope_DEFAULT NULL
|
||||
#define meshtastic_ServiceEnvelope_packet_MSGTYPE meshtastic_MeshPacket
|
||||
|
||||
#define meshtastic_MapReport_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, STRING, long_name, 1) \
|
||||
X(a, STATIC, SINGULAR, STRING, short_name, 2) \
|
||||
X(a, STATIC, SINGULAR, UENUM, role, 3) \
|
||||
X(a, STATIC, SINGULAR, UENUM, hw_model, 4) \
|
||||
X(a, STATIC, SINGULAR, STRING, firmware_version, 5) \
|
||||
X(a, STATIC, SINGULAR, UENUM, region, 6) \
|
||||
X(a, STATIC, SINGULAR, UENUM, modem_preset, 7) \
|
||||
X(a, STATIC, SINGULAR, BOOL, has_default_channel, 8) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, latitude_i, 9) \
|
||||
X(a, STATIC, SINGULAR, SFIXED32, longitude_i, 10) \
|
||||
X(a, STATIC, SINGULAR, INT32, altitude, 11) \
|
||||
X(a, STATIC, SINGULAR, UINT32, position_precision, 12) \
|
||||
X(a, STATIC, SINGULAR, UINT32, num_online_local_nodes, 13)
|
||||
#define meshtastic_MapReport_CALLBACK NULL
|
||||
#define meshtastic_MapReport_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t meshtastic_ServiceEnvelope_msg;
|
||||
extern const pb_msgdesc_t meshtastic_MapReport_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define meshtastic_ServiceEnvelope_fields &meshtastic_ServiceEnvelope_msg
|
||||
#define meshtastic_MapReport_fields &meshtastic_MapReport_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* meshtastic_ServiceEnvelope_size depends on runtime parameters */
|
||||
#define meshtastic_MapReport_size 108
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
@ -122,6 +122,8 @@ typedef enum _meshtastic_PortNum {
|
||||
/* ATAK Plugin
|
||||
Portnum for payloads from the official Meshtastic ATAK plugin */
|
||||
meshtastic_PortNum_ATAK_PLUGIN = 72,
|
||||
/* Provides unencrypted information about a node for consumption by a map via MQTT */
|
||||
meshtastic_PortNum_MAP_REPORT_APP = 73,
|
||||
/* 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)) */
|
||||
|
@ -7,9 +7,19 @@
|
||||
|
||||
PaxcounterModule *paxcounterModule;
|
||||
|
||||
void NullFunc(){};
|
||||
|
||||
// paxcounterModule->sendInfo(NODENUM_BROADCAST);
|
||||
/**
|
||||
* Callback function for libpax.
|
||||
* We only clear our sent flag here, since this function is called from another thread, so we
|
||||
* cannot send to the mesh directly.
|
||||
*/
|
||||
void PaxcounterModule::handlePaxCounterReportRequest()
|
||||
{
|
||||
// The libpax library already updated our data structure, just before invoking this callback.
|
||||
LOG_INFO("PaxcounterModule: libpax reported new data: wifi=%d; ble=%d; uptime=%lu\n",
|
||||
paxcounterModule->count_from_libpax.wifi_count, paxcounterModule->count_from_libpax.ble_count, millis() / 1000);
|
||||
paxcounterModule->reportedDataSent = false;
|
||||
paxcounterModule->setIntervalFromNow(0);
|
||||
}
|
||||
|
||||
PaxcounterModule::PaxcounterModule()
|
||||
: concurrency::OSThread("PaxcounterModule"),
|
||||
@ -17,11 +27,20 @@ PaxcounterModule::PaxcounterModule()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the Pax information to the mesh if we got new data from libpax.
|
||||
* This is called periodically from our runOnce() method and will actually send the data to the mesh
|
||||
* if libpax updated it since the last transmission through the callback.
|
||||
* @param dest - destination node (usually NODENUM_BROADCAST)
|
||||
* @return false if sending is unnecessary, true if information was sent
|
||||
*/
|
||||
bool PaxcounterModule::sendInfo(NodeNum dest)
|
||||
{
|
||||
libpax_counter_count(&count_from_libpax);
|
||||
LOG_INFO("(Sending): pax: wifi=%d; ble=%d; uptime=%d\n", count_from_libpax.wifi_count, count_from_libpax.ble_count,
|
||||
millis() / 1000);
|
||||
if (paxcounterModule->reportedDataSent)
|
||||
return false;
|
||||
|
||||
LOG_INFO("PaxcounterModule: sending pax info wifi=%d; ble=%d; uptime=%lu\n", count_from_libpax.wifi_count,
|
||||
count_from_libpax.ble_count, millis() / 1000);
|
||||
|
||||
meshtastic_Paxcount pl = meshtastic_Paxcount_init_default;
|
||||
pl.wifi = count_from_libpax.wifi_count;
|
||||
@ -34,6 +53,9 @@ bool PaxcounterModule::sendInfo(NodeNum dest)
|
||||
p->priority = meshtastic_MeshPacket_Priority_MIN;
|
||||
|
||||
service.sendToMesh(p, RX_SRC_LOCAL, true);
|
||||
|
||||
paxcounterModule->reportedDataSent = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -67,7 +89,7 @@ int32_t PaxcounterModule::runOnce()
|
||||
libpax_default_config(&configuration);
|
||||
|
||||
configuration.blecounter = 1;
|
||||
configuration.blescantime = 0; // infinit
|
||||
configuration.blescantime = 0; // infinite
|
||||
configuration.wificounter = 1;
|
||||
configuration.wifi_channel_map = WIFI_CHANNEL_ALL;
|
||||
configuration.wifi_channel_switch_interval = 50;
|
||||
@ -76,7 +98,8 @@ int32_t PaxcounterModule::runOnce()
|
||||
libpax_update_config(&configuration);
|
||||
|
||||
// internal processing initialization
|
||||
libpax_counter_init(NullFunc, &count_from_libpax, UINT16_MAX, 1);
|
||||
libpax_counter_init(handlePaxCounterReportRequest, &count_from_libpax,
|
||||
moduleConfig.paxcounter.paxcounter_update_interval, 0);
|
||||
libpax_counter_start();
|
||||
} else {
|
||||
sendInfo(NODENUM_BROADCAST);
|
||||
|
@ -8,11 +8,15 @@
|
||||
#include <libpax_api.h>
|
||||
|
||||
/**
|
||||
* A simple example module that just replies with "Message received" to any message it receives.
|
||||
* Wrapper module for the estimate passenger (PAX) count library (https://github.com/dbinfrago/libpax) which
|
||||
* implements the core functionality of the ESP32 Paxcounter project (https://github.com/cyberman54/ESP32-Paxcounter)
|
||||
*/
|
||||
class PaxcounterModule : private concurrency::OSThread, public ProtobufModule<meshtastic_Paxcount>
|
||||
{
|
||||
bool firstTime = true;
|
||||
bool reportedDataSent = true;
|
||||
|
||||
static void handlePaxCounterReportRequest();
|
||||
|
||||
public:
|
||||
PaxcounterModule();
|
||||
|
@ -77,8 +77,7 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length)
|
||||
if (jsonPayloadStr.length() <= sizeof(p->decoded.payload.bytes)) {
|
||||
memcpy(p->decoded.payload.bytes, jsonPayloadStr.c_str(), jsonPayloadStr.length());
|
||||
p->decoded.payload.size = jsonPayloadStr.length();
|
||||
meshtastic_MeshPacket *packet = packetPool.allocCopy(*p);
|
||||
service.sendToMesh(packet, RX_SRC_LOCAL);
|
||||
service.sendToMesh(p, RX_SRC_LOCAL);
|
||||
} else {
|
||||
LOG_WARN("Received MQTT json payload too long, dropping\n");
|
||||
}
|
||||
@ -186,10 +185,17 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
|
||||
statusTopic = moduleConfig.mqtt.root + statusTopic;
|
||||
cryptTopic = moduleConfig.mqtt.root + cryptTopic;
|
||||
jsonTopic = moduleConfig.mqtt.root + jsonTopic;
|
||||
mapTopic = moduleConfig.mqtt.root + jsonTopic;
|
||||
} else {
|
||||
statusTopic = "msh" + statusTopic;
|
||||
cryptTopic = "msh" + cryptTopic;
|
||||
jsonTopic = "msh" + jsonTopic;
|
||||
mapTopic = "msh" + mapTopic;
|
||||
}
|
||||
|
||||
if (moduleConfig.mqtt.map_reporting_enabled && moduleConfig.mqtt.has_map_report_settings) {
|
||||
map_position_precision = moduleConfig.mqtt.map_report_settings.position_precision;
|
||||
map_publish_interval_secs = moduleConfig.mqtt.map_report_settings.publish_interval_secs;
|
||||
}
|
||||
|
||||
#ifdef HAS_NETWORKING
|
||||
@ -365,27 +371,30 @@ void MQTT::sendSubscriptions()
|
||||
|
||||
bool MQTT::wantsLink() const
|
||||
{
|
||||
bool hasChannel = false;
|
||||
bool hasChannelorMapReport = false;
|
||||
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
// No need for link if no channel needed it
|
||||
size_t numChan = channels.getNumChannels();
|
||||
for (size_t i = 0; i < numChan; i++) {
|
||||
const auto &ch = channels.getByIndex(i);
|
||||
if (ch.settings.uplink_enabled || ch.settings.downlink_enabled) {
|
||||
hasChannel = true;
|
||||
break;
|
||||
hasChannelorMapReport = moduleConfig.mqtt.map_reporting_enabled;
|
||||
if (!hasChannelorMapReport) {
|
||||
// No need for link if no channel needed it
|
||||
size_t numChan = channels.getNumChannels();
|
||||
for (size_t i = 0; i < numChan; i++) {
|
||||
const auto &ch = channels.getByIndex(i);
|
||||
if (ch.settings.uplink_enabled || ch.settings.downlink_enabled) {
|
||||
hasChannelorMapReport = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasChannel && moduleConfig.mqtt.proxy_to_client_enabled)
|
||||
if (hasChannelorMapReport && moduleConfig.mqtt.proxy_to_client_enabled)
|
||||
return true;
|
||||
|
||||
#if HAS_WIFI
|
||||
return hasChannel && WiFi.isConnected();
|
||||
return hasChannelorMapReport && WiFi.isConnected();
|
||||
#endif
|
||||
#if HAS_ETHERNET
|
||||
return hasChannel && Ethernet.linkStatus() == LinkON;
|
||||
return hasChannelorMapReport && Ethernet.linkStatus() == LinkON;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@ -397,6 +406,8 @@ int32_t MQTT::runOnce()
|
||||
|
||||
bool wantConnection = wantsLink();
|
||||
|
||||
perhapsReportToMap();
|
||||
|
||||
// If connected poll rapidly, otherwise only occasionally check for a wifi connection change and ability to contact server
|
||||
if (moduleConfig.mqtt.proxy_to_client_enabled) {
|
||||
publishQueuedMessages();
|
||||
@ -536,6 +547,78 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp, const meshtastic_MeshPacket &
|
||||
}
|
||||
}
|
||||
|
||||
void MQTT::perhapsReportToMap()
|
||||
{
|
||||
if (!moduleConfig.mqtt.map_reporting_enabled || !(moduleConfig.mqtt.proxy_to_client_enabled || isConnectedDirectly()))
|
||||
return;
|
||||
|
||||
if (map_position_precision == 0 || (localPosition.latitude_i == 0 && localPosition.longitude_i == 0)) {
|
||||
LOG_WARN("MQTT Map reporting is enabled, but precision is 0 or no position available.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (millis() - last_report_to_map < map_publish_interval_secs * 1000) {
|
||||
return;
|
||||
} else {
|
||||
// Allocate ServiceEnvelope and fill it
|
||||
meshtastic_ServiceEnvelope *se = mqttPool.allocZeroed();
|
||||
se->channel_id = (char *)channels.getGlobalId(channels.getPrimaryIndex()); // Use primary channel as the channel_id
|
||||
se->gateway_id = owner.id;
|
||||
|
||||
// Allocate MeshPacket and fill it
|
||||
meshtastic_MeshPacket *mp = packetPool.allocZeroed();
|
||||
mp->which_payload_variant = meshtastic_MeshPacket_decoded_tag;
|
||||
mp->from = nodeDB.getNodeNum();
|
||||
mp->to = NODENUM_BROADCAST;
|
||||
mp->decoded.portnum = meshtastic_PortNum_MAP_REPORT_APP;
|
||||
|
||||
// Fill MapReport message
|
||||
meshtastic_MapReport mapReport = meshtastic_MapReport_init_default;
|
||||
memcpy(mapReport.long_name, owner.long_name, sizeof(owner.long_name));
|
||||
memcpy(mapReport.short_name, owner.short_name, sizeof(owner.short_name));
|
||||
mapReport.role = config.device.role;
|
||||
mapReport.hw_model = owner.hw_model;
|
||||
strncpy(mapReport.firmware_version, optstr(APP_VERSION), sizeof(mapReport.firmware_version));
|
||||
mapReport.region = config.lora.region;
|
||||
mapReport.modem_preset = config.lora.modem_preset;
|
||||
mapReport.has_default_channel = channels.hasDefaultChannel();
|
||||
|
||||
// Set position with precision (same as in PositionModule)
|
||||
if (map_position_precision < 32 && map_position_precision > 0) {
|
||||
mapReport.latitude_i = localPosition.latitude_i & (UINT32_MAX << (32 - map_position_precision));
|
||||
mapReport.longitude_i = localPosition.longitude_i & (UINT32_MAX << (32 - map_position_precision));
|
||||
mapReport.latitude_i += (1 << (31 - map_position_precision));
|
||||
mapReport.longitude_i += (1 << (31 - map_position_precision));
|
||||
} else {
|
||||
mapReport.latitude_i = localPosition.latitude_i;
|
||||
mapReport.longitude_i = localPosition.longitude_i;
|
||||
}
|
||||
mapReport.altitude = localPosition.altitude;
|
||||
mapReport.position_precision = map_position_precision;
|
||||
|
||||
mapReport.num_online_local_nodes = nodeDB.getNumOnlineMeshNodes(true);
|
||||
|
||||
// Encode MapReport message and set it to MeshPacket in ServiceEnvelope
|
||||
mp->decoded.payload.size = pb_encode_to_bytes(mp->decoded.payload.bytes, sizeof(mp->decoded.payload.bytes),
|
||||
&meshtastic_MapReport_msg, &mapReport);
|
||||
se->packet = mp;
|
||||
|
||||
// FIXME - this size calculation is super sloppy, but it will go away once we dynamically alloc meshpackets
|
||||
static uint8_t bytes[meshtastic_MeshPacket_size + 64];
|
||||
size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, se);
|
||||
|
||||
LOG_INFO("MQTT Publish map report to %s\n", mapTopic.c_str());
|
||||
publish(mapTopic.c_str(), bytes, numBytes, false);
|
||||
|
||||
// Release the allocated memory for ServiceEnvelope and MeshPacket
|
||||
mqttPool.release(se);
|
||||
packetPool.release(mp);
|
||||
|
||||
// Update the last report time
|
||||
last_report_to_map = millis();
|
||||
}
|
||||
}
|
||||
|
||||
// converts a downstream packet into a json message
|
||||
std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
||||
{
|
||||
|
@ -79,11 +79,18 @@ class MQTT : private concurrency::OSThread
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
private:
|
||||
std::string statusTopic = "/2/stat/";
|
||||
std::string cryptTopic = "/2/e/"; // msh/2/e/CHANNELID/NODEID
|
||||
std::string jsonTopic = "/2/json/"; // msh/2/json/CHANNELID/NODEID
|
||||
/** return true if we have a channel that wants uplink/downlink
|
||||
*/
|
||||
std::string statusTopic = "/2/stat/"; // For "online"/"offline" message
|
||||
std::string cryptTopic = "/2/e/"; // msh/2/e/CHANNELID/NODEID
|
||||
std::string jsonTopic = "/2/json/"; // msh/2/json/CHANNELID/NODEID
|
||||
std::string mapTopic = "/2/map/"; // For protobuf-encoded MapReport messages
|
||||
|
||||
// For map reporting (only applies when enabled)
|
||||
uint32_t last_report_to_map = 0;
|
||||
uint32_t map_position_precision = 32; // default to full precision
|
||||
uint32_t map_publish_interval_secs = 60 * 15; // default to 15 minutes
|
||||
|
||||
/** return true if we have a channel that wants uplink/downlink or map reporting is enabled
|
||||
*/
|
||||
bool wantsLink() const;
|
||||
|
||||
/** Tell the server what subscriptions we want (based on channels.downlink_enabled)
|
||||
@ -102,6 +109,9 @@ class MQTT : private concurrency::OSThread
|
||||
void publishStatus();
|
||||
void publishQueuedMessages();
|
||||
|
||||
// Check if we should report unencrypted information about our node for consumption by a map
|
||||
void perhapsReportToMap();
|
||||
|
||||
// returns true if this is a valid JSON envelope which we accept on downlink
|
||||
bool isValidJsonEnvelope(JSONObject &json);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user