# Copilot / AI Agent Instructions for system2mqtt Short, actionable guidance so an AI coding agent can be immediately productive. 1. Purpose - This repo collects host metrics and publishes them to Home Assistant over MQTT. - Main entry point: `system2mqtt` console script (defined in `setup.py`). 2. How to run (development) - Create a venv and install deps: ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt pip install -e . ``` - Run the service with the provided entry point: ```bash system2mqtt ``` - Environment override: set `SYSTEM2MQTT_CONFIG` to point to a `config.yaml` path. 3. Big-picture architecture - `system2mqtt.main` (console entry) loads configuration, connects to MQTT, discovers collector modules under `src/system2mqtt/collectors/`, and loops to: - call each collector's `collect_metrics()` - publish Home Assistant discovery payloads and state/attributes topics - publish availability to `system2mqtt/{HOSTNAME}/status` - Collectors are pure Python modules (examples: `collectors/system_metrics.py`, `collectors/cpu_temperature.py`, `collectors/zfs_pools.py`). The main program imports them dynamically via `collectors.` and expects a `collect_metrics()` function. 4. Collector conventions (exact, follow these) - Each collector should expose `collect_metrics() -> Dict` which returns a dict with an `entities` list. - Each entity must include at least: `sensor_id`, `name`, `value`, `state_class`, `unit_of_measurement`, `device_class`, and `attributes`. - Optional: module-level `DEFAULT_INTERVAL` can be present (collectors include this today), but note: current `main` does not use per-collector intervals (see "Notable quirks"). - Example entity (from `system_metrics.py`): ```py { "sensor_id": "cpu_usage", "name": "CPU Usage", "value": "12.3", "state_class": "measurement", "unit_of_measurement": "%", "device_class": "power_factor", "attributes": {"friendly_name": "CPU Usage"} } ``` 5. Configuration and secrets - Default config path: `~/.config/system2mqtt/config.yaml` (created from `config.yaml.example` on first run). - `SYSTEM2MQTT_CONFIG` env var can override the config file location. - Required config keys under `mqtt`: `host`, `port`, `username`, `password`, `client_id`, `discovery_prefix`. 6. MQTT topics & discovery (concrete examples) - Discovery topic format published by `main`: `{discovery_prefix}/sensor/system2mqtt_{HOSTNAME}_{sensor_id}/config` - State topic format: `system2mqtt/{HOSTNAME}/{sensor_id}/state` - Attributes topic: `system2mqtt/{HOSTNAME}/{sensor_id}/attributes` (JSON) - Availability: `system2mqtt/{HOSTNAME}/status` with `online` / `offline` payloads (retained) 7. Integration points & dependencies - MQTT client: `paho-mqtt` (callback handlers in `main.py`). - System metrics: `psutil` used by `collectors/system_metrics.py`. - ZFS collectors call `zpool` binaries via `subprocess` (requires ZFS tools present on host). 8. Notable quirks & places to be careful - The README mentions per-collector update intervals, and collector modules define `DEFAULT_INTERVAL`, but `main.py` currently uses a fixed `time.sleep(60)` and does not schedule collectors individually. If changing scheduling, update `main.py` to read collector `DEFAULT_INTERVAL` or config `collectors.intervals`. - `main.py` lists collectors from the relative `collectors` directory using `os.listdir('collectors')`. For correct imports: - Run from package-installed environment (`pip install -e .`) and call `system2mqtt` (recommended), or - Ensure working directory / `PYTHONPATH` is set so `collectors` import works. - On first run the code copies `config.yaml.example` to the user config dir and exits — tests or CI should populate a config before invoking `system2mqtt`. 9. Suggested tasks for AI agents (concrete, small changes) - Implement per-collector scheduling using `DEFAULT_INTERVAL` or `config['collectors']['intervals']`. - Add unit tests around collector `collect_metrics()` return schema (validate required keys). - Improve error handling around dynamic imports (log which path was attempted). 10. Where to look in the code - Entry point & runtime: `src/system2mqtt/main.py` - Collector examples: `src/system2mqtt/collectors/*.py` (`system_metrics.py`, `cpu_temperature.py`, `zfs_pools.py`) - Example config: `config.yaml.example` - Packaging / console script: `setup.py` (entry point `system2mqtt`) If anything here is unclear or you want the instructions to emphasize other areas (tests, CI, packaging), tell me which part to expand or correct.