Metadata-Version: 2.4
Name: kamio
Version: 1.0.0b4
Summary: Declarative asynchronous IoT framework for Python with MQTT support
Author-email: Данил Сытников <d.sytnikov@int-sys.ru>
License: Apache-2.0
Project-URL: Homepage, https://github.com/Peim0n/kamio
Project-URL: Repository, https://github.com/Peim0n/kamio.git
Project-URL: Documentation, https://github.com/Peim0n/kamio#readme
Project-URL: Bug Tracker, https://github.com/Peim0n/kamio/issues
Keywords: iot,mqtt,home-automation,asyncio,framework,smart-home
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Home Automation
Classifier: Topic :: System :: Hardware
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: gmqtt>=0.7.0
Provides-Extra: gpio
Requires-Dist: gpiod>=1.6.0; extra == "gpio"
Provides-Extra: serial
Requires-Dist: pyserial>=3.5; extra == "serial"
Provides-Extra: http
Requires-Dist: aiohttp>=3.8.0; extra == "http"
Provides-Extra: all-drivers
Requires-Dist: gpiod>=1.6.0; extra == "all-drivers"
Requires-Dist: pyserial>=3.5; extra == "all-drivers"
Requires-Dist: aiohttp>=3.8.0; extra == "all-drivers"
Provides-Extra: hot-reload
Requires-Dist: watchdog>=3.0; extra == "hot-reload"
Provides-Extra: dev
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: isort>=5.12; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Requires-Dist: pylint>=2.17; extra == "dev"
Provides-Extra: test
Requires-Dist: pytest>=7.4; extra == "test"
Requires-Dist: pytest-asyncio>=0.21; extra == "test"
Requires-Dist: pytest-cov>=4.1; extra == "test"
Requires-Dist: pytest-mock>=3.11; extra == "test"
Provides-Extra: full
Requires-Dist: gpiod>=1.6.0; extra == "full"
Requires-Dist: pyserial>=3.5; extra == "full"
Requires-Dist: aiohttp>=3.8.0; extra == "full"
Requires-Dist: watchdog>=3.0; extra == "full"
Requires-Dist: black>=23.0; extra == "full"
Requires-Dist: isort>=5.12; extra == "full"
Requires-Dist: mypy>=1.0; extra == "full"
Requires-Dist: pylint>=2.17; extra == "full"
Requires-Dist: pytest>=7.4; extra == "full"
Requires-Dist: pytest-asyncio>=0.21; extra == "full"
Requires-Dist: pytest-cov>=4.1; extra == "full"
Requires-Dist: pytest-mock>=3.11; extra == "full"
Dynamic: license-file

# Kamio v1.0.0b4

![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)
![Version](https://img.shields.io/badge/version-1.0.0b4--beta-blue.svg)
![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)
![MQTT](https://img.shields.io/badge/MQTT-v5-orange.svg)
![Coverage](https://img.shields.io/badge/coverage-94%25-brightgreen.svg)
![Tests](https://github.com/Peim0n/kamio/actions/workflows/ci.yml/badge.svg)

**Kamio** is a declarative asynchronous IoT framework for Python built on MQTT. Describe your devices as classes, connect hardware with drivers, and automate with rules.

## Features

- **Declarative devices** — `state`, `telemetry`, `event`, `config` fields via Python annotations
- **Drivers** — GPIO, Serial, Telnet, HTTP, UDP, Modbus TCP, Mock (latency/failure simulation)
- **MQTT v5** — reliable communication, auto-reconnect, backward compatibility with legacy topics
- **Asynchronous** — fully `asyncio`, no blocking calls in the event loop
- **Automation rules** — react to field changes and periodic intervals
- **Plugin System** — isolated plugins with automatic cleanup via `PluginContext`
- **Hot-Reload** — reload rules and devices without stopping the application
- **Custom MQTT Nodes** — arbitrary MQTT nodes with message routing
- **Home Assistant Discovery** — lazy-init, activated only when `enable_ha_discovery()` is called
- **Configuration** — JSON files + `Kamio_*` environment variables

## Installation

```bash
pip install kamio
```

### Requirements

- Python 3.10+
- MQTT broker (Mosquitto recommended)

```bash
# Ubuntu/Debian
sudo apt-get install mosquitto mosquitto-clients
# macOS
brew install mosquitto
# Windows: https://mosquitto.org/download/
```

### Additional Dependencies

```bash
pip install kamio[gpio]           # GPIO (gpiod)
pip install kamio[serial]          # Serial (pyserial)
pip install kamio[http]            # HTTP (aiohttp)
pip install kamio[all-drivers]   # all external driver dependencies (gpiod, pyserial, aiohttp)
pip install kamio[dev]            # formatting, type checking
pip install kamio[test]           # pytest, pytest-asyncio
```

> `UDPDriver`, `TelnetDriver`, and `ModbusTCPDriver` use only the Python standard library and are available without extras.

## Quick Start

```python
import asyncio
from kamio import KamioApp, Device, command, state, telemetry

app = KamioApp(mqtt_broker="mqtt://localhost:1883")


class SmartLight(Device):
    power:      bool  = state(default=False, writable=True)
    brightness: int   = state(default=100, min=0, max=255, writable=True)
    energy_wh:  float = telemetry(default=0.0, unit="Wh")

    @command
    async def toggle(self):
        self.power = not self.power
        return {"power": self.power}


class MotionSensor(Device):
    motion_detected: bool = state(default=False, writable=True)


@app.rule(device=MotionSensor, fields=["motion_detected"])
async def on_motion(event, app):
    if event.data["motion_detected"]:
        light = app.devices.get("living_room")
        if light:
            await light.handle_state({"power": True, "brightness": 200})


async def main():
    # You can pass a driver: Serial/Telnet/HTTP/UDP/Modbus TCP
    # await app.add_device("living_room", SmartLight, driver=TelnetDriver("10.0.0.10"))
    await app.add_device("living_room", SmartLight)
    await app.add_device("hall_sensor", MotionSensor)
    await app.start()


if __name__ == "__main__":
    asyncio.run(main())
    # OR blocking startup with SIGINT/SIGTERM handling:
    # app.run()
```

## Usage Examples

### Plugins

```python
from kamio.plugins.builtin.metrics_plugin import MetricsPlugin

metrics = await app.load_plugin(MetricsPlugin)
print(metrics.get_counter("device_state_changed"))
```

### Hot-reload rules

```python
app.watch_directory("rules/", "*.py", app.hot_reload.make_rules_handler())
app.enable_hot_reload()
```

### Home Assistant Discovery

```python
app.enable_ha_discovery(prefix="homeassistant")
# HADiscovery is created only here, not during KamioApp initialization
```

### Custom MQTT node

```python
from kamio.core.custom_nodes import CustomNode

class BridgeNode(CustomNode):
    async def handle_message(self, topic: str, payload: bytes):
        print(f"Bridge received: {topic}")

app.register_custom_node("bridge", BridgeNode(app.mqtt_client, "bridge"))
```

### Configuration via file

```python
app = KamioApp(config_path="config.json")
```

```json
{
  "mqtt_broker": "mqtt://broker.local:1883",
  "log_level": "INFO"
}
```

Or via environment variables:
```bash
Kamio_MQTT_BROKER=mqtt://broker.local:1883
Kamio_LOG_LEVEL=DEBUG
```

## Test Structure

```
tests/
  unit/         # isolated component tests (751 tests, 94% coverage)
  stress/       # load tests (16 tests)
```

```bash
pytest                          # all tests
pytest tests/unit/              # unit only
pytest tests/stress/            # stress only
pytest --cov=kamio              # with coverage report
```

## Documentation

- [API](docs/api.md) — reference for all classes and methods v1.0.0b4
- [Architecture](docs/architecture.md) — detailed architecture overview v1.0.0b4
- [CHANGELOG](CHANGELOG.md) — changelog

## License

Apache-2.0 — see the [LICENSE](LICENSE) file
