Skip to main content

Home Lighting Programmer

Ecosystem-agnostic smart home automation using the Matter protocol. Replaces physical switches with sensor-driven control of lights (circadian-aware brightness + color temperature schedules) and air conditioners (temperature-driven hysteresis with occupancy gating).

Note: For domestic use only. Not hardened for production/commercial deployment.

How It Works

The system runs a 1Hz loop that:

  1. Reads real-time sensor data (motion/presence) via Server-Sent Events
  2. Interpolates the configured schedule to determine target brightness and color temperature
  3. Sends commands only when the target state changes

Three lighting modes are supported:

  • Decoration - Static color and intensity
  • Utility - Sensor-triggered, low-latency response
  • Ambient - Time-based color temperature and brightness that follows natural daylight

Requirements

Installation

pip install light-programmer

Quick Start

# Step 1: Auto-generate config from your hardware
light-genconfig --ip 192.168.1.220 --port 8080 --out config.json

# Step 2: Edit config.json to customize schedules and sensor logic

# Step 3: Run
light-programmer --server 192.168.1.220:8080 --config config.json

Configuration

Each device entry in the config JSON has:

{
    "id": "dev_kitchen_sink",       // Matter node ID
    "note": "Sink area light",      // Human-readable description
    "schedule": [                   // Time-based control points
        { "time": "06:30", "level": 50,  "kelvin": 4000 },
        { "time": "12:00", "level": 100, "kelvin": 4000 },
        { "time": "21:30", "level": 100, "kelvin": 2700 }
    ],
    "sensor": [                     // Simple sensor trigger
        { "id": "kitchen_motion", "timeout": 5 }
    ]
}
  • level: Brightness 0-100%
  • kelvin: Color temperature 2700-6500K (omit for non-color lights)
  • timeout: Seconds to keep light on after sensor clears
  • Values between schedule points are linearly interpolated

See sample.json for a full working example.

Advanced Sensor Logic

For complex scenarios, use sensor_condition instead of sensor. It supports a tree of boolean operators:

Node Type Description
sensor true if occupied or within timeout
time_window true if current time is between start and end (cross-midnight supported)
AND All operands must be true
OR At least one operand must be true
NOT Inverts its operand

Example: Light on only when at desk AND not in bed

{
    "sensor_condition": {
        "operator": "AND",
        "operands": [
            { "type": "sensor", "id": "desk_presence", "timeout": 15 },
            {
                "operator": "NOT",
                "operands": [
                    { "type": "sensor", "id": "bed_presence", "timeout": 5 }
                ]
            }
        ]
    }
}

Example: Follow schedule during day, sensor-only at night

{
    "sensor_condition": {
        "operator": "OR",
        "operands": [
            { "type": "time_window", "start": "06:00", "end": "22:00" },
            { "type": "sensor", "id": "room_motion", "timeout": 5 }
        ]
    }
}

During 06:00-22:00 the light follows its schedule regardless of sensors. Outside that window, it only turns on when the sensor detects motion.

Air Conditioner Control

AC entries are climate-driven (no time schedule). They use a Matter thermostat (/api/ac) and read ambient state via /api/climate — either from one or more standalone climate sensors, or directly from the AC's own thermostat (local_temperature) when no sensor is configured.

{
    "id": "dev_ac_livingroom",
    "type": "ac",                          // marks this entry as an AC
    "climate_sensor": "dev_temp_livingroom",
    "mode": "cool",                        // cool / heat / dry / fan / auto
    "setpoint": 26.0,                      // °C sent to the thermostat
    "on_above": 29.0,                      // turn on when ambient ≥ 29 °C
    "off_below": 26.5,                     // turn off when ambient ≤ 26.5 °C
    "on_delay_minutes": 5,                 // require continuous occupancy ≥ 5 min before turning on
    "active_window": {"start": "10:00", "end": "23:30"},
    "sensor": [
        {"id": "dev_occ_livingroom", "timeout": 15}
    ]
}

Bring-up rule (off → on): climate trigger AND occupancy continuously satisfied for on_delay_minutes AND time within active_window.

Bring-down rule (on → off): climate trigger no longer met, OR occupancy fails (after each sensor's timeout hold), OR outside active_window.

The climate trigger is the OR of two independent hysteresis loops — temperature (on_above / off_below) and humidity (humidity_above / humidity_below). The AC turns on when either dimension says on, and off only when every configured dimension says off. In the dead band of every dimension, it holds the previous state. Use climate_sensors (list) to aggregate readings across multiple sensors with any-trigger semantics (max temp / max humidity). For mode: "heat", use on_below / off_above instead.

The same sensor / sensor_condition AST used by lights applies — combine multiple occupancy sensors with AND/OR/NOT as needed. If a climate reading is unavailable, that dimension holds its last decision rather than flapping.

MCP Server (AI Agent Configuration)

An MCP server is bundled so AI agents (Claude Desktop, Claude Code, etc.) can discover devices and edit the config for you.

pip install light-programmer[mcp]
light-programmer-mcp                  # stdio transport

Example Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "light-programmer": {
      "command": "light-programmer-mcp",
      "env": { "MATTER_SRV_KEY": "your-api-key" }
    }
  }
}

Tools exposed:

Tool Purpose
list_devices Discover lights / sensors / climate / AC from /api/metadata
read_climate, read_ac_state, read_status Live readings
read_config, write_config, validate_config Whole-file CRUD with schema validation
upsert_entry, remove_entry Per-entry edits keyed by device id
set_light, set_ac Direct device control for quick tests
config_schema (prompt) Schema reference an agent can pull when authoring entries

Validation rejects writes with bad time formats, out-of-range levels/Kelvin, missing thresholds, or hysteresis bands where off_below ≥ on_above (cool) / off_above ≤ on_below (heat).

Project Structure

File Purpose
light_programmer/programmer.py Main automation controller — runs the 1Hz loop for lights and ACs
light_programmer/matter_lib.py Device abstractions: LightDevice, SensorDevice, ClimateSensorDevice, ACDevice
light_programmer/genconfig.py Generates config JSON from hardware discovery
light_programmer/mcp_server.py MCP server exposing discovery + config CRUD tools to AI agents
sample.json Example configuration with 11 devices
pyproject.toml Package configuration and CLI entry points

License

MIT

Metadata

Release files for light-programmer 0.6.2

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

Source distribution (sdist)

Source distribution for light-programmer 0.6.2
File Size Uploaded Provenance Actions
light_programmer-0.6.2.tar.gz 27.4 kB With provenance Details for light_programmer-0.6.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for light-programmer 0.6.2
File Interpreter ABI Platform Actions
light_programmer-0.6.2-py3-none-any.whl Python 3 none any Details for light_programmer-0.6.2-py3-none-any.whl

Total release size: 55.1 kB

Release files / light_programmer-0.6.2.tar.gz

Download URL light_programmer-0.6.2.tar.gz
Size 27.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8311fe03d8e3b0e51513c4c751d0233771869c942b38ce187d6e197f71fd692c
BLAKE2b-256 checksum
How to use checksums
952851e7af2cce77ed339f8fc48545dbd3dd25b2bf6d2c148e5193ada6dc5b8c
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 / light_programmer-0.6.2-py3-none-any.whl

Download URL light_programmer-0.6.2-py3-none-any.whl
Size 27.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fa81cc37369c881f6cddd4f1df1db8276cedaf352ff4c5ada71ec3a0be91dd18
BLAKE2b-256 checksum
How to use checksums
061379a3631b37ff6e1faead98e6d59af41166b3bc82ea6327fb40040826ceee
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 light-programmer 0.6.2

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 light_programmer-0.6.2.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