This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is an unofficial Home Assistant custom component that integrates Alarm.com security systems and devices. The integration communicates with Alarm.com's unofficial web API via the pyalarmdotcomajax library. It supports alarm panels, sensors, locks, lights, garage doors, thermostats, and other Alarm.com-connected devices.
Important: This is a safety-critical integration. Changes must be thoroughly tested and never rely on untested code for security functions.
The integration follows Home Assistant's standard custom component architecture:
custom_components/alarmdotcom/: Main integration directory__init__.py: Integration setup, config entry management, and config entry migrations (v1→v5)hub.py: Core controller (AlarmHub) that manages the pyalarmdotcomajaxAlarmBridgeAPI connection and WebSocket event monitoringentity.py: Base classes for all Alarm.com entitiesAdcEntity: Generic base entity with pub/sub event handlingAdcEntityDescription: Descriptor class using generics for type-safe entity definitions
- Platform files (e.g.,
alarm_control_panel.py,binary_sensor.py,lock.py,light.py,climate.py,cover.py,valve.py,button.py): Implement specific Home Assistant platforms config_flow.py: Configuration UI flow with OTP/2FA supportconst.py: Constants and configuration optionsutil.py: Helper functions
-
Initialization (
hub.py):AlarmHubcreatesAlarmBridge(from pyalarmdotcomajax) with credentialsinitialize()logs into Alarm.com and fetches initial device state- WebSocket connection starts via
start_event_monitoring()for real-time updates
-
Entity Creation (platform files):
- Each platform's
async_setup_entry()iterates through devices - Entities are created using descriptors (
AdcEntityDescription) - Entities subscribe to event broker messages for their device
- Each platform's
-
State Updates:
- WebSocket events flow through pyalarmdotcomajax's event broker
AdcEntity.event_handler()receives messages (RESOURCE_ADDED, RESOURCE_UPDATED, RESOURCE_DELETED, CONNECTION_EVENT)- Each entity's
update_state()method processes relevant changes - Entity calls
async_write_ha_state()to update Home Assistant
-
Device Control:
- User actions trigger entity methods (e.g.,
async_alarm_arm_away()) - Methods call controller functions from pyalarmdotcomajax (e.g.,
PartitionController.arm_away()) - Controllers send commands to Alarm.com API
- WebSocket events confirm state changes
- User actions trigger entity methods (e.g.,
- Generic Entity System: Entity descriptors use Python generics (
AdcManagedDeviceT,AdcControllerT) for type safety across device types - Event-Driven Architecture: All state updates flow through pyalarmdotcomajax's pub/sub event broker system
- Controller Pattern: Each device type has a controller in pyalarmdotcomajax that handles API calls
- Config Entry Migrations: Version migrations in
__init__.pyhandle config schema changes (currently at v5)
# Run all pre-commit hooks
pre-commit run --all-files
# Run Ruff linter with auto-fix
ruff check --fix .
# Run MyPy type checking
mypy .
# Run specific pre-commit hooks
pre-commit run ruff --all-files
pre-commit run mypy --all-files
pre-commit run codespell --all-files
pre-commit run yamllint --all-filesThis integration is tested by installing it in a Home Assistant instance (there's no standalone pytest suite in this repo):
- Copy
custom_components/alarmdotcom/to a Home Assistant installation - Configure via Home Assistant UI: Configuration → Integrations → Add Integration → Alarm.com
- Test with real Alarm.com credentials or use Home Assistant's test environment
- pre-commit: Runs on all commits (via GitHub Actions on PRs and master)
- hassfest: Home Assistant's integration validation tool (runs daily and on PRs)
- HACS validation: Ensures HACS compatibility
The integration uses config entry migrations to handle schema changes. Current version is 5. When adding new options:
- Update version in
config_flow.py:VERSION = X - Add migration logic in
__init__.py:async_migrate_entry() - Update
CONF_OPTIONS_DEFAULTinconst.pyif needed
- WebSocket state is managed by pyalarmdotcomajax
- State handler (
_ws_state_handlerinhub.py) monitors connection health - DEAD state raises
ConfigEntryNotReadyto trigger reconnection - All state updates flow through WebSocket; HTTP polling is not used
Three arming modes (home/away/night) each support three options:
force_bypass: Bypass open zones when armingsilent_arming: No beeps, double delayno_entry_delay: Skip entry delay
These are stored as lists in config options (e.g., CONF_ARM_HOME = ["force_bypass", "silent_arming"]).
Each device creates multiple entities:
- Primary entity (e.g., alarm panel, lock, sensor)
- Battery status entity (via
sensor_battery.pyor platform-specific implementations) - Malfunction status entity (reported via device attributes)
This integration is a thin wrapper around pyalarmdotcomajax. Most API logic lives in that library:
- Device resource management
- API authentication and session handling
- WebSocket connection
- Command execution
When adding support for new device types, changes often require updates to both repositories.
- All functions must have type hints (enforced by MyPy with
disallow_untyped_defs = true) - Use
from __future__ import annotationsfor forward references - Import types under
if TYPE_CHECKING:to avoid circular imports
- Use module-level logger:
log = logging.getLogger(__name__) - Log levels:
log.debug(): Routine state changes, entity initializationlog.info(): Integration startup, connection eventslog.warning(): Unexpected but recoverable issueslog.error(): Errors requiring user attention
- Include context in log messages (device names, IDs)
- Max line length: 120 characters
- Use Ruff for formatting and linting (config in
pyproject.toml) - Double quotes for strings
- Follow Home Assistant's entity naming conventions
- Verify device appears in pyalarmdotcomajax's device list
- If not, add to pyalarmdotcomajax first (device model, controller)
- Create platform file in
custom_components/alarmdotcom/(e.g.,switch.py) - Define entity description(s) with controller function
- Implement entity class extending
AdcEntity - Add platform to
PLATFORMSlist inconst.py - Test with real Alarm.com device
- Enable debug logging in Home Assistant:
logger: default: info logs: custom_components.alarmdotcom: debug pyalarmdotcomajax: debug
- Fire debug event to dump device data:
service: homeassistant.fire_event data: event_type: alarmdotcom_debug_request event_data: resource_id: "<device_id>"
- Check WebSocket connection state in logs
- Verify device state in pyalarmdotcomajax resource manager
- pyalarmdotcomajax: Update version in
manifest.jsonrequirements and.pre-commit-config.yamlmypy additional_dependencies - Home Assistant: Update in
requirements-dev.txtand.pre-commit-config.yamlmypy additional_dependencies - Version constraints use
>=for minimum versions
- Main Repository: https://github.com/pyalarmdotcom/alarmdotcom
- pyalarmdotcomajax Library: Separate package for Alarm.com API
- Home Assistant Integration Docs: https://developers.home-assistant.io/docs/creating_component_index/
- Issue Tracker: https://github.com/pyalarmdotcom/alarmdotcom/issues