Skip to main content

A platform-agnostic home topology kernel for modeling spaces and attaching behavior modules

Project description

home-topology

CI License: MIT Python 3.10+ Code style: black

A platform-agnostic home topology kernel for modeling spaces (Locations), attaching behavior (Modules), and wiring everything together with a location-aware Event Bus.

home-topology is the structural backbone for smart homes:

  • It models where things are (rooms, floors, zones, virtual spaces).
  • It lets you attach modules like Occupancy, Actions, Comfort, Energy.
  • It routes events through this topology so modules can react cleanly.
  • It stays independent of Home Assistant or any specific platform.

Think of it as a tiny "operating system" for your home's spatial model.
Occupancy, automations, energy logic, etc. are apps running on top.


Why Home Topology?

If every room had a perfect presence sensor, occupancy detection would be trivial. But reality is different:

  • Sensors are expensive – $30-50 per room adds up fast for a whole house
  • Batteries die – Motion sensors need constant maintenance
  • Devices go offline – More devices = more failure points
  • Coverage gaps – Even good sensors miss corners and edges

Home Topology lets you use what you already have:

Device Occupancy Signal
💡 Light switch turned on Someone's in the room
🚪 Door opened Someone entered
📺 TV playing Living room is occupied
🌡️ Thermostat adjusted Someone's home
🔊 Speaker volume changed Activity detected

Combine signals from motion sensors, switches, doors, media players, and more into reliable occupancy detection – without buying more hardware.

Your storage room doesn't need a motion sensor. Turn on the light → room is occupied → lights turn off after timeout. Simple.


Features

  • 🧱 Location graph (topology)
    Structured model of your home: house → floors → rooms → zones, with optional links to Home Assistant Areas.

  • 🧠 Modules as plug-ins
    Occupancy, Actions, Comfort, Energy, etc. are independent modules that attach to Locations and react to events.

  • 🔁 Location-aware Event Bus
    Simple, synchronous event pipeline with filters for type / location / ancestors / descendants. Location mutations can publish core events (location.created, location.renamed, location.parent_changed, location.deleted, location.reordered) when LocationManager is attached to an event bus.

  • 🧩 Schema-driven configuration
    Each module exposes a config schema; UIs can render dynamic forms per location without custom frontend code.

  • 🧪 Platform agnostic
    Core library has no dependency on Home Assistant. HA support is a thin adapter layer.

  • 💾 Config & state evolution
    Modules can version and migrate their configs, and optionally dump/restore runtime state via the host platform.


Installation

pip install home-topology

(Placeholder – adjust once published.)


Core Concepts

Location

A Location is a logical space: a room, floor, area, or virtual zone.

from dataclasses import dataclass
from typing import Optional, Dict, List

@dataclass
class Location:
    id: str
    name: str
    parent_id: Optional[str]
    ha_area_id: Optional[str]           # optional link to a HA Area
    entity_ids: List[str]               # platform entity IDs mapped here
    modules: Dict[str, Dict]            # per-module config blobs

Locations form a hierarchy (e.g. house → main_floor → kitchen → kitchen_table_zone).

LocationManager

LocationManager owns the topology and config, not the behavior.

Responsibilities:

  • Store the location tree.

  • Provide graph queries: parent_of, children_of, ancestors_of, descendants_of.

  • Maintain canonical sibling ordering (Location.order) and indexed reorder operations.

  • Maintain entity → location mappings.

  • Store per-location module config:

    location.modules["occupancy"]  # config for the Occupancy module on this location
    

It does not implement occupancy, energy, or actions logic.

Event Bus

The Event Bus is a simple, synchronous dispatcher for domain events:

from dataclasses import dataclass
from datetime import datetime
from typing import Optional, Dict, Any

@dataclass
class Event:
    type: str                  # "sensor.state_changed", "occupancy.changed", ...
    source: str                # "ha", "occupancy", "actions", ...
    location_id: Optional[str]
    entity_id: Optional[str]
    payload: Dict[str, Any]
    timestamp: datetime
  • publish(event) synchronously delivers events to subscribers.
  • Handlers are wrapped in try/except so one bad module cannot crash the kernel.
  • Modules treat handlers as fast and CPU-bound.
  • For I/O-heavy work, the host integration should offload asynchronously.

Modules

Modules are plug-ins that add behavior to the topology:

  • OccupancyModule – computes occupied / confidence per Location.
  • ActionsModule – runs automations in response to semantic events.
  • ComfortModule (future) – room comfort metrics.
  • EnergyModule (future) – room-level energy and power.

A module:

  • Receives events from the Event Bus.
  • Uses the LocationManager to understand hierarchy.
  • Maintains its own runtime state.
  • Emits semantic events that other modules can consume.

Example interface (simplified):

class LocationModule:
    id: str
    CURRENT_CONFIG_VERSION: int

    def attach(self, bus, loc_manager) -> None:
        """Register event subscriptions and capture references."""

    def default_config(self) -> dict:
        """Default per-location config."""

    def location_config_schema(self) -> dict:
        """JSON-schema-like definition for UI configuration."""

    def migrate_config(self, config: dict) -> dict:
        """Upgrade older config versions to CURRENT_CONFIG_VERSION."""

    def on_location_config_changed(self, location_id: str, config: dict) -> None:
        """React to config updates for a given location."""

    def dump_state(self) -> dict:
        """Optional: serialize runtime state (host is responsible for storage)."""

    def restore_state(self, state: dict) -> None:
        """Optional: restore runtime state from serialized form."""

Quick Example

Note: This is illustrative, not a final API.

from home_topology.core.manager import LocationManager
from home_topology.core.bus import EventBus, Event
from home_topology.modules.occupancy.module import OccupancyModule

# 1. Kernel components
loc_mgr = LocationManager()
bus = EventBus()

# 2. Create a simple topology
kitchen = loc_mgr.create_location(
    id="kitchen",
    name="Kitchen",
    parent_id="main_floor",
    ha_area_id="area.kitchen",
)

# Map a motion sensor entity to the kitchen
loc_mgr.add_entity_to_location("binary_sensor.kitchen_motion", "kitchen")

# 3. Attach the Occupancy module
occupancy = OccupancyModule()
occupancy.attach(bus, loc_mgr)

# Optionally override per-location config
loc_mgr.set_module_config(
    location_id="kitchen",
    module_id="occupancy",
    config={
        "version": occupancy.CURRENT_CONFIG_VERSION,
        "motion_sensors": ["binary_sensor.kitchen_motion"],
        "timeout_seconds": 300,
    },
)

# 4. Feed a normalized occupancy signal into the kernel
bus.publish(
    Event(
        type="occupancy.signal",
        source="ha_adapter",
        location_id="kitchen",
        entity_id="binary_sensor.kitchen_motion",
        payload={
            "event_type": "trigger",
            "source_id": "binary_sensor.kitchen_motion",
            "timeout": 300,
        },
        timestamp=datetime.utcnow(),
    )
)

# 5. Query occupancy state (implementation-dependent)
state = occupancy.get_location_state("kitchen")
print(state.occupied, state.confidence)

In a Home Assistant integration, you'd:

  • Translate HA state changes → Events.
  • Expose module state back as HA entities.
  • Optionally provide a UI to configure modules per location.

See the Integration Guide for a complete, production-ready Home Assistant integration example.


Relationship to Home Assistant

home-topology is not a Home Assistant custom component. It's a pure Python library that can back a HA integration (and other platforms).

A typical HA setup would add:

  • custom_components/home_topology/

    • Uses this library to:

      • Build a location graph from HA Areas / devices / entities.
      • Feed HA events into the Event Bus.
      • Expose module state (e.g., occupancy sensors) back to HA.
      • Provide a UI for Locations and their modules (with an "Unassigned/Inbox" view for entities).

Building an integration? See the complete Integration Guide for step-by-step instructions, patterns, and a full Home Assistant example.


Project Status

This is a work-in-progress architecture focused on:

  • Clean separation between topology, events, and behavior.
  • Extensibility via modules.
  • Strong testability in pure Python (without spinning up HA).

Expect breaking changes while the core stabilizes.


Development

Quick Start

# Clone and setup
git clone https://github.com/mjcumming/home-topology.git
cd home-topology
python3 -m venv .venv
source .venv/bin/activate

# Install in development mode
make dev-install

# Run tests
make test

# Run example
make example

# Run all checks
make check

Documentation

📖 Start Here:

🔌 Integration:

📊 Project:

🏗️ Architecture:

📦 Modules:

🧪 Testing:

📚 Reference:

Development Commands

make help          # Show all available commands
make test-cov      # Run tests with coverage
make format        # Format code with black
make lint          # Run ruff linter
make typecheck     # Run mypy type checker
make check         # Run all quality checks

Contributing

Contributions are welcome! Please read CONTRIBUTING.md before submitting PRs.

Key guidelines:


License

MIT License - see LICENSE for details.


Links

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

home_topology-0.2.0a0.tar.gz (227.0 kB view details)

Uploaded Source

Built Distribution

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

home_topology-0.2.0a0-py3-none-any.whl (63.6 kB view details)

Uploaded Python 3

File details

Details for the file home_topology-0.2.0a0.tar.gz.

File metadata

  • Download URL: home_topology-0.2.0a0.tar.gz
  • Upload date:
  • Size: 227.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for home_topology-0.2.0a0.tar.gz
Algorithm Hash digest
SHA256 453ef48f4f1ce7984e2e85beecdf5e7c17c7c66a9ad1ce2259dea7250a8d6d06
MD5 58680a8f97e841455046a0b284ffc16c
BLAKE2b-256 7845f23406b3f7a7c9e6e3ff18e950c3cf43759af9138af5e43a366e650405de

See more details on using hashes here.

Provenance

The following attestation bundles were made for home_topology-0.2.0a0.tar.gz:

Publisher: release.yml on mjcumming/home-topology

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

File details

Details for the file home_topology-0.2.0a0-py3-none-any.whl.

File metadata

File hashes

Hashes for home_topology-0.2.0a0-py3-none-any.whl
Algorithm Hash digest
SHA256 cd5c6b85a231b646c510a201622f8719ef8f9cb89820f981373bbeab9dbaf501
MD5 e4f6bc014d1274488b31c69efd1dcb98
BLAKE2b-256 1169c88e2c83df3704d26457bffbbbf954eada631f02dc0122f7a1d3831f809a

See more details on using hashes here.

Provenance

The following attestation bundles were made for home_topology-0.2.0a0-py3-none-any.whl:

Publisher: release.yml on mjcumming/home-topology

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