Skip to content

Latest commit

 

History

History
124 lines (88 loc) · 5.8 KB

File metadata and controls

124 lines (88 loc) · 5.8 KB

AI Agent Instructions for RFPlayer Integration

Project Overview

RFPlayer is a Home Assistant integration for the GCE RF Player gateway. It provides a bridge between RF (radio frequency) devices and Home Assistant, supporting protocols like X10, RTS, BLYSS, OREGON, and many others. The integration handles device discovery, event processing, and entity mapping through a plugin-based device profile system.

Architecture

Core Components

  • Gateway (gateway.py): Central orchestrator managing RF device connections, event handling, and service registration. Single instance per config entry.
  • Device Profiles (device_profiles.py): Plugin system mapping RF device JSON events to Home Assistant platforms (binary_sensor, sensor, light, climate, cover, switch).
  • RfPlayerLib (rfplayerlib/): Low-level async client for USB serial communication with RF Player hardware.
  • Entity classes (binary_sensor.py, sensor.py, etc.): Platform adapters using common base from entity.py.

Data Flow

  1. RF event arrives via USB serial → RfplayerProtocol.connection_made()
  2. Event decoded to RfDeviceEventGateway.async_handle_rf_event()
  3. Device profile matched & platform entities created → state updated via dispatcher signals
  4. Config changes trigger async_options_updated() to reload affected entities

Configuration Versioning

  • Current: Version 1, Minor 2 (VERSION = 1, MINOR_VERSION = 1 in config_flow.py)
  • New entries default to Version 1, Minor 1
  • Migrations: Defined in migration.py using async_migrate_entry() hook
  • Always update both version and minor_version in async_update_entry() call

Key Patterns & Conventions

Device Profile System

  • Device profiles are YAML files defining protocol + address → entity mappings
  • Uses JSONPath expressions to extract values from RF event JSON payloads
  • Value converters: bit_mask, bit_offset, map, factor for data transformation
  • Located: device-profiles.yaml (auto-loaded) + tests/rfplayer/device_profiles/frames/ (test data)
  • Always use async_get_profile_registry() to load lazily on first use

Entity Implementation

  • All entities inherit from RfEntity base class (entity.py)
  • Device identifiers built via build_device_id_from_device_info() with protocol + address
  • Always call async_write_ha_state() within platform handlers to notify HA
  • Dispatcher signals for event updates: SIGNAL_RFPLAYER_EVENT, SIGNAL_RFPLAYER_AVAILABILITY

Config Flow & Options

  • Single config entry per RF Player gateway (enforced: single_instance_allowed)
  • Entry data immutable after creation; use options flow for user-changeable settings
  • Device addition flow: manual config → auto-discovery on events (when enabled)
  • Schema defaults: see const.py (DEFAULT_RECONNECT_INTERVAL=10s, DEFAULT_RECEIVER_PROTOCOLS=all modes)

Testing Patterns

  • Mock only external dependencies (Home Assistant, device registry), not your code
  • Use Mock(spec=...) to prevent mock drift
  • Test behavior with assert_called_once_with(), not just return values
  • Always patch at import site: "custom_components.rfplayer.migration.dr.async_get" not homeassistant.helpers.device_registry
  • Use @pytest.mark.asyncio for async test functions
  • Fixture: setup_rfplayer_test_cfg() creates valid test config entry

Logging

  • Critical: Use _LOGGER = get_logger() not __name__ for HA to display logs
  • Logs become visible in HA UI after enabling debug logging for rfplayer domain

Code Style

  • Enforced via ruff (configuration in pyproject.toml)

Development Workflow

Setup

source .venv/bin/activate
cd /workspaces/HacsRfPlayer

Commands

  • Format (github workflow + pre-commit hook): uv run ruff format --check
  • Lint (github workflow + pre-commit hook): uv run ruff check --fix
  • Typing (github workflow + pre-commit hook):uv run mypy custom_components tests
  • Test (github workflow): uv run pytest tests/
  • Run HA locally: Task "Run Home Assistant on port 8123" (executes scripts/develop)

Before Submitting

  1. Run formmatter and linter, validate typing
  2. Run tests: uv run pytest tests/ -v (all tests must pass)
  3. Use conventional commits for PR titles (e.g., feat:, fix:, refactor:) - CHANGELOG is auto-generated by semantic-release
  4. Verify device profile YAML syntax if modified

Platform Support Matrix

All platforms share common setup via async_forward_entry_setups(entry, PLATFORMS):

  • binary_sensor (BinarySensorDeviceClass via profiles)
  • sensor (SensorDeviceClass via profiles)
  • light (on/off and brightness from RF commands)
  • climate (temperature control)
  • cover (position control)
  • switch (on/off control)

Dependencies & Constraints

  • Home Assistant: ≥2025.1.0 (from hacs.json)
  • Python: ≥3.13.2 (from pyproject.toml)
  • Key libs: pydantic (data validation), jsonpath-ng (device profile queries), serialx (USB communication)
  • USB device detection via serial.tools.list_ports.comports()

Common Gotchas

  1. Device ID format: Must be slugified (no hyphens). Migration 1.1→1.2 removes old format devices.
  2. Config immutability: Don't modify entry.data directly; use async_update_entry().
  3. Registry access: Get via dr.async_get(hass), then call methods on registry object (not hass).
  4. Simulator: Use SIMULATOR_PORT = "/simulator" constant when testing without hardware.
  5. Entry updates: Always use version= and minor_version= parameters together; old code with only version=2 fails.
  6. Versioning:
    • Integration version managed with semantic release from conventional commits
    • manifest.json dependencies updated automatically with github workflow (see update_manifest.py)
    • version in RfplayerConfigFlow is not aligned with integration version (only for migration)