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
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