Daemon, Driver and Config Inventory#
This page is the concrete inventory the COO specification asks each instrument
to provide: what daemons exist, what hardware each owns, which driver it uses,
and what it exposes. It describes the current main branch and needs updating
whenever a daemon is added.
Daemon inventory#
Daemons are split by reusability, not by subsystem. daemons/generic/ holds
daemons whose behaviour is fully determined by config and which are therefore
shared across subsystems; daemons/<subsystem>/ holds daemons tied to one
subsystem’s hardware or to mechanism-specific logic. The PDU daemons in
daemons/hspower/ are as config-driven as the generic daemons, but every
instance of them belongs to the hspower service, so they sit there with
their shared pdu_base.py base class.
Daemon |
Driver |
Hardware |
Deployed instances |
|---|---|---|---|
|
|
Thorlabs FW102C filter wheel |
|
|
|
Lakeshore 336/224 temperature controller |
|
|
|
SRS PTC10 thermal controller |
|
|
|
Inficon VGC502 vacuum gauge controller |
|
|
|
H2RG on an STA Archon, through |
|
|
|
PI C-663 / C-863 / E-754 motion controllers |
|
|
|
Newport SMC100PP ADC prism rotators |
|
|
|
Sunpower cryocooler |
|
|
|
Thorlabs PPC102 piezo gimbal mount |
|
|
|
Xeryon XD-M-3 piezo motion controllers |
|
|
|
Standa SMC8 (libximc) attenuator |
|
|
|
Eaton EMAT08-10 networked PDU |
|
|
|
FIB trunk interface box, over MQTT 5 |
|
Thirty-five instances are currently defined under systemd/instances/,
running twelve distinct daemon scripts — the config-driven design paying off
directly.
Subsystem view#
hsfei — Front End Instrument#
The FEI is the most complete subsystem, covering the pickoff and acquisition path, the ADC, the PIAA gimbal mounts, and the ATC (acquisition and tracking camera) environment.
Instance |
Mechanism |
|---|---|
|
FEI pickoff |
|
mask selector (two daisy-chained PI stages, H and V) |
|
lens selector mechanism |
|
ATC lens stage |
|
ATC pickoff stage |
|
atmospheric dispersion corrector, two prism rotators |
|
PIAA gimbal mounts, blue and red |
|
PIAA lens deploy, blue and red in/out |
|
fiber alignment mechanisms, blue and red |
|
ATC filter wheel |
|
ATC temperature control |
|
ATC vacuum pressure |
|
ATC cryocooler |
|
ATC camera, the only instance on |
hscal — Calibration#
The calibration unit covers the HK (red) and YJ (blue) calibration paths and the gas cell.
Instance |
Mechanism |
|---|---|
|
HK calibration filter wheels |
|
YJ calibration filter wheels |
|
gas cell filter wheel |
|
gas cell heaters |
|
etalon thermal control |
|
HK etalon attenuator |
hsfibers: FIB#
The FIB PCBs run their own firmware and are reached over MQTT 5 through the
mosquitto broker on hispec.caltech.edu. The daemon is read only: its driver
can only send allowlisted queries, so it cannot turn on a laser or move a
switch.
Instance |
Mechanism |
|---|---|
|
trunk interface box: MEMS switches, routes, lasers, attenuators, photodiodes, all read only |
hspower — power distribution#
Every networked PDU in the instrument is one hspower instance, and they
all live in this one service rather than with the subsystem they power, so
that outlet control is in a single place. Each is named for where the unit is.
Every deployed unit is an Eaton (hspower/eaton_pdu) today; see below for
how to add a daemon for another PDU.
Instance |
PDU |
|---|---|
|
FEI, two units ( |
|
CAL, four units |
|
FIB |
|
BSPEC ( |
|
RSPEC |
The addresses for the CAL, FIB and RSPEC units are not documented anywhere in
the repo yet, so those configs carry a TODO and no ip_address; such an
instance starts and serves its keywords, reporting missing PDU connection parameters through its error keyword, and connects once an address is
filled in. outlet_count is likewise a placeholder of 8 in every config
until each unit is confirmed as an EMAT-08 or an EMAT-10 — it decides how
many outlet keyword blocks the daemon registers.
The Telnet login is not in the configs. They name the environment variables
holding it (hardware.username_env, hardware.password_env, both pointing
at HISPEC_PDU_* today), which systemd supplies from root-only
/etc/hispec/secrets.env — the same arrangement the keygrabber uses for its
InfluxDB token. An inline hardware.username / hardware.password still
works for a bench test and logs a warning against committing it.
Each PDU family gets its own daemon script, and each subclasses PduDaemon
in daemons/hspower/pdu_base.py: eaton_pdu for the Eaton EMAT-08/10 over
Telnet, and dli_pdu for the DLI DC3 over SSH. The base class does everything common to every PDU:
config, credentials, connecting, the status keyword and the outlet basics
(state<n>, name<n>, switchable<n>). The script fills
in how to talk to its hardware and registers whatever else that PDU can do,
which for the Eaton is per-outlet metering and auto-restart, and for the DLI
per-outlet power cycling.
Supporting another PDU means copying eaton_pdu, filling in its hardware
methods, and keeping only the extras the new PDU has. The steps are at the
top of pdu_base.py.
Placeholder subsystems#
daemons/hscryo, daemons/hstt and daemons/hscam exist as empty
placeholders for the cryostat, tip-tilt and detector subsystems. The
spectrograph itself has no daemon directory yet.
Keyword inventory#
Keywords every daemon has#
Inherited from LibbyDaemon and registered without the daemon asking:
Keyword |
Type |
Access |
Meaning |
|---|---|---|---|
|
int |
read |
Whole seconds since the daemon started serving. |
|
string |
read / clear |
The most recent message passed to |
|
service |
read |
Registered keyword names, |
|
service |
read |
Full metadata for one keyword: type, access, units, description, timeout. |
Registered by HISPEC daemons themselves, by near-universal convention:
Keyword |
Type |
Access |
Meaning |
|---|---|---|---|
|
bool |
read / write |
Whether the daemon holds a live connection to its controller. Writing |
|
string |
read |
Last error string recorded by the daemon’s own error state. |
|
trigger |
write |
Stop this daemon gracefully. |
Per-daemon keywords#
Motion daemons (pi-daemon, adc, filterwheel, smc8_attenuator)
share a vocabulary:
Keyword |
Meaning |
|---|---|
|
Current position in the mechanism’s configured units. Writable to move. |
|
Current position as a configured name; writable to move to a named position. |
|
Motion in progress. |
|
Stage has been homed. Writable to home. |
|
Servo loop closed. Writable. |
|
Daemon-enforced limits, writable at runtime. |
|
Controller limits, read-only. |
|
Trigger — stop motion on all axes. |
Multi-axis daemons suffix the per-axis keywords and add an aggregate. A
mechanism with more than one stage registers positionvalue<suffix>,
ismoving<suffix> and so on — the PI daemon uses the stage name from config
(positionvalueh, positionvaluev for the mask selector), the ADC uses the
stage number (positionvalue1, positionvalue2). Alongside those, the daemon
registers unsuffixed consolidated keywords covering the whole mechanism:
isreferenced is true when all stages are referenced and writing it homes
every stage, ismoving is true when any stage is moving, isloopclosed
aggregates likewise and one write closes every loop. A single-stage config
registers the bare names directly, so a client that only cares about the
mechanism as a whole uses the same keyword either way.
Thermal daemons (lakeshore, srs_thermal) generate their keywords from
config. Each entry in sensors: produces one read-only temperature keyword
under the name the config chose; each entry in heaters: produces a writable
setpoint and <name>_output plus, for the Lakeshore, <name>_status and one
keyword per PID term.
atccryo exposes cryocooler state — cold_head_temp, reject_temp,
target_temp, measured_power, commanded_power, control_mode,
cooler_error — plus pid_<term> keywords for the control loop.
inficon exposes pressure1, pressure2, temperature, units and
units_code. The gauge’s pressure unit is settable from its front panel, so
each pressure read fetches the unit alongside the value and reports it on that
reading rather than trusting a cached one.
piaa-gimbalmount carries the largest keyword set: X/Y positions in both
position and voltage units, per-axis and combined loop-closed state, and a full
soft/hard limit matrix in both units — softmaxx, softminvolty, hardmaxx
and so on.
eaton_pdu registers device-level keywords (model, firmware,
manufacturer, serial, outletcount, status) plus a per-outlet block of
state<n>, name<n>, switchable<n>, current<n>,
power<n>, energy<n>, autorestart<n> and
resetstatistics<n>. The first three outlet keywords and model/firmware
come from pdu_base.py; the rest are the Eaton’s own. The outlet count comes
from config. An outlet listed in the optional hardware.outlet_names map
(outlet number to a name; characters other than letters, digits and
underscores become underscores) uses
_<name> in place of <n>, so outlet 1 named arclamp gets
state_arclamp; unlisted outlets keep the number.
dli_pdu registers the same base keywords (model, firmware,
outletcount, status, state<n>, name<n>, switchable<n>) plus
cycle<n>, a trigger that power cycles the outlet, and cycledelay<n>, the
read-only off time of that cycle in seconds. Outlet names work as for
eaton_pdu.
Config inventory#
config/<subsystem>/<instance>.yaml, one file per instance, forty-four
files at present — thirty-five of them backing a deployed systemd instance.
config/example/ holds templates for daemons not yet deployed.
Config is the source of truth for:
Parameter group |
Owner |
Runtime mutability |
|---|---|---|
|
config only |
fixed at startup |
|
config only |
fixed at startup |
|
config, overridable |
writable via |
|
controller, or config where the controller cannot report them |
read-only |
|
config only |
fixed at startup |
|
config only |
fixed at startup; determines which keywords exist |
|
config only |
fixed at startup |
The one writable-at-runtime group is soft limits. A runtime change to
softmin/softmax lives only in the daemon process and is lost on restart,
which is worth knowing before relying on one during AIT.
Adding a daemon#
The mechanics, in the order they are done:
Add the vendor driver as a submodule under
src/hispec/driver/if it is not already vendored.If an existing daemon covers the hardware, skip to step 4 — most new mechanisms need no new Python.
Otherwise write
daemons/<subsystem>/<name>: subclassHispecDaemon, register keywords inon_start, disconnect inon_stop, and give it anargparse-c/--configentry point that callsfrom_config_file(...)thenserve().Add
config/<subsystem>/<instance>.yaml.Add
systemd/instances/<instance>.envnaming the script and the deployed config path.Add the row to the instance table in Running the HISPEC Daemons with systemd and to the daemon inventory above.
Commit, then on the host
git pullandhispec deploy <instance>, which copies both files into/etc/hispec, enables and starts it.