Project Siphon: v0.4 Architecture, The HA Add-on, and The Web UI

Overview

Siphon's project page.

Building telemetry pipelines is inherently messy. Every new sensor, webhook, or external API wants to dictate how you receive data. For the last few months, Siphon existed to solve that problem by acting as a rigid, decoupled gateway between the chaotic outside world and your pristine internal data bus, but it evolved.

Here is a breakdown of the architectural shifts and how you can deploy.

The V2 Engine: Decoupled by Design

The biggest flaw in the v1 architecture was coupling. A pipeline cared too much about how a collector acquired data. The v2 engine fixes this by introducing an isolated, asynchronous Event Bus.

"Dumb" Collectors Ingestion engines (mqtt, file, webhook, shell) are now purposefully ignorant of the data they consume. Their only job is to acquire raw bytes, attach a logical alias to them, and throw them onto the bus.

Stateful Cron Merging

Because the Event Bus caches parsed state in memory, we can now do things that previously required complex Python scripts. You can configure a cron pipeline to wake up on a schedule, grab the latest cached states from completely different collectors, and merge them into a single, sanitized JSON payload before firing it off to a sink.

The Pipeline Sandbox

Here is what merging local system thermals via file and room sensors via mqtt into a unified payload looks like in the new schema:

 1version: 2
 2
 3collectors:
 4  mqtt_broker:
 5    type: mqtt
 6    params: { url: "tcp://192.168.1.1:1883" }
 7    topics:
 8      sensor_raw: "sensor/room" # Alias -> MQTT Topic
 9
10  sys_metrics:
11    type: file
12    params: { interval: 10 }
13    topics:
14      cpu_raw: "/sys/class/thermal/thermal_zone0/temp"
15
16pipelines:
17  # Ingest and Parse MQTT Data
18  - name: mqtt_state
19    topics: ["sensor_raw"]
20    parser:
21      type: jsonpath
22      vars: { temp: "$.T" }
23
24  # Ingest and Parse File Data
25  - name: file_state
26    topics: ["cpu_raw"]
27    parser:
28      type: regex
29      vars: { temp_str: "[0-9]+" }
30
31  # Merge them using the internal Expr engine
32  - name: unified_dispatcher
33    type: cron
34    stateful: true
35    schedule: "*/30 * * * * *" # every 30s
36    topics: ["mqtt_state", "file_state"]
37    sinks:
38      - name: my_backend
39        format: expr
40        spec: |
41          {
42            "merged_data": {
43              "room_temperature": temp ?? 0,
44              "server_cpu": temp_str ?? 0
45              }
46          }

Siphon in Home Assistant

While you can still deploy Siphon in an isolated Docker container on your DMZ (the purist approach), I wanted an escape hatch. Siphon is now a first-class citizen in Home Assistant, installable directly via a custom Add-on repository.

Zero-Setup Auth & Environment Isolation

If Siphon detects the Mosquitto broker Add-on, it automatically injects the credentials into the environment. You use %%MQTT_HOST%%, %%MQTT_PORT%%, %%MQTT_USER%%, and %%MQTT_PASS%% in your config without ever hardcoding a password. Furthermore, you can define external environment variables in your config directly in the Add-on UI, keeping your config.yaml clean and safe to commit to version control. The defined variables could be injected to config using %%ENV_VARIABLE%% syntax.

The Native hass Collector

Because running as an Add-on grants Siphon a $SUPERVISOR_TOKEN, I wrote a new native hass collector. It leverages this token to poll Home Assistant entities directly via the internal REST API. No Long-Lived Access Tokens, no external network calls. Just clean, local, secure polling.

 1collectors:
 2  local_ha:
 3    type: hass
 4    params:
 5      interval: 60
 6    topics:
 7      outdoor_temp: "sensor.backyard_temperature"
 8
 9pipelines:
10  # Process the data from Home Assistant
11  - name: process_ha_temp
12    topics: ["outdoor_temp"] # Listen to the alias!
13    bus_mode: volatile
14    parser:
15      type: jsonpath
16      vars:
17        # The HA API always returns a standard JSON object.
18        # You can extract the main state or nested attributes.
19        temp: "$.state"
20        unit: "$.attributes.unit_of_measurement"
21
22    # Transform...
23    transform:
24      tempStr: "string(float(temp))+' '+unit"

Some more examples are described on github.

The Web Interface

SSH-ing into a container to edit a YAML file gets old fast. Siphon now features an embedded web UI powered by Ace.js, accessible directly through Home Assistant Ingress.

It provides a fast, syntax-highlighted editor directly in your HA sidebar.

What's Next

The v0.4 release also includes a complete rewrite of the Windy PWS sink to support their new 2026 API requirements, alongside fixes for the gotify and ntfy integrations.

Siphon is officially ready to handle your edge telemetry. Check out the GitHub repository to grab the Add-on URL or pull the latest Docker image. Let Home Assistant run the automations; let Siphon guard the gate.

mekops-labs/siphon mekops-labs/siphon-ha-addon