Skip to content

Commit b8b79a6

Browse files
author
marq24
committed
implemented 'nextScheduledDepartureTime' as requested #158
1 parent 06ea729 commit b8b79a6

2 files changed

Lines changed: 66 additions & 4 deletions

File tree

custom_components/fordpass/const.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@ class HONK_AND_FLASH(Enum):
271271
XEVBATTERYCHARGEDISPLAY_STATE_STOPPED, XEVBATTERYCHARGEDISPLAY_STATE_FAULT,
272272
XEVBATTERYCHARGEDISPLAY_STATION_NOT_DETECTED]
273273

274+
DAYS_MAP = {
275+
"MONDAY": 0,
276+
"TUESDAY": 1,
277+
"WEDNESDAY":2,
278+
"THURSDAY": 3,
279+
"FRIDAY": 4,
280+
"SATURDAY": 5,
281+
"SUNDAY": 6,
282+
}
283+
274284
TRANSLATIONS: Final = {
275285
"de":{
276286
"account": "Konto",

custom_components/fordpass/fordpass_handler.py

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
import logging
3-
from datetime import timedelta
3+
from datetime import timedelta, datetime
44
from numbers import Number
55
from re import sub
66
from typing import Final, Iterable
@@ -20,7 +20,7 @@
2020
XEVPLUGCHARGER_STATE_DISCONNECTED, XEVPLUGCHARGER_STATE_CONNECTED,
2121
XEVBATTERYCHARGEDISPLAY_STATE_IN_PROGRESS,
2222
VEHICLE_LOCK_STATE_LOCKED, VEHICLE_LOCK_STATE_PARTLY, VEHICLE_LOCK_STATE_UNLOCKED,
23-
REMOTE_START_STATE_ACTIVE, REMOTE_START_STATE_INACTIVE, HONK_AND_FLASH
23+
REMOTE_START_STATE_ACTIVE, REMOTE_START_STATE_INACTIVE, HONK_AND_FLASH, DAYS_MAP
2424
)
2525

2626
_LOGGER = logging.getLogger(__name__)
@@ -37,6 +37,7 @@
3737
ROOT_UPDTIME: Final = "updateTime"
3838

3939
UNSUPPORTED: Final = str("Unsupported")
40+
UNDEFINED: Final = str("Undefined")
4041

4142
class FordpassDataHandler:
4243
# Helper functions to simplify the callable implementations
@@ -543,6 +544,9 @@ def get_elveh_attrs(data, units:UnitSystem):
543544
else:
544545
attrs["motorkW"] = 0
545546

547+
xev_next_departure_time_schedule_id = None
548+
xev_next_departure_time_location_id = None
549+
546550
if "customMetrics" in data_metrics:
547551
for key in data_metrics.get("customMetrics", {}):
548552
if "accumulated-vehicle-speed-cruising-coaching-score" in key:
@@ -562,8 +566,56 @@ def get_elveh_attrs(data, units:UnitSystem):
562566
attrs["remoteDataResponseStatus"] = data_metrics.get("customMetrics", {}).get(key, {}).get("value")
563567

564568
if ":custom:xev-" in key:
565-
entryName = FordpassDataHandler.to_camel(key.split(":custom:xev-")[1])
566-
attrs[entryName] = data_metrics.get("customMetrics", {}).get(key, {}).get("value")
569+
if "next-departure-time-schedule-id" in key:
570+
xev_next_departure_time_schedule_id = data_metrics.get("customMetrics", {}).get(key, {}).get("value")
571+
elif "next-departure-time-location-id" in key:
572+
xev_next_departure_time_location_id = data_metrics.get("customMetrics", {}).get(key, {}).get("value")
573+
else:
574+
entryName = FordpassDataHandler.to_camel(key.split(":custom:xev-")[1])
575+
attrs[entryName] = data_metrics.get("customMetrics", {}).get(key, {}).get("value")
576+
577+
if xev_next_departure_time_schedule_id is not None: #and xev_next_departure_time_location_id is not None:
578+
# IF there is a 'schedule_id' defined, then we set the attribute, in order to make the processing
579+
# of this data a bit easier - since you must not check for existence of both id's all the time
580+
attrs["nextScheduledDepartureTime"] = UNDEFINED
581+
xev_departure_locations = data_metrics.get("configurations", {}).get("xevDepartureSchedulesSetting",{}).get("value", {}).get("departureLocations", {})
582+
for a_depart_location in xev_departure_locations:
583+
if "departureSchedules" in a_depart_location and (
584+
len(xev_departure_locations) == 1 or
585+
a_depart_location.get("locationId", None) == xev_next_departure_time_location_id
586+
) :
587+
for a_schedule in a_depart_location["departureSchedules"]:
588+
if str(a_schedule.get("scheduleId", None)) == str(xev_next_departure_time_schedule_id):
589+
if a_schedule.get("scheduleStatus", "OFF").upper() == "ON":
590+
a_schedule_obj = a_schedule.get("schedule", {})
591+
if len(a_schedule_obj) > 0:
592+
_LOGGER.debug(f"{a_schedule_obj}")
593+
time_obj = a_schedule_obj.get("weeklySchedule", {})
594+
day_of_week = time_obj.get("dayOfWeek", UNSUPPORTED).upper()
595+
time_of_day = time_obj.get("timeOfDay", UNSUPPORTED)
596+
tz = a_schedule_obj.get("timeZone", UNSUPPORTED)
597+
598+
if "LOCAL_TIME" == tz:
599+
if day_of_week in DAYS_MAP and time_of_day != UNSUPPORTED:
600+
# Get the current date and time in local timezone
601+
now = datetime.now()
602+
603+
# Get the weekday number for the specified day
604+
target_weekday = DAYS_MAP[day_of_week]
605+
target_time = datetime.strptime(time_of_day, "%H:%M").time()
606+
607+
# Calculate days until the next target day
608+
days_until = (target_weekday - now.weekday() + 7) % 7
609+
if days_until == 0 and now.time() >= target_time:
610+
days_until = 7 # If today is Friday but the time is past, go to next week
611+
612+
# Calculate the next date
613+
next_date = now + timedelta(days=days_until)
614+
615+
# Set the target time
616+
attrs["nextScheduledDepartureTime"] = next_date.replace(hour=target_time.hour, minute=target_time.minute, second=0, microsecond=0)
617+
618+
break
567619

568620
data_events = FordpassDataHandler.get_events(data)
569621
if "customEvents" in data_events:

0 commit comments

Comments
 (0)