mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-22 10:42:49 +00:00
Initial air quality telemetry feature
This commit is contained in:
128
src/modules/Telemetry/AirQualityTelemetry.cpp
Normal file
128
src/modules/Telemetry/AirQualityTelemetry.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user