menzelandClaude Opus 4.8 6b75401aec epics2sms: move site config to an untracked epics2sms.conf
Split all site-specific settings (RECIPIENTS, FROM_ADDR, ALERT_SUBJECT,
CA_TIMEOUT, MONITORS) out of EPICS2SMS.sh into a separate config file that
is sourced at startup, so "git pull" no longer clobbers local settings.

- epics2sms.conf is git-ignored (local, per-host).
- epics2sms.conf.example is tracked and documents the format.
- Config path: first CLI arg > EPICS2SMS_CONF env var > epics2sms.conf beside
  the script. Missing config or empty RECIPIENTS/MONITORS exits with a clear
  error pointing at the template.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 12:55:36 +02:00

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 header From: 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 | msg_delay_s | 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 (how often the average is refreshed and recovery is checked)
n_avg samples averaged before an alarm can fire ("N Mittel")
n_msg max messages per alarm episode, then silent ("N Messages")
msg_delay_s minimum seconds between two alarm messages; polling keeps running faster, but messages are throttled to this spacing (the first message of an episode goes out immediately)
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|300|X12SA-OP-CC:L1Level_MON <55%"
  "X12SA-OP-CC:L1Level_MON|gt|75|10|10|4|10|300|X12SA-OP-CC:L1Level_MON >75%"
)

On startup, the script sends one brief notification to all recipients listing the monitors it is watching (PV, threshold, timing) so you can confirm it is running. This is best-effort: if it fails to send, monitoring still starts.

Behaviour of one monitor:

  • polls the PV every poll_s seconds while normal, every alarm_poll_s while in alarm
  • keeps a moving average of the last n_avg samples; 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 the first message immediately, then up to n_msg messages total, spaced at least msg_delay_s apart, then stays silent
  • once the average returns to normal, it resets the message counter and — if at least one alarm message was sent this episode — sends one recovery ("RESOLVED") message
  • 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

All site-specific settings live in an untracked config file, so git pull never touches them. Copy the template once and edit it:

cp epics2sms.conf.example epics2sms.conf
$EDITOR epics2sms.conf

epics2sms.conf is git-ignored; epics2sms.conf.example is tracked and documents the format. The config file is sourced as bash and may set:

  • MONITORS
    One entry per monitor (see Monitors above).
  • RECIPIENTS
    Applied to every monitor. Include the SMS gateway address, e.g.:
    • 0041797554007@sms.switch.ch
    • 079XXXXXXX@mail2sms.swisscom.com
  • FROM_ADDR
    Must be a registered PSI system/application sender, e.g. cSAXS@psi.ch.
  • ALERT_SUBJECT
    Subject used for alert mails/SMS.
  • CA_TIMEOUT
    Channel Access timeout (caget -w) in seconds. The caget default (~1 s) can be too short for the first connection to a PV, which then looks like "not connected"; keep this well below the shortest poll interval.

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.

By default the config is read from epics2sms.conf next to the script; override the path with the EPICS2SMS_CONF environment variable or the first command-line argument (./EPICS2SMS.sh /path/to/other.conf).

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.py directly for transport debugging (it should return non-zero on errors).
S
Description
Collection of small, self-contained tools and scripts made publicly available for PSI collaborators and other researchers.
Readme
113 KiB
Languages
Python 74.9%
Shell 25.1%