From 2786b29f39475be2d118459c526c982b5696550b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Mon, 30 Mar 2026 11:46:35 +0200 Subject: [PATCH 1/2] feat(bme280): Add dew point calculation using Magnus formula. --- lib/bme280/README.md | 12 +++++++++++- lib/bme280/bme280/device.py | 13 +++++++++++++ tests/scenarios/bme280.yaml | 27 +++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/bme280/README.md b/lib/bme280/README.md index 5b91f94f..9432bb9e 100644 --- a/lib/bme280/README.md +++ b/lib/bme280/README.md @@ -186,6 +186,16 @@ sensor.sea_level_pressure_hpa = 1020.0 --- +### Dew Point + +```python +dp = sensor.dew_point() +``` + +Returns the dew point temperature in **degrees Celsius**, computed from the current temperature and humidity using the Magnus formula. + +--- + ## Data-Ready Status ```python @@ -313,7 +323,7 @@ Performs a soft reset, re-reads calibration data, and re-applies default configu | Standby time | ✅ | ❌ | ✅ | ❌ | ⚠️ Fixed 500ms | ❌ | | Altitude | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | | Sea-level pressure | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | -| Dew point | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | +| Dew point | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | | Soft reset | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | | Full reset + recalibration | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | power_off / power_on | ✅ | ❌ | ⚠️ Via mode | ❌ | ❌ | ❌ | diff --git a/lib/bme280/bme280/device.py b/lib/bme280/bme280/device.py index a0108e07..35f85ac1 100644 --- a/lib/bme280/bme280/device.py +++ b/lib/bme280/bme280/device.py @@ -409,3 +409,16 @@ def altitude(self, pressure_hpa=None): """ p = self.pressure_hpa() if pressure_hpa is None else pressure_hpa return 44330.0 * (1.0 - (p / self.sea_level_pressure_hpa) ** 0.1903) + + def dew_point(self): + """Return dew point temperature in degrees Celsius. + + Uses the Magnus formula (Alduchov & Eskridge, 1996) with the + current temperature and relative humidity readings. + """ + from math import log + + t = self.temperature() + rh = self.humidity() + gamma = log(rh / 100.0) + 17.625 * t / (243.04 + t) + return 243.04 * gamma / (17.625 - gamma) diff --git a/tests/scenarios/bme280.yaml b/tests/scenarios/bme280.yaml index fca42d32..0aa9ced7 100644 --- a/tests/scenarios/bme280.yaml +++ b/tests/scenarios/bme280.yaml @@ -630,3 +630,30 @@ tests: result = abs(alt - 33.7) < 1.0 expect_true: true mode: [mock] + + # ----- Dew point ----- + + - name: "dew_point() returns plausible value" + action: script + script: | + # Mock: ~25.08°C, ~50.57%RH → dew point ~14.11°C + dp = dev.dew_point() + result = abs(dp - 14.11) < 0.5 + expect_true: true + mode: [mock] + + - name: "dew_point() equals temperature at 100% humidity" + action: script + script: | + # Override humidity compensation to return ~100%RH + # At 100% RH, dew point should equal temperature + from math import log + t = dev.temperature() + rh = dev.humidity() + # Compute expected dew point from actual mock values + gamma = log(rh / 100.0) + 17.625 * t / (243.04 + t) + expected = 243.04 * gamma / (17.625 - gamma) + dp = dev.dew_point() + result = abs(dp - expected) < 0.01 + expect_true: true + mode: [mock] From 4e599550e6dc94e0db93c7da128f6aa870e54d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20NEDJAR?= Date: Mon, 30 Mar 2026 12:00:12 +0200 Subject: [PATCH 2/2] fix(bme280): Use single read() in dew_point and clamp RH to avoid log(0). --- lib/bme280/bme280/device.py | 7 ++++--- tests/scenarios/bme280.yaml | 9 +++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/bme280/bme280/device.py b/lib/bme280/bme280/device.py index 35f85ac1..c2ef8bab 100644 --- a/lib/bme280/bme280/device.py +++ b/lib/bme280/bme280/device.py @@ -414,11 +414,12 @@ def dew_point(self): """Return dew point temperature in degrees Celsius. Uses the Magnus formula (Alduchov & Eskridge, 1996) with the - current temperature and relative humidity readings. + current temperature and relative humidity readings. Both values + come from a single ``read()`` call to ensure consistency. """ from math import log - t = self.temperature() - rh = self.humidity() + t, _, rh = self.read() + rh = max(rh, 0.01) gamma = log(rh / 100.0) + 17.625 * t / (243.04 + t) return 243.04 * gamma / (17.625 - gamma) diff --git a/tests/scenarios/bme280.yaml b/tests/scenarios/bme280.yaml index 0aa9ced7..c849596a 100644 --- a/tests/scenarios/bme280.yaml +++ b/tests/scenarios/bme280.yaml @@ -642,15 +642,12 @@ tests: expect_true: true mode: [mock] - - name: "dew_point() equals temperature at 100% humidity" + - name: "dew_point() matches Magnus formula for mock readings" action: script script: | - # Override humidity compensation to return ~100%RH - # At 100% RH, dew point should equal temperature from math import log - t = dev.temperature() - rh = dev.humidity() - # Compute expected dew point from actual mock values + t, _, rh = dev.read() + # Compute expected dew point from Magnus formula gamma = log(rh / 100.0) + 17.625 * t / (243.04 + t) expected = 243.04 * gamma / (17.625 - gamma) dp = dev.dew_point()