Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![HACS Custom](https://img.shields.io/badge/HACS-Custom-blue.svg)](https://hacs.xyz/)
[![Hassfest](https://github.com/WickedGhost/avinor_flight_data/actions/workflows/hassfest.yml/badge.svg)](https://github.com/WickedGhost/avinor_flight_data/actions/workflows/hassfest.yml)
[![HACS Validation](https://github.com/WickedGhost/avinor_flight_data/actions/workflows/hacs.yml/badge.svg)](https://github.com/WickedGhost/avinor_flight_data/actions/workflows/hacs.yml)
[![Version 1.0.8](https://img.shields.io/badge/Version-1.0.8-orange.svg)](custom_components/avinor_flight_data/manifest.json)
[![Version 1.0.9](https://img.shields.io/badge/Version-1.0.9-orange.svg)](custom_components/avinor_flight_data/manifest.json)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

Custom Home Assistant integration that keeps your dashboards up to date with arrivals and departures from the official Avinor data feed.
Expand All @@ -16,6 +16,7 @@ Custom Home Assistant integration that keeps your dashboards up to date with arr
- [Features](#features)
- [Installation](#installation)
- [Configuration](#configuration)
- [Known Limitations](#known-limitations)
- [Flight Details (Airlabs)](#flight-details-airlabs)
- [Companion Lovelace Card](#companion-lovelace-card)
- [Example Dashboard Card](#example-dashboard-card)
Expand Down Expand Up @@ -68,6 +69,12 @@ Custom Home Assistant integration that keeps your dashboards up to date with arr

Each configured sensor reports the flight count as its state and exposes detailed flight data through the `flights` attribute.

## Known Limitations

- This integration mirrors the public Avinor flight feed and does not supplement missing airport data from other sources.
- Avinor documents that the service does not include data from private airports such as Sandefjord Airport, Torp (TRF).
- Private airports may therefore show incomplete, delayed, or missing arrivals and departures even when the integration is working correctly.

## Flight Details (Airlabs)

This integration can optionally fetch details for a specific flight from the Airlabs Flight API:
Expand Down Expand Up @@ -145,6 +152,8 @@ title: Ankomster OSL

## Release Notes

- **1.0.9**
- Documented the upstream Avinor limitation for private airports such as TRF/Torp.
- **0.2.1**
- Split the Lovelace card into its own repository.
- Updated HACS/Hassfest workflows to meet current validation requirements.
Expand Down
2 changes: 1 addition & 1 deletion custom_components/avinor_flight_data/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"issue_tracker": "https://github.com/WickedGhost/avinor_flight_data/issues",
"loggers": ["custom_components.avinor_flight_data"],
"requirements": ["xmltodict==0.13.0"],
"version": "1.0.8"
"version": "1.0.9"
}
48 changes: 47 additions & 1 deletion tests/test_api_parsing.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import asyncio
from types import SimpleNamespace
import pytest

from custom_components.avinor_flight_data.api import AvinorApiClient
from custom_components.avinor_flight_data.api import AirlabsApiClient
from custom_components.avinor_flight_data.sensor import _apply_flight_type_filter, _compact_flight
from custom_components.avinor_flight_data.sensor import (
AvinorFlightsSensor,
_apply_flight_type_filter,
_compact_flight,
)


class StubClient(AvinorApiClient):
Expand Down Expand Up @@ -108,6 +113,47 @@ def test_apply_flight_type_filter():
assert [f["flightId"] for f in _apply_flight_type_filter(flights, "s")] == ["SK3"]


def test_sensor_entity_applies_flight_type_per_entry():
flights = [
{"flightId": "SK1", "dom_int": "D"},
{"flightId": "SK2", "dom_int": "I"},
{"flightId": "SK3", "dom_int": "S"},
]
coordinator = SimpleNamespace(data={"lastUpdate": "2025-01-01T12:00:00Z", "flights": flights})

domestic_sensor = object.__new__(AvinorFlightsSensor)
domestic_sensor.coordinator = coordinator
domestic_sensor._entry = SimpleNamespace(
data={
"airport": "OSL",
"direction": "A",
"flight_type": "D",
"time_from": 1,
"time_to": 7,
},
options={},
)

all_types_sensor = object.__new__(AvinorFlightsSensor)
all_types_sensor.coordinator = coordinator
all_types_sensor._entry = SimpleNamespace(
data={
"airport": "TRF",
"direction": "A",
"flight_type": "",
"time_from": 1,
"time_to": 7,
},
options={},
)

assert domestic_sensor.native_value == 1
assert [f["flightId"] for f in domestic_sensor.extra_state_attributes["flights"]] == ["SK1"]

assert all_types_sensor.native_value == 3
assert [f["flightId"] for f in all_types_sensor.extra_state_attributes["flights"]] == ["SK1", "SK2", "SK3"]


def test_compact_flight_contains_expected_keys():
flight = {
"flightId": "DY123",
Expand Down
Loading