231 lines
8.4 KiB
Markdown
231 lines
8.4 KiB
Markdown
This repository holds the custom integration for Home Assistant that is polling data from the electricity grid provider, to catch and notify home assistant whn there are power outages planned/unplanned.
|
|
|
|
The integration follows home assistant best practices.
|
|
|
|
It has the following configurations:
|
|
|
|
1. DEER Region: [TN, TS, MN] for Transilvania Nord, Transilvania Sud, Muntentia Nord
|
|
For Cluj County it should default to TN.
|
|
|
|
2. City/Village: The city/village for which notifications should be raised
|
|
3. Street: the street name, if left blank, notifications will be raised for all streets in the city/village.
|
|
4. Polling interval standard: default to 15 minutes
|
|
5. Polling interval for power outages: default to 1 minute
|
|
|
|
How It works:
|
|
|
|
Scenario 1: Normal operation
|
|
The integration will poll the electricity grid provider every 15 minutes (or the custom set interval) and check if there are any power outages planned/unplanned. If there are, it will raise a notification.
|
|
The endpoints polled are:
|
|
https://outages.distributie-energie.ro/api/incidents/{Region}/0 for unplanned power outages
|
|
https://outages.distributie-energie.ro/api/scheduled/{Region}/0/15 for planned power outages in the next 15 days.
|
|
https://outages.distributie-energie.ro/api/scheduled/{Region}/0/azi for planned power outages today.
|
|
|
|
The data returned has the following format(s):
|
|
|
|
For scheduled power outages:
|
|
[
|
|
{
|
|
"id": "82540",
|
|
"nivel": "JT",
|
|
"sucursala": "BAIA MARE",
|
|
"judet": null,
|
|
"centru": null,
|
|
"linie": null,
|
|
"denumireInst": null,
|
|
"ansambluFunctional": "CALINESTI, Strada PRINCIPALA",
|
|
"catInstalatii": null,
|
|
"instalatie": null,
|
|
"dataProgramareStart": "14/01/2026 08:00",
|
|
"dataProgramareStop": "14/01/2026 15:00",
|
|
"durataProgramare": "7h : 0'",
|
|
"adreseLucrari": null,
|
|
"intervaluriProgramari": null
|
|
}
|
|
]
|
|
|
|
In this case, the integration will search the fields: "ansambluFunctional" and "adreseLucrari" to see if the city/village and street name are present. the logic will follow the following process:
|
|
we'll have a variable: cityPresent=city/village name is present, comparison done by first making both the expected and actual values as lower case.
|
|
if it's true, we'l check in a simillar fashion the street name
|
|
If we have a planned outage: we'll raise a home assistant event, with attributes for the planned start/stop and duration for the fields: dataProgramareStart, durataProgramareStop, durataProgramare, also ansamblulFunctional and adreseLucrari.
|
|
|
|
For unplanned power outages:
|
|
[
|
|
{
|
|
"id": "69706",
|
|
"judet": "SIBIU",
|
|
"localitate": null,
|
|
"sat": null,
|
|
"tipArtera": null,
|
|
"artera": null,
|
|
"numar": null,
|
|
"bloc": null,
|
|
"adresa": "Loc: SURA MARE, Strada: VETERANILOR<br />Loc: SURA MARE",
|
|
"dataStart": "10/01/2026 01:00",
|
|
"dataStop": ""
|
|
},
|
|
|
|
In this case the search will be done in field: adresa, and the logic will follow the same process as above.
|
|
in case of unplanned power outages, we'll raise a home assistant event with the attributes: dataStart, dataStop, adresa.
|
|
|
|
When a planned or unplanned power outage is raised, the integration keep track of the notification data, and will only raise a new notification if the start dates/ duration or end date changes.
|
|
|
|
Scenario 2: Home assistant restart
|
|
In case home assistant is restarted, the integration will keep track of the notification data, and will only raise a new notification if the start dates/ duration or end date changes.
|
|
|
|
Scenario 3: Power outage in progress
|
|
The integration exposes a switch entity to control the polling interval.
|
|
When home assistant detects that a power outage is in progress, the polling interval will be set to 1 minute (or the configured time), by enabling the outage polling mode switch.
|
|
|
|
## Entities Created
|
|
|
|
The integration creates the following entities:
|
|
|
|
### Sensors (11 total)
|
|
|
|
#### Planned Outages (15 days)
|
|
- `sensor.deer_outages_planned_15_start` - Start datetime of planned outage (device_class: timestamp)
|
|
- `sensor.deer_outages_planned_15_end` - End datetime of planned outage (device_class: timestamp)
|
|
- `sensor.deer_outages_planned_15_duration` - Duration text (e.g., "7h : 0'")
|
|
- `sensor.deer_outages_planned_15_address` - Location address text
|
|
|
|
#### Planned Outages (Today)
|
|
- `sensor.deer_outages_planned_today_start` - Start datetime of today's planned outage (device_class: timestamp)
|
|
- `sensor.deer_outages_planned_today_end` - End datetime of today's planned outage (device_class: timestamp)
|
|
- `sensor.deer_outages_planned_today_duration` - Duration text
|
|
- `sensor.deer_outages_planned_today_address` - Location address text
|
|
|
|
#### Unplanned Incidents
|
|
- `sensor.deer_outages_unplanned_start` - Start datetime of unplanned incident (device_class: timestamp)
|
|
- `sensor.deer_outages_unplanned_end` - End datetime of unplanned incident (device_class: timestamp)
|
|
- `sensor.deer_outages_unplanned_address` - Location address text
|
|
|
|
All sensors use `RestoreEntity` to persist their state across Home Assistant restarts.
|
|
|
|
### Switch Entity
|
|
|
|
- `switch.deer_outages_outage_polling_mode` - Controls polling interval
|
|
- **Off (default)**: Normal polling mode - polls every 15 minutes (or configured interval)
|
|
- **On**: Outage polling mode - polls every 1 minute (or configured interval) for faster updates during active outages
|
|
|
|
The switch state is preserved across Home Assistant restarts.
|
|
|
|
## Events
|
|
|
|
In addition to sensors, the integration fires Home Assistant events for automation triggers:
|
|
|
|
### Event Types
|
|
|
|
1. **`deer_outages_planned`** - Fired when a planned outage is detected or changed
|
|
|
|
Event data:
|
|
```python
|
|
{
|
|
"start": "14/01/2026 08:00",
|
|
"end": "14/01/2026 15:00",
|
|
"duration": "7h : 0'",
|
|
"address": "CALINESTI, Strada PRINCIPALA",
|
|
"city": "Cluj-Napoca",
|
|
"street": "Principala",
|
|
"type": "planned_15" # or "planned_today"
|
|
}
|
|
```
|
|
|
|
2. **`deer_outages_unplanned`** - Fired when an unplanned incident is detected or changed
|
|
|
|
Event data:
|
|
```python
|
|
{
|
|
"start": "10/01/2026 01:00",
|
|
"end": "",
|
|
"address": "Loc: SURA MARE, Strada: VETERANILOR",
|
|
"city": "Sura Mare",
|
|
"street": ""
|
|
}
|
|
```
|
|
|
|
Events are only fired when:
|
|
- A new outage is detected (wasn't present before)
|
|
- An existing outage's start date, end date, or duration changes
|
|
|
|
## Automation Examples
|
|
|
|
### Example 1: Notification on Planned Outage
|
|
```yaml
|
|
automation:
|
|
- alias: "Notify on Planned Outage"
|
|
trigger:
|
|
- platform: event
|
|
event_type: deer_outages_planned
|
|
action:
|
|
- service: notify.mobile_app
|
|
data:
|
|
title: "Planned Power Outage"
|
|
message: >
|
|
Outage from {{ trigger.event.data.start }}
|
|
to {{ trigger.event.data.end }}
|
|
at {{ trigger.event.data.address }}
|
|
```
|
|
|
|
### Example 2: Using Sensor States
|
|
```yaml
|
|
automation:
|
|
- alias: "Alert on Today's Outage"
|
|
trigger:
|
|
- platform: state
|
|
entity_id: sensor.deer_outages_planned_today_start
|
|
to: ~
|
|
condition:
|
|
- condition: template
|
|
value_template: "{{ states('sensor.deer_outages_planned_today_start') not in ['unknown', 'unavailable', 'None'] }}"
|
|
action:
|
|
- service: notify.mobile_app
|
|
data:
|
|
title: "Power Outage Today!"
|
|
message: >
|
|
Power outage scheduled for today from
|
|
{{ states('sensor.deer_outages_planned_today_start') }}
|
|
to {{ states('sensor.deer_outages_planned_today_end') }}
|
|
```
|
|
|
|
### Example 3: Auto-Enable Outage Mode
|
|
```yaml
|
|
automation:
|
|
- alias: "Enable Fast Polling on Active Outage"
|
|
trigger:
|
|
- platform: state
|
|
entity_id: sensor.deer_outages_unplanned_start
|
|
to: ~
|
|
condition:
|
|
- condition: template
|
|
value_template: "{{ states('sensor.deer_outages_unplanned_start') not in ['unknown', 'unavailable', 'None'] }}"
|
|
action:
|
|
- service: switch.turn_on
|
|
target:
|
|
entity_id: switch.deer_outages_outage_polling_mode
|
|
```
|
|
|
|
## Installation
|
|
|
|
### Manual Installation
|
|
1. Copy the `custom_components/deer_outages` directory to your Home Assistant `custom_components` directory
|
|
2. Restart Home Assistant
|
|
3. Go to **Settings** > **Devices & Services** > **Add Integration**
|
|
4. Search for "DEER Power Outages"
|
|
5. Complete the configuration:
|
|
- Select your region (TN, TS, or MN)
|
|
- Enter your city/village name
|
|
- Optionally enter your street name
|
|
- Configure polling intervals (defaults: 15 min normal, 1 min outage)
|
|
|
|
### Testing the API
|
|
Before installing in Home Assistant, you can test the API connection using the standalone script:
|
|
|
|
```bash
|
|
python test_api.py TN Cluj-Napoca "Strada Avram Iancu"
|
|
```
|
|
|
|
This will:
|
|
- Test all three API endpoints
|
|
- Show filtered results for your location
|
|
- Validate the filtering logic |