From da466efdb3cd5ffd665166ffc454db2319e28aac Mon Sep 17 00:00:00 2001 From: "James Bateman (hp-laptop)" Date: Tue, 11 Aug 2026 16:41:53 +0100 Subject: [PATCH] Add Home Assistant dashboard and config for the rack Minimal HA content to reproduce the Butterfly Rack GUI: a YAML-mode dashboard (power graphs in mW, temperature graph, dual dBm/mW output readout, staged seed/booster controls, emergency-off), MQTT template sensors deriving mW from the dBm telemetry, and an emergency-shutdown script. Snippets merge into configuration.yaml / scripts.yaml; the dashboard file is copied whole. See homeassistant/README.md. Co-Authored-By: Claude Opus 4.8 (1M context) --- homeassistant/README.md | 37 ++++++ homeassistant/configuration.snippet.yaml | 55 +++++++++ homeassistant/scripts.snippet.yaml | 19 ++++ homeassistant/ui-lovelace-butterfly.yaml | 136 +++++++++++++++++++++++ 4 files changed, 247 insertions(+) create mode 100644 homeassistant/README.md create mode 100644 homeassistant/configuration.snippet.yaml create mode 100644 homeassistant/scripts.snippet.yaml create mode 100644 homeassistant/ui-lovelace-butterfly.yaml diff --git a/homeassistant/README.md b/homeassistant/README.md new file mode 100644 index 0000000..4e0233b --- /dev/null +++ b/homeassistant/README.md @@ -0,0 +1,37 @@ +# Home Assistant integration + +Config for presenting the Butterfly EDFA Rack in Home Assistant. The rack's sensors, switches and numbers are auto-discovered over MQTT (the firmware publishes `homeassistant/.../config` topics), so these files only add what discovery cannot: derived mW power sensors and a dedicated dashboard. + +Target: the HA instance on the lab broker host (`192.168.0.102`), running in Docker with its config bind-mounted at `~/HA/homeassistant/` (that is HA's `/config`). + +## Files + +| File | Goes to | Purpose | +|------|---------|---------| +| `configuration.snippet.yaml` | merge into `/config/configuration.yaml` | MQTT template sensors (dBm→mW for the EDFA input, pre-amp and output PDs) + the `butterfly-rack` YAML dashboard registration | +| `scripts.snippet.yaml` | merge into `/config/scripts.yaml` | `butterfly_edfa_shutdown` emergency-off script | +| `ui-lovelace-butterfly.yaml` | copy to `/config/ui-lovelace-butterfly.yaml` | the dashboard itself (graphs of power in mW + temperatures, dual dBm/mW output readout, staged seed/booster controls, emergency-off) | + +The `*.snippet.yaml` files hold top-level keys (`mqtt:`, `lovelace:`, and the script) to merge into the matching HA files — they are not standalone configs. `ui-lovelace-butterfly.yaml` is copied whole. + +## Deploy + +From this directory, with the HA container named `homeassistant`: + +```bash +host=lab@192.168.0.102 +scp ui-lovelace-butterfly.yaml $host:/tmp/ +ssh $host 'docker cp /tmp/ui-lovelace-butterfly.yaml homeassistant:/config/ui-lovelace-butterfly.yaml' +# then hand-merge the two snippets into /config/configuration.yaml and +# /config/scripts.yaml, and validate + restart: +ssh $host 'docker exec homeassistant python -m homeassistant --script check_config -c /config' +ssh $host 'docker restart homeassistant' +``` + +The dashboard reloads on browser refresh; changes to `configuration.yaml`/`scripts.yaml` need the restart. The dashboard appears in the sidebar as **Butterfly Rack** (`/butterfly-rack`). + +## Notes + +- The `*_mw` sensors are grouped onto the same `butterfly_edfa_rack` device via the shared `identifiers`. +- mW figures are derived from the internal-PD dBm telemetry, which reads ~0.5 dB optimistic — indicative, not calibrated. +- The seed temperature setpoint is the CTL200 thermistor resistance (`rtset`, ohms); the °C readout is a firmware-side NTC β-model. See the repo root README. diff --git a/homeassistant/configuration.snippet.yaml b/homeassistant/configuration.snippet.yaml new file mode 100644 index 0000000..3d841c8 --- /dev/null +++ b/homeassistant/configuration.snippet.yaml @@ -0,0 +1,55 @@ +# Butterfly EDFA Rack — snippet to merge into Home Assistant's configuration.yaml. +# These are top-level keys; add them alongside your existing config (the rack's +# sensors/switches/numbers come in automatically over MQTT discovery, so only +# the derived mW power sensors and the dashboard registration live here). +# +# The internal PDs read ~0.5 dB optimistic, so the mW figures are indicative. + +mqtt: + sensor: + - name: "Output Power mW" + unique_id: butterfly_edfa_rack_out_mw + state_topic: "lab/laser/butterfly_edfa_rack/amp/output1_power_dbm" + value_template: "{{ (10 ** (value | float / 10)) | round(1) }}" + unit_of_measurement: "mW" + device_class: power + state_class: measurement + availability_topic: "lab/laser/butterfly_edfa_rack/availability" + payload_available: "online" + payload_not_available: "offline" + device: { identifiers: ["butterfly_edfa_rack"] } + # EDFA input PD = seed AFTER the external attenuators (not seed output power). + - name: "Amp Input Power mW" + unique_id: butterfly_edfa_rack_ampin_mw + state_topic: "lab/laser/butterfly_edfa_rack/amp/input_power_dbm" + value_template: "{{ (10 ** (value | float / 10)) | round(3) }}" + unit_of_measurement: "mW" + device_class: power + state_class: measurement + availability_topic: "lab/laser/butterfly_edfa_rack/availability" + payload_available: "online" + payload_not_available: "offline" + device: { identifiers: ["butterfly_edfa_rack"] } + - name: "Pre-amp Power mW" + unique_id: butterfly_edfa_rack_preamp_mw + state_topic: "lab/laser/butterfly_edfa_rack/amp/preamp_power_dbm" + value_template: "{{ (10 ** (value | float / 10)) | round(1) }}" + unit_of_measurement: "mW" + device_class: power + state_class: measurement + availability_topic: "lab/laser/butterfly_edfa_rack/availability" + payload_available: "online" + payload_not_available: "offline" + device: { identifiers: ["butterfly_edfa_rack"] } + +# YAML-mode dashboard registration. Points at ui-lovelace-butterfly.yaml, which +# must sit next to configuration.yaml in the HA config directory. +lovelace: + mode: storage + dashboards: + butterfly-rack: + mode: yaml + title: Butterfly Rack + icon: mdi:laser-pointer + show_in_sidebar: true + filename: ui-lovelace-butterfly.yaml diff --git a/homeassistant/scripts.snippet.yaml b/homeassistant/scripts.snippet.yaml new file mode 100644 index 0000000..0ba79a8 --- /dev/null +++ b/homeassistant/scripts.snippet.yaml @@ -0,0 +1,19 @@ +# Butterfly EDFA Rack — snippet to merge into Home Assistant's scripts.yaml. +# Emergency shutdown: ramp pump-1 to 0, disable the booster, then the seed. + +butterfly_edfa_shutdown: + alias: Butterfly EDFA emergency shutdown + icon: mdi:alarm-light + mode: single + sequence: + - service: number.set_value + target: + entity_id: number.butterfly_edfa_rack_amp_pump_current + data: + value: 0 + - service: switch.turn_off + target: + entity_id: switch.butterfly_edfa_rack_amp_pump + - service: switch.turn_off + target: + entity_id: switch.butterfly_edfa_rack_seed_laser diff --git a/homeassistant/ui-lovelace-butterfly.yaml b/homeassistant/ui-lovelace-butterfly.yaml new file mode 100644 index 0000000..38932c4 --- /dev/null +++ b/homeassistant/ui-lovelace-butterfly.yaml @@ -0,0 +1,136 @@ +# Butterfly EDFA Rack (MOPA) — YAML-mode dashboard. +# Registered in configuration.yaml (lovelace: dashboards: butterfly-rack). +# Entities auto-discovered over MQTT; the *_mw power sensors are MQTT template +# sensors defined in configuration.yaml (dBm -> mW). +title: Butterfly Rack +views: + - title: MOPA + path: mopa + icon: mdi:laser-pointer + cards: + - type: vertical-stack + title: Butterfly EDFA Rack (MOPA, 1550 nm, Class 4) + cards: + # ===== Graphs at the top: powers (mW) and temperatures ===== + - type: history-graph + title: EDFA output & pre-amp PD (mW) + hours_to_show: 1 + entities: + - entity: sensor.butterfly_edfa_rack_output_power_mw + name: Output PD + - entity: sensor.butterfly_edfa_rack_pre_amp_power_mw + name: Pre-amp PD + + - type: history-graph + title: EDFA input PD (mW) — seed after attenuators + hours_to_show: 1 + entities: + - entity: sensor.butterfly_edfa_rack_amp_input_power_mw + name: EDFA input + + # Seed-side signal: CTL200 monitor photodiode current. Tracks seed + # output relatively; NOT a calibrated optical power. + - type: history-graph + title: Seed monitor PD (mA — relative, uncalibrated) + hours_to_show: 1 + entities: + - entity: sensor.butterfly_edfa_rack_seed_photodiode_current + name: Seed monitor PD + + - type: history-graph + title: Temperatures (°C) + hours_to_show: 1 + entities: + - entity: sensor.butterfly_edfa_rack_seed_temperature + name: Seed + - entity: sensor.butterfly_edfa_rack_seed_board_temperature + name: Seed board + - entity: sensor.butterfly_edfa_rack_amp_module_temperature + name: Amp module + - entity: sensor.butterfly_edfa_rack_amp_pre_amp_temperature + name: Amp pre-amp + + # ===== Status + headline values ===== + - type: glance + columns: 3 + entities: + - entity: binary_sensor.butterfly_edfa_rack_seed_link + name: Seed link + - entity: binary_sensor.butterfly_edfa_rack_amp_link + name: Amp link + - entity: sensor.butterfly_edfa_rack_amp_warnings + name: Warnings + + - type: glance + title: Power now (internal PDs, indicative) + columns: 3 + entities: + - entity: sensor.butterfly_edfa_rack_amp_input_power_mw + name: EDFA in mW + - entity: sensor.butterfly_edfa_rack_output_power + name: Out dBm + - entity: sensor.butterfly_edfa_rack_output_power_mw + name: Out mW + + # ===== Stage 1: seed (Koheron CTL200) ===== + - type: entities + title: Stage 1 — Seed (turn on FIRST) + state_color: true + entities: + - entity: switch.butterfly_edfa_rack_seed_laser + name: Seed laser + - entity: number.butterfly_edfa_rack_seed_set_current + name: Seed current set (<= 300 mA) + - entity: sensor.butterfly_edfa_rack_seed_current + name: Seed current (actual) + - entity: number.butterfly_edfa_rack_seed_thermistor_setpoint + name: Seed temp setpoint (Ω, rtset) + - entity: sensor.butterfly_edfa_rack_seed_temperature + name: Seed temperature (from thermistor) + - entity: sensor.butterfly_edfa_rack_seed_photodiode_current + name: Seed monitor PD (mA, relative) + + # ===== Stage 2: booster (Agiltron M511, ACC) ===== + - type: entities + title: Stage 2 — Booster (ACC; ramp gently, settles 2-4 s) + state_color: true + entities: + - entity: switch.butterfly_edfa_rack_amp_pump + name: Booster pump enable + - entity: number.butterfly_edfa_rack_amp_pump_current + name: Pump-1 current set (<= 4000 mA ~ 1 W) + - entity: sensor.butterfly_edfa_rack_amp_pump_1_current + name: Pump-1 current (actual) + - entity: sensor.butterfly_edfa_rack_amp_module_temperature + name: Module temp + + # ===== Emergency off ===== + - type: horizontal-stack + cards: + - type: button + name: PUMP OFF + icon: mdi:power-off + icon_height: 40px + tap_action: + action: call-service + service: switch.turn_off + target: + entity_id: switch.butterfly_edfa_rack_amp_pump + - type: button + name: SEED OFF + icon: mdi:power-off + icon_height: 40px + tap_action: + action: call-service + service: switch.turn_off + target: + entity_id: switch.butterfly_edfa_rack_seed_laser + - type: button + name: SHUTDOWN + icon: mdi:alarm-light + icon_height: 40px + tap_action: + action: call-service + service: script.butterfly_edfa_shutdown + confirmation: + text: Ramp pump to 0, disable booster, then seed?