JSON to Matter bridge¶
Overview¶
PurpleAirMatterDataLogger publishes current PurpleAir readings as
Matter-shaped JSON. Google Home and Home Assistant cannot commission that HTTP
API directly because it does not implement Matter discovery, commissioning,
secure sessions, fabrics, or subscriptions.
A companion plugin in the purpleair-matterbridge repository provides the missing protocol boundary. The plugin reads the logger’s JSON API and registers each PurpleAir sensor as a bridged Matter Air Quality Sensor. Matterbridge then provides the commissionable Matter bridge, QR code, network discovery, security, and fabric storage.
The companion plugin is maintained in the purpleair-matterbridge repository. Follow that repository’s README for current installation and development instructions.
Architecture¶
PurpleAir sensors
|
v
PurpleAirMatterDataLogger
http://127.0.0.1:9855/matter/sensors
|
v
matterbridge-purpleair plugin
JSON parsing, endpoint identity, cluster updates
|
v
Matterbridge / matter.js
mDNS, commissioning, secure sessions, fabrics
|
+-------------------+
| |
v v
Google Home Home Assistant
Matterbridge is the Matter device in this design. The Python logger remains the
sensor-data source and does not become a Matter transport implementation.
python-matter-server is a Matter controller and is not a replacement for the
bridge shown above.
Plugin responsibilities¶
The companion plugin:
Accepts the logger base URL and polling interval as configuration.
Reads
GET /matter/sensorswhen it starts and on every polling cycle.Validates the top-level
sensorslist and eachsensor_indexanddeviceobject before applying updates.Assigns one stable bridged endpoint to each unique
sensor_index.Persists the
sensor_indexto endpoint mapping across restarts.Adds newly discovered sensors without changing existing endpoint identities.
Retains the last-known-good Matter attributes when the HTTP request or one sensor payload fails.
Updates Matter attributes only after a complete sensor payload has been validated.
Reports connection and payload errors without terminating the bridge.
Removes or disables a sensor only through explicit configuration, not because it is absent from one response.
The device.endpoint value in the JSON payload is descriptive and is 1
for each converted sensor. A bridge must not reuse that value for every child.
Matterbridge must allocate a distinct and stable endpoint for each PurpleAir
sensor_index.
Matter data mapping¶
The current HTTP payload has this shape:
{
"sensors": [
{
"sensor_index": 123456,
"device": {
"device_type": {"id": 45, "label": "Air Quality Sensor"},
"sensor_name": "Example sensor",
"clusters": {
"air_quality_measurement": {"attributes": {}},
"temperature_measurement": {"attributes": {}},
"humidity_measurement": {"attributes": {}},
"pressure_measurement": {"attributes": {}}
}
}
}
],
"count": 1
}
The plugin must map the JSON values into Matterbridge cluster APIs. It must not publish the entire JSON object as if every JSON property were a standard Matter attribute.
JSON source |
Matter representation |
Notes |
|---|---|---|
|
Air Quality Sensor |
The legacy converter currently emits decimal |
|
Air Quality cluster |
Use the Matter enumeration value supplied by the converter. |
PM1, PM2.5, and PM10 density values |
Corresponding concentration measurement clusters |
Use distinct standard clusters rather than custom Air Quality attributes. |
VOC density |
Total VOC concentration measurement cluster |
Omit the cluster when the source value is unavailable. |
|
Temperature Measurement cluster |
The JSON value is in hundredths of a degree Celsius. |
|
Relative Humidity Measurement cluster |
The JSON value is in hundredths of a percent. |
|
Pressure Measurement cluster |
Pass the converted integer using the units expected by matter.js. |
|
Bridged Basic Information |
Use as the user-visible product or node label. |
|
Bridged Basic Information |
Publish only where the Matterbridge API supports the fields. |
The plugin should use matter.js or Matterbridge types for range checking and attribute encoding. It should not duplicate Matter unit conversion rules with untyped JSON manipulation.
Companion project¶
The companion plugin is maintained at github.com/carlkidcrypto/purpleair-matterbridge. Clone that repository and follow its README for the current installation and development workflow. The implementation uses TypeScript, Vitest, oxlint, and oxfmt. Its main configuration fields are:
feedUrlFull PurpleAir Matter feed URL. Default:
http://127.0.0.1:9855/matter/sensors.pollIntervalSecondsJSON polling interval. It should not be shorter than the Python logger’s polling interval. Default:
60.requestTimeoutSecondsHTTP request timeout. Default:
10.whiteListandblackListMatterbridge device filters populated from discovered sensor names and stable serial numbers.
Running the data source¶
When Matterbridge runs on the same host, keep the safer loopback binding:
python3 -m purpleair_data_logger.PurpleAirMatterDataLogger \
-paa_local_sensor_request_json_file \
./sample_json_config_files/sample_local_sensor_request_json_file.json \
--matter-only
The plugin can then use http://127.0.0.1:9855/matter/sensors. If Matterbridge runs on a
separate trusted host, bind the logger to a LAN interface:
python3 -m purpleair_data_logger.PurpleAirMatterDataLogger \
-paa_local_sensor_request_json_file \
./sample_json_config_files/sample_local_sensor_request_json_file.json \
--http-host 0.0.0.0 \
--matter-only
The HTTP API has no authentication or TLS. Restrict port 9855 to the bridge
host with a firewall and do not expose it to the internet.
Installing and pairing¶
After cloning the companion repository, its local development flow is:
git clone https://github.com/carlkidcrypto/purpleair-matterbridge.git
cd purpleair-matterbridge
npm install --global --prefix "$HOME/.local" matterbridge@3.10.3
npm install
npm_config_prefix="$HOME/.local" npm link matterbridge --no-save
npm run build
npm test
"$HOME/.local/bin/matterbridge" --add .
"$HOME/.local/bin/matterbridge" --bridge
Matterbridge provides its frontend on port 8283 by default and displays the
bridge QR code in the frontend and console.
Matterbridge is linked rather than declared as a package dependency. This is a Matterbridge requirement that prevents a plugin from loading a second, incompatible matter.js instance.
To pair with Home Assistant:
Install and configure Home Assistant’s Matter integration.
In the Home Assistant companion app, choose Settings > Matter > Add device.
Scan the Matterbridge QR code or enter its numeric commissioning code.
Verify that every allowed PurpleAir sensor appears as a sensor device.
To pair with Google Home:
Ensure a compatible Google Matter hub is present in the home.
In Google Home, choose Add > Device > Matter-enabled device.
Scan the Matterbridge QR code.
Verify that each bridged PurpleAir Air Quality Sensor appears.
Matter supports multiple fabrics. After pairing the bridge with one ecosystem, open a new commissioning window from that ecosystem or from Matterbridge and use the generated sharing code to add the bridge to the second ecosystem.
Network requirements¶
Matter commissioning and operation require local IPv6 and working mDNS multicast between Matterbridge and the controllers. The internet connection does not need IPv6, but the LAN does. Avoid firewall, VLAN, container, or virtual machine settings that block IPv6 or multicast traffic.
This repository commonly runs under WSL. The Python HTTP service can run there, but Matterbridge must run in an environment whose mDNS and IPv6 traffic reaches the physical LAN. Native Linux, a correctly configured host-network container, or a supported native Windows Matterbridge installation is generally easier to diagnose than default WSL NAT networking.
Compatibility and certification¶
Google Home lists the Matter Air Quality Sensor device type and Matter bridges as supported. Controller user interfaces may still expose only a subset of the available clusters or attributes. Home Assistant generally exposes a broader set of sensor entities, but behavior depends on its current Matter Server and Matter specification support.
Development and personal testing can use Matterbridge’s development commissioning credentials. A distributed commercial product requires the applicable Connectivity Standards Alliance certification, device attestation, and ecosystem integration testing. A working development QR code is not proof of Matter certification.
Acceptance criteria¶
The first usable plugin release should demonstrate all of the following:
Matterbridge starts while the Python logger is serving two or more sensors.
One stable Matter endpoint is created per
sensor_index.Temperature, humidity, pressure, air quality, and available concentration measurements update after subsequent JSON polls.
A transient logger outage leaves the last-known-good values available.
Restarting Matterbridge does not change endpoint identities.
The bridge commissions successfully into Home Assistant.
The same bridge can be added to Google Home through a second fabric.
Neither controller requires direct access to port
9855.