Repository navigation
feat: run an external program for each reading (--exec) - #8
Merged
Merged
Conversation
Closes the README item "call external scripts".
--exec /path/to/script runs a program once per reading. The reading is handed
over twice so a script can use whichever is easier: as MITEMPR_* environment
variables, and as one JSON object on stdin.
#!/bin/sh
[ -n "$MITEMPR_TEMPERATURE" ] || exit 0
echo "$MITEMPR_NAME is at ${MITEMPR_TEMPERATURE} C"
Every variable is always set, empty when the sensor did not report that
measurement. Omitting them instead would let a value inherited from mitempr's
own environment show through, and an empty string is easy to test for in shell.
Rate limiting, because a Pi Zero W has one core and sensors advertise every
second or two:
- --exec-interval SECS is the shortest gap between two runs for the same
sensor, tracked per address. Default 0, i.e. every reading.
- At most four hooks run at once. Beyond that, readings are dropped with a
warning rather than queued: a backlog of stale temperatures is worse than
a gap, and an unbounded queue on this hardware ends badly.
- A hook that has not finished within 30 seconds is killed, so a stuck script
cannot hold one of those four slots forever.
The child is spawned into its own task, so a slow script delays its own next
run but never the scan.
Its stdout goes to /dev/null on purpose: with --format json, anything the
script printed would otherwise interleave with the reading stream and corrupt
it. stderr is inherited so a broken script can still complain visibly.
Five tests cover the environment mapping, the empty-variable rule, the
per-sensor interval, and one end-to-end case that writes a real shell script to
a temporary directory and checks what it actually received on stdin and in its
environment.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mreymann
marked this pull request as ready for review
August 4, 2026 16:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the README item "call external scripts".
--exec /path/to/scriptruns a program once per reading. The reading is handed over twice so a script can use whichever is easier — asMITEMPR_*environment variables, and as one JSON object on stdin:Every variable is always set, empty when the sensor did not report that measurement. Omitting them instead would let a value inherited from mitempr's own environment show through, and an empty string is easy to test for in shell.
Rate limiting, because a Pi Zero W has one core and sensors advertise every second or two:
--exec-interval SECSis the shortest gap between two runs for the same sensor, tracked per address. Default 0, i.e. every reading.The child is spawned into its own task, so a slow script delays its own next run but never the scan.
Its stdout goes to
/dev/nullon purpose: with--format json, anything the script printed would otherwise interleave with the reading stream and corrupt it. stderr is inherited so a broken script can still complain visibly.Five tests, including one end-to-end case that writes a real shell script to a temp directory and checks what it actually received on stdin and in its environment.
I went through the README TODO list and found a few real bugs on the way, so this
is one of ten PRs. They are meant to be reviewed and merged in this order, and
each is a separate branch so you can take some and leave others:
chore/ci-deps-and-metadata— CI, unused deps, lockfiletest/decoder-assertions— make the decoder tests actually assertfix/bthome-object-lengths— BTHome parser desync + encryption flagfix/mibeacon-frame-control— MiBeacon hardcoded offset + encryption flagfix/continuous-scan— one reading per sensor ever, and the watchdog loopfeat/logging-and-output(draft) — log levels,--format jsonfeat/config-file(draft) — name, calibrate and filter sensorsfeat/exec-hook(draft) —--execfeat/prometheus(draft) —--metrics-addrand--pushgateway-urlfeat/encrypted-payloads(draft) — AES-CCM bind keys6–10 are drafts because they build on each other; GitHub can only point a
cross-fork PR at
main, so until the ones before it are merged each diff alsoshows its ancestors. I will rebase and force-push as things merge, so each
shrinks to its own change. Nothing here is urgent — take them at whatever pace
suits, or tell me to close some.
Everything is checked with
cargo fmt --check,cargo clippy -D warningsandcargo testin arust:1.96container, sincebluer'sbluetoothdfeature isLinux-only and I develop on a Mac.