New: the AI firewall watches the whole platform and explains each incident in plain words. See how it works

Have a Pi in the lab read new Hermetry alarms out loud through a speaker

Have a Pi in the lab read new Hermetry alarms out loud through a speaker

Solved 6 6

Me again. Our lab has 6 freezers and incubators on Hermetry with alarm rules and they work, but alerts go to the bell and nobody looks at the screen while wearing gloves. The PI asked if a speaker could just say “Freezer 3 temperature high” in the room.

I have a spare Pi 4 and a USB speaker. Offline text to speech works (I tested piper and espeak-ng, piper sounds much nicer). The part I don’t get is how the Pi finds out about a new alarm. I set up a webhook in Hermetry pointing at the Pi and nothing ever arrives. The Pi is on the university network behind NAT, no public address. Is a webhook the wrong tool?

Timestamps in UTC or it didn't happen.
♥ 0

Could you have it announce by e-mail somehow? Like read the inbox?

♥ 0

Webhooks need an HTTPS URL Hermetry can reach from outside, so behind NAT they’ll never land. You’d need a tunnel or a reverse proxy, and uni IT will probably say no.

♥ 2

Or turn it around and have the Pi ask. Pull beats push when the receiver is behind NAT.

♥ 0

following, I want this for my intercom thing too lol

Ask me about 4–20 mA.
♥ 0

We do this on our plant floor, a Pi with a horn speaker reads critical alarms over the noise. Ciaran’s right, poll the Alarms API.

Ask your admin for an API key with only the alarm read permission (reading alarms is a User-level permission by default) and an IP allowlist for the uni’s address. Then:

import requests, subprocess, time
H = {"Authorization": f"Bearer {API_KEY}"}
URL = f"https://{HOST}/tenant/{TENANT}/api/iot/alarms"
seen = set()
while True:
    r = requests.get(URL, headers=H, params={"status": "OPEN", "severity": "CRITICAL,MAJOR",
                                             "sort": "opened:desc", "pageSize": 20}, timeout=10)
    for a in r.json()["items"]:
        if a["alarmId"] not in seen:
            seen.add(a["alarmId"])
            subprocess.run(["sh", "-c", f'echo "{a["deviceName"]}: {a["title"]}" | piper --model en_GB-alan-medium.onnx --output-raw | aplay -r 22050 -f S16_LE'])
    time.sleep(15)

Status OPEN means acknowledged alarms stop being read, which people like: ack it in the app and the room goes quiet. Give your alarm rules readable titles because that’s what gets spoken, e.g. “{{device.name}} temperature {{value}}”. Fifteen seconds is a polite poll rate, stay well under the API limits. If you ever do get a public endpoint, the alarm.created webhook would replace the polling: Webhooks.

Accepted solution♥ 2

Got it running yesterday, everyone in the lab loves it. Had to ask IT nothing, which was a win. Only thing: I first used status=active and it kept repeating acknowledged alarms after a restart because my seen-set was empty, switched to OPEN like you wrote. Also had to change device names from “frz-03” to “freezer three” because piper read it as “frz”.

Timestamps in UTC or it didn't happen.
♥ 1
Viewing 7 posts – 1 through 7 (of 7 total)
  • You must be logged in to reply to this topic.

Join the conversation

Sign in to ask and answer, like helpful posts and mark the reply that solved your problem. Every contribution earns points and levels.

Share