Skip to content

Commit 14e5500

Browse files
Sub devices (#3944)
1 parent 5eb2521 commit 14e5500

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+6177
-3364
lines changed

.github/ISSUE_TEMPLATE/bug.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ body:
1010
attributes:
1111
label: Checklist
1212
options:
13-
- label: I have added `battery_notes:` to my configuration.yaml and restarted.
13+
- label: I have restarted Home Assistant after the HACS or manual install.
1414
required: true
1515
- label: I have read the [FAQ's](https://andrew-codechimp.github.io/HA-Battery-Notes/faq).
1616
required: true

.github/copilot-instructions.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# Battery Notes - AI Coding Instructions
2+
3+
## Project Overview
4+
Battery Notes is a Home Assistant custom integration that tracks battery information for IoT devices. It uses a **sub-entry architecture** where a single config entry can manage multiple battery devices via ConfigSubentry objects.
5+
6+
## Architecture & Core Components
7+
8+
### Config Entry Structure (Critical)
9+
- **Main Config Entry**: Domain-level configuration (`BatteryNotesConfigEntry`)
10+
- **Sub-entries**: Individual device configurations (`ConfigSubentry`) stored in `config_entry.runtime_data.subentries`
11+
- **Coordinators**: Each sub-entry has its own `BatteryNotesSubentryCoordinator` in `config_entry.runtime_data.subentry_coordinators[subentry_id]`
12+
13+
**Key Pattern**: Always iterate through `subentry_coordinators.values()` not the main coordinator when looking for devices.
14+
15+
### Entity Inheritance Structure
16+
- `BatteryNotesEntity` (base class in `entity.py`) - handles device association and common setup
17+
- Sensor classes inherit from both `BatteryNotesEntity` and HA sensor classes
18+
- Example: `class BatteryNotesTypeSensor(BatteryNotesEntity, RestoreSensor)`
19+
20+
### Device Discovery & Library
21+
- `library/library.json`: 10K+ device definitions with battery types
22+
- `discovery.py`: Auto-discovers devices and creates config entries
23+
- Device matching: `manufacturer` + `model` (+ optional `hw_version`)
24+
25+
## Key File Responsibilities
26+
27+
### Core Files
28+
- `__init__.py`: Config entry setup, sub-entry management, platform loading
29+
- `coordinator.py`: Data coordination, battery level tracking, event firing
30+
- `config_flow.py`: UI configuration flows for manual device addition
31+
- `services.py`: Battery replacement service handlers
32+
- `entity.py`: Base entity class with device association logic
33+
34+
### Platform Files
35+
- `sensor.py`: Battery type, battery+, and last replaced sensors
36+
- `binary_sensor.py`: Battery low binary sensors
37+
- `button.py`: Battery replaced action buttons
38+
39+
### Supporting Files
40+
- `library.py`: Device library management and updates
41+
- `discovery.py`: Automatic device discovery from library
42+
- `const.py`: All constants, service schemas, event names
43+
- `store.py`: Persistent storage for user data
44+
45+
## Development Workflow
46+
47+
### Local Development
48+
```bash
49+
# Start HA development server on port 8123
50+
./scripts/develop
51+
52+
# Lint code
53+
./scripts/lint
54+
55+
# Check types (if mypy installed)
56+
mypy custom_components/battery_notes/ --check-untyped-defs
57+
```
58+
59+
### File Structure Conventions
60+
- Put constants in `const.py` with proper categorization
61+
- Use dataclasses for configuration objects
62+
- Service schemas defined in `const.py`, handlers in `services.py`
63+
- All entities extend `BatteryNotesEntity` base class
64+
65+
## Critical Patterns
66+
67+
### Sub-entry Iteration Pattern
68+
```python
69+
# CORRECT - iterate through sub-entry coordinators
70+
for config_entry in hass.config_entries.async_loaded_entries(DOMAIN):
71+
if not config_entry.runtime_data.subentry_coordinators:
72+
continue
73+
for coordinator in config_entry.runtime_data.subentry_coordinators.values():
74+
if coordinator.device_id == target_device_id:
75+
# Process device
76+
```
77+
78+
### Entity Registration Pattern
79+
```python
80+
# Use unique_id from coordinator + description suffix
81+
self._attr_unique_id = f"{coordinator.device_id}_{description.unique_id_suffix}"
82+
83+
# Handle entity naming based on device association
84+
if coordinator.source_entity_id and not coordinator.device_id:
85+
self._attr_translation_placeholders = {"device_name": coordinator.device_name + " "}
86+
```
87+
88+
### Service Implementation Pattern
89+
```python
90+
# Always validate device exists before processing
91+
device_found = False
92+
for coordinator in subentry_coordinators.values():
93+
if coordinator.device_id == device_id:
94+
device_found = True
95+
# Process service call
96+
break
97+
98+
if not device_found:
99+
_LOGGER.error("Device %s not configured in Battery Notes", device_id)
100+
return None
101+
```
102+
103+
## Testing & Validation
104+
105+
### Type Checking
106+
- Project uses mypy with `--check-untyped-defs`
107+
- All major classes use type hints
108+
- ConfigEntry typing: `BatteryNotesConfigEntry = ConfigEntry[BatteryNotesData]`
109+
110+
### Linting
111+
- Uses `ruff` for code formatting and linting
112+
- Config in `pyproject.toml`
113+
- Run `./scripts/lint` before commits
114+
115+
## Integration Points
116+
117+
### Home Assistant APIs
118+
- Device Registry: Link entities to HA devices
119+
- Entity Registry: Manage entity lifecycle
120+
- Event Bus: Fire battery events (`EVENT_BATTERY_THRESHOLD`, `EVENT_BATTERY_REPLACED`)
121+
- Config Flow: Handle UI configuration
122+
123+
### External Dependencies
124+
- Library updates from `https://battery-notes-data.codechimp.org/library.json`
125+
- Version checking with `awesomeversion`
126+
- Data validation with `voluptuous`
127+
128+
## Common Tasks
129+
130+
### Adding New Entity Types
131+
1. Create entity description in appropriate platform file
132+
2. Extend `BatteryNotesEntity` base class
133+
3. Add to platform's `async_setup_entry` function
134+
4. Register constants in `const.py`
135+
136+
### Adding New Services
137+
1. Define schema in `const.py`
138+
2. Implement handler in `services.py` using sub-entry iteration pattern
139+
3. Register in `__init__.py` `async_setup_entry`
140+
4. Add service definition to `services.yaml`

.github/workflows/lint.yaml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ jobs:
3030
with:
3131
args: check --output-format=github
3232

33-
#TODO: Temporary disable until V3
34-
# - name: Ruff Format
35-
# uses: astral-sh/ruff-action@v3
36-
# with:
37-
# args: format --check --diff
33+
- name: Ruff Format
34+
uses: astral-sh/ruff-action@v3
35+
with:
36+
args: format --check --diff

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ config/*
1717
!config/configuration.yaml
1818
.DS_Store
1919
config/configuration.yaml
20-
20+
backup/*
2121
custom_components/battery_notes/frontend/node_modules

README.md

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,38 +29,29 @@ _If you want to show your support please_
2929

3030
## Installation
3131

32-
**Important**
33-
34-
Once you have installed battery notes using either HACS or manually as per the instructions below you must add the following entry to your `configuration.yaml`, then restart Home Assistant. This will enable discovery of your devices.
35-
36-
```
37-
battery_notes:
38-
```
39-
40-
If you need to add a device that is not automatically discovered from the library go to Settings -> Integrations click "+" and search for "Battery Notes"
41-
4232
### HACS Installation
4333

4434
[![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=andrew-codechimp&repository=HA-Battery-Notes&category=Integration)
4535

4636
Or
4737
Search for `Battery Notes` in HACS and install it under the "Integrations" category.
4838

39+
Restart Home Assistant
40+
41+
In the HA UI go to Settings -> Integrations click "+ Add integration" and search for "Battery Notes"
42+
43+
This will create the main Battery Notes integration service and discovery will start shortly afterwards, or you can battery notes manually within the integration.
44+
4945
### Manual Installation
5046

5147
<details>
5248
<summary>More Details</summary>
5349

5450
- You should take the battery_notes.zip file from the latest [published release](https://github.com/andrew-codechimp/ha-battery-notes/releases).
5551
- To install, place the contents of `custom_components` into the `<config directory>/custom_components` folder of your Home Assistant installation.
56-
- Add the following entry to your `configuration.yaml`
57-
58-
```
59-
battery_notes:
60-
```
61-
6252
- Restart Home Assistant
63-
- In the HA UI go to Settings -> Integrations click "+" and search for "Battery Notes"
53+
- In the HA UI go to Settings -> Integrations click "+ Add integration" and search for "Battery Notes"
54+
- This will create the main Battery Notes integration service and discovery will start shortly afterwards, or you can battery notes manually within the integration.
6455
</details>
6556

6657
## Docs

0 commit comments

Comments
 (0)