Initial air quality telemetry feature

This commit is contained in:
Ben Meadors 2023-02-04 13:07:14 -06:00
parent 22500a6c34
commit d83a0b1818
13 changed files with 301 additions and 19 deletions

View File

@ -2,7 +2,7 @@
; https://docs.platformio.org/page/projectconf.html ; https://docs.platformio.org/page/projectconf.html
[platformio] [platformio]
;default_envs = tbeam default_envs = tbeam
;default_envs = pico ;default_envs = pico
;default_envs = tbeam-s3-core ;default_envs = tbeam-s3-core
;default_envs = tbeam0.7 ;default_envs = tbeam0.7
@ -109,3 +109,4 @@ lib_deps =
adafruit/Adafruit SHTC3 Library@^1.0.0 adafruit/Adafruit SHTC3 Library@^1.0.0
adafruit/Adafruit LPS2X@^2.0.4 adafruit/Adafruit LPS2X@^2.0.4
adafruit/Adafruit SHT31 Library@^2.2.0 adafruit/Adafruit SHT31 Library@^2.2.0
adafruit/Adafruit PM25 AQI Sensor@^1.0.6

@ -1 +1 @@
Subproject commit 516074f2e49743c234430abb2ea43ea3f66b0acb Subproject commit 384b664a759592d9393642ba98835f69bb8f2fb2

View File

@ -116,6 +116,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define LPS22HB_ADDR 0x5C #define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D #define LPS22HB_ADDR_ALT 0x5D
#define SHT31_ADDR 0x44 #define SHT31_ADDR 0x44
#define PMSA0031_ADDR 0x12
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Security // Security

View File

@ -218,6 +218,10 @@ void scanI2Cdevice()
LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n"); LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC5883L] = addr; nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_QMC5883L] = addr;
} }
if (addr == PMSA0031_ADDR) {
LOG_INFO("PMSA0031 air quality sensor found\n");
nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I] = addr;
}
} else if (err == 4) { } else if (err == 4) {
LOG_ERROR("Unknow error at address 0x%x\n", addr); LOG_ERROR("Unknow error at address 0x%x\n", addr);
} }

View File

@ -276,7 +276,6 @@ void setup()
LOG_INFO("PCF8563 RTC found\n"); LOG_INFO("PCF8563 RTC found\n");
} }
#endif #endif
// We need to scan here to decide if we have a screen for nodeDB.init() // We need to scan here to decide if we have a screen for nodeDB.init()
scanI2Cdevice(); scanI2Cdevice();

View File

@ -9,6 +9,9 @@
PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2) PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2)
PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO)

View File

@ -57,6 +57,18 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
} meshtastic_AdminMessage_ModuleConfigType; } meshtastic_AdminMessage_ModuleConfigType;
/* Struct definitions */ /* Struct definitions */
/* Parameters for setting up Meshtastic for ameteur radio usage */
typedef struct _meshtastic_HamParameters {
/* Amateur radio call sign, eg. KD2ABC */
char call_sign[8];
/* Transmit power in dBm at the LoRA transceiver, not including any amplification */
int32_t tx_power;
/* The selected frequency of LoRA operation
Please respect your local laws, regulations, and band plans.
Ensure your radio is capable of operating of the selected frequency before setting this. */
float frequency;
} meshtastic_HamParameters;
/* This message is handled by the Admin module and is responsible for all settings/channel read/write operations. /* This message is handled by the Admin module and is responsible for all settings/channel read/write operations.
This message is used to do settings operations to both remote AND local nodes. This message is used to do settings operations to both remote AND local nodes.
(Prior to 1.2 these operations were done via special ToRadio operations) */ (Prior to 1.2 these operations were done via special ToRadio operations) */
@ -96,6 +108,8 @@ typedef struct _meshtastic_AdminMessage {
bool get_device_connection_status_request; bool get_device_connection_status_request;
/* Device connection status response */ /* Device connection status response */
meshtastic_DeviceConnectionStatus get_device_connection_status_response; meshtastic_DeviceConnectionStatus get_device_connection_status_response;
/* Setup a node for licensed amateur (ham) radio operation */
meshtastic_HamParameters set_ham_mode;
/* Set the owner for this node */ /* Set the owner for this node */
meshtastic_User set_owner; meshtastic_User set_owner;
/* Set channels (using the new API). /* Set channels (using the new API).
@ -152,11 +166,17 @@ extern "C" {
#define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType #define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType
/* Initializer values for message structs */ /* Initializer values for message structs */
#define meshtastic_AdminMessage_init_default {0, {0}} #define meshtastic_AdminMessage_init_default {0, {0}}
#define meshtastic_HamParameters_init_default {"", 0, 0}
#define meshtastic_AdminMessage_init_zero {0, {0}} #define meshtastic_AdminMessage_init_zero {0, {0}}
#define meshtastic_HamParameters_init_zero {"", 0, 0}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
#define meshtastic_HamParameters_call_sign_tag 1
#define meshtastic_HamParameters_tx_power_tag 2
#define meshtastic_HamParameters_frequency_tag 3
#define meshtastic_AdminMessage_get_channel_request_tag 1 #define meshtastic_AdminMessage_get_channel_request_tag 1
#define meshtastic_AdminMessage_get_channel_response_tag 2 #define meshtastic_AdminMessage_get_channel_response_tag 2
#define meshtastic_AdminMessage_get_owner_request_tag 3 #define meshtastic_AdminMessage_get_owner_request_tag 3
@ -173,6 +193,7 @@ extern "C" {
#define meshtastic_AdminMessage_get_ringtone_response_tag 15 #define meshtastic_AdminMessage_get_ringtone_response_tag 15
#define meshtastic_AdminMessage_get_device_connection_status_request_tag 16 #define meshtastic_AdminMessage_get_device_connection_status_request_tag 16
#define meshtastic_AdminMessage_get_device_connection_status_response_tag 17 #define meshtastic_AdminMessage_get_device_connection_status_response_tag 17
#define meshtastic_AdminMessage_set_ham_mode_tag 18
#define meshtastic_AdminMessage_set_owner_tag 32 #define meshtastic_AdminMessage_set_owner_tag 32
#define meshtastic_AdminMessage_set_channel_tag 33 #define meshtastic_AdminMessage_set_channel_tag 33
#define meshtastic_AdminMessage_set_config_tag 34 #define meshtastic_AdminMessage_set_config_tag 34
@ -206,6 +227,7 @@ X(a, STATIC, ONEOF, BOOL, (payload_variant,get_ringtone_request,get_rin
X(a, STATIC, ONEOF, STRING, (payload_variant,get_ringtone_response,get_ringtone_response), 15) \ X(a, STATIC, ONEOF, STRING, (payload_variant,get_ringtone_response,get_ringtone_response), 15) \
X(a, STATIC, ONEOF, BOOL, (payload_variant,get_device_connection_status_request,get_device_connection_status_request), 16) \ X(a, STATIC, ONEOF, BOOL, (payload_variant,get_device_connection_status_request,get_device_connection_status_request), 16) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_connection_status_response,get_device_connection_status_response), 17) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,get_device_connection_status_response,get_device_connection_status_response), 17) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_ham_mode,set_ham_mode), 18) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_owner,set_owner), 32) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_channel,set_channel), 33) \
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,set_config,set_config), 34) \
@ -228,18 +250,29 @@ X(a, STATIC, ONEOF, INT32, (payload_variant,nodedb_reset,nodedb_reset),
#define meshtastic_AdminMessage_payload_variant_get_module_config_response_MSGTYPE meshtastic_ModuleConfig #define meshtastic_AdminMessage_payload_variant_get_module_config_response_MSGTYPE meshtastic_ModuleConfig
#define meshtastic_AdminMessage_payload_variant_get_device_metadata_response_MSGTYPE meshtastic_DeviceMetadata #define meshtastic_AdminMessage_payload_variant_get_device_metadata_response_MSGTYPE meshtastic_DeviceMetadata
#define meshtastic_AdminMessage_payload_variant_get_device_connection_status_response_MSGTYPE meshtastic_DeviceConnectionStatus #define meshtastic_AdminMessage_payload_variant_get_device_connection_status_response_MSGTYPE meshtastic_DeviceConnectionStatus
#define meshtastic_AdminMessage_payload_variant_set_ham_mode_MSGTYPE meshtastic_HamParameters
#define meshtastic_AdminMessage_payload_variant_set_owner_MSGTYPE meshtastic_User #define meshtastic_AdminMessage_payload_variant_set_owner_MSGTYPE meshtastic_User
#define meshtastic_AdminMessage_payload_variant_set_channel_MSGTYPE meshtastic_Channel #define meshtastic_AdminMessage_payload_variant_set_channel_MSGTYPE meshtastic_Channel
#define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config #define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config
#define meshtastic_AdminMessage_payload_variant_set_module_config_MSGTYPE meshtastic_ModuleConfig #define meshtastic_AdminMessage_payload_variant_set_module_config_MSGTYPE meshtastic_ModuleConfig
#define meshtastic_HamParameters_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, STRING, call_sign, 1) \
X(a, STATIC, SINGULAR, INT32, tx_power, 2) \
X(a, STATIC, SINGULAR, FLOAT, frequency, 3)
#define meshtastic_HamParameters_CALLBACK NULL
#define meshtastic_HamParameters_DEFAULT NULL
extern const pb_msgdesc_t meshtastic_AdminMessage_msg; extern const pb_msgdesc_t meshtastic_AdminMessage_msg;
extern const pb_msgdesc_t meshtastic_HamParameters_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ /* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg #define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg
#define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define meshtastic_AdminMessage_size 234 #define meshtastic_AdminMessage_size 234
#define meshtastic_HamParameters_size 25
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -12,6 +12,9 @@ PB_BIND(meshtastic_DeviceMetrics, meshtastic_DeviceMetrics, AUTO)
PB_BIND(meshtastic_EnvironmentMetrics, meshtastic_EnvironmentMetrics, AUTO) PB_BIND(meshtastic_EnvironmentMetrics, meshtastic_EnvironmentMetrics, AUTO)
PB_BIND(meshtastic_AirQualityMetrics, meshtastic_AirQualityMetrics, AUTO)
PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO) PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO)

View File

@ -10,7 +10,7 @@
#endif #endif
/* Enum definitions */ /* Enum definitions */
/* TODO: REPLACE */ /* Supported I2C Sensors for telemetry in Meshtastic */
typedef enum _meshtastic_TelemetrySensorType { typedef enum _meshtastic_TelemetrySensorType {
/* No external telemetry sensor explicitly set */ /* No external telemetry sensor explicitly set */
meshtastic_TelemetrySensorType_SENSOR_UNSET = 0, meshtastic_TelemetrySensorType_SENSOR_UNSET = 0,
@ -37,7 +37,9 @@ typedef enum _meshtastic_TelemetrySensorType {
/* 3-Axis magnetic sensor */ /* 3-Axis magnetic sensor */
meshtastic_TelemetrySensorType_QMC5883L = 11, meshtastic_TelemetrySensorType_QMC5883L = 11,
/* High accuracy temperature and humidity */ /* High accuracy temperature and humidity */
meshtastic_TelemetrySensorType_SHT31 = 12 meshtastic_TelemetrySensorType_SHT31 = 12,
/* PM2.5 air quality sensor */
meshtastic_TelemetrySensorType_PMSA003I = 13
} meshtastic_TelemetrySensorType; } meshtastic_TelemetrySensorType;
/* Struct definitions */ /* Struct definitions */
@ -69,6 +71,34 @@ typedef struct _meshtastic_EnvironmentMetrics {
float current; float current;
} meshtastic_EnvironmentMetrics; } meshtastic_EnvironmentMetrics;
/* Air quality metrics */
typedef struct _meshtastic_AirQualityMetrics {
/* Standard PM1.0 */
uint32_t pm10_standard;
/* Standard PM2.5 */
uint32_t pm25_standard;
/* Standard PM10.0 */
uint32_t pm100_standard;
/* Environmental PM1.0 */
uint32_t pm10_environmental;
/* Environmental PM2.5 */
uint32_t pm25_environmental;
/* Environmental PM10.0 */
uint32_t pm100_environmental;
/* 0.3um Particle Count */
uint32_t particles_03um;
/* 0.5um Particle Count */
uint32_t particles_05um;
/* 1.0um Particle Count */
uint32_t particles_10um;
/* 2.5um Particle Count */
uint32_t particles_25um;
/* 5.0um Particle Count */
uint32_t particles_50um;
/* 10.0um Particle Count */
uint32_t particles_100um;
} meshtastic_AirQualityMetrics;
/* Types of Measurements the telemetry module is equipped to handle */ /* Types of Measurements the telemetry module is equipped to handle */
typedef struct _meshtastic_Telemetry { typedef struct _meshtastic_Telemetry {
/* This is usually not sent over the mesh (to save space), but it is sent /* This is usually not sent over the mesh (to save space), but it is sent
@ -83,6 +113,8 @@ typedef struct _meshtastic_Telemetry {
meshtastic_DeviceMetrics device_metrics; meshtastic_DeviceMetrics device_metrics;
/* Weather station or other environmental metrics */ /* Weather station or other environmental metrics */
meshtastic_EnvironmentMetrics environment_metrics; meshtastic_EnvironmentMetrics environment_metrics;
/* Air quality metrics */
meshtastic_AirQualityMetrics air_quality_metrics;
} variant; } variant;
} meshtastic_Telemetry; } meshtastic_Telemetry;
@ -93,8 +125,9 @@ extern "C" {
/* Helper constants for enums */ /* Helper constants for enums */
#define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET
#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SHT31 #define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_PMSA003I
#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SHT31+1)) #define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_PMSA003I+1))
@ -103,9 +136,11 @@ extern "C" {
/* Initializer values for message structs */ /* Initializer values for message structs */
#define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0} #define meshtastic_DeviceMetrics_init_default {0, 0, 0, 0}
#define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_EnvironmentMetrics_init_default {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}} #define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
#define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0} #define meshtastic_DeviceMetrics_init_zero {0, 0, 0, 0}
#define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_EnvironmentMetrics_init_zero {0, 0, 0, 0, 0, 0}
#define meshtastic_AirQualityMetrics_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}} #define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
/* Field tags (for use in manual encoding/decoding) */ /* Field tags (for use in manual encoding/decoding) */
@ -119,9 +154,22 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_gas_resistance_tag 4 #define meshtastic_EnvironmentMetrics_gas_resistance_tag 4
#define meshtastic_EnvironmentMetrics_voltage_tag 5 #define meshtastic_EnvironmentMetrics_voltage_tag 5
#define meshtastic_EnvironmentMetrics_current_tag 6 #define meshtastic_EnvironmentMetrics_current_tag 6
#define meshtastic_AirQualityMetrics_pm10_standard_tag 1
#define meshtastic_AirQualityMetrics_pm25_standard_tag 2
#define meshtastic_AirQualityMetrics_pm100_standard_tag 3
#define meshtastic_AirQualityMetrics_pm10_environmental_tag 4
#define meshtastic_AirQualityMetrics_pm25_environmental_tag 5
#define meshtastic_AirQualityMetrics_pm100_environmental_tag 6
#define meshtastic_AirQualityMetrics_particles_03um_tag 7
#define meshtastic_AirQualityMetrics_particles_05um_tag 8
#define meshtastic_AirQualityMetrics_particles_10um_tag 9
#define meshtastic_AirQualityMetrics_particles_25um_tag 10
#define meshtastic_AirQualityMetrics_particles_50um_tag 11
#define meshtastic_AirQualityMetrics_particles_100um_tag 12
#define meshtastic_Telemetry_time_tag 1 #define meshtastic_Telemetry_time_tag 1
#define meshtastic_Telemetry_device_metrics_tag 2 #define meshtastic_Telemetry_device_metrics_tag 2
#define meshtastic_Telemetry_environment_metrics_tag 3 #define meshtastic_Telemetry_environment_metrics_tag 3
#define meshtastic_Telemetry_air_quality_metrics_tag 4
/* Struct field encoding specification for nanopb */ /* Struct field encoding specification for nanopb */
#define meshtastic_DeviceMetrics_FIELDLIST(X, a) \ #define meshtastic_DeviceMetrics_FIELDLIST(X, a) \
@ -142,28 +190,49 @@ X(a, STATIC, SINGULAR, FLOAT, current, 6)
#define meshtastic_EnvironmentMetrics_CALLBACK NULL #define meshtastic_EnvironmentMetrics_CALLBACK NULL
#define meshtastic_EnvironmentMetrics_DEFAULT NULL #define meshtastic_EnvironmentMetrics_DEFAULT NULL
#define meshtastic_AirQualityMetrics_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, pm10_standard, 1) \
X(a, STATIC, SINGULAR, UINT32, pm25_standard, 2) \
X(a, STATIC, SINGULAR, UINT32, pm100_standard, 3) \
X(a, STATIC, SINGULAR, UINT32, pm10_environmental, 4) \
X(a, STATIC, SINGULAR, UINT32, pm25_environmental, 5) \
X(a, STATIC, SINGULAR, UINT32, pm100_environmental, 6) \
X(a, STATIC, SINGULAR, UINT32, particles_03um, 7) \
X(a, STATIC, SINGULAR, UINT32, particles_05um, 8) \
X(a, STATIC, SINGULAR, UINT32, particles_10um, 9) \
X(a, STATIC, SINGULAR, UINT32, particles_25um, 10) \
X(a, STATIC, SINGULAR, UINT32, particles_50um, 11) \
X(a, STATIC, SINGULAR, UINT32, particles_100um, 12)
#define meshtastic_AirQualityMetrics_CALLBACK NULL
#define meshtastic_AirQualityMetrics_DEFAULT NULL
#define meshtastic_Telemetry_FIELDLIST(X, a) \ #define meshtastic_Telemetry_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, FIXED32, time, 1) \ X(a, STATIC, SINGULAR, FIXED32, time, 1) \
X(a, STATIC, ONEOF, MESSAGE, (variant,device_metrics,variant.device_metrics), 2) \ X(a, STATIC, ONEOF, MESSAGE, (variant,device_metrics,variant.device_metrics), 2) \
X(a, STATIC, ONEOF, MESSAGE, (variant,environment_metrics,variant.environment_metrics), 3) X(a, STATIC, ONEOF, MESSAGE, (variant,environment_metrics,variant.environment_metrics), 3) \
X(a, STATIC, ONEOF, MESSAGE, (variant,air_quality_metrics,variant.air_quality_metrics), 4)
#define meshtastic_Telemetry_CALLBACK NULL #define meshtastic_Telemetry_CALLBACK NULL
#define meshtastic_Telemetry_DEFAULT NULL #define meshtastic_Telemetry_DEFAULT NULL
#define meshtastic_Telemetry_variant_device_metrics_MSGTYPE meshtastic_DeviceMetrics #define meshtastic_Telemetry_variant_device_metrics_MSGTYPE meshtastic_DeviceMetrics
#define meshtastic_Telemetry_variant_environment_metrics_MSGTYPE meshtastic_EnvironmentMetrics #define meshtastic_Telemetry_variant_environment_metrics_MSGTYPE meshtastic_EnvironmentMetrics
#define meshtastic_Telemetry_variant_air_quality_metrics_MSGTYPE meshtastic_AirQualityMetrics
extern const pb_msgdesc_t meshtastic_DeviceMetrics_msg; extern const pb_msgdesc_t meshtastic_DeviceMetrics_msg;
extern const pb_msgdesc_t meshtastic_EnvironmentMetrics_msg; extern const pb_msgdesc_t meshtastic_EnvironmentMetrics_msg;
extern const pb_msgdesc_t meshtastic_AirQualityMetrics_msg;
extern const pb_msgdesc_t meshtastic_Telemetry_msg; extern const pb_msgdesc_t meshtastic_Telemetry_msg;
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ /* Defines for backwards compatibility with code written before nanopb-0.4.0 */
#define meshtastic_DeviceMetrics_fields &meshtastic_DeviceMetrics_msg #define meshtastic_DeviceMetrics_fields &meshtastic_DeviceMetrics_msg
#define meshtastic_EnvironmentMetrics_fields &meshtastic_EnvironmentMetrics_msg #define meshtastic_EnvironmentMetrics_fields &meshtastic_EnvironmentMetrics_msg
#define meshtastic_AirQualityMetrics_fields &meshtastic_AirQualityMetrics_msg
#define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg #define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg
/* Maximum encoded size of messages (where known) */ /* Maximum encoded size of messages (where known) */
#define meshtastic_AirQualityMetrics_size 72
#define meshtastic_DeviceMetrics_size 21 #define meshtastic_DeviceMetrics_size 21
#define meshtastic_EnvironmentMetrics_size 30 #define meshtastic_EnvironmentMetrics_size 30
#define meshtastic_Telemetry_size 37 #define meshtastic_Telemetry_size 79
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -14,6 +14,7 @@
#include "modules/TraceRouteModule.h" #include "modules/TraceRouteModule.h"
#include "modules/WaypointModule.h" #include "modules/WaypointModule.h"
#if HAS_TELEMETRY #if HAS_TELEMETRY
#include "modules/Telemetry/AirQualityTelemetry.h"
#include "modules/Telemetry/DeviceTelemetry.h" #include "modules/Telemetry/DeviceTelemetry.h"
#include "modules/Telemetry/EnvironmentTelemetry.h" #include "modules/Telemetry/EnvironmentTelemetry.h"
#endif #endif
@ -63,6 +64,9 @@ void setupModules()
#if HAS_TELEMETRY #if HAS_TELEMETRY
new DeviceTelemetryModule(); new DeviceTelemetryModule();
new EnvironmentTelemetryModule(); new EnvironmentTelemetryModule();
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I] > 0) {
new AirQualityTelemetryModule();
}
#endif #endif
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) #if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2)
new SerialModule(); new SerialModule();

View File

@ -0,0 +1,128 @@
#include "AirQualityTelemetry.h"
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "PowerFSM.h"
#include "RTC.h"
#include "Router.h"
#include "configuration.h"
#include "main.h"
int32_t AirQualityTelemetryModule::runOnce()
{
#ifndef ARCH_PORTDUINO
int32_t result = INT32_MAX;
/*
Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI.
*/
// moduleConfig.telemetry.environment_measurement_enabled = 1;
if (!(moduleConfig.telemetry.environment_measurement_enabled)) {
// If this module is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
return disable();
}
if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup
firstTime = 0;
if (moduleConfig.telemetry.environment_measurement_enabled) {
LOG_INFO("Air quality Telemetry: Initializing\n");
if (!aqi.begin_I2C()) {
LOG_WARN("Could not establish i2c connection to AQI sensor\n");
return disable();
}
return 1000;
}
return result;
} else {
// if we somehow got to a second run of this module with measurement disabled, then just wait forever
if (!moduleConfig.telemetry.environment_measurement_enabled)
return result;
uint32_t now = millis();
if (((lastSentToMesh == 0) ||
((now - lastSentToMesh) >= getConfiguredOrDefaultMs(moduleConfig.telemetry.environment_update_interval))) &&
airTime->isTxAllowedAirUtil()) {
sendTelemetry();
lastSentToMesh = now;
} else if (service.isToPhoneQueueEmpty()) {
// Just send to phone when it's not our time to send to mesh yet
// Only send while queue is empty (phone assumed connected)
sendTelemetry(NODENUM_BROADCAST, true);
}
}
return sendToPhoneIntervalMs;
#endif
}
bool AirQualityTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t)
{
if (t->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
const char *sender = getSenderShortName(mp);
LOG_INFO("(Received from %s): pm10_standard=%i, pm25_standard=%i, pm100_standard=%i\n", sender,
t->variant.air_quality_metrics.pm10_standard, t->variant.air_quality_metrics.pm25_standard,
t->variant.air_quality_metrics.pm100_standard);
LOG_INFO(" | PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i\n",
t->variant.air_quality_metrics.pm10_environmental, t->variant.air_quality_metrics.pm25_environmental,
t->variant.air_quality_metrics.pm100_environmental);
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
packetPool.release(lastMeasurementPacket);
lastMeasurementPacket = packetPool.allocCopy(mp);
}
return false; // Let others look at this message also if they want
}
bool AirQualityTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
{
if (!aqi.read(&data)) {
LOG_WARN("Skipping send measurements. Could not read AQIn\n");
return false;
}
meshtastic_Telemetry m;
m.time = getTime();
m.which_variant = meshtastic_Telemetry_air_quality_metrics_tag;
m.variant.air_quality_metrics.pm10_standard = data.pm10_standard;
m.variant.air_quality_metrics.pm25_standard = data.pm25_standard;
m.variant.air_quality_metrics.pm100_standard = data.pm100_standard;
m.variant.air_quality_metrics.pm10_environmental = data.pm10_env;
m.variant.air_quality_metrics.pm25_environmental = data.pm25_env;
m.variant.air_quality_metrics.pm100_environmental = data.pm100_env;
LOG_INFO("(Sending): PM1.0(Standard)=%i, PM2.5(Standard)=%i, PM10.0(Standard)=%i\n",
m.variant.air_quality_metrics.pm10_standard, m.variant.air_quality_metrics.pm25_standard,
m.variant.air_quality_metrics.pm100_standard);
LOG_INFO(" | PM1.0(Environmental)=%i, PM2.5(Environmental)=%i, PM10.0(Environmental)=%i\n",
m.variant.air_quality_metrics.pm10_environmental, m.variant.air_quality_metrics.pm25_environmental,
m.variant.air_quality_metrics.pm100_environmental);
meshtastic_MeshPacket *p = allocDataProtobuf(m);
p->to = dest;
p->decoded.want_response = false;
p->priority = meshtastic_MeshPacket_Priority_MIN;
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
packetPool.release(lastMeasurementPacket);
lastMeasurementPacket = packetPool.allocCopy(*p);
if (phoneOnly) {
LOG_INFO("Sending packet to phone\n");
service.sendToPhone(p);
} else {
LOG_INFO("Sending packet to mesh\n");
service.sendToMesh(p, RX_SRC_LOCAL, true);
}
return true;
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "Adafruit_PM25AQI.h"
#include "NodeDB.h"
#include "ProtobufModule.h"
class AirQualityTelemetryModule : private concurrency::OSThread, public ProtobufModule<meshtastic_Telemetry>
{
public:
AirQualityTelemetryModule()
: concurrency::OSThread("AirQualityTelemetryModule"),
ProtobufModule("AirQualityTelemetry", meshtastic_PortNum_TELEMETRY_APP, &meshtastic_Telemetry_msg)
{
lastMeasurementPacket = nullptr;
setIntervalFromNow(10 * 1000);
aqi = Adafruit_PM25AQI();
}
protected:
/** 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_Telemetry *p) override;
virtual int32_t runOnce() override;
/**
* Send our Telemetry into the mesh
*/
bool sendTelemetry(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private:
Adafruit_PM25AQI aqi;
PM25_AQI_Data data;
bool firstTime = 1;
meshtastic_MeshPacket *lastMeasurementPacket;
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
uint32_t lastSentToMesh = 0;
};

View File

@ -118,6 +118,16 @@ int32_t EnvironmentTelemetryModule::runOnce()
#endif #endif
} }
bool EnvironmentTelemetryModule::wantUIFrame()
{
return moduleConfig.telemetry.environment_screen_enabled;
}
float EnvironmentTelemetryModule::CelsiusToFahrenheit(float c)
{
return (c * 9) / 5 + 32;
}
uint32_t GetTimeSinceMeshPacket(const meshtastic_MeshPacket *mp) uint32_t GetTimeSinceMeshPacket(const meshtastic_MeshPacket *mp)
{ {
uint32_t now = getTime(); uint32_t now = getTime();
@ -130,16 +140,6 @@ uint32_t GetTimeSinceMeshPacket(const meshtastic_MeshPacket *mp)
return delta; return delta;
} }
bool EnvironmentTelemetryModule::wantUIFrame()
{
return moduleConfig.telemetry.environment_screen_enabled;
}
float EnvironmentTelemetryModule::CelsiusToFahrenheit(float c)
{
return (c * 9) / 5 + 32;
}
void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);