Skip to content

feat(bme280): Implement _ensure_data() auto-trigger pattern#318

Merged
nedseb merged 3 commits intomainfrom
feat/bme280-ensure-data
Mar 29, 2026
Merged

feat(bme280): Implement _ensure_data() auto-trigger pattern#318
nedseb merged 3 commits intomainfrom
feat/bme280-ensure-data

Conversation

@nedseb
Copy link
Copy Markdown
Contributor

@nedseb nedseb commented Mar 29, 2026

Closes #159

Summary

  • _is_sleep_mode(): reads ctrl_meas register and checks if mode bits are 0x00 (sleep)
  • _ensure_data(): if the sensor is in sleep mode, triggers a forced measurement and waits for completion; no-op in normal mode
  • Auto-trigger in measurement methods: temperature(), pressure_hpa(), humidity(), and read() now call _ensure_data() before reading registers, so they always return fresh data regardless of the current operating mode
  • read_one_shot() is unchanged — it explicitly triggers a forced measurement regardless of mode
  • 6 new mock tests: _is_sleep_mode() in sleep/normal, _ensure_data() trigger/no-op, temperature() and read() auto-trigger verification

Test plan

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

Copilot AI review requested due to automatic review settings March 29, 2026 11:59
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 an auto-trigger “ensure fresh data” pattern to the BME280 driver so measurement APIs can transparently perform a forced conversion when the device is in sleep mode (aligning with the repo’s broader auto-trigger conventions).

Changes:

  • Add _is_sleep_mode() and _ensure_data() helpers to detect sleep mode and trigger/wait for a forced measurement.
  • Update temperature(), pressure_hpa(), humidity(), and read() to call _ensure_data() before reading sensor registers.
  • Add mock scenario tests in tests/scenarios/bme280.yaml to validate sleep/normal detection and auto-trigger behavior.

Reviewed changes

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

File Description
lib/bme280/bme280/device.py Introduces _ensure_data()/_is_sleep_mode() and wires auto-trigger into measurement methods.
tests/scenarios/bme280.yaml Adds mock scenarios covering sleep/normal mode checks and auto-triggered measurement writes.

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

Comment on lines +246 to +255
def _ensure_data(self):
"""Trigger a forced measurement if the sensor is in sleep mode.

In normal mode this is a no-op. In sleep mode it triggers a
single conversion and waits for completion so that subsequent
register reads return fresh data.
"""
if self._is_sleep_mode():
self.trigger_one_shot()
self._wait_measurement()
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

_ensure_data() relies on _wait_measurement(), which currently raises BME280Error("BME280 measurement timeout"). The auto-trigger convention in issue #159 calls for raising OSError on timeout; as implemented, callers will see a driver-specific exception type instead. Consider changing the timeout exception to OSError (or making BME280Error inherit from OSError) so timeout handling is consistent with the convention across drivers.

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.

The project convention uses driver-specific exceptions (e.g. WSENPADSTimeout in wsen-pads, BME280Error here), all inheriting from Exception, not OSError. This is consistent across all drivers in the repo. Keeping BME280Error for now to stay aligned.

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.

You were right — fixed in 3e6fd4f. The convention from #44 is indeed OSError for timeouts, and 5 out of 7 drivers already follow it. I had incorrectly aligned with WSEN-PADS/WSEN-HIDS which are the two outliers. Created #319 to harmonize those two remaining drivers.

Comment on lines 372 to 379
def read(self):
"""Return (temperature_c, pressure_hpa, humidity_rh) tuple."""
"""Return (temperature_c, pressure_hpa, humidity_rh) tuple.

If the sensor is in sleep mode, a forced measurement is triggered
automatically before reading.
"""
self._ensure_data()
raw_temp, raw_press, raw_hum = self._read_raw()
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

read_one_shot() calls read(), and read() now calls _ensure_data(). On real BME280 hardware, a forced measurement typically returns the sensor to sleep mode after completion; that would make read() immediately trigger a second forced measurement, so read_one_shot() could perform two conversions instead of one. To avoid double-triggering, consider having read_one_shot() read/compensate directly (bypassing _ensure_data), or add an internal/read parameter that skips auto-trigger when read_one_shot() has already triggered a conversion.

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 in d39f467: read_one_shot() now reads and compensates directly instead of calling read(), avoiding the double-trigger. A new test "read_one_shot does not double-trigger" verifies that exactly one forced mode write occurs.

Comment thread tests/scenarios/bme280.yaml Outdated
Comment on lines +537 to +539
result = triggered and abs(t - 25.08) < 0.1
expect_true: true
mode: [mock]
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

The new auto-trigger coverage only verifies temperature() and read() behavior in sleep mode. Since pressure_hpa() and humidity() were also updated to call _ensure_data(), consider adding similar mock assertions for those methods (and/or asserting p and h in the read() auto-trigger test) to ensure all updated APIs are covered.

Suggested change
result = triggered and abs(t - 25.08) < 0.1
expect_true: true
mode: [mock]
result = (
triggered
and abs(t - 25.08) < 0.1
and abs(p - 1009.21) < 0.1
and abs(h - 50.57) < 0.1
)
expect_true: true
mode: [mock]
- name: "pressure_hpa() auto-triggers in sleep mode"
action: script
script: |
dev.power_off()
i2c.clear_write_log()
p = dev.pressure_hpa()
log = i2c.get_write_log()
triggered = any(reg == 0xF4 and (data[0] & 0x03) == 0x01 for reg, data in log)
result = triggered and abs(p - 1009.21) < 0.1
expect_true: true
mode: [mock]
- name: "humidity() auto-triggers in sleep mode"
action: script
script: |
dev.power_off()
i2c.clear_write_log()
h = dev.humidity()
log = i2c.get_write_log()
triggered = any(reg == 0xF4 and (data[0] & 0x03) == 0x01 for reg, data in log)
result = triggered and abs(h - 50.57) < 0.1
expect_true: true
mode: [mock]

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 in d39f467: added auto-trigger tests for pressure_hpa() and humidity(), and the read() test now also validates pressure and humidity values.

Comment thread tests/scenarios/bme280.yaml Outdated
i2c.clear_write_log()
dev._ensure_data()
log = i2c.get_write_log()
# In normal mode, only a read of ctrl_meas (no write to 0xF4)
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

This comment says "In normal mode, only a read of ctrl_meas (no write to 0xF4)", but the mock I2C write log does not record reads—so the log will be empty here. Consider rewording to avoid implying the read is observable in the write log.

Suggested change
# In normal mode, only a read of ctrl_meas (no write to 0xF4)
# In normal mode, _ensure_data must not write to ctrl_meas (0xF4); the write log may be empty

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 in d39f467: reworded comment to clarify that the write log should not contain a forced mode write.

@nedseb nedseb added the driver Concerne un driver spécifique label Mar 29, 2026
@nedseb nedseb merged commit a0d344d into main Mar 29, 2026
9 checks passed
semantic-release-updater Bot pushed a commit that referenced this pull request Mar 29, 2026
# [0.7.0](v0.6.0...v0.7.0) (2026-03-29)

### Features

* **bme280:** Implement _ensure_data() auto-trigger pattern ([#318](#318)) ([a0d344d](a0d344d))
@semantic-release-updater
Copy link
Copy Markdown

🎉 This PR is included in version 0.7.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@nedseb nedseb deleted the feat/bme280-ensure-data branch March 29, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

driver Concerne un driver spécifique released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bme280: Implement _ensure_data() auto-trigger pattern.

2 participants