diff --git a/kubernetes/apps/home-assistant/kustomization.yaml b/kubernetes/apps/home-assistant/kustomization.yaml index 590aae42..59168249 100644 --- a/kubernetes/apps/home-assistant/kustomization.yaml +++ b/kubernetes/apps/home-assistant/kustomization.yaml @@ -24,6 +24,9 @@ resources: - mosquitto-iot-service.yaml - mosquitto-deployment.yaml - mosquitto-evcc-credentials-externalsecret.yaml + # One-off read of the Room DIDs 1884-1943 via open3e/cmnd (REN-826). + # Remove after the result is on the card. + - open3e-room-setpoint-read-job.yaml - shelly-manager-pvc.yaml - shelly-manager-network-attachment.yaml - shelly-manager-firmware-rbac.yaml diff --git a/kubernetes/apps/home-assistant/open3e-room-setpoint-read-job.yaml b/kubernetes/apps/home-assistant/open3e-room-setpoint-read-job.yaml new file mode 100644 index 00000000..223471d7 --- /dev/null +++ b/kubernetes/apps/home-assistant/open3e-room-setpoint-read-job.yaml @@ -0,0 +1,100 @@ +# One-off read of the Room DIDs 1884-1943 (Property / Setpoints / +# CurrentValues, rooms 1-20) through edge-1's running open3e (REN-826). +# The Job sends three READ commands on open3e/cmnd and prints the replies on +# stdout, which Loki keeps. No write mode is used; open3e, Mosquitto and HA +# config are not changed. +# +# Why through open3e/cmnd: only one UDS client may run on the CAN bus, so the +# read must go through the running listener. Modes read-json / read-raw go +# through readByDid, which catches a negative response or a timeout and +# publishes an ERR topic. read-pure is NOT used: it crashes the listener on a +# timeout (wiki open3e-cli-operational-gotchas). +# +# Commands, paced 20 s apart: +# 1. read-json 0x6c3 [256, 1884..1943] decoded JSON or NRC; 256 = positive control +# 2. read-raw 0x6c3 [1884..1943] raw hex +# 3. read-json 0x6e0 [1885] SMARTROOMCONTROL; one read, 3 s timeout +# +# Credential: the `open3e` broker user, the only one besides HA that may +# publish to open3e/cmnd (readwrite open3e/#, mosquitto-deployment.yaml). +# +# Line format: +# +# backoffLimit 0 and no ttlSecondsAfterFinished: a retry or a TTL delete +# would send the commands again. Remove this file in a follow-up PR once the +# result is on REN-826. +apiVersion: batch/v1 +kind: Job +metadata: + name: open3e-room-setpoint-read + namespace: home-assistant + labels: + app.kubernetes.io/name: open3e-room-setpoint-read +spec: + backoffLimit: 0 + activeDeadlineSeconds: 300 + template: + metadata: + labels: + app.kubernetes.io/name: open3e-room-setpoint-read + spec: + restartPolicy: Never + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + runAsUser: 1883 + runAsGroup: 1883 + seccompProfile: + type: RuntimeDefault + containers: + - name: read + # Same image as the broker, pinned by digest so image automation + # never edits this (immutable) Job template. + image: docker.io/library/eclipse-mosquitto:2.0.22@sha256:212f89e1eaeb2c322d6441b64396e3346026674db8fa9c27beac293405c32b3c + command: + - sh + - -c + - | + set -eu + DIDS=$(awk 'BEGIN { for (i = 1884; i <= 1943; i++) printf "%s%d", (i > 1884 ? "," : ""), i }') + mosquitto_sub -h mosquitto -p 1883 \ + -u open3e -P "$MQTT_PASSWORD" \ + -i open3e-room-read-sub-ren826 -q 0 \ + -t 'open3e/#' -W 80 -F '%I %t %p' | + awk '$2 ~ /^open3e\/[^\/]*_(0256|188[4-9]|189[0-9]|19[0-3][0-9]|194[0-3])_/ { print; fflush() }' & + sleep 5 + pub() { + echo "$(date -u +%FT%TZ) CMD $1" + mosquitto_pub -h mosquitto -p 1883 \ + -u open3e -P "$MQTT_PASSWORD" \ + -i open3e-room-read-pub-ren826 -q 1 \ + -t open3e/cmnd -m "$1" + } + pub "{\"mode\":\"read-json\",\"addr\":\"0x6c3\",\"data\":[256,$DIDS]}" + sleep 20 + pub "{\"mode\":\"read-raw\",\"addr\":\"0x6c3\",\"data\":[$DIDS]}" + sleep 20 + pub '{"mode":"read-json","addr":"0x6e0","data":[1885]}' + # The subscriber's -W 80 window ends the Job. + wait + echo "$(date -u +%FT%TZ) END" + env: + - name: TZ + value: UTC + - name: MQTT_PASSWORD + valueFrom: + secretKeyRef: + name: mosquitto-open3e-credentials + key: password + resources: + requests: + cpu: 5m + memory: 16Mi + limits: + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: ["ALL"]