Aisha has it. Hermetry stores a body that isn’t JSON as a single raw key, which is why you see your template text. Build the JSON with printf, and send all sites in one message, cheaper and tidier:
#!/bin/bash
json="{"
while read -r ip name; do
if ping -c 3 -W 2 "$ip" > /dev/null 2>&1; then ok=1; else ok=0; fi
json+=$(printf '"%s.up":%d,' "$name" "$ok")
done < /home/pi/sites.txt
json="${json%,}}"
mosquitto_pub -h "$BROKER" -p 8883 --capath /etc/ssl/certs -u "$TOKEN" -q 1
-t v1/telemetry -m "$json"
Three pings, not one: counts as up if any one comes back.
For the alert, an alarm rule on the profile per site key with a count debounce, so it needs several bad readings in a row before it opens and several good ones to clear:
{ "type": "pump3_unreachable",
"title": "Pump 3 modem not answering",
"severities": [ { "severity": "MAJOR", "condition": { "key": "pump3.up", "op": "==", "value": 0 } } ],
"debounce": { "mode": "count", "raise": 5, "clear": 2 },
"enabled": true }
Five minutes of failed pings before anyone hears about it. Add a Device offline rule for the Pi too, otherwise a dead Pi looks like „everything fine“. Debounce options: Debounce, hysteresis and dampening.

