Repository navigation
Developer Documentation: Crow AAP IP Module Integration Version 1.2.8 and higher
ARCHIVED - historical reference only. This page documents a superseded version of the integration and is no longer maintained. For current documentation see https://github.com/acdcnow/Crow-AAP-Alarm-System-for-Home-Assistant/wiki/Home and https://github.com/acdcnow/Crow-AAP-Alarm-System-for-Home-Assistant/wiki/HA-2026.09-Development-Branch . Full index: https://github.com/acdcnow/Crow-AAP-Alarm-System-for-Home-Assistant/wiki/Archived-Documentation ---
Project: Crow/AAP Alarm IP Module Integration for Home Assistant
Version: 1.2.8
Date: January 2026
The Crow IP Module Integration enables local control and monitoring of Crow Runner and AAP alarm systems via the IP-150 / IP Module using a direct TCP/IP connection. This document outlines the architectural changes and design philosophy behind version 1.2.8.
The primary driver for this release was to eliminate external dependency risks and enhance system stability. Previous versions relied on fetching the pycrowipmodule library from PyPI, which caused compatibility issues when Python environments were updated or when the external package became deprecated.
Key Architectural Shifts:
-
Monolithic Distribution: The communication library is now embedded directly within the integration (
/custom_components/). -
Enhanced Observability: Granular entities for diagnostics (Tamper, Bypass) and System Health.
-
Dynamic Configuration: Hardcoded limits have been replaced with user-configurable counts for Zones and Outputs via the UI.
The system follows a standard Home Assistant Hub architecture but utilizes a custom "Path Injection" pattern to incorporate the legacy library without requiring source code modifications.
-
Home Assistant Core: Manages the lifecycle of the integration and provides the Event Bus.
-
Integration Layer (
custom_components/crowipmodule):-
Config Flow: Handles UI Setup and Option/Update listeners.
-
Entity Mapping: Maps internal states to Home Assistant Entities (Binary Sensor, Alarm Panel, Switch).
-
Orchestration: Manages the Event Loop and ensures thread safety.
-
-
Communication Layer (
pycrowipmodule- Embedded):-
A legacy Python 3 library acting as the hardware driver.
-
Maintains the persistent TCP socket to the hardware.
-
Parses ASCII streams using Regex patterns.
-
-
Hardware (Crow IP Module):
-
Listens on TCP Port 5002 (default).
-
Emulates a keypad protocol.
-
To migrate from an external pip requirement to a native library without rewriting the library’s internal absolute imports, the following architectural pattern is applied:
-
Problem: The library files use
from pycrowipmodule import x. If moved to a subfolder, these imports fail in standard Python environments. -
Solution: In
init.py, the integration dynamically appends its own directory to Python’ssys.pathbefore importing the library.current_dir = os.path.dirname(os.path.abspath(__file__)) if current_dir not in sys.path: sys.path.append(current_dir)
-
Benefit: The original library code remains 100% untouched (preserving the "Golden Source"), yet it runs locally within the integration.
The folder structure is flattened to support the embedded library strategy.
custom_components/crowipmodule/
├── __init__.py # Entry point, Path Injection, Signal Dispatching
├── manifest.json # Metadata (No 'requirements' tag)
├── const.py # Constants, Firmware Profiles, Defaults
├── config_flow.py # UI Logic for Setup & Options
├── strings.json # Translation Keys (EN base)
├── translations/ # JSON files for DE, ES, FR, IT
│
├── platforms/
│ ├── alarm_control_panel.py # Main Arm/Disarm Logic
│ ├── binary_sensor.py # Zone Sensors (Split logic: Open, Tamper, Bypass)
│ ├── sensor.py # Text Sensors (Last Alarm, System Status)
│ └── switch.py # Output Control (Relays)
│
└── pycrowipmodule/ # EMBEDDED LIBRARY (Source v0.32)
├── __init__.py
├── alarm_panel.py # Main Controller Class
├── crow_base_client.py # Asyncio Protocol & TCP Logic
├── crow_defs.py # Command/Response Dictionaries
└── status_state.py # State Data Classes
-
Path Injection: Executes
sys.path.appendimmediately. -
Connection Lifecycle:
-
Initializes the
CrowIPAlarmPanelclass. -
Registers
async_dispatcher_sendcallbacks for:zones,areas,system,output. -
Socket Cleanup: Implements a 2.0s sleep before connection to ensure previous socket closures (vital for "Reload" operations).
-
Background Thread: Runs
controller.start()inhass.async_add_executor_jobto prevent blocking the HA Main Loop. -
Options Listener: Registers
entry.add_update_listenerto trigger a reload when settings change.
In v1.2.8, the entity model was significantly changed to comply with modern HA standards.
Instead of one sensor per zone, the system now instantiates three entities per configured zone:
-
Main Sensor:
device_class: window/door(Category: None/Main). -
Tamper Sensor:
device_class: tamper(Category: Diagnostic). -
Bypass Sensor:
device_class: safety(Category: Diagnostic).
Design Note: This separation prevents the dashboard from being cluttered with technical status flags while keeping security data accessible.
-
User Step: Prompts for Host, Port, and Firmware Profile.
-
Firmware Profile: User selects from a
vol.Inlist (e.g., "Ver 2.10…"). The system automatically maps this to a hardcoded Build Date to ensure consistent Device Info. -
Dynamic Counts: Users specify
number_of_zones(1-16) andnumber_of_outputs(1-8). The SDD dictates that entities are generated strictly based on these loops to save resources.
The system operates on an asynchronous push model.
-
TCP Ingress:
crow_base_client.pyreceives raw bytes (e.g.,ZO1\r\n). -
Parsing:
parseHandlermatches Regex (e.g.,r’ZO(?P<data>\d+)'→ Zone Open). -
State Update: The library updates its internal
_zoneStatedictionary. -
Callback: The library calls the injected
callback_zone_state_change. -
Dispatcher:
init.pyreceives the callback and fires a HA Signal:crowipmodule.zones_updated. -
Entity Update:
-
CrowZoneSensorlistens to the signal. -
It checks
if signal_data == self.zone_id. -
Calls
self.async_write_ha_state()to push the change to the UI.
-
-
Constraint: The Telnet protocol does not support querying firmware versions.
-
Solution: Firmware data is injected via
config_entryoptions. -
Implementation: All entity classes (
CrowBaseEntity) acceptfw_versionandfw_datein their constructor and pass this to thedevice_infoproperty. This groups all entities under a single "Device" in the HA Registry with consistent metadata.
-
Code Injection: No external code is downloaded at runtime.
-
Thread Safety: All calls from the threaded library to HA are wrapped in
hass.loop.call_soon_threadsafe. -
Panic Handling: The
alarm_triggerfunction maps directly to the hardware PANIC command.
| Feature | Old Architecture | New Architecture (v1.2.8) |
| Library Source | PyPI (pip install) | Local (custom_components) |
| Dependencies | High risk of version conflict | Zero external dependencies |
| Zone Entities | Single entity (attributes hidden) | Split entities (Open, Tamper, Bypass) |
| Configuration | Hardcoded limits | Dynamic (UI configurable) |
| Diagnostics | Minimal | Full System Health (Fuse, Batt, Line) |
| Translations | English only | EN, DE, FR, IT, ES |
| Reloading | Restart HA required | Instant Reload via UI |