diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml
index 79bdf4778..bcb75d550 100644
--- a/.trunk/trunk.yaml
+++ b/.trunk/trunk.yaml
@@ -10,14 +10,14 @@ lint:
enabled:
- renovate@40.0.6
- prettier@3.5.3
- - trufflehog@3.88.29
+ - trufflehog@3.88.32
- yamllint@1.37.1
- bandit@1.8.3
- trivy@0.62.1
- taplo@0.9.3
- - ruff@0.11.9
+ - ruff@0.11.10
- isort@6.0.1
- - markdownlint@0.44.0
+ - markdownlint@0.45.0
- oxipng@9.1.5
- svgo@3.3.2
- actionlint@1.7.7
diff --git a/platformio.ini b/platformio.ini
index 836b723af..d7504e6c5 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -108,7 +108,7 @@ lib_deps =
[device-ui_base]
lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
- https://github.com/meshtastic/device-ui/archive/0e9bb792bb4b015b487397427781eda2767c87e6.zip
+ https://github.com/meshtastic/device-ui/archive/e63b219e78e9655be10745b4037cefd2c608d258.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
@@ -161,6 +161,8 @@ lib_deps =
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2
+ # renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/Adafruit PCT2075
+ adafruit/Adafruit PCT2075@1.0.5
; (not included in native / portduino)
[environmental_extra]
diff --git a/protobufs b/protobufs
index 0b32ce24f..91484534a 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit 0b32ce24f029f69635026aec9428b5c8176e2ce1
+Subproject commit 91484534a58cb4da8ab68ac046f1e76fd1936bf7
diff --git a/src/configuration.h b/src/configuration.h
index 4138d6950..fb078e2be 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -80,10 +80,10 @@ along with this program. If not, see .
// Override user saved region, for producing region-locked builds
// #define REGULATORY_LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923
-// Total system gain in dBm to subtract from Tx power to remain within regulatory ERP limit for non-licensed operators
-// This value should be set in variant.h and is PA gain + antenna gain (if system ships with an antenna)
-#ifndef REGULATORY_GAIN_LORA
-#define REGULATORY_GAIN_LORA 0
+// Total system gain in dBm to subtract from Tx power to remain within regulatory and Tx PA limits
+// This value should be set in variant.h and is PA gain + antenna gain (if variant has a non-removable antenna)
+#ifndef TX_GAIN_LORA
+#define TX_GAIN_LORA 0
#endif
// -----------------------------------------------------------------------------
@@ -153,6 +153,7 @@ along with this program. If not, see .
#define CGRADSENS_ADDR 0x66
#define LTR390UV_ADDR 0x53
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
+#define PCT2075_ADDR 0x37
// -----------------------------------------------------------------------------
// ACCELEROMETER
diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h
index e43bc7017..daab968e1 100644
--- a/src/detect/ScanI2C.h
+++ b/src/detect/ScanI2C.h
@@ -71,6 +71,7 @@ class ScanI2C
DPS310,
LTR390UV,
TCA8418KB,
+ PCT2075,
CST226SE,
} DeviceType;
diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp
index 740649a1b..bcb1af556 100644
--- a/src/detect/ScanI2CTwoWire.cpp
+++ b/src/detect/ScanI2CTwoWire.cpp
@@ -434,6 +434,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address);
+ SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(CST226SE_ADDR, CST226SE, "CST226SE", (uint8_t)addr.address);
#ifdef HAS_TPS65233
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
diff --git a/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp b/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp
new file mode 100644
index 000000000..a0ff63258
--- /dev/null
+++ b/src/graphics/niche/Drivers/EInk/GDEY0213B74.cpp
@@ -0,0 +1,61 @@
+#include "./GDEY0213B74.h"
+
+#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
+
+using namespace NicheGraphics::Drivers;
+
+// Map the display controller IC's output to the connected panel
+void GDEY0213B74::configScanning()
+{
+ // "Driver output control"
+ sendCommand(0x01);
+ sendData(0xF9);
+ sendData(0x00);
+ sendData(0x00);
+
+ // To-do: delete this method?
+ // Values set here might be redundant: F9, 00, 00 seems to be default
+}
+
+// Specify which information is used to control the sequence of voltages applied to move the pixels
+// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
+// the controller IC's OTP memory, when the update procedure begins.
+void GDEY0213B74::configWaveform()
+{
+ sendCommand(0x3C); // Border waveform:
+ sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white)
+
+ sendCommand(0x18); // Temperature sensor:
+ sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform
+}
+
+void GDEY0213B74::configUpdateSequence()
+{
+ switch (updateType) {
+ case FAST:
+ sendCommand(0x22); // Set "update sequence"
+ sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
+ break;
+
+ case FULL:
+ default:
+ sendCommand(0x22); // Set "update sequence"
+ sendData(0xF7); // Will load LUT from OTP memory
+ break;
+ }
+}
+
+// Once the refresh operation has been started,
+// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
+// Only used when refresh is "async"
+void GDEY0213B74::detachFromUpdate()
+{
+ switch (updateType) {
+ case FAST:
+ return beginPolling(50, 500); // At least 500ms for fast refresh
+ case FULL:
+ default:
+ return beginPolling(100, 2000); // At least 2 seconds for full refresh
+ }
+}
+#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
\ No newline at end of file
diff --git a/src/graphics/niche/Drivers/EInk/GDEY0213B74.h b/src/graphics/niche/Drivers/EInk/GDEY0213B74.h
new file mode 100644
index 000000000..2212fe92a
--- /dev/null
+++ b/src/graphics/niche/Drivers/EInk/GDEY0213B74.h
@@ -0,0 +1,42 @@
+/*
+
+E-Ink display driver
+ - GDEY0213B74
+ - Manufacturer: Goodisplay
+ - Size: 2.13 inch
+ - Resolution: 250px x 122px
+ - Flex connector marking: FPC-A002
+
+*/
+
+#pragma once
+
+#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
+
+#include "configuration.h"
+
+#include "./SSD16XX.h"
+
+namespace NicheGraphics::Drivers
+{
+class GDEY0213B74 : public SSD16XX
+{
+ // Display properties
+ private:
+ static constexpr uint32_t width = 122;
+ static constexpr uint32_t height = 250;
+ static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
+
+ public:
+ GDEY0213B74() : SSD16XX(width, height, supported) {}
+
+ protected:
+ virtual void configScanning() override;
+ virtual void configWaveform() override;
+ virtual void configUpdateSequence() override;
+ void detachFromUpdate() override;
+};
+
+} // namespace NicheGraphics::Drivers
+
+#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index fbb1beb92..5c114086d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -732,6 +732,7 @@ void setup()
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_RAIN, meshtastic_TelemetrySensorType_DFROBOT_RAIN);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LTR390UV, meshtastic_TelemetrySensorType_LTR390UV);
scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DPS310, meshtastic_TelemetrySensorType_DPS310);
+ scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PCT2075, meshtastic_TelemetrySensorType_PCT2075);
i2cScanner.reset();
#endif
diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp
index aecc8f722..8cc05994c 100644
--- a/src/mesh/LR11x0Interface.cpp
+++ b/src/mesh/LR11x0Interface.cpp
@@ -71,6 +71,8 @@ template bool LR11x0Interface::init()
RadioLibInterface::init();
+ limitPower();
+
if (power > LR1110_MAX_POWER) // Clamp power to maximum defined level
power = LR1110_MAX_POWER;
@@ -80,8 +82,6 @@ template bool LR11x0Interface::init()
preambleLength = 12; // 12 is the default for operation above 2GHz
}
- limitPower();
-
#ifdef LR11X0_RF_SWITCH_SUBGHZ
pinMode(LR11X0_RF_SWITCH_SUBGHZ, OUTPUT);
digitalWrite(LR11X0_RF_SWITCH_SUBGHZ, getFreq() < 1e9 ? HIGH : LOW);
diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp
index 1dfc72708..943a79a5f 100644
--- a/src/mesh/RF95Interface.cpp
+++ b/src/mesh/RF95Interface.cpp
@@ -122,11 +122,11 @@ bool RF95Interface::init()
power = dacDbValues.db;
#endif
+ limitPower();
+
if (power > RF95_MAX_POWER) // This chip has lower power limits than some
power = RF95_MAX_POWER;
- limitPower();
-
iface = lora = new RadioLibRF95(&module);
#ifdef RF95_TCXO
diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp
index 86903153b..06398e6c3 100644
--- a/src/mesh/RadioInterface.cpp
+++ b/src/mesh/RadioInterface.cpp
@@ -528,8 +528,8 @@ void RadioInterface::applyModemConfig()
power = loraConfig.tx_power;
- if ((power == 0) || ((power + REGULATORY_GAIN_LORA > myRegion->powerLimit) && !devicestate.owner.is_licensed))
- power = myRegion->powerLimit - REGULATORY_GAIN_LORA;
+ if ((power == 0) || ((power > myRegion->powerLimit) && !devicestate.owner.is_licensed))
+ power = myRegion->powerLimit;
if (power == 0)
power = 17; // Default to this power level if we don't have a valid regional power limit (powerLimit of myRegion defaults
@@ -616,7 +616,12 @@ void RadioInterface::limitPower()
power = maxPower;
}
- LOG_INFO("Set radio: final power level=%d", power);
+ if (TX_GAIN_LORA > 0) {
+ LOG_INFO("Requested Tx power: %d dBm; Device LoRa Tx gain: %d dB", power, TX_GAIN_LORA);
+ power -= TX_GAIN_LORA;
+ }
+
+ LOG_INFO("Final Tx power: %d dBm", power);
}
void RadioInterface::deliverToReceiver(meshtastic_MeshPacket *p)
diff --git a/src/mesh/STM32WLE5JCInterface.cpp b/src/mesh/STM32WLE5JCInterface.cpp
index 6a340dd28..3c8bf89c3 100644
--- a/src/mesh/STM32WLE5JCInterface.cpp
+++ b/src/mesh/STM32WLE5JCInterface.cpp
@@ -25,11 +25,11 @@ bool STM32WLE5JCInterface::init()
lora.setRfSwitchTable(rfswitch_pins, rfswitch_table);
+ limitPower();
+
if (power > STM32WLx_MAX_POWER) // This chip has lower power limits than some
power = STM32WLx_MAX_POWER;
- limitPower();
-
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage);
LOG_INFO("STM32WLx init result %d", res);
diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp
index c867466b7..e5ecd9302 100644
--- a/src/mesh/SX126xInterface.cpp
+++ b/src/mesh/SX126xInterface.cpp
@@ -69,11 +69,11 @@ template bool SX126xInterface::init()
RadioLibInterface::init();
+ limitPower();
+
if (power > SX126X_MAX_POWER) // Clamp power to maximum defined level
power = SX126X_MAX_POWER;
- limitPower();
-
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength, tcxoVoltage, useRegulatorLDO);
// \todo Display actual typename of the adapter, not just `SX126x`
LOG_INFO("SX126x init result %d", res);
diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp
index 23a023d3f..2b17543fc 100644
--- a/src/mesh/SX128xInterface.cpp
+++ b/src/mesh/SX128xInterface.cpp
@@ -62,11 +62,11 @@ template bool SX128xInterface::init()
RadioLibInterface::init();
+ limitPower();
+
if (power > SX128X_MAX_POWER) // This chip has lower power limits than some
power = SX128X_MAX_POWER;
- limitPower();
-
preambleLength = 12; // 12 is the default for this chip, 32 does not RX at all
int res = lora.begin(getFreq(), bw, sf, cr, syncWord, power, preambleLength);
diff --git a/src/mesh/TypeConversions.cpp b/src/mesh/TypeConversions.cpp
index c47a67e68..17cd92851 100644
--- a/src/mesh/TypeConversions.cpp
+++ b/src/mesh/TypeConversions.cpp
@@ -87,6 +87,8 @@ meshtastic_UserLite TypeConversions::ConvertToUserLite(meshtastic_User user)
memcpy(lite.macaddr, user.macaddr, sizeof(lite.macaddr));
memcpy(lite.public_key.bytes, user.public_key.bytes, sizeof(lite.public_key.bytes));
lite.public_key.size = user.public_key.size;
+ lite.has_is_unmessagable = user.has_is_unmessagable;
+ lite.is_unmessagable = user.is_unmessagable;
return lite;
}
@@ -103,6 +105,8 @@ meshtastic_User TypeConversions::ConvertToUser(uint32_t nodeNum, meshtastic_User
memcpy(user.macaddr, lite.macaddr, sizeof(user.macaddr));
memcpy(user.public_key.bytes, lite.public_key.bytes, sizeof(user.public_key.bytes));
user.public_key.size = lite.public_key.size;
+ user.has_is_unmessagable = lite.has_is_unmessagable;
+ user.is_unmessagable = lite.is_unmessagable;
return user;
}
\ No newline at end of file
diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h
index 4071c611e..4fa673df8 100644
--- a/src/mesh/generated/meshtastic/telemetry.pb.h
+++ b/src/mesh/generated/meshtastic/telemetry.pb.h
@@ -277,6 +277,10 @@ typedef struct _meshtastic_LocalStats {
/* Number of times we canceled a packet to be relayed, because someone else did it before us.
This will always be zero for ROUTERs/REPEATERs. If this number is high, some other node(s) is/are relaying faster than you. */
uint32_t num_tx_relay_canceled;
+ /* Number of bytes used in the heap */
+ uint32_t heap_total_bytes;
+ /* Number of bytes free in the heap */
+ uint32_t heap_free_bytes;
} meshtastic_LocalStats;
/* Health telemetry metrics */
@@ -374,7 +378,7 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_PowerMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_AirQualityMetrics_init_default {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
-#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+#define meshtastic_LocalStats_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_HealthMetrics_init_default {false, 0, false, 0, false, 0}
#define meshtastic_HostMetrics_init_default {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
#define meshtastic_Telemetry_init_default {0, 0, {meshtastic_DeviceMetrics_init_default}}
@@ -383,7 +387,7 @@ extern "C" {
#define meshtastic_EnvironmentMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_PowerMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
#define meshtastic_AirQualityMetrics_init_zero {false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0, false, 0}
-#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+#define meshtastic_LocalStats_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define meshtastic_HealthMetrics_init_zero {false, 0, false, 0, false, 0}
#define meshtastic_HostMetrics_init_zero {0, 0, 0, false, 0, false, 0, 0, 0, 0, false, ""}
#define meshtastic_Telemetry_init_zero {0, 0, {meshtastic_DeviceMetrics_init_zero}}
@@ -447,6 +451,8 @@ extern "C" {
#define meshtastic_LocalStats_num_rx_dupe_tag 9
#define meshtastic_LocalStats_num_tx_relay_tag 10
#define meshtastic_LocalStats_num_tx_relay_canceled_tag 11
+#define meshtastic_LocalStats_heap_total_bytes_tag 12
+#define meshtastic_LocalStats_heap_free_bytes_tag 13
#define meshtastic_HealthMetrics_heart_bpm_tag 1
#define meshtastic_HealthMetrics_spO2_tag 2
#define meshtastic_HealthMetrics_temperature_tag 3
@@ -544,7 +550,9 @@ X(a, STATIC, SINGULAR, UINT32, num_online_nodes, 7) \
X(a, STATIC, SINGULAR, UINT32, num_total_nodes, 8) \
X(a, STATIC, SINGULAR, UINT32, num_rx_dupe, 9) \
X(a, STATIC, SINGULAR, UINT32, num_tx_relay, 10) \
-X(a, STATIC, SINGULAR, UINT32, num_tx_relay_canceled, 11)
+X(a, STATIC, SINGULAR, UINT32, num_tx_relay_canceled, 11) \
+X(a, STATIC, SINGULAR, UINT32, heap_total_bytes, 12) \
+X(a, STATIC, SINGULAR, UINT32, heap_free_bytes, 13)
#define meshtastic_LocalStats_CALLBACK NULL
#define meshtastic_LocalStats_DEFAULT NULL
@@ -621,7 +629,7 @@ extern const pb_msgdesc_t meshtastic_Nau7802Config_msg;
#define meshtastic_EnvironmentMetrics_size 113
#define meshtastic_HealthMetrics_size 11
#define meshtastic_HostMetrics_size 264
-#define meshtastic_LocalStats_size 60
+#define meshtastic_LocalStats_size 72
#define meshtastic_Nau7802Config_size 16
#define meshtastic_PowerMetrics_size 30
#define meshtastic_Telemetry_size 272
diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp
index 56f9d7433..51f076552 100644
--- a/src/modules/Telemetry/EnvironmentTelemetry.cpp
+++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp
@@ -157,6 +157,13 @@ BMP3XXSensor bmp3xxSensor;
NullSensor bmp3xxSensor;
#endif
+#if __has_include()
+#include "Sensor/PCT2075Sensor.h"
+PCT2075Sensor pct2075Sensor;
+#else
+NullSensor pct2075Sensor;
+#endif
+
RCWL9620Sensor rcwl9620Sensor;
CGRadSensSensor cgRadSens;
#endif
@@ -264,6 +271,8 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = max17048Sensor.runOnce();
if (cgRadSens.hasSensor())
result = cgRadSens.runOnce();
+ if (pct2075Sensor.hasSensor())
+ result = pct2075Sensor.runOnce();
// this only works on the wismesh hub with the solar option. This is not an I2C sensor, so we don't need the
// sensormap here.
#ifdef HAS_RAKPROT
@@ -595,6 +604,10 @@ bool EnvironmentTelemetryModule::getEnvironmentTelemetry(meshtastic_Telemetry *m
valid = valid && cgRadSens.getMetrics(m);
hasSensor = true;
}
+ if (pct2075Sensor.hasSensor()) {
+ valid = valid && pct2075Sensor.getMetrics(m);
+ hasSensor = true;
+ }
#ifdef HAS_RAKPROT
valid = valid && rak9154Sensor.getMetrics(m);
hasSensor = true;
diff --git a/src/modules/Telemetry/Sensor/PCT2075Sensor.cpp b/src/modules/Telemetry/Sensor/PCT2075Sensor.cpp
new file mode 100644
index 000000000..d2b50d983
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/PCT2075Sensor.cpp
@@ -0,0 +1,35 @@
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "PCT2075Sensor.h"
+#include "TelemetrySensor.h"
+#include
+
+PCT2075Sensor::PCT2075Sensor() : TelemetrySensor(meshtastic_TelemetrySensorType_PCT2075, "PCT2075") {}
+
+int32_t PCT2075Sensor::runOnce()
+{
+ LOG_INFO("Init sensor: %s", sensorName);
+ if (!hasSensor()) {
+ return DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS;
+ }
+
+ status = pct2075.begin(nodeTelemetrySensorsMap[sensorType].first, nodeTelemetrySensorsMap[sensorType].second);
+
+ return initI2CSensor();
+}
+
+void PCT2075Sensor::setup() {}
+
+bool PCT2075Sensor::getMetrics(meshtastic_Telemetry *measurement)
+{
+ measurement->variant.environment_metrics.has_temperature = true;
+
+ measurement->variant.environment_metrics.temperature = pct2075.getTemperature();
+
+ return true;
+}
+
+#endif
diff --git a/src/modules/Telemetry/Sensor/PCT2075Sensor.h b/src/modules/Telemetry/Sensor/PCT2075Sensor.h
new file mode 100644
index 000000000..842c973d0
--- /dev/null
+++ b/src/modules/Telemetry/Sensor/PCT2075Sensor.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "configuration.h"
+
+#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && __has_include()
+
+#include "../mesh/generated/meshtastic/telemetry.pb.h"
+#include "TelemetrySensor.h"
+#include
+
+class PCT2075Sensor : public TelemetrySensor
+{
+ private:
+ Adafruit_PCT2075 pct2075;
+
+ protected:
+ virtual void setup() override;
+
+ public:
+ PCT2075Sensor();
+ virtual int32_t runOnce() override;
+ virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
+};
+
+#endif
diff --git a/variants/xiao_ble/variant.h b/variants/xiao_ble/variant.h
index d00f8be89..b46aa96ae 100644
--- a/variants/xiao_ble/variant.h
+++ b/variants/xiao_ble/variant.h
@@ -145,12 +145,12 @@ static const uint8_t SCK = PIN_SPI_SCK;
#ifdef EBYTE_E22_900M30S
// 10dB PA gain and 30dB rated output; based on measurements from
// https://github.com/S5NC/EBYTE_ESP32-S3/blob/main/E22-900M30S%20power%20output%20testing.txt
-#define REGULATORY_GAIN_LORA 7
+#define TX_GAIN_LORA 7
#define SX126X_MAX_POWER 22
#endif
#ifdef EBYTE_E22_900M33S
// 25dB PA gain and 33dB rated output; based on TX Power Curve from E22-900M33S_UserManual_EN_v1.0.pdf
-#define REGULATORY_GAIN_LORA 25
+#define TX_GAIN_LORA 25
#define SX126X_MAX_POWER 8
#endif
#endif