diff --git a/platformio.ini b/platformio.ini
index 673966494..06cc6e583 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -195,16 +195,10 @@ lib_deps =
adafruit/Adafruit BMP3XX Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
- # renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
- adafruit/Adafruit SHTC3 Library@1.0.2
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
- # renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library
- adafruit/Adafruit SHT31 Library@2.2.2
# renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library
adafruit/Adafruit VEML7700 Library@2.1.6
- # renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library
- adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
@@ -219,6 +213,8 @@ lib_deps =
sensirion/Sensirion I2C SFA3x@1.0.0
# renovate: datasource=custom.pio depName=Sensirion I2C SCD30 packageName=sensirion/library/Sensirion I2C SCD30
sensirion/Sensirion I2C SCD30@1.0.0
+ # renovate: datasource=custom.pio depName=arduino-sht packageName=sensirion/library/arduino-sht
+ sensirion/arduino-sht@1.2.6
; Environmental sensors with BSEC2 (Bosch proprietary IAQ)
[environmental_extra]
diff --git a/src/configuration.h b/src/configuration.h
index 11be86007..84dabee4e 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -231,7 +231,7 @@ along with this program. If not, see .
#define BME_ADDR 0x76
#define BME_ADDR_ALTERNATE 0x77
#define MCP9808_ADDR 0x18
-#define INA_ADDR 0x40
+#define INA_ADDR 0x40 // same as SHT2X
#define INA_ADDR_ALTERNATE 0x41
#define INA_ADDR_WAVESHARE_UPS 0x43
#define INA3221_ADDR 0x42
@@ -244,8 +244,8 @@ along with this program. If not, see .
#define LPS22HB_ADDR 0x5C
#define LPS22HB_ADDR_ALT 0x5D
#define SFA30_ADDR 0x5D
-#define SHT31_4x_ADDR 0x44
-#define SHT31_4x_ADDR_ALT 0x45
+#define SHTXX_ADDR 0x44
+#define SHTXX_ADDR_ALT 0x45
#define PMSA003I_ADDR 0x12
#define QMA6100P_ADDR 0x12
#define AHT10_ADDR 0x38
diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h
index cc83a8d7b..d451d3948 100644
--- a/src/detect/ScanI2C.h
+++ b/src/detect/ScanI2C.h
@@ -31,9 +31,6 @@ class ScanI2C
INA3221,
MAX17048,
MCP9808,
- SHT31,
- SHT4X,
- SHTC3,
LPS22HB,
QMC6310U,
QMC6310N,
@@ -94,7 +91,8 @@ class ScanI2C
SFA30,
CW2015,
SCD30,
- ADS1115
+ ADS1115,
+ SHTXX
} DeviceType;
// typedef uint8_t DeviceAddress;
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 2e00c11ce..052b2245a 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -136,7 +136,9 @@ bool ScanI2CTwoWire::i2cCommandResponseLength(ScanI2C::DeviceAddress addr, uint1
return match;
}
-/// for SEN5X detection
+#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR
+// FIXME Move to a separate file for detection of sensors that require more complex interactions?
+// For SEN5X detection
// Note, this code needs to be called before setting the I2C bus speed
// for the screen at high speed. The speed needs to be at 100kHz, otherwise
// detection will not work
@@ -174,6 +176,46 @@ String readSEN5xProductName(TwoWire *i2cBus, uint8_t address)
return String(productName);
}
+#endif
+
+#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
+bool detectSHT21SerialNumber(TwoWire *i2cBus, uint8_t address)
+{
+
+ i2cBus->beginTransmission(address);
+ i2cBus->write(0xFA);
+ i2cBus->write(0x0F);
+
+ if (i2cBus->endTransmission() != 0)
+ return false;
+
+ if (i2cBus->requestFrom(address, (uint8_t)8) != 8)
+ return false;
+
+ // Just flush the data
+ while (i2cBus->available() < 8) {
+ i2cBus->read();
+ }
+
+ i2cBus->beginTransmission(address);
+ i2cBus->write(0xFC);
+ i2cBus->write(0xC9);
+
+ if (i2cBus->endTransmission() != 0)
+ return false;
+
+ if (i2cBus->requestFrom(address, (uint8_t)6) != 6)
+ return false;
+
+ // Just flush the data
+ while (i2cBus->available() < 6) {
+ i2cBus->read();
+ }
+
+ // Assume we detect the SHT21 if something came back from the request
+ return true;
+}
+#endif
#define SCAN_SIMPLE_CASE(ADDR, T, ...) \
case ADDR: \
@@ -371,7 +413,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
break;
#endif
#if !defined(M5STACK_UNITC6L)
- case INA_ADDR:
+ case INA_ADDR: // Same as SHT2X
case INA_ADDR_ALTERNATE:
case INA_ADDR_WAVESHARE_UPS:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2);
@@ -387,7 +429,12 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
logFoundDevice("INA260", (uint8_t)addr.address);
type = INA260;
}
- } else { // Assume INA219 if INA260 ID is not found
+#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
+ } else if (detectSHT21SerialNumber(i2cBus, (uint8_t)addr.address)) {
+ logFoundDevice("SHTXX (SHT2X)", (uint8_t)addr.address);
+ type = SHTXX;
+#endif
+ } else { // Assume INA219 if none of the above ones are found
logFoundDevice("INA219", (uint8_t)addr.address);
type = INA219;
}
@@ -448,22 +495,19 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
}
break;
}
- case SHT31_4x_ADDR: // same as OPT3001_ADDR_ALT
- case SHT31_4x_ADDR_ALT: // same as OPT3001_ADDR
+ case SHTXX_ADDR: // same as OPT3001_ADDR_ALT
+ case SHTXX_ADDR_ALT: // same as OPT3001_ADDR
if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) {
type = OPT3001;
logFoundDevice("OPT3001", (uint8_t)addr.address);
- } else if (i2cCommandResponseLength(addr, 0x89, 6)) { // SHT4x serial number (6 bytes inc. CRC)
- type = SHT4X;
- logFoundDevice("SHT4X", (uint8_t)addr.address);
- } else {
- type = SHT31;
- logFoundDevice("SHT31", (uint8_t)addr.address);
+ } else { // SHTXX
+ type = SHTXX;
+ logFoundDevice("SHTXX", (uint8_t)addr.address);
}
break;
- SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3", (uint8_t)addr.address)
+ SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTXX, "SHTXX", (uint8_t)addr.address)
case RCWL9620_ADDR:
// get MAX30102 PARTID
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 1);
@@ -675,6 +719,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
logFoundDevice("BMX160", (uint8_t)addr.address);
break;
} else {
+#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_AIR_QUALITY_SENSOR
String prod = "";
prod = readSEN5xProductName(i2cBus, addr.address);
if (prod.startsWith("SEN55")) {
@@ -690,6 +735,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
logFoundDevice("Sensirion SEN50", addr.address);
break;
}
+#endif
if (addr.address == BMX160_ADDR) {
type = BMX160;
logFoundDevice("BMX160", (uint8_t)addr.address);
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index b7b6e04a9..684d408a1 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -66,18 +66,10 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c
#include "Sensor/MCP9808Sensor.h"
#endif
-#if __has_include()
-#include "Sensor/SHT31Sensor.h"
-#endif
-
#if __has_include()
#include "Sensor/LPS22HBSensor.h"
#endif
-#if __has_include()
-#include "Sensor/SHTC3Sensor.h"
-#endif
-
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
#include "Sensor/RAK12035Sensor.h"
#endif
@@ -94,8 +86,8 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c
#include "Sensor/OPT3001Sensor.h"
#endif
-#if __has_include()
-#include "Sensor/SHT4XSensor.h"
+#if __has_include()
+#include "Sensor/SHTXXSensor.h"
#endif
#if __has_include()
@@ -155,6 +147,15 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
}
LOG_INFO("Environment 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.
+ */
+
+ // moduleConfig.telemetry.environment_measurement_enabled = 1;
+ // moduleConfig.telemetry.environment_screen_enabled = 1;
+ // moduleConfig.telemetry.environment_update_interval = 15;
+
// order by priority of metrics/values (low top, high bottom)
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
@@ -202,15 +203,9 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
#if __has_include()
addSensor(i2cScanner, ScanI2C::DeviceType::MCP9808);
#endif
-#if __has_include()
- addSensor(i2cScanner, ScanI2C::DeviceType::SHT31);
-#endif
#if __has_include()
addSensor(i2cScanner, ScanI2C::DeviceType::LPS22HB);
#endif
-#if __has_include()
- addSensor(i2cScanner, ScanI2C::DeviceType::SHTC3);
-#endif
#if __has_include("RAK12035_SoilMoisture.h") && defined(RAK_4631) && RAK_4631 == 1
addSensor(i2cScanner, ScanI2C::DeviceType::RAK12035);
#endif
@@ -223,13 +218,9 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
#if __has_include()
addSensor(i2cScanner, ScanI2C::DeviceType::OPT3001);
#endif
-#if __has_include()
- addSensor(i2cScanner, ScanI2C::DeviceType::SHT4X);
-#endif
#if __has_include()
addSensor(i2cScanner, ScanI2C::DeviceType::MLX90632);
#endif
-
#if __has_include()
addSensor(i2cScanner, ScanI2C::DeviceType::BMP_3XX);
#endif
@@ -245,7 +236,10 @@ void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
#if __has_include()
addSensor(i2cScanner, ScanI2C::DeviceType::BH1750);
#endif
-
+#if __has_include()
+ // TODO Can we scan for multiple sensors connected on the same bus?
+ addSensor(i2cScanner, ScanI2C::DeviceType::SHTXX);
+#endif
#endif
}
@@ -260,14 +254,6 @@ int32_t EnvironmentTelemetryModule::runOnce()
}
uint32_t result = UINT32_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;
- // moduleConfig.telemetry.environment_screen_enabled = 1;
- // moduleConfig.telemetry.environment_update_interval = 15;
if (!(moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled ||
ENVIRONMENTAL_TELEMETRY_MODULE_ENABLE)) {
diff --git a/src/modules/Telemetry/Sensor/SHT31Sensor.cpp b/src/modules/Telemetry/Sensor/SHT31Sensor.cpp
deleted file mode 100644
index 67a36933d..000000000
--- a/src/modules/Telemetry/Sensor/SHT31Sensor.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "configuration.h"
-
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
-
-#include "../mesh/generated/meshtastic/telemetry.pb.h"
-#include "SHT31Sensor.h"
-#include "TelemetrySensor.h"
-#include
-
-SHT31Sensor::SHT31Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHT31, "SHT31") {}
-
-bool SHT31Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
-{
- LOG_INFO("Init sensor: %s", sensorName);
- sht31 = Adafruit_SHT31(bus);
- status = sht31.begin(dev->address.address);
- initI2CSensor();
- return status;
-}
-
-bool SHT31Sensor::getMetrics(meshtastic_Telemetry *measurement)
-{
- measurement->variant.environment_metrics.has_temperature = true;
- measurement->variant.environment_metrics.has_relative_humidity = true;
- measurement->variant.environment_metrics.temperature = sht31.readTemperature();
- measurement->variant.environment_metrics.relative_humidity = sht31.readHumidity();
-
- return true;
-}
-
-#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/SHT31Sensor.h b/src/modules/Telemetry/Sensor/SHT31Sensor.h
deleted file mode 100644
index ecb7d63a6..000000000
--- a/src/modules/Telemetry/Sensor/SHT31Sensor.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "configuration.h"
-
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
-
-#include "../mesh/generated/meshtastic/telemetry.pb.h"
-#include "TelemetrySensor.h"
-#include
-
-class SHT31Sensor : public TelemetrySensor
-{
- private:
- Adafruit_SHT31 sht31;
-
- public:
- SHT31Sensor();
- virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
- virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
-};
-
-#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/SHT4XSensor.cpp b/src/modules/Telemetry/Sensor/SHT4XSensor.cpp
deleted file mode 100644
index b11795d97..000000000
--- a/src/modules/Telemetry/Sensor/SHT4XSensor.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "configuration.h"
-
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
-
-#include "../mesh/generated/meshtastic/telemetry.pb.h"
-#include "SHT4XSensor.h"
-#include "TelemetrySensor.h"
-#include
-
-SHT4XSensor::SHT4XSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHT4X, "SHT4X") {}
-
-bool SHT4XSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
-{
- LOG_INFO("Init sensor: %s", sensorName);
-
- uint32_t serialNumber = 0;
-
- status = sht4x.begin(bus);
- if (!status) {
- return status;
- }
-
- serialNumber = sht4x.readSerial();
- if (serialNumber != 0) {
- LOG_DEBUG("serialNumber : %x", serialNumber);
- status = 1;
- } else {
- LOG_DEBUG("Error trying to execute readSerial(): ");
- status = 0;
- }
-
- initI2CSensor();
- return status;
-}
-
-bool SHT4XSensor::getMetrics(meshtastic_Telemetry *measurement)
-{
- measurement->variant.environment_metrics.has_temperature = true;
- measurement->variant.environment_metrics.has_relative_humidity = true;
-
- sensors_event_t humidity, temp;
- sht4x.getEvent(&humidity, &temp);
- measurement->variant.environment_metrics.temperature = temp.temperature;
- measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity;
- return true;
-}
-
-#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/SHT4XSensor.h b/src/modules/Telemetry/Sensor/SHT4XSensor.h
deleted file mode 100644
index 7311d2366..000000000
--- a/src/modules/Telemetry/Sensor/SHT4XSensor.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "configuration.h"
-
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
-
-#include "../mesh/generated/meshtastic/telemetry.pb.h"
-#include "TelemetrySensor.h"
-#include
-
-class SHT4XSensor : public TelemetrySensor
-{
- private:
- Adafruit_SHT4x sht4x = Adafruit_SHT4x();
-
- public:
- SHT4XSensor();
- virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
- virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
-};
-
-#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp b/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp
deleted file mode 100644
index fdab0b266..000000000
--- a/src/modules/Telemetry/Sensor/SHTC3Sensor.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "configuration.h"
-
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
-
-#include "../mesh/generated/meshtastic/telemetry.pb.h"
-#include "SHTC3Sensor.h"
-#include "TelemetrySensor.h"
-#include
-
-SHTC3Sensor::SHTC3Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHTC3, "SHTC3") {}
-
-bool SHTC3Sensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
-{
- LOG_INFO("Init sensor: %s", sensorName);
- status = shtc3.begin(bus);
-
- initI2CSensor();
- return status;
-}
-
-bool SHTC3Sensor::getMetrics(meshtastic_Telemetry *measurement)
-{
- measurement->variant.environment_metrics.has_temperature = true;
- measurement->variant.environment_metrics.has_relative_humidity = true;
-
- sensors_event_t humidity, temp;
- shtc3.getEvent(&humidity, &temp);
-
- measurement->variant.environment_metrics.temperature = temp.temperature;
- measurement->variant.environment_metrics.relative_humidity = humidity.relative_humidity;
-
- return true;
-}
-
-#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/SHTC3Sensor.h b/src/modules/Telemetry/Sensor/SHTC3Sensor.h
deleted file mode 100644
index 51cee18f7..000000000
--- a/src/modules/Telemetry/Sensor/SHTC3Sensor.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "configuration.h"
-
-#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
-
-#include "../mesh/generated/meshtastic/telemetry.pb.h"
-#include "TelemetrySensor.h"
-#include
-
-class SHTC3Sensor : public TelemetrySensor
-{
- private:
- Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();
-
- public:
- SHTC3Sensor();
- virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
- virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
-};
-
-#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/SHTXXSensor.cpp b/src/modules/Telemetry/Sensor/SHTXXSensor.cpp
new file mode 100644
index 000000000..92cac7f77
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/SHTXXSensor.cpp
@@ -0,0 +1,145 @@
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "SHTXXSensor.h"
+#include "TelemetrySensor.h"
+#include
+
+SHTXXSensor::SHTXXSensor() : TelemetrySensor(meshtastic_TelemetrySensorType_SHTXX, "SHTXX") {}
+
+void SHTXXSensor::getSensorVariant(SHTSensor::SHTSensorType sensorType)
+{
+ switch (sensorType) {
+ case SHTSensor::SHTSensorType::SHT2X:
+ sensorVariant = "SHT2x";
+ break;
+
+ case SHTSensor::SHTSensorType::SHT3X:
+ case SHTSensor::SHTSensorType::SHT85:
+ sensorVariant = "SHT3x/SHT85";
+ break;
+
+ case SHTSensor::SHTSensorType::SHT3X_ALT:
+ sensorVariant = "SHT3x";
+ break;
+
+ case SHTSensor::SHTSensorType::SHTW1:
+ case SHTSensor::SHTSensorType::SHTW2:
+ case SHTSensor::SHTSensorType::SHTC1:
+ case SHTSensor::SHTSensorType::SHTC3:
+ sensorVariant = "SHTC1/SHTC3/SHTW1/SHTW2";
+ break;
+
+ case SHTSensor::SHTSensorType::SHT4X:
+ sensorVariant = "SHT4x";
+ break;
+
+ default:
+ sensorVariant = "Unknown";
+ break;
+ }
+}
+
+bool SHTXXSensor::initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev)
+{
+ LOG_INFO("Init sensor: %s", sensorName);
+
+ _bus = bus;
+ _address = dev->address.address;
+
+ if (sht.init(*_bus)) {
+ LOG_INFO("%s: init(): success", sensorName);
+ getSensorVariant(sht.mSensorType);
+ LOG_INFO("%s Sensor detected: %s on 0x%x", sensorName, sensorVariant, _address);
+ status = 1;
+ } else {
+ LOG_ERROR("%s: init(): failed", sensorName);
+ }
+
+ initI2CSensor();
+ return status;
+}
+
+/**
+ * Accuracy setting of measurement.
+ * Not all sensors support changing the sampling accuracy (only SHT3X and SHT4X)
+ * SHTAccuracy:
+ * - SHT_ACCURACY_HIGH: Highest repeatability at the cost of slower measurement
+ * - SHT_ACCURACY_MEDIUM: Balanced repeatability and speed of measurement
+ * - SHT_ACCURACY_LOW: Fastest measurement but lowest repeatability
+ */
+bool SHTXXSensor::setAccuracy(SHTSensor::SHTAccuracy newAccuracy)
+{
+ // Only SHT3X-family (including alternates) and SHT4X support changing accuracy
+ if (sht.mSensorType != SHTSensor::SHTSensorType::SHT3X && sht.mSensorType != SHTSensor::SHTSensorType::SHT3X_ALT &&
+ sht.mSensorType != SHTSensor::SHTSensorType::SHT85 && sht.mSensorType != SHTSensor::SHTSensorType::SHT4X) {
+ LOG_WARN("%s doesn't support accuracy setting", sensorVariant);
+ return false;
+ }
+ LOG_INFO("%s: setting new accuracy setting", sensorVariant);
+ accuracy = newAccuracy;
+ return sht.setAccuracy(accuracy);
+}
+
+bool SHTXXSensor::getMetrics(meshtastic_Telemetry *measurement)
+{
+ if (sht.readSample()) {
+ measurement->variant.environment_metrics.has_temperature = true;
+ measurement->variant.environment_metrics.has_relative_humidity = true;
+ measurement->variant.environment_metrics.temperature = sht.getTemperature();
+ measurement->variant.environment_metrics.relative_humidity = sht.getHumidity();
+
+ LOG_INFO("%s (%s): Got: temp:%fdegC, hum:%f%%rh", sensorName, sensorVariant,
+ measurement->variant.environment_metrics.temperature,
+ measurement->variant.environment_metrics.relative_humidity);
+
+ return true;
+ } else {
+ LOG_ERROR("%s (%s): read sample failed", sensorName, sensorVariant);
+ return false;
+ }
+}
+
+AdminMessageHandleResult SHTXXSensor::handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request,
+ meshtastic_AdminMessage *response)
+{
+ AdminMessageHandleResult result;
+ result = AdminMessageHandleResult::NOT_HANDLED;
+
+ switch (request->which_payload_variant) {
+ case meshtastic_AdminMessage_sensor_config_tag:
+ if (!request->sensor_config.has_shtxx_config) {
+ result = AdminMessageHandleResult::NOT_HANDLED;
+ break;
+ }
+
+ // Check for sensor accuracy setting
+ if (request->sensor_config.shtxx_config.has_set_accuracy) {
+ SHTSensor::SHTAccuracy newAccuracy;
+ if (request->sensor_config.shtxx_config.set_accuracy == 0) {
+ newAccuracy = SHTSensor::SHT_ACCURACY_LOW;
+ } else if (request->sensor_config.shtxx_config.set_accuracy == 1) {
+ newAccuracy = SHTSensor::SHT_ACCURACY_MEDIUM;
+ } else if (request->sensor_config.shtxx_config.set_accuracy == 2) {
+ newAccuracy = SHTSensor::SHT_ACCURACY_HIGH;
+ } else {
+ LOG_ERROR("%s: incorrect accuracy setting", sensorName);
+ result = AdminMessageHandleResult::HANDLED;
+ break;
+ }
+ this->setAccuracy(newAccuracy);
+ }
+
+ result = AdminMessageHandleResult::HANDLED;
+ break;
+
+ default:
+ result = AdminMessageHandleResult::NOT_HANDLED;
+ }
+
+ return result;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/modules/Telemetry/Sensor/SHTXXSensor.h b/src/modules/Telemetry/Sensor/SHTXXSensor.h
new file mode 100644
index 000000000..e354e113f
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/SHTXXSensor.h
@@ -0,0 +1,29 @@
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include
+
+class SHTXXSensor : public TelemetrySensor
+{
+ private:
+ SHTSensor sht;
+ TwoWire *_bus{};
+ uint8_t _address{};
+ SHTSensor::SHTAccuracy accuracy{};
+ bool setAccuracy(SHTSensor::SHTAccuracy newAccuracy);
+
+ public:
+ SHTXXSensor();
+ virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
+ virtual bool initDevice(TwoWire *bus, ScanI2C::FoundDevice *dev) override;
+ void getSensorVariant(SHTSensor::SHTSensorType);
+ const char *sensorVariant{};
+
+ AdminMessageHandleResult handleAdminMessage(const meshtastic_MeshPacket &mp, meshtastic_AdminMessage *request,
+ meshtastic_AdminMessage *response) override;
+};
+
+#endif
\ No newline at end of file