kopia lustrzana https://github.com/meshtastic/firmware
				
				
				
			Initial air quality telemetry feature
							rodzic
							
								
									22500a6c34
								
							
						
					
					
						commit
						d83a0b1818
					
				|  | @ -2,7 +2,7 @@ | |||
| ; https://docs.platformio.org/page/projectconf.html | ||||
| 
 | ||||
| [platformio] | ||||
| ;default_envs = tbeam | ||||
| default_envs = tbeam | ||||
| ;default_envs = pico | ||||
| ;default_envs = tbeam-s3-core | ||||
| ;default_envs = tbeam0.7 | ||||
|  | @ -109,3 +109,4 @@ lib_deps = | |||
|   adafruit/Adafruit SHTC3 Library@^1.0.0 | ||||
|   adafruit/Adafruit LPS2X@^2.0.4 | ||||
|   adafruit/Adafruit SHT31 Library@^2.2.0 | ||||
|   adafruit/Adafruit PM25 AQI Sensor@^1.0.6 | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| Subproject commit 516074f2e49743c234430abb2ea43ea3f66b0acb | ||||
| Subproject commit 384b664a759592d9393642ba98835f69bb8f2fb2 | ||||
|  | @ -116,6 +116,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||
| #define LPS22HB_ADDR 0x5C | ||||
| #define LPS22HB_ADDR_ALT 0x5D | ||||
| #define SHT31_ADDR 0x44 | ||||
| #define PMSA0031_ADDR 0x12 | ||||
| 
 | ||||
| // -----------------------------------------------------------------------------
 | ||||
| // Security
 | ||||
|  |  | |||
|  | @ -218,6 +218,10 @@ void scanI2Cdevice() | |||
|                 LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n"); | ||||
|                 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) { | ||||
|             LOG_ERROR("Unknow error at address 0x%x\n", addr); | ||||
|         } | ||||
|  |  | |||
|  | @ -276,7 +276,6 @@ void setup() | |||
|         LOG_INFO("PCF8563 RTC found\n"); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|     // We need to scan here to decide if we have a screen for nodeDB.init()
 | ||||
|     scanI2Cdevice(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,9 @@ | |||
| PB_BIND(meshtastic_AdminMessage, meshtastic_AdminMessage, 2) | ||||
| 
 | ||||
| 
 | ||||
| PB_BIND(meshtastic_HamParameters, meshtastic_HamParameters, AUTO) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -57,6 +57,18 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType { | |||
| } meshtastic_AdminMessage_ModuleConfigType; | ||||
| 
 | ||||
| /* 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 used to do settings operations to both remote AND local nodes. | ||||
|  (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; | ||||
|         /* 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 */ | ||||
|         meshtastic_User set_owner; | ||||
|         /* 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 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Initializer values for message structs */ | ||||
| #define meshtastic_AdminMessage_init_default     {0, {0}} | ||||
| #define meshtastic_HamParameters_init_default    {"", 0, 0} | ||||
| #define meshtastic_AdminMessage_init_zero        {0, {0}} | ||||
| #define meshtastic_HamParameters_init_zero       {"", 0, 0} | ||||
| 
 | ||||
| /* 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_response_tag 2 | ||||
| #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_device_connection_status_request_tag 16 | ||||
| #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_channel_tag  33 | ||||
| #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,    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,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_channel,set_channel),  33) \ | ||||
| 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_device_metadata_response_MSGTYPE meshtastic_DeviceMetadata | ||||
| #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_channel_MSGTYPE meshtastic_Channel | ||||
| #define meshtastic_AdminMessage_payload_variant_set_config_MSGTYPE meshtastic_Config | ||||
| #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_HamParameters_msg; | ||||
| 
 | ||||
| /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ | ||||
| #define meshtastic_AdminMessage_fields &meshtastic_AdminMessage_msg | ||||
| #define meshtastic_HamParameters_fields &meshtastic_HamParameters_msg | ||||
| 
 | ||||
| /* Maximum encoded size of messages (where known) */ | ||||
| #define meshtastic_AdminMessage_size             234 | ||||
| #define meshtastic_HamParameters_size            25 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
|  |  | |||
|  | @ -12,6 +12,9 @@ PB_BIND(meshtastic_DeviceMetrics, meshtastic_DeviceMetrics, AUTO) | |||
| PB_BIND(meshtastic_EnvironmentMetrics, meshtastic_EnvironmentMetrics, AUTO) | ||||
| 
 | ||||
| 
 | ||||
| PB_BIND(meshtastic_AirQualityMetrics, meshtastic_AirQualityMetrics, AUTO) | ||||
| 
 | ||||
| 
 | ||||
| PB_BIND(meshtastic_Telemetry, meshtastic_Telemetry, AUTO) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| #endif | ||||
| 
 | ||||
| /* Enum definitions */ | ||||
| /* TODO: REPLACE */ | ||||
| /* Supported I2C Sensors for telemetry in Meshtastic */ | ||||
| typedef enum _meshtastic_TelemetrySensorType { | ||||
|     /* No external telemetry sensor explicitly set */ | ||||
|     meshtastic_TelemetrySensorType_SENSOR_UNSET = 0, | ||||
|  | @ -37,7 +37,9 @@ typedef enum _meshtastic_TelemetrySensorType { | |||
|     /* 3-Axis magnetic sensor */ | ||||
|     meshtastic_TelemetrySensorType_QMC5883L = 11, | ||||
|     /* High accuracy temperature and humidity */ | ||||
|     meshtastic_TelemetrySensorType_SHT31 = 12 | ||||
|     meshtastic_TelemetrySensorType_SHT31 = 12, | ||||
|     /* PM2.5 air quality sensor */ | ||||
|     meshtastic_TelemetrySensorType_PMSA003I = 13 | ||||
| } meshtastic_TelemetrySensorType; | ||||
| 
 | ||||
| /* Struct definitions */ | ||||
|  | @ -69,6 +71,34 @@ typedef struct _meshtastic_EnvironmentMetrics { | |||
|     float current; | ||||
| } 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 */ | ||||
| typedef struct _meshtastic_Telemetry { | ||||
|     /* 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; | ||||
|         /* Weather station or other environmental metrics */ | ||||
|         meshtastic_EnvironmentMetrics environment_metrics; | ||||
|         /* Air quality metrics */ | ||||
|         meshtastic_AirQualityMetrics air_quality_metrics; | ||||
|     } variant; | ||||
| } meshtastic_Telemetry; | ||||
| 
 | ||||
|  | @ -93,8 +125,9 @@ extern "C" { | |||
| 
 | ||||
| /* Helper constants for enums */ | ||||
| #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET | ||||
| #define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SHT31 | ||||
| #define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SHT31+1)) | ||||
| #define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_PMSA003I | ||||
| #define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_PMSA003I+1)) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -103,9 +136,11 @@ extern "C" { | |||
| /* Initializer values for message structs */ | ||||
| #define meshtastic_DeviceMetrics_init_default    {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_DeviceMetrics_init_zero       {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}} | ||||
| 
 | ||||
| /* Field tags (for use in manual encoding/decoding) */ | ||||
|  | @ -119,9 +154,22 @@ extern "C" { | |||
| #define meshtastic_EnvironmentMetrics_gas_resistance_tag 4 | ||||
| #define meshtastic_EnvironmentMetrics_voltage_tag 5 | ||||
| #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_device_metrics_tag  2 | ||||
| #define meshtastic_Telemetry_environment_metrics_tag 3 | ||||
| #define meshtastic_Telemetry_air_quality_metrics_tag 4 | ||||
| 
 | ||||
| /* Struct field encoding specification for nanopb */ | ||||
| #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_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) \ | ||||
| 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,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_DEFAULT NULL | ||||
| #define meshtastic_Telemetry_variant_device_metrics_MSGTYPE meshtastic_DeviceMetrics | ||||
| #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_EnvironmentMetrics_msg; | ||||
| extern const pb_msgdesc_t meshtastic_AirQualityMetrics_msg; | ||||
| extern const pb_msgdesc_t meshtastic_Telemetry_msg; | ||||
| 
 | ||||
| /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ | ||||
| #define meshtastic_DeviceMetrics_fields &meshtastic_DeviceMetrics_msg | ||||
| #define meshtastic_EnvironmentMetrics_fields &meshtastic_EnvironmentMetrics_msg | ||||
| #define meshtastic_AirQualityMetrics_fields &meshtastic_AirQualityMetrics_msg | ||||
| #define meshtastic_Telemetry_fields &meshtastic_Telemetry_msg | ||||
| 
 | ||||
| /* Maximum encoded size of messages (where known) */ | ||||
| #define meshtastic_AirQualityMetrics_size        72 | ||||
| #define meshtastic_DeviceMetrics_size            21 | ||||
| #define meshtastic_EnvironmentMetrics_size       30 | ||||
| #define meshtastic_Telemetry_size                37 | ||||
| #define meshtastic_Telemetry_size                79 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include "modules/TraceRouteModule.h" | ||||
| #include "modules/WaypointModule.h" | ||||
| #if HAS_TELEMETRY | ||||
| #include "modules/Telemetry/AirQualityTelemetry.h" | ||||
| #include "modules/Telemetry/DeviceTelemetry.h" | ||||
| #include "modules/Telemetry/EnvironmentTelemetry.h" | ||||
| #endif | ||||
|  | @ -63,6 +64,9 @@ void setupModules() | |||
| #if HAS_TELEMETRY | ||||
|         new DeviceTelemetryModule(); | ||||
|         new EnvironmentTelemetryModule(); | ||||
|         if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I] > 0) { | ||||
|             new AirQualityTelemetryModule(); | ||||
|         } | ||||
| #endif | ||||
| #if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(TTGO_T_ECHO) && !defined(CONFIG_IDF_TARGET_ESP32S2) | ||||
|         new SerialModule(); | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  | @ -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; | ||||
| }; | ||||
|  | @ -118,6 +118,16 @@ int32_t EnvironmentTelemetryModule::runOnce() | |||
| #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 now = getTime(); | ||||
|  | @ -130,16 +140,6 @@ uint32_t GetTimeSinceMeshPacket(const meshtastic_MeshPacket *mp) | |||
|     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) | ||||
| { | ||||
|     display->setTextAlignment(TEXT_ALIGN_LEFT); | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Ben Meadors
						Ben Meadors