Rewrite epics2sms.sh from a single-PV/single-alert monitor into a driver
that runs multiple independent monitors from a MONITORS config array, each
as its own background loop with isolated state.
Per monitor:
- directional threshold (lt/gt) on a moving average over the last n_avg
samples ("N Mittel"); alarm only fires once the window is full, so a
single spurious reading cannot trigger it
- separate normal and alarm poll intervals; one message is sent per alarm
poll, so alarm_poll_s governs the minimum spacing between messages
- up to n_msg messages per alarm episode ("N Messages"), then silent;
counter resets on recovery
- unreadable/non-numeric reads are logged and skipped
Config format: pv | dir | threshold | poll_s | alarm_poll_s | n_avg | n_msg | text
Recipient updated to 0041797554007@sms.switch.ch. README updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EPICS2SMS
Monitor one or more EPICS PVs and send an SMS alert via PSI mail infrastructure.
This tool does not use local /usr/sbin/sendmail. It sends mail via direct SMTP
to smtp.psi.ch to ensure the message is handled as a registered
system/application sender.
Files
-
epics2sms.sh
Runs one or more independent monitors, each polling a PV, keeping a moving average, and sending SMS/mail when the average crosses a directional threshold. -
smtp_send.py
SMTP transport helper (no authentication). Sets both headerFrom:and envelope sender (MAIL FROM) to the configured sender address.
Monitors
Each monitor is one pipe-separated entry in the MONITORS array:
pv | dir | threshold | poll_s | alarm_poll_s | n_avg | n_msg | text
| Field | Meaning |
|---|---|
pv |
EPICS PV name |
dir |
alarm direction: lt (avg < threshold) or gt (avg > threshold) |
threshold |
numeric threshold |
poll_s |
seconds between polls while in normal state |
alarm_poll_s |
seconds between polls while in alarm; since one message is sent per alarm poll, this also sets the minimum interval between messages |
n_avg |
samples averaged before an alarm can fire ("N Mittel") |
n_msg |
max messages per alarm episode, then silent ("N Messages") |
text |
message text, also the start of the SMS body |
Multiple monitors may watch the same PV with different thresholds and timing; each runs as its own background loop with independent state.
Example (current config):
MONITORS=(
"X12SA-OP-CC:L1Level_MON|lt|55|60|60|4|10|X12SA-OP-CC:L1Level_MON <55%"
"X12SA-OP-CC:L1Level_MON|gt|75|10|10|4|10|X12SA-OP-CC:L1Level_MON >75%"
)
Behaviour of one monitor:
- polls the PV every
poll_sseconds while normal, everyalarm_poll_swhile in alarm - keeps a moving average of the last
n_avgsamples; an alarm can only fire once the window is full, so a single spurious reading cannot trigger it - while the average is in alarm, sends one message per alarm poll, up to
n_msgmessages, then stays silent — soalarm_poll_sgoverns the minimum spacing between messages - once the average returns to normal, the message counter resets
- unreadable / non-numeric reads are logged and skipped (they do not enter the average and never trigger an alarm)
Why SMTP instead of sendmail?
On beamline console hosts, local sendmail may be routed through internal relays
or firewall rules and can lead to silent drops for mail-to-SMS gateways.
Direct SMTP to smtp.psi.ch makes the transport path explicit and reproducible.
Requirements
- EPICS CA tools available on the host (
caget). - Python 3 available (
python3). - Network access from the host to
smtp.psi.ch:25.
Configuration
Edit epics2sms.sh:
MONITORS
One entry per monitor (see Monitors above).RECIPIENTS
Applied to every monitor. Include the SMS gateway address, e.g.:0041797554007@sms.switch.ch079XXXXXXX@mail2sms.swisscom.com
FROM_ADDR
Must be a registered PSI system/application sender, e.g.cSAXS@psi.ch.
FROM_ADDR is critical: messages from host/user addresses like
e23080@x12sa-cons-02.psi.ch may be filtered and never reach the SMS gateway.
Quick test
Send a normal email:
python3 smtp_send.py --to andreas.menzel@psi.ch --from-addr cSAXS@psi.ch "Test $(date)"
Send an SMS (via mail2sms):
python3 smtp_send.py --to 079XXXXXXX@mail2sms.swisscom.com --from-addr cSAXS@psi.ch "SMS test $(date)"
Run the monitor
./epics2sms.sh
All monitors run in one process; Ctrl-C (or SIGTERM) stops them together.
Notes / Troubleshooting
- If no SMS arrives but SMTP returns success, ask IT to check Exchange/relay transport rules for the registered sender and the mail2sms gateway domain.
- Use
smtp_send.pydirectly for transport debugging (it should return non-zero on errors).