Skip to content

Commit 2416ac3

Browse files
committed
feat(bme280): Implement _ensure_data() auto-trigger pattern.
1 parent c041dcc commit 2416ac3

2 files changed

Lines changed: 105 additions & 4 deletions

File tree

lib/bme280/bme280/device.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,21 @@ def humidity_ready(self):
239239
# Forced measurement trigger
240240
# --------------------------------------------------
241241

242+
def _is_sleep_mode(self):
243+
"""Return True if the sensor is in sleep mode."""
244+
return (self._read_reg(REG_CTRL_MEAS) & MODE_MASK) == MODE_SLEEP
245+
246+
def _ensure_data(self):
247+
"""Trigger a forced measurement if the sensor is in sleep mode.
248+
249+
In normal mode this is a no-op. In sleep mode it triggers a
250+
single conversion and waits for completion so that subsequent
251+
register reads return fresh data.
252+
"""
253+
if self._is_sleep_mode():
254+
self.trigger_one_shot()
255+
self._wait_measurement()
256+
242257
def trigger_one_shot(self):
243258
"""Trigger a single forced measurement. Poll data_ready() for completion."""
244259
ctrl = self._read_reg(REG_CTRL_MEAS)
@@ -323,24 +338,44 @@ def _compensate_humidity(self, raw_hum):
323338
# --------------------------------------------------
324339

325340
def temperature(self):
326-
"""Return compensated temperature in °C (float)."""
341+
"""Return compensated temperature in °C (float).
342+
343+
If the sensor is in sleep mode, a forced measurement is triggered
344+
automatically before reading.
345+
"""
346+
self._ensure_data()
327347
raw_temp, _, _ = self._read_raw()
328348
return self._compensate_temperature(raw_temp) / 100.0
329349

330350
def pressure_hpa(self):
331-
"""Return compensated pressure in hPa (float)."""
351+
"""Return compensated pressure in hPa (float).
352+
353+
If the sensor is in sleep mode, a forced measurement is triggered
354+
automatically before reading.
355+
"""
356+
self._ensure_data()
332357
raw_temp, raw_press, _ = self._read_raw()
333358
self._compensate_temperature(raw_temp)
334359
return self._compensate_pressure(raw_press) / 25600.0
335360

336361
def humidity(self):
337-
"""Return compensated relative humidity in %RH (float)."""
362+
"""Return compensated relative humidity in %RH (float).
363+
364+
If the sensor is in sleep mode, a forced measurement is triggered
365+
automatically before reading.
366+
"""
367+
self._ensure_data()
338368
raw_temp, _, raw_hum = self._read_raw()
339369
self._compensate_temperature(raw_temp)
340370
return self._compensate_humidity(raw_hum) / 1024.0
341371

342372
def read(self):
343-
"""Return (temperature_c, pressure_hpa, humidity_rh) tuple."""
373+
"""Return (temperature_c, pressure_hpa, humidity_rh) tuple.
374+
375+
If the sensor is in sleep mode, a forced measurement is triggered
376+
automatically before reading.
377+
"""
378+
self._ensure_data()
344379
raw_temp, raw_press, raw_hum = self._read_raw()
345380
temp_c = self._compensate_temperature(raw_temp) / 100.0
346381
press_hpa = self._compensate_pressure(raw_press) / 25600.0

tests/scenarios/bme280.yaml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,3 +471,69 @@ tests:
471471
prompt: "Do the values look reasonable?"
472472
expect_true: true
473473
mode: [hardware]
474+
475+
# ----- Auto-trigger (_ensure_data) -----
476+
477+
- name: "_is_sleep_mode returns True after init"
478+
action: script
479+
script: |
480+
result = dev._is_sleep_mode()
481+
expect_true: true
482+
mode: [mock]
483+
484+
- name: "_is_sleep_mode returns False in normal mode"
485+
action: script
486+
script: |
487+
dev.power_on()
488+
result = not dev._is_sleep_mode()
489+
expect_true: true
490+
mode: [mock]
491+
492+
- name: "_ensure_data triggers forced mode in sleep"
493+
action: script
494+
script: |
495+
dev.power_off()
496+
i2c.clear_write_log()
497+
dev._ensure_data()
498+
log = i2c.get_write_log()
499+
triggered = any(reg == 0xF4 and (data[0] & 0x03) == 0x01 for reg, data in log)
500+
result = triggered
501+
expect_true: true
502+
mode: [mock]
503+
504+
- name: "_ensure_data is no-op in normal mode"
505+
action: script
506+
script: |
507+
dev.power_on()
508+
i2c.clear_write_log()
509+
dev._ensure_data()
510+
log = i2c.get_write_log()
511+
# In normal mode, only a read of ctrl_meas (no write to 0xF4)
512+
wrote_forced = any(reg == 0xF4 and (data[0] & 0x03) == 0x01 for reg, data in log)
513+
result = not wrote_forced
514+
expect_true: true
515+
mode: [mock]
516+
517+
- name: "temperature() auto-triggers in sleep mode"
518+
action: script
519+
script: |
520+
dev.power_off()
521+
i2c.clear_write_log()
522+
t = dev.temperature()
523+
log = i2c.get_write_log()
524+
triggered = any(reg == 0xF4 and (data[0] & 0x03) == 0x01 for reg, data in log)
525+
result = triggered and abs(t - 25.08) < 0.1
526+
expect_true: true
527+
mode: [mock]
528+
529+
- name: "read() auto-triggers in sleep mode"
530+
action: script
531+
script: |
532+
dev.power_off()
533+
i2c.clear_write_log()
534+
t, p, h = dev.read()
535+
log = i2c.get_write_log()
536+
triggered = any(reg == 0xF4 and (data[0] & 0x03) == 0x01 for reg, data in log)
537+
result = triggered and abs(t - 25.08) < 0.1
538+
expect_true: true
539+
mode: [mock]

0 commit comments

Comments
 (0)