Allow re-scan of AirQualityModule for late-coming sensors

* Define map for sensors to re-scan
* Add re-scan on runOnce
This commit is contained in:
oscgonfer
2026-05-31 20:06:34 +02:00
parent caa300d2fb
commit 6d52fea75e
3 changed files with 67 additions and 2 deletions

View File

@@ -13,6 +13,7 @@
#include "Router.h"
#include "TransmitHistory.h"
#include "UnitConversions.h"
#include "detect/ScanI2CTwoWire.h"
#include "graphics/ScreenFonts.h"
#include "graphics/SharedUIDisplay.h"
#include "graphics/images.h"
@@ -41,12 +42,13 @@ void AirQualityTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
if (!moduleConfig.telemetry.air_quality_enabled && !AIR_QUALITY_TELEMETRY_MODULE_ENABLE) {
return;
}
LOG_INFO("Air Quality Telemetry adding I2C devices...");
/*
Uncomment the preferences below if you want to use the module
without having to configure it from the PythonAPI or WebUI.
Note: this was previously on runOnce, which didnt take effect
Note: this was previously on runOnce, which didn't take effect
as other modules already had already been initialized (screen)
*/
@@ -54,6 +56,52 @@ void AirQualityTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
// moduleConfig.telemetry.air_quality_screen_enabled = 1;
// moduleConfig.telemetry.air_quality_interval = 15;
// Add here supported sensors in the Air Quality module
// These sensors will be scanned twice, once in the first scan,
// and secondly in the first run of the module
if (!supportedSensors.count(PMSA003I_ADDR))
supportedSensors[PMSA003I_ADDR] = ScanI2C::DeviceType::PMSA003I;
if (!supportedSensors.count(SEN5X_ADDR))
supportedSensors[SEN5X_ADDR] = ScanI2C::DeviceType::SEN5X;
#if __has_include(<SensirionI2cScd4x.h>)
if (!supportedSensors.count(SCD4X_ADDR))
supportedSensors[SCD4X_ADDR] = ScanI2C::DeviceType::SCD4X;
#endif
#if __has_include(<SensirionI2cSfa3x.h>)
if (!supportedSensors.count(SFA30_ADDR))
supportedSensors[SFA30_ADDR] = ScanI2C::DeviceType::SFA30;
#endif
#if __has_include(<SensirionI2cScd30.h>)
if (!supportedSensors.count(SCD30_ADDR))
supportedSensors[SCD30_ADDR] = ScanI2C::DeviceType::SCD30;
#endif
if (!firstTime) {
// Re-scan for late comming sensors
LOG_INFO("Re-scanning supported sensors...");
for (const auto &[address, type] : supportedSensors) {
if (!i2cScanner->exists(type)) {
LOG_INFO("Re-scanning on address 0x%x", address);
uint8_t array_address[1] = {address};
#if defined(I2C_SDA1) || (defined(NRF52840_XXAA) && (WIRE_INTERFACES_COUNT == 2))
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE1, array_address, sizeof(array_address));
#endif
#if defined(I2C_SDA)
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE, array_address, sizeof(array_address));
#elif defined(ARCH_PORTDUINO)
if (portduino_config.i2cdev != "") {
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE, array_address, sizeof(array_address));
}
#elif HAS_WIRE
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE, array_address, sizeof(array_address));
#endif
}
}
}
// order by priority of metrics/values (low top, high bottom)
addSensor<PMSA003ISensor>(i2cScanner, ScanI2C::DeviceType::PMSA003I);
addSensor<SEN5XSensor>(i2cScanner, ScanI2C::DeviceType::SEN5X);
@@ -94,6 +142,10 @@ int32_t AirQualityTelemetryModule::runOnce()
if (moduleConfig.telemetry.air_quality_enabled) {
LOG_INFO("Air quality Telemetry: init");
// Re-scan I2C bus
auto i2cScanner = std::unique_ptr<ScanI2CTwoWire>(new ScanI2CTwoWire());
i2cScanFinished(i2cScanner.get());
// check if we have at least one sensor
if (!sensors.empty()) {
result = DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;

View File

@@ -3,8 +3,8 @@
#if !MESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR
#pragma once
#include "BaseTelemetryModule.h"
#include <map>
#ifndef AIR_QUALITY_TELEMETRY_MODULE_ENABLE
#define AIR_QUALITY_TELEMETRY_MODULE_ENABLE 0
@@ -13,6 +13,7 @@
#include "../mesh/generated/meshtastic/telemetry.pb.h"
#include "NodeDB.h"
#include "ProtobufModule.h"
#include "detect/ScanI2C.h"
#include "detect/ScanI2CConsumer.h"
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
@@ -69,6 +70,9 @@ class AirQualityTelemetryModule : private concurrency::OSThread,
uint32_t sendToPhoneIntervalMs = SECONDS_IN_MINUTE * 1000; // Send to phone every minute
// uint32_t sendToPhoneIntervalMs = 1000; // Send to phone every minute
uint32_t lastSentToPhone = 0;
// Map for supported sensors to re-scan
std::map<uint8_t, ScanI2C::DeviceType> supportedSensors;
};
#endif

View File

@@ -11,6 +11,15 @@ static std::forward_list<TelemetrySensor *> sensors;
template <typename T> void addSensor(const ScanI2C *i2cScanner, ScanI2C::DeviceType type)
{
ScanI2C::FoundDevice dev = i2cScanner->find(type);
// Avoid adding the same device twice
if (dev.type != ScanI2C::DeviceType::NONE) {
for (TelemetrySensor *_sensor : sensors) {
if ((_sensor->_address == dev.address.address) && (_sensor->_port == dev.address.port)) {
return;
}
}
}
if (dev.type != ScanI2C::DeviceType::NONE || type == ScanI2C::DeviceType::NONE) {
TelemetrySensor *sensor = new T();
#if WIRE_INTERFACES_COUNT > 1