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
10 changes: 8 additions & 2 deletions custom_components/avinor_flight_data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.exceptions import HomeAssistantError

from .const import DOMAIN, PLATFORMS, UPDATE_INTERVAL_SECONDS, CONF_AIRLABS_API_KEY, SERVICE_GET_FLIGHT_DETAILS
from .const import DOMAIN, PLATFORMS, UPDATE_INTERVAL_SECONDS, CONF_AIRLABS_API_KEY, SERVICE_GET_FLIGHT_DETAILS, CONF_SCHEDULE_SOURCE, CONF_AIRLABS_FREE_TIER, AIRLABS_FREE_TIER_UPDATE_INTERVAL_SECONDS
from .coordinator import AvinorCoordinator
from .api import AvinorApiClient, AirlabsApiClient

Expand Down Expand Up @@ -131,12 +131,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: AvinorConfigEntry) -> bo
# Merge options over data so updated options take effect on reloads
conf = {**entry.data, **entry.options}

# Use hourly update interval for Airlabs free-tier (1 000 requests/month)
if conf.get(CONF_SCHEDULE_SOURCE) == "airlabs" and conf.get(CONF_AIRLABS_FREE_TIER):
interval = timedelta(seconds=AIRLABS_FREE_TIER_UPDATE_INTERVAL_SECONDS)
else:
interval = timedelta(seconds=UPDATE_INTERVAL_SECONDS)

coordinator = AvinorCoordinator(
hass,
api,
airlabs_api,
conf,
update_interval=timedelta(seconds=UPDATE_INTERVAL_SECONDS),
update_interval=interval,
)

await coordinator.async_config_entry_first_refresh()
Expand Down
8 changes: 7 additions & 1 deletion custom_components/avinor_flight_data/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
CONF_FLIGHT_TYPE,
CONF_AIRLABS_API_KEY,
CONF_SCHEDULE_SOURCE,
CONF_AIRLABS_FREE_TIER,
DEFAULT_TIME_FROM,
DEFAULT_TIME_TO,
DEFAULT_FLIGHT_TYPE,
Expand Down Expand Up @@ -65,8 +66,10 @@ async def async_step_user(self, user_input: Dict[str, Any] | None = None) -> Flo
title_suffix = "All" if flight_type == "ALL" else flight_type
if schedule_source == "airlabs":
title_suffix = f"{title_suffix} Airlabs"
direction_labels = {"A": "Arrivals", "D": "Departures"}
direction_label = direction_labels.get(user_input[CONF_DIRECTION], user_input[CONF_DIRECTION])
return self.async_create_entry(
title=f"{user_input[CONF_AIRPORT]} {user_input[CONF_DIRECTION]} {title_suffix}",
title=f"{user_input[CONF_AIRPORT]} {direction_label} {title_suffix}",
data=user_input,
)

Expand Down Expand Up @@ -105,6 +108,7 @@ async def async_step_user(self, user_input: Dict[str, Any] | None = None) -> Flo
"airlabs": "Airlabs schedules",
}),
vol.Optional(CONF_AIRLABS_API_KEY): vol.All(str, vol.Length(min=1)),
vol.Optional(CONF_AIRLABS_FREE_TIER, default=False): bool,
}
)

Expand Down Expand Up @@ -143,6 +147,7 @@ async def async_step_init(self, user_input: Dict[str, Any] | None = None) -> Flo
flight_type_default = current.get(CONF_FLIGHT_TYPE, DEFAULT_FLIGHT_TYPE)
schedule_source_default = current.get(CONF_SCHEDULE_SOURCE, DEFAULT_SCHEDULE_SOURCE)
airlabs_key_default = current.get(CONF_AIRLABS_API_KEY)
airlabs_free_tier_default = current.get(CONF_AIRLABS_FREE_TIER, False)

# Build airport field - use simple vol.In for reliability
if airports:
Expand Down Expand Up @@ -175,6 +180,7 @@ async def async_step_init(self, user_input: Dict[str, Any] | None = None) -> Flo
"airlabs": "Airlabs schedules",
}),
vol.Optional(CONF_AIRLABS_API_KEY, default=airlabs_key_default): vol.Any(None, vol.All(str, vol.Length(min=1))),
vol.Optional(CONF_AIRLABS_FREE_TIER, default=airlabs_free_tier_default): bool,
}
)
return self.async_show_form(step_id="init", data_schema=data_schema)
Expand Down
3 changes: 3 additions & 0 deletions custom_components/avinor_flight_data/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# Optional Airlabs integration (flight details)
CONF_AIRLABS_API_KEY = "airlabs_api_key"
CONF_SCHEDULE_SOURCE = "schedule_source"
CONF_AIRLABS_FREE_TIER = "airlabs_free_tier"

# Client-side filtering options
CONF_FLIGHT_TYPE = "flight_type" # Avinor dom_int field
Expand All @@ -34,3 +35,5 @@

# Update every 3 minutes as suggested by Avinor docs
UPDATE_INTERVAL_SECONDS = 180
# Hourly update interval for Airlabs free-tier API (1 000 requests/month)
AIRLABS_FREE_TIER_UPDATE_INTERVAL_SECONDS = 3600
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.1.2"
"version": "1.1.3"
}
4 changes: 3 additions & 1 deletion custom_components/avinor_flight_data/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ def __init__(self, entry: ConfigEntry, coordinator) -> None:
name_suffix = "All" if flight_type == "ALL" else flight_type
if schedule_source == "airlabs":
name_suffix = f"{name_suffix} Airlabs"
self._attr_name = f"Avinor {airport} {direction} {name_suffix}"
direction_labels = {"A": "Arrivals", "D": "Departures"}
direction_label = direction_labels.get(direction, direction)
self._attr_name = f"Avinor {airport} {direction_label} {name_suffix}"

@property
def device_info(self):
Expand Down
12 changes: 8 additions & 4 deletions custom_components/avinor_flight_data/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"time_to": "Hours Forward",
"flight_type": "Flight type",
"schedule_source": "Schedule source",
"airlabs_api_key": "Airlabs API key"
"airlabs_api_key": "Airlabs API key",
"airlabs_free_tier": "Airlabs free tier (hourly updates)"
},
"data_description": {
"airport": "Select the airport to monitor (IATA code). Search by typing the airport name or code.",
Expand All @@ -20,7 +21,8 @@
"time_to": "Include flights up to this many hours ahead (0-72 hours).",
"flight_type": "Filter by flight type. All = no filtering.",
"schedule_source": "Choose Avinor for the default feed, or Airlabs schedules when you need broader airport coverage. Airlabs requires an API key. The same key is also used when you want to click a flight for details.",
"airlabs_api_key": "Required for Airlabs schedules and for opening flight details when clicking a flight in supported cards."
"airlabs_api_key": "Required for Airlabs schedules and for opening flight details when clicking a flight in supported cards.",
"airlabs_free_tier": "Enable to limit Airlabs schedule updates to once per hour, preserving the free-tier quota of 1\u202f000 requests/month. Flight detail lookups are always on-demand and unaffected."
}
}
}
Expand All @@ -36,7 +38,8 @@
"time_to": "Hours Forward",
"flight_type": "Flight type",
"schedule_source": "Schedule source",
"airlabs_api_key": "Airlabs API key"
"airlabs_api_key": "Airlabs API key",
"airlabs_free_tier": "Airlabs free tier (hourly updates)"
},
"data_description": {
"airport": "Change the airport to monitor a different location.",
Expand All @@ -45,7 +48,8 @@
"time_to": "Adjust the time window for future flights (0-72 hours).",
"flight_type": "Filter by flight type. All = no filtering.",
"schedule_source": "Choose Avinor for the default feed, or Airlabs schedules when you need broader airport coverage. Airlabs requires an API key. The same key is also used when you want to click a flight for details.",
"airlabs_api_key": "Required for Airlabs schedules and for opening flight details when clicking a flight in supported cards."
"airlabs_api_key": "Required for Airlabs schedules and for opening flight details when clicking a flight in supported cards.",
"airlabs_free_tier": "Enable to limit Airlabs schedule updates to once per hour, preserving the free-tier quota of 1\u202f000 requests/month. Flight detail lookups are always on-demand and unaffected."
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions custom_components/avinor_flight_data/translations/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"time_to": "Timer frem",
"flight_type": "Flytype",
"schedule_source": "Datakilde",
"airlabs_api_key": "Airlabs API-nøkkel"
"airlabs_api_key": "Airlabs API-nøkkel",
"airlabs_free_tier": "Airlabs gratisplan (oppdatering per time)"
},
"data_description": {
"airport": "Velg flyplassen du vil overvåke (IATA-kode). Søk ved å skrive flyplassnavn eller kode.",
Expand All @@ -20,7 +21,8 @@
"time_to": "Inkluder fly opptil dette antall timer frem (0-72 timer).",
"flight_type": "Filtrer på flytype. Alle = ingen filtrering.",
"schedule_source": "Velg Avinor for standardstrømmen, eller Airlabs schedules når du trenger bredere flyplassdekning. Airlabs krever API-nøkkel. Den samme nøkkelen brukes også hvis du vil kunne klikke på et fly for detaljer.",
"airlabs_api_key": "Påkrevd for Airlabs schedules og for å åpne flydetaljer når du klikker på et fly i kort som støtter dette."
"airlabs_api_key": "Påkrevd for Airlabs schedules og for å åpne flydetaljer når du klikker på et fly i kort som støtter dette.",
"airlabs_free_tier": "Aktiver for å begrense Airlabs-oppdateringer til én gang per time og bevare gratisplanens kvote på 1\u202f000 forespørsler/måned. Oppslag av flydetaljer skjer alltid på forespørsel og påvirkes ikke."
}
}
}
Expand All @@ -36,7 +38,8 @@
"time_to": "Timer frem",
"flight_type": "Flytype",
"schedule_source": "Datakilde",
"airlabs_api_key": "Airlabs API-nøkkel"
"airlabs_api_key": "Airlabs API-nøkkel",
"airlabs_free_tier": "Airlabs gratisplan (oppdatering per time)"
},
"data_description": {
"airport": "Bytt flyplass for å overvåke en annen lokasjon.",
Expand All @@ -45,7 +48,8 @@
"time_to": "Juster tidsvinduet for fremtidige fly (0-72 timer).",
"flight_type": "Filtrer på flytype. Alle = ingen filtrering.",
"schedule_source": "Velg Avinor for standardstrømmen, eller Airlabs schedules når du trenger bredere flyplassdekning. Airlabs krever API-nøkkel. Den samme nøkkelen brukes også hvis du vil kunne klikke på et fly for detaljer.",
"airlabs_api_key": "Påkrevd for Airlabs schedules og for å åpne flydetaljer når du klikker på et fly i kort som støtter dette."
"airlabs_api_key": "Påkrevd for Airlabs schedules og for å åpne flydetaljer når du klikker på et fly i kort som støtter dette.",
"airlabs_free_tier": "Aktiver for å begrense Airlabs-oppdateringer til én gang per time og bevare gratisplanens kvote på 1\u202f000 forespørsler/måned. Oppslag av flydetaljer skjer alltid på forespørsel og påvirkes ikke."
}
}
}
Expand Down
Loading