Skip to content

Commit

Permalink
Added flight events
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandrErohin committed May 28, 2024
1 parent e1bdcde commit eb0fe21
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 18 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Flightradar24 integration for Home Assistant
Flightradar24 integration allows one to track overhead flights in a given region or particular planes. It will also fire Home Assistant events when flights enter and exit the defined region.
Flightradar24 integration allows one to track overhead flights in a given region or particular planes. It will also fire Home Assistant events when flights enter/exit/landed/took off.

<b>IMPORTANT: No need FlightRadar24 subscription!</b>

Expand All @@ -19,6 +19,10 @@ It allows you:
- flightradar24_entry: Fired when a flight enters the region.
- flightradar24_exit: Fired when a flight exits the region.
- flightradar24_most_tracked_new: Fired when a new flight appears in top 10 most tracked flights on FlightRadar24
- flightradar24_area_landed: Fired when a flight lands in your area.
- flightradar24_area_took_off: Fired when a flight takes off in your area.
- flightradar24_tracked_landed: Fired when a tracked flight lands.
- flightradar24_tracked_took_off: Fired when a tracked flight takes off.

### Sensors
- Current in area
Expand Down
10 changes: 7 additions & 3 deletions custom_components/flightradar24/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@
CONF_MOST_TRACKED = "most_tracked"
CONF_MOST_TRACKED_DEFAULT = True

EVENT_FLIGHTRADAR24_ENTRY = f"{DOMAIN}_entry"
EVENT_FLIGHTRADAR24_EXIT = f"{DOMAIN}_exit"
EVENT_FLIGHTRADAR24_MOST_TRACKED_NEW = f"{DOMAIN}_most_tracked_new"
EVENT_ENTRY = f"{DOMAIN}_entry"
EVENT_EXIT = f"{DOMAIN}_exit"
EVENT_AREA_LANDED = f"{DOMAIN}_area_landed"
EVENT_AREA_TOOK_OFF = f"{DOMAIN}_area_took_off"
EVENT_TRACKED_LANDED = f"{DOMAIN}_tracked_landed"
EVENT_TRACKED_TOOK_OFF = f"{DOMAIN}_tracked_took_off"
EVENT_MOST_TRACKED_NEW = f"{DOMAIN}_most_tracked_new"

MIN_ALTITUDE = -1
MAX_ALTITUDE = 100000
55 changes: 42 additions & 13 deletions custom_components/flightradar24/coordinator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations
from typing import Any
from enum import Enum
from datetime import timedelta
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
Expand All @@ -9,14 +10,23 @@
DOMAIN,
URL,
DEFAULT_NAME,
EVENT_FLIGHTRADAR24_ENTRY,
EVENT_FLIGHTRADAR24_EXIT,
EVENT_FLIGHTRADAR24_MOST_TRACKED_NEW,
EVENT_ENTRY,
EVENT_EXIT,
EVENT_MOST_TRACKED_NEW,
EVENT_AREA_LANDED,
EVENT_AREA_TOOK_OFF,
EVENT_TRACKED_LANDED,
EVENT_TRACKED_TOOK_OFF,
)
from logging import Logger
from FlightRadar24 import FlightRadar24API, Flight, Entity


class SensorType(Enum):
TRACKED = 1
IN_AREA = 2


class FlightRadar24Coordinator(DataUpdateCoordinator[int]):

def __init__(
Expand Down Expand Up @@ -105,15 +115,15 @@ async def _update_flights_in_area(self) -> None:
for obj in flights:
if not self.min_altitude <= obj.altitude <= self.max_altitude:
continue
await self._update_flights_data(obj, current, self.in_area)
await self._update_flights_data(obj, current, self.in_area, SensorType.IN_AREA)

if self.in_area is not None:
entries = current.keys() - self.in_area.keys()
self.entered = [current[x] for x in entries]
exits = self.in_area.keys() - current.keys()
self.exited = [self.in_area[x] for x in exits]
self._handle_boundary(EVENT_FLIGHTRADAR24_ENTRY, self.entered)
self._handle_boundary(EVENT_FLIGHTRADAR24_EXIT, self.exited)
self._handle_boundary(EVENT_ENTRY, self.entered)
self._handle_boundary(EVENT_EXIT, self.exited)
self.in_area = current

async def _update_flights_tracked(self) -> None:
Expand All @@ -126,7 +136,7 @@ async def _update_flights_tracked(self) -> None:
)
current: dict[int, dict[str, Any]] = {}
for obj in flights:
await self._update_flights_data(obj, current, self.tracked)
await self._update_flights_data(obj, current, self.tracked, SensorType.TRACKED)
self.tracked = current

async def _update_most_tracked(self) -> None:
Expand All @@ -151,15 +161,18 @@ async def _update_most_tracked(self) -> None:
}
entries = self.entered = [current[x] for x in (current.keys() - self.most_tracked.keys())]
self.most_tracked = current
self._handle_boundary(EVENT_FLIGHTRADAR24_MOST_TRACKED_NEW, entries)
self._handle_boundary(EVENT_MOST_TRACKED_NEW, entries)

async def _update_flights_data(self,
obj: Flight,
current: dict[int, dict[str, Any]],
area: dict[str, dict[str, Any]],
tracked: dict[str, dict[str, Any]],
sensor_type: SensorType | None = None,
) -> None:
if area is not None and obj.id in area and self._is_valid(area[obj.id]):
flight = area[obj.id]
altitude = None
if tracked is not None and obj.id in tracked and self._is_valid(tracked[obj.id]):
flight = tracked[obj.id]
altitude = flight.get('altitude')
else:
data = await self.hass.async_add_executor_job(
self._client.get_flight_details, obj
Expand All @@ -175,11 +188,27 @@ async def _update_flights_data(self,
flight['squawk'] = obj.squawk
flight['vertical_speed'] = obj.vertical_speed
flight['distance'] = obj.get_distance_from(self.point)
self._takeoff_and_landing(flight, altitude, obj.altitude, sensor_type)

def _handle_boundary(self, event: str, flights: list[dict[str, Any]]) -> None:
for flight in flights:
flight['tracked_by_device'] = self.config_entry.title
self.hass.bus.fire(event, flight)
self._fire_event(event, flight)

def _fire_event(self, event: str, flight: dict[str, Any]) -> None:
flight['tracked_by_device'] = self.config_entry.title
self.hass.bus.fire(event, flight)

def _takeoff_and_landing(self,
flight: dict[str, Any],
altitude_old, altitude_new,
sensor_type: SensorType | None) -> None:
if sensor_type is None or altitude_old is None:
return
if altitude_old < 10 and altitude_new >= 10:
self._fire_event(EVENT_AREA_TOOK_OFF if SensorType.IN_AREA == sensor_type else EVENT_TRACKED_TOOK_OFF,
flight)
elif altitude_old > 0 and altitude_new <= 0:
self._fire_event(EVENT_AREA_LANDED if SensorType.IN_AREA == sensor_type else EVENT_TRACKED_LANDED, flight)

@staticmethod
def _is_valid(flight: dict) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion custom_components/flightradar24/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/AlexandrErohin/home-assistant-flightradar24/issues",
"requirements": ["FlightRadarAPI==1.3.25", "pycountry==23.12.11"],
"version": "1.13.0"
"version": "1.14.0"
}

0 comments on commit eb0fe21

Please sign in to comment.