#!/bin/sh # --------------------------------------------------------------------------- # The fixture's JSON publisher. Runs inside a second eclipse-mosquitto container (the # image already ships mosquitto_pub, so no bespoke image / paho dependency is needed) # and feeds the broker over the PLAIN listener from inside the compose network — # authenticated like every other client, since the broker is allow_anonymous false. # # Topics (all under $TOPIC_PREFIX, default otopcua/fixture): # # retained/seed published EXACTLY ONCE, retain=true, never republished. # This is what makes the retained-seed test meaningful: a # subscriber that connects minutes later and still receives a # value on this topic can only have received the BROKER'S # RETAINED COPY. On a topic that is also republished every few # seconds, a retained seed is indistinguishable from a live # publish that happened to arrive quickly. # line1/temperature JSON object, retain=true, republished every $PUBLISH_INTERVAL # line1/counter JSON object, retain=true, monotonically increasing # line1/state bare scalar text (no JSON), retain=true # noise/chatter JSON, retain=FALSE — deliberately never authored as a tag. # A broker carrying traffic the deployment did not author is # the normal case, and the driver must stay silent about it. # --------------------------------------------------------------------------- set -eu HOST=${BROKER_HOST:-mosquitto} PORT=${BROKER_PORT:-1883} PREFIX=${TOPIC_PREFIX:-otopcua/fixture} INTERVAL=${PUBLISH_INTERVAL:-2} : "${MQTT_FIXTURE_USERNAME:?publisher needs MQTT_FIXTURE_USERNAME}" : "${MQTT_FIXTURE_PASSWORD:?publisher needs MQTT_FIXTURE_PASSWORD}" pub_retained() { mosquitto_pub -h "$HOST" -p "$PORT" \ -u "$MQTT_FIXTURE_USERNAME" -P "$MQTT_FIXTURE_PASSWORD" \ -q 1 -r -t "$1" -m "$2" } pub_volatile() { mosquitto_pub -h "$HOST" -p "$PORT" \ -u "$MQTT_FIXTURE_USERNAME" -P "$MQTT_FIXTURE_PASSWORD" \ -q 0 -t "$1" -m "$2" } echo "publisher: broker=$HOST:$PORT prefix=$PREFIX interval=${INTERVAL}s" # The one-shot retained seed. Published before the loop starts and never again. pub_retained "$PREFIX/retained/seed" \ '{"value":42.5,"unit":"C","note":"published once at fixture start; never republished"}' echo "publisher: retained seed published on $PREFIX/retained/seed" n=0 while true; do n=$((n + 1)) temperature=$(awk "BEGIN { printf \"%.2f\", 20 + ($n % 50) / 10 }") pub_retained "$PREFIX/line1/temperature" \ "{\"value\":$temperature,\"unit\":\"C\",\"seq\":$n}" pub_retained "$PREFIX/line1/counter" "{\"value\":$n}" pub_retained "$PREFIX/line1/state" "RUNNING" # Unauthored chatter — the driver must never materialise a tag for this. pub_volatile "$PREFIX/noise/chatter" "{\"value\":$n,\"source\":\"chatter\"}" sleep "$INTERVAL" done