A hierarchical occupancy tracking engine with locking and identity logic.
Project description
Occupancy Manager
A hierarchical occupancy tracking engine with locking and identity logic.
Overview
Occupancy Manager is a pure Python library for managing hierarchical occupancy state. It accepts events from sensors, calculates the state of logical "Locations" (Rooms, Floors, Zones), and maintains a hierarchy where occupancy bubbles up from child to parent locations.
Features
- Hierarchical Location Tracking: Support for parent-child location relationships with upward propagation
- Identity Management: Track active occupants across locations with individual arrival/departure handling
- Locking Logic: Freeze location state when needed (party mode)
- Multiple Occupancy Strategies: Independent locations or locations that follow parent state
- Time-Agnostic: All time operations accept
nowas an argument (no system clock access) - Pure Python: No external dependencies, standard library only
- Event Types: Support for momentary events (motion), holds (presence/radar), and manual overrides
Installation
pip install occupancy-manager
Quick Start
from datetime import datetime, timedelta
from occupancy_manager import (
LocationConfig,
LocationKind,
OccupancyEvent,
EventType,
OccupancyEngine,
)
# Create location configuration
kitchen = LocationConfig(
id="kitchen",
kind=LocationKind.AREA,
timeouts={"motion": 10, "presence": 5}
)
# Initialize engine with list of configs
engine = OccupancyEngine([kitchen])
# Create an event
now = datetime.now()
event = OccupancyEvent(
location_id="kitchen",
event_type=EventType.MOMENTARY,
category="motion",
source_id="binary_sensor.kitchen_motion",
timestamp=now,
)
# Process event
result = engine.handle_event(event, now)
# Check for transitions
for transition in result.transitions:
print(f"{transition.location_id}: {'occupied' if transition.new_state.is_occupied else 'vacant'}")
print(f" Occupants: {transition.new_state.active_occupants}")
print(f" Expires at: {transition.new_state.occupied_until}")
# Check when next timeout check is needed
if result.next_expiration:
print(f"Next timeout check: {result.next_expiration}")
Identity Tracking Example
from datetime import datetime
from occupancy_manager import (
LocationConfig,
LocationKind,
OccupancyEvent,
EventType,
OccupancyEngine,
)
# Setup
kitchen = LocationConfig(id="kitchen", kind=LocationKind.AREA)
engine = OccupancyEngine([kitchen])
now = datetime.now()
# Mike arrives (Bluetooth presence start)
event = OccupancyEvent(
location_id="kitchen",
event_type=EventType.HOLD_START,
category="presence",
source_id="ble_mike",
timestamp=now,
occupant_id="Mike",
)
result = engine.handle_event(event, now)
print(f"Occupants: {engine.state['kitchen'].active_occupants}") # {'Mike'}
# Marla arrives
event = OccupancyEvent(
location_id="kitchen",
event_type=EventType.HOLD_START,
category="presence",
source_id="ble_marla",
timestamp=now,
occupant_id="Marla",
)
result = engine.handle_event(event, now)
print(f"Occupants: {engine.state['kitchen'].active_occupants}") # {'Mike', 'Marla'}
# Mike leaves (Bluetooth presence end)
event = OccupancyEvent(
location_id="kitchen",
event_type=EventType.HOLD_END,
category="presence",
source_id="ble_mike",
timestamp=now,
occupant_id="Mike",
)
result = engine.handle_event(event, now)
print(f"Occupants: {engine.state['kitchen'].active_occupants}") # {'Marla'}
print(f"Still occupied: {engine.state['kitchen'].is_occupied}") # True
Development
This project uses:
- Python 3.11+
rufffor linting and formattingmypyfor type checking (strict mode)pytestfor testing
Setup
# Create virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in editable mode
pip install -e .
# Install development dependencies
pip install -e ".[dev]"
Running Tests
pytest
Running Linters
ruff check .
ruff format .
mypy src/
License
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file occupancy_manager-0.1.0.tar.gz.
File metadata
- Download URL: occupancy_manager-0.1.0.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef96fd9f40aaa884d477d6b8dddd8f901d2fa0408f45546de51779c670158fa5
|
|
| MD5 |
4aa5cc476b9419b1c38481c3d21fdc58
|
|
| BLAKE2b-256 |
a1b493c99a2f7fce3a08022fb4e2c0c34a2065b77059674f67126de086cc0c1f
|
File details
Details for the file occupancy_manager-0.1.0-py3-none-any.whl.
File metadata
- Download URL: occupancy_manager-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d541ebc0631d86262915fed6cc0fb31c69c55a06d7d03a38b712920be85a74c
|
|
| MD5 |
462ca98cc1a176a8906f723ab7aa806c
|
|
| BLAKE2b-256 |
10f53c51f6109f4a3df2498325a457e691bb4d85e9638d2e92a2097caa062876
|