Skip to content

feat(bme280): Add dew point calculation using Magnus formula#322

Merged
nedseb merged 2 commits intomainfrom
feat/bme280-dew-point
Mar 30, 2026
Merged

feat(bme280): Add dew point calculation using Magnus formula#322
nedseb merged 2 commits intomainfrom
feat/bme280-dew-point

Conversation

@nedseb
Copy link
Copy Markdown
Contributor

@nedseb nedseb commented Mar 30, 2026

Closes #316

Summary

  • dew_point() method: computes dew point temperature in degrees Celsius from current temperature and humidity using the Magnus formula (Alduchov & Eskridge, 1996 constants: a=17.625, b=243.04)
  • math.log imported lazily inside the method to avoid RAM usage when not needed
  • README: new Dew Point section in API reference, comparison table updated
  • 2 new mock tests: plausible value check (~14.11 C from mock data), consistency verification against direct formula

Depends on #321 (altitude branch) — both branch from the same base.

Test plan

  • 54 mock tests pass (make test-bme280)
  • Hardware validation

Copilot AI review requested due to automatic review settings March 30, 2026 09:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds derived environmental calculations to the BME280 driver and updates docs/examples/tests to expose them.

Changes:

  • Add BME280.dew_point() using the Magnus formula (Alduchov & Eskridge constants).
  • Add altitude support via BME280.altitude() and a configurable sea_level_pressure reference.
  • Update README, example script, and scenario tests to cover the new APIs.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
lib/bme280/bme280/device.py Introduces sea_level_pressure, altitude(), and dew_point() methods.
tests/scenarios/bme280.yaml Adds mock scenario coverage for altitude and dew point.
lib/bme280/examples/weather_station.py Switches altitude calculation to sensor.altitude() and documents sea_level_pressure.
lib/bme280/README.md Documents Altitude/Dew Point APIs and updates the feature comparison table.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/bme280/bme280/device.py Outdated
Comment on lines +417 to +420
t = self.temperature()
rh = self.humidity()
gamma = log(rh / 100.0) + 17.625 * t / (243.04 + t)
return 243.04 * gamma / (17.625 - gamma)
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dew_point() calls temperature() and humidity() separately. In sleep/forced mode this will trigger two measurements via _ensure_data(), and it can also mix readings from different conversions. Consider using a single read() (or read_one_shot() if you want a fresh forced conversion) to get temperature/humidity from the same sample and avoid the extra I2C traffic and power usage.

Suggested change
t = self.temperature()
rh = self.humidity()
gamma = log(rh / 100.0) + 17.625 * t / (243.04 + t)
return 243.04 * gamma / (17.625 - gamma)
t, _, rh = self.read()
gamma = log(rh / 100.0) + 17.625 * t / (243.04 + t)
return 243.04 * gamma / (17.625 - gamma)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: dew_point() now uses a single self.read() call to get temperature and humidity from the same measurement, avoiding double trigger and inconsistent readings.

Comment thread lib/bme280/bme280/device.py Outdated
from math import log

t = self.temperature()
rh = self.humidity()
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dew_point() uses log(rh / 100.0) without guarding against rh being 0.0 (possible with the current humidity compensation which clamps to 0). This can raise a math domain error at runtime. Clamp RH to a small positive minimum (and optionally cap to 100%) before taking the log, or define a clear behavior/error for RH<=0.

Suggested change
rh = self.humidity()
rh = self.humidity()
# Clamp RH to a small positive minimum and a maximum of 100% to
# avoid math domain errors from log(rh / 100.0) when rh <= 0.
rh = max(0.01, min(100.0, rh))

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: added rh = max(rh, 0.01) before log() to prevent math domain error when humidity compensation clamps to 0.


Uses the ICAO barometric formula with ``sea_level_pressure`` as
reference (default 1013.25 hPa, adjustable).
"""
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

altitude() divides by self.sea_level_pressure without validating it. Since this is a public attribute, it’s easy for users/tests to set it to 0 or a negative value and trigger a ZeroDivisionError or complex results. Consider validating sea_level_pressure > 0 (e.g., raise a clear exception) before computing altitude.

Suggested change
"""
"""
# Validate sea_level_pressure before using it as a divisor to avoid
# ZeroDivisionError or invalid results if it has been set to a
# non-positive value by user code.
if not hasattr(self, "sea_level_pressure") or self.sea_level_pressure <= 0:
raise ValueError(
"sea_level_pressure must be a positive value for altitude calculation"
)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not addressed: same rationale as PR #321 — no validation on internal attributes per project convention. See discussion on PR #321.

Comment thread tests/scenarios/bme280.yaml Outdated
Comment on lines +636 to +644
- 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
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dew point scenario is labeled as “equals temperature at 100% humidity”, but the script doesn’t set RH to 100% (it reads the mock ~50%RH) and it computes expected from the same Magnus formula, so it’s really a formula-consistency test. Rename/update the test (and comments) to match what it asserts, or actually force RH=100% and assert dew_point() == temperature() within tolerance.

Suggested change
- 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
- name: "dew_point() matches Magnus formula for mock readings"
action: script
script: |
# Validate dew_point() implementation against the Magnus formula
# using the current mock temperature and humidity readings
from math import log
t = dev.temperature()
rh = dev.humidity()
# Compute expected dew point from Magnus formula using these values

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: test renamed to "dew_point() matches Magnus formula for mock readings" and uses dev.read() for consistency with the implementation.

Comment thread lib/bme280/bme280/device.py Outdated
Comment on lines +400 to +407
def altitude(self):
"""Return estimated altitude in meters from current pressure.

Uses the ICAO barometric formula with ``sea_level_pressure`` as
reference (default 1013.25 hPa, adjustable).
"""
p = self.pressure_hpa()
return 44330.0 * (1.0 - (p / self.sea_level_pressure) ** 0.1903)
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR title/summary focus on adding dew_point(), but this diff also introduces the sea_level_pressure attribute and altitude() API (plus README + example + scenario updates for altitude). If this is a stacked PR that depends on #321, consider rebasing onto that branch/retargeting so this PR only contains the dew point-related changes, or update the PR description/title to reflect the additional API surface.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

@nedseb nedseb Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The branch is based on feat/bme280-altitude and will be rebased on main.

@nedseb nedseb force-pushed the feat/bme280-dew-point branch from 626f6b9 to 95bfb54 Compare March 30, 2026 10:03
@nedseb nedseb force-pushed the feat/bme280-dew-point branch from 95bfb54 to 4e59955 Compare March 30, 2026 10:07
@nedseb nedseb merged commit 8e730ad into main Mar 30, 2026
9 checks passed
@nedseb nedseb deleted the feat/bme280-dew-point branch March 30, 2026 10:10
semantic-release-updater Bot pushed a commit that referenced this pull request Mar 30, 2026
# [0.9.0](v0.8.0...v0.9.0) (2026-03-30)

### Features

* **bme280:** Add dew point calculation using Magnus formula ([#322](#322)) ([8e730ad](8e730ad))
@semantic-release-updater
Copy link
Copy Markdown

🎉 This PR is included in version 0.9.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bme280: Add dew point calculation.

2 participants