Skip to main content

Ecosystem-agnostic smart home lighting & AC automation using Matter protocol

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

light_programmer-0.6.2.tar.gz (27.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

light_programmer-0.6.2-py3-none-any.whl (27.7 kB view details)

Uploaded Python 3

File details

Details for the file light_programmer-0.6.2.tar.gz.

File metadata

  • Download URL: light_programmer-0.6.2.tar.gz
  • Upload date:
  • Size: 27.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for light_programmer-0.6.2.tar.gz
Algorithm Hash digest
SHA256 8311fe03d8e3b0e51513c4c751d0233771869c942b38ce187d6e197f71fd692c
MD5 f5ade4e5187186e3badcbcbc1e84a056
BLAKE2b-256 952851e7af2cce77ed339f8fc48545dbd3dd25b2bf6d2c148e5193ada6dc5b8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for light_programmer-0.6.2.tar.gz:

Publisher: python-publish.yml on dongnh/light_programmer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file light_programmer-0.6.2-py3-none-any.whl.

File metadata

File hashes

Hashes for light_programmer-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 fa81cc37369c881f6cddd4f1df1db8276cedaf352ff4c5ada71ec3a0be91dd18
MD5 ed4b4cd697a252d9514590e2e13a558c
BLAKE2b-256 061379a3631b37ff6e1faead98e6d59af41166b3bc82ea6327fb40040826ceee

See more details on using hashes here.

Provenance

The following attestation bundles were made for light_programmer-0.6.2-py3-none-any.whl:

Publisher: python-publish.yml on dongnh/light_programmer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page