Node-RED and Scripts
Anything that can send an HTTPS request can drive Aivi. On Home Assistant, use the Live Activities guide and the blueprints; on the iPhone itself, use Shortcuts; on openHAB, see openHAB. This page covers the rest: Node-RED, a Homematic CCU with RedMatic, and plain scripts.
Every update is one PATCH request with your API token, sent to the slug of a
widget or activity you created in the app. See the API
reference for the request body of each.
From a script or cron job
Section titled “From a script or cron job”This keeps a Gauge widget with the slug
nas-disk in sync with a disk’s usage on a Linux machine. Create the widget in
the app’s Widgets tab first, then run the script on a schedule:
#!/bin/shUSED=$(df --output=pcent /srv | tail -1 | tr -dc '0-9')
curl -sS --fail-with-body \ -X PATCH https://api.getaivi.app/widget/nas-disk \ -H 'Authorization: Token [token]' \ -H 'Content-Type: application/json' \ --data-binary @- <<EOF{ "content": { "template": "gauge", "value": $USED, "min_value": 0, "max_value": 100, "unit": "%", "label": "NAS disk", "icon": "externaldrive" }}EOFA crontab line such as */15 * * * * /usr/local/bin/aivi-disk.sh updates it
every 15 minutes. The same request works from Python, a CI job, or any other
language; only the URL, the two headers, and the JSON matter.
From Node-RED
Section titled “From Node-RED”The built-in http request node sends the update, and a function node builds it from whatever comes in: an MQTT message, a device node, or a timer.
-
In the Aivi app’s Widgets tab, create a widget with the Gauge template and the slug
living-room. -
Give Node-RED your API token as an environment variable named
AIVI_TOKEN: double-click the flow’s tab and add it under Environment Variables, so the token stays out of the flow itself. -
Copy the flow below, then choose Import from the Node-RED menu and paste it.
-
Replace the Every 5 minutes inject node with your real source, wired into Build Aivi widget update. The function expects the reading in
msg.payload. -
Deploy. The Aivi response debug node shows
200for every successful update.
The function node sets the URL, the headers, and the body:
// msg.payload is the reading to show, e.g. a temperature.const slug = "living-room";
msg.url = `https://api.getaivi.app/widget/${slug}`;msg.headers = { "Authorization": `Token ${env.get("AIVI_TOKEN")}`, "Content-Type": "application/json",};msg.payload = { content: { template: "gauge", value: Number(msg.payload), min_value: 10, max_value: 35, unit: "°C", label: "Living room", icon: "thermometer.medium", },};return msg;The flow to import
[ { "id": "aivi_inject", "type": "inject", "name": "Every 5 minutes", "repeat": "300", "once": true, "onceDelay": "1", "topic": "", "payload": "21.5", "payloadType": "num", "props": [{ "p": "payload" }], "x": 150, "y": 80, "wires": [["aivi_function"]] }, { "id": "aivi_function", "type": "function", "name": "Build Aivi widget update", "func": "// msg.payload is the reading to show, e.g. a temperature.\nconst slug = \"living-room\";\n\nmsg.url = `https://api.getaivi.app/widget/${slug}`;\nmsg.headers = {\n \"Authorization\": `Token ${env.get(\"AIVI_TOKEN\")}`,\n \"Content-Type\": \"application/json\",\n};\nmsg.payload = {\n content: {\n template: \"gauge\",\n value: Number(msg.payload),\n min_value: 10,\n max_value: 35,\n unit: \"°C\",\n label: \"Living room\",\n icon: \"thermometer.medium\",\n },\n};\nreturn msg;", "outputs": 1, "x": 390, "y": 80, "wires": [["aivi_request"]] }, { "id": "aivi_request", "type": "http request", "name": "PATCH to Aivi", "method": "PATCH", "ret": "obj", "paytoqs": "ignore", "url": "", "persist": false, "senderr": false, "headers": [], "x": 620, "y": 80, "wires": [["aivi_debug"]] }, { "id": "aivi_debug", "type": "debug", "name": "Aivi response", "active": true, "complete": "statusCode", "targetType": "msg", "x": 820, "y": 80, "wires": [] }]To drive a Live Activity instead, send to /activity/{slug} with a state and
a Live Activity template in the body; see Update an
activity.
On a Homematic CCU with RedMatic
Section titled “On a Homematic CCU with RedMatic”RedMatic runs Node-RED on a CCU3 or
OpenCCU, so the same flow works there. Use a ccu value node for your
device’s datapoint as the source, for example a thermostat’s
ACTUAL_TEMPERATURE, and wire it into Build Aivi widget update.
Responses
Section titled “Responses”A 200 means the update was accepted and is on its way to every device that
shows the widget or activity. Errors return a JSON detail: 401 for a wrong
token, 402 without an active subscription, 404 for an unknown slug, and
422 when the body does not match the template. See
Errors for the full list.
Aivi: Live Activities and widgets over an API · Pricing · App Store