Skip to content

Commit

Permalink
Upcoming flights sensor
Browse files Browse the repository at this point in the history
Added sensor to profile device to show number of upcoming flights.

Moved header info for boarding pass request to json file so it doesn't have to rely on other coordinators.

Added support for connecting flights by iterating segments instead of journey. This will bring in any connecting flights.

Each journey will produce a device with entities for boarding passes and flight info.
  • Loading branch information
jampez77 committed Sep 26, 2023
1 parent 4f23ccf commit e0afe88
Show file tree
Hide file tree
Showing 9 changed files with 383 additions and 273 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ This component will allow you to bring your upcoming Ryanair flight information
* Check in open / close time.
* Arrival / departure time.
* Passengers name and seat number.
* Mobile frienldy boarding passes.
* number of upcoming flights.
* flight cancellation status.

This project is very much a work in progress and there are still many issue that need addressing. If you have the skills, time and implication then please feel free to contribute.

Expand Down
6 changes: 1 addition & 5 deletions custom_components/ryanair/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ async def options_update_listener(hass: HomeAssistant, config_entry: ConfigEntry

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[hass.config_entries.async_forward_entry_unload(entry, "sensor")]
)
)
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
# Remove options_update_listener.
hass.data[DOMAIN][entry.entry_id]["unsub_options_update_listener"]()

Expand Down
8 changes: 5 additions & 3 deletions custom_components/ryanair/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@
MFA_CODE,
CODE_MFA_CODE_WRONG,
PERSISTENCE,
LOCAL_FOLDER
)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .coordinator import RyanairCoordinator, RyanairMfaCoordinator
from .errors import CannotConnect, RyanairError

_LOGGER = logging.getLogger(__name__)
CREDENTIALS = LOCAL_FOLDER + PERSISTENCE

STEP_USER_DATA_SCHEMA = vol.Schema(
{
Expand Down Expand Up @@ -152,7 +154,7 @@ async def async_step_mfa(
CUSTOMER_ID: info["data"][CUSTOMER_ID],
TOKEN: info["data"][TOKEN],
}
save_json(self.hass.config.path(PERSISTENCE), ryanairData)
save_json(CREDENTIALS, ryanairData)
return self.async_create_entry(
title=info["title"], data=ryanairData
)
Expand Down Expand Up @@ -215,8 +217,8 @@ async def async_step_user(
CUSTOMER_ID: info["data"][CUSTOMER_ID],
TOKEN: info["data"][TOKEN],
}
save_json(self.hass.config.path(
PERSISTENCE), ryanairData)

save_json(CREDENTIALS, ryanairData)
return self.async_create_entry(
title=info["title"], data=ryanairData
)
Expand Down
4 changes: 4 additions & 0 deletions custom_components/ryanair/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
CODE_UNKNOWN_DEVICE = "Account.UnknownDeviceFingerprint"
CODE_MFA_TOKEN = "Mfa.Token"
PERSISTENCE = ".ryanair.json"
BOARDING_PASS_HEADERS = ".boarding_pass.json"
LOCAL_FOLDER = "homeassistant/components/ryanair/"
BOARDING_PASSES_URI = "boardingpasses/"
BOOKING_REFERENCES = "bookingreferences"
X_REMEMBER_ME_TOKEN = "X-REMEMBERME-TOKEN"
ACCESS_DENIED = "access-denied"
CAUSE = "cause"
Expand Down
46 changes: 32 additions & 14 deletions custom_components/ryanair/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,23 @@
TYPE,
BOARDING_PASS_URL,
EMAIL,
RECORD_LOCATOR
RECORD_LOCATOR,
LOCAL_FOLDER,
BOARDING_PASSES_URI,
BOARDING_PASS_HEADERS
)
from .errors import RyanairError, InvalidAuth, APIRatelimitExceeded, UnknownError
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.util.json import JsonArrayType, load_json_object
from homeassistant.util.json import load_json_object
from homeassistant.helpers.json import save_json

_LOGGER = logging.getLogger(__name__)

USER_PROFILE_URL = HOST + USER_PROFILE + V
ORDERS_URL = HOST + ORDERS + V

CREDENTIALS = LOCAL_FOLDER + PERSISTENCE


async def rememberMeToken(self, data):
rememberMeTokenResp = await self.session.request(
Expand Down Expand Up @@ -98,7 +103,7 @@ async def refreshToken(self, data):
X_REMEMBER_ME_TOKEN: rememberMeTokenResp[TOKEN]
}

save_json(self.hass.config.path(PERSISTENCE), ryanairData)
save_json(CREDENTIALS, ryanairData)
return ryanairData


Expand Down Expand Up @@ -148,7 +153,7 @@ async def getBoardingPasses(self, data, headers):
}
)
body = await resp.json()

print("getBoardingPasses")
return body


Expand All @@ -164,7 +169,7 @@ def __init__(self, hass: HomeAssistant, session, data) -> None:
# Name of the data. For logging purposes.
name="Ryanair",
# Polling interval. Will only be polled if there are subscribers.
update_interval=timedelta(seconds=300),
update_interval=timedelta(seconds=30),
)
self.email = data[EMAIL]
self.record_locator = data[RECORD_LOCATOR]
Expand All @@ -173,7 +178,7 @@ def __init__(self, hass: HomeAssistant, session, data) -> None:
async def _async_update_data(self):
"""Fetch data from API endpoint."""
try:
data = load_json_object(self.hass.config.path(PERSISTENCE))
data = load_json_object(CREDENTIALS)

if X_REMEMBER_ME_TOKEN not in data:
rememberMeTokenResp = await rememberMeToken(self, data)
Expand All @@ -184,7 +189,7 @@ async def _async_update_data(self):
TOKEN: data[TOKEN],
X_REMEMBER_ME_TOKEN: rememberMeTokenResp[TOKEN]
}
save_json(self.hass.config.path(PERSISTENCE), data)
save_json(CREDENTIALS, data)

headers = {
EMAIL: self.email,
Expand All @@ -207,11 +212,24 @@ async def _async_update_data(self):

for boardingPass in body:
aztec_code = AztecCode(boardingPass['barcode'])
fileName = re.sub(
"[\W_]", "", boardingPass['barcode']) + ".png"

flightName = "(" + boardingPass["flight"]["label"] + ") " + \
boardingPass["departure"]["name"] + \
" - " + boardingPass["arrival"]["name"]

seat = boardingPass["seat"]["designator"]

passenger = boardingPass["name"]["first"] + \
" " + boardingPass["name"]["last"]

name = passenger + ": " + \
flightName + "(" + seat + ")"

fileName = re.sub(
"[\W_]", "", name + boardingPass["departure"]["dateUTC"]) + ".png"
print("Saving Aztec")
aztec_code.save(
"homeassistant/components/ryanair/" + fileName, module_size=16)
LOCAL_FOLDER + BOARDING_PASSES_URI + fileName, module_size=16)

except InvalidAuth as err:
raise ConfigEntryAuthFailed from err
Expand Down Expand Up @@ -251,7 +269,7 @@ def __init__(self, hass: HomeAssistant, session, data) -> None:
async def _async_update_data(self):
"""Fetch data from API endpoint."""
try:
data = load_json_object(self.hass.config.path(PERSISTENCE))
data = load_json_object(CREDENTIALS)

if X_REMEMBER_ME_TOKEN not in data:
rememberMeTokenResp = await rememberMeToken(self, data)
Expand All @@ -262,7 +280,7 @@ async def _async_update_data(self):
TOKEN: data[TOKEN],
X_REMEMBER_ME_TOKEN: rememberMeTokenResp[TOKEN]
}
save_json(self.hass.config.path(PERSISTENCE), data)
save_json(CREDENTIALS, data)

body = await getFlights(self, data)

Expand Down Expand Up @@ -311,7 +329,7 @@ def __init__(self, hass: HomeAssistant, session, data) -> None:
async def _async_update_data(self):
"""Fetch data from API endpoint."""
try:
data = load_json_object(self.hass.config.path(PERSISTENCE))
data = load_json_object(CREDENTIALS)

if X_REMEMBER_ME_TOKEN not in data:
rememberMeTokenResp = await rememberMeToken(self, data)
Expand All @@ -322,7 +340,7 @@ async def _async_update_data(self):
TOKEN: data[TOKEN],
X_REMEMBER_ME_TOKEN: rememberMeTokenResp[TOKEN]
}
save_json(self.hass.config.path(PERSISTENCE), data)
save_json(CREDENTIALS, data)

body = await getUserProfile(self, data)

Expand Down
Loading

0 comments on commit e0afe88

Please sign in to comment.