Skip to main content

Casambi Web Controller

Local Casambi BLE lighting control exposed as an HTTP API. Compatible with matter_webcontrol v0.25.0+ federation, so a Casambi network can be merged into a Matter fabric as a logical bridge.

Architecture

FastAPI middleware over the casambi-bt library. The server discovers a Casambi network over BLE, authenticates with the network password, and exposes each unit through a REST API that matches matter_webcontrol's federation contract — so federation peers call /api/devices, /api/level, /api/mired, /api/set directly without embedded scripts (no RCE surface).

┌──────────────┐    HTTP+API key    ┌──────────────────┐    BLE    ┌──────────┐
│ matter-srv   │ ─────────────────▶ │ casambi-srv      │ ────────▶ │ Casambi  │
│ (Matter      │                    │ (this project)   │           │ network  │
│  fabric)     │ ◀─── /api/devices  │ FastAPI + bleak  │ ◀──notif─ │          │
└──────────────┘                    └──────────────────┘           └──────────┘

Limitations

  • Single Casambi network per server instance (uses devices[0] from discovery).
  • Lighting units only — sensor / occupancy not exposed.
  • BLE depends on host OS permissions (on macOS, grant Bluetooth to the parent process via System Settings → Privacy & Security → Bluetooth).

Install

pip install -e .            # from source
# or
pip install casambi-web-controller   # from PyPI

Run

casambi-srv --port 8000 --api-key <secret>
# or via env:
CASAMBI_NETWORK_PWD=<network-password> CASAMBI_SRV_KEY=<secret> casambi-srv --port 8000

CLI options:

Flag Default Description
--port 8000 Web server port
--host 127.0.0.1 Bind address. Use 0.0.0.0 to expose on LAN (warns if no API key)
--api-key $CASAMBI_SRV_KEY Require X-API-Key header on all requests
--password — Casambi network password (see below)

Password resolution order: --password flag → $CASAMBI_NETWORK_PWD env var → interactive getpass prompt. The env var is preferred over --password because CLI args are visible to other users via ps. Whichever source supplies it, the value is held only on app.state and the env var is pop()'d so it does not leak via /proc/PID/environ.

Federation with matter_webcontrol

Once both servers are running, register this server as a logical bridge on the Matter side:

GET http://<matter-host>:8080/api/bridge?ip=<casambi-host>&port=8000&api_key=<secret>

After this, every Casambi device appears under matter's /api/devices with id cas_* and is controllable through any matter endpoint (/api/level, /api/set, /api/toggle, etc.). Matter routes calls back through this server's REST API.

API endpoints

All endpoints require X-API-Key: <secret> if --api-key was set.

GET /api/devices

Federation device list. Each entry: {id, names, states}.

[
  {
    "id": "cas_d8dccdc7a8bc4f079f4e76d49bf9c7bc",
    "names": ["Sofa and Painting"],
    "states": {"on_off": false, "brightness_raw": 0}
  }
]

states keys (only emitted when the unit type supports the control):

  • on_off (bool)
  • brightness_raw (int 0–254, Matter scale)
  • color_temp_mireds (int 153–500)

GET /api/lights

Light-only view with normalized fields.

[{"id": "cas_…", "names": ["…"], "on_off": true, "brightness": 0.78}]

GET /api/status

Summary counts.

{"lights_on": 1, "lights_off": 7, "sensors_active": 0, "logical_bridges": 0, "total_devices": 8}

GET|POST /api/level

Read or write Matter-scale level (0–254).

Param Type Required Notes
id str yes Canonical device id (cas_*)
level int no If absent, returns current level. If present (0–254), sets it

Body for POST: {"id": "cas_…", "level": 200}. Read-back response: {id, level}. Write response: {status, id, level, type}.

GET|POST /api/mired

Color temperature in mireds (153–500). Auto-clamped to per-unit Kelvin range. Returns 400 for units without temperature control.

Body for POST: {"id": "cas_…", "mireds": 250}.

GET|POST /api/set

Multi-attribute write. At least one of brightness / temperature is required (else 400).

Param Type Range
id str required
brightness float 0.0–1.0
temperature int Kelvin

Body for POST: {"id": "cas_…", "brightness": 0.5, "temperature": 4000}.

GET /api/toggle?id=

Flip on/off. When turning on, restores the last non-zero level (cached in-memory) instead of jumping to 100%.

GET /api/refresh

If BLE is connected, no-op (state is push-driven via Casambi notifications). If disconnected, attempts a reconnect using the cached network password.

GET /api/metadata

Declarative bridge metadata for federation discovery. No embedded Python scripts — peers consume the device list via /api/devices and call control endpoints directly.

{
  "bridge": {
    "id": "casambi_bridge_http",
    "type": "lighting_controller",
    "network_host": "192.168.1.220",
    "network_port": 8000,
    "api_version": "2"
  },
  "devices": [
    {
      "id": "cas_d8dccdc7a8bc4f079f4e76d49bf9c7bc",
      "name": "Sofa and Painting",
      "names": ["Sofa and Painting"],
      "hardware_type": "dimmable_light",
      "capabilities": ["on_off", "brightness"],
      "states": {"on_off": false, "brightness_raw": 0}
    }
  ]
}

Security notes

  • X-API-Key comparison is constant-time (hmac.compare_digest) to resist timing attacks.
  • The Casambi network password is held on app.state and not written into os.environ (no leak via /proc/PID/environ on Linux).
  • Default bind is 127.0.0.1. Binding to 0.0.0.0 without --api-key logs a warning.
  • /api/metadata no longer emits executable Python; the previous events.{name}.script shape was removed in v0.9.0 to match matter_webcontrol v0.25.0 (closes a federation RCE risk).

Compatibility matrix

casambi_webcontrol matter_webcontrol
0.9.x 0.25.x + (federation v2: REST + auth)
≤ 0.6.x ≤ 0.22.x (legacy embedded scripts)

Metadata

Release files for casambi-web-controller 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for casambi-web-controller 0.9.0
File Size Uploaded Provenance Actions
casambi_web_controller-0.9.0.tar.gz 9.1 kB With provenance Details for casambi_web_controller-0.9.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for casambi-web-controller 0.9.0
File Interpreter ABI Platform Actions
casambi_web_controller-0.9.0-py3-none-any.whl Python 3 none any Details for casambi_web_controller-0.9.0-py3-none-any.whl

Total release size: 18.9 kB

Release files / casambi_web_controller-0.9.0.tar.gz

Download URL casambi_web_controller-0.9.0.tar.gz
Size 9.1 kB
Tags Source
SHA-256 checksum
How to use checksums
b2dbb7cfe0bdd4cfe7c1cff89d355f5778b04209fe205271eb202abaca3c5150
BLAKE2b-256 checksum
How to use checksums
e2812b66f62b895651191440759888270008b797d13973221f2e0e3a64d52e1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 4, 2026.

Transparency log

Release files / casambi_web_controller-0.9.0-py3-none-any.whl

Download URL casambi_web_controller-0.9.0-py3-none-any.whl
Size 9.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6ac96e948a8bd21f953b9d27bd713766fbb9051008a8a7e7fee973d9a4f42b34
BLAKE2b-256 checksum
How to use checksums
2f4df55ef1277d0b4f27d8c83292db1b687e62388c4f0285bd57fe138e29d63c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 4, 2026.

Transparency log

Security for casambi-web-controller 0.9.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for casambi_web_controller-0.9.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page