Skip to content

Commit

Permalink
Stop --> Destination (#12)
Browse files Browse the repository at this point in the history
* added destination filter for a stop

* updated instructions for destination
  • Loading branch information
anand-p-r committed Feb 7, 2021
1 parent 75fc68a commit cab51f3
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 48 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
3. If the files are placed correctly, it should have the hierarchy as: <HA configuration directory>/custom_components/hslhrt
5. Restart Home Assistant
6. Install integration from UI (Configuration --> Intergations --> + --> Search for "hsl")
7. Specify stop name (e.g. töölöntori) or stop code (e.g. H0209) and optionally the route number (e.g. 8)
7. Specify stop name (e.g. töölöntori) or stop code (e.g. H0209). Optionally the route number (e.g. 8) or the destination can be specified as well.
1. Route takes precedence over destination, if specified. Both options are case in-sensitive.
2. In case, route and destination are not needed, leave the default values as "ALL" or "all".

<br/>

Expand Down
63 changes: 43 additions & 20 deletions custom_components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@
from python_graphql_client import GraphqlClient

from .const import (
BASE_URL,
BASE_URL, DESTINATION,
DOMAIN,
STOP_NAME,
STOP_GTFS,
STOP_CODE,
ROUTE,
DESTINATION,
ROUTE_QUERY_WITH_LIMIT,
MIN_TIME_BETWEEN_UPDATES,
COORDINATOR,
Expand All @@ -40,12 +41,14 @@
graph_client = GraphqlClient(endpoint=BASE_URL)


def base_unique_id(gtfs_id, route=None):
def base_unique_id(gtfs_id, route=None, dest=None):
"""Return unique id for entries in configuration."""
if route is None or route.lower() == ALL:
return f"{gtfs_id} all"
if (route is not None) and (route.lower() != ALL):
return f"{gtfs_id} {route.upper()}"
elif (dest is not None) and (dest.lower() != ALL):
return f"{gtfs_id} {dest.upper()}"
else:
return f"{gtfs_id} {route}"
return f"{gtfs_id} ALL"


async def async_setup(hass: HomeAssistant, config: Config) -> bool:
Expand Down Expand Up @@ -104,11 +107,18 @@ class HSLHRTDataUpdateCoordinator(DataUpdateCoordinator):
def __init__(self, hass, session, config_entry):
"""Initialize."""

_LOGGER.debug("Using Name/Code: %s and route: %s",
config_entry.data[STOP_NAME], config_entry.data[ROUTE])
##if config_entry.data.get(STOP_NAME, "None") is not None:
_LOGGER.debug("Using Name/Code: %s", config_entry.data.get(STOP_NAME, "None"))

##if config_entry.data.get(ROUTE, "None") is not None:
_LOGGER.debug("Using Route: %s", config_entry.data.get(ROUTE, "None"))

##if config_entry.data.get(DESTINATION, "None") is not None:
_LOGGER.debug("Using Destination: %s", config_entry.data.get(DESTINATION, "None"))

self.gtfs_id = config_entry.data.get(STOP_GTFS, "")
self.route = config_entry.data.get(ROUTE, "")
self.dest = config_entry.data.get(DESTINATION, "")

self.route_data = None
self._hass = hass
Expand All @@ -123,7 +133,7 @@ def __init__(self, hass, session, config_entry):
async def _async_update_data(self):
"""Update data via HSl HRT Open API."""

def parse_data(data, line_from_user = ""):
def parse_data(data=None, line_from_user=None, dest_from_user=None):

parsed_data = {}
bus_lines = {}
Expand Down Expand Up @@ -189,17 +199,30 @@ def parse_data(data, line_from_user = ""):
return

time_line_parsed_data = []
if line_from_user.lower() != ALL.lower():
if line_from_user.lower() != "":
routes = parsed_data.get(DICT_KEY_ROUTES, None)
if routes is not None:
for rt in routes:
line_in_data = rt.get(DICT_KEY_ROUTE, None)
if line_in_data is not None:
if line_from_user.lower() == line_in_data.lower():
time_line_parsed_data.append(rt)

parsed_data[DICT_KEY_ROUTES] = time_line_parsed_data
if line_from_user is not None:
if line_from_user.lower() != ALL.lower():
if line_from_user.lower() != "":
routes = parsed_data.get(DICT_KEY_ROUTES, None)
if routes is not None:
for rt in routes:
line_in_data = rt.get(DICT_KEY_ROUTE, None)
if line_in_data is not None:
if line_from_user.lower() == line_in_data.lower():
time_line_parsed_data.append(rt)

parsed_data[DICT_KEY_ROUTES] = time_line_parsed_data
elif dest_from_user is not None:
if dest_from_user.lower() != ALL.lower():
if dest_from_user.lower() != "":
routes = parsed_data.get(DICT_KEY_ROUTES, None)
if routes is not None:
for rt in routes:
dest_in_data = rt.get(DICT_KEY_DEST, None)
if dest_in_data is not None:
if dest_from_user.lower() in dest_in_data.lower():
time_line_parsed_data.append(rt)

parsed_data[DICT_KEY_ROUTES] = time_line_parsed_data
else:
routes = parsed_data.get(DICT_KEY_ROUTES, None)
if routes is not None:
Expand Down Expand Up @@ -229,7 +252,7 @@ def parse_data(data, line_from_user = ""):
graph_client.execute, ROUTE_QUERY_WITH_LIMIT, variables
)

self.route_data = parse_data(data, self.route)
self.route_data = parse_data(data=data, line_from_user=self.route, dest_from_user=self.dest)
_LOGGER.debug(f"DATA: {self.route_data}")

except Exception as error:
Expand Down
65 changes: 47 additions & 18 deletions custom_components/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
ERROR,
ALL,
VAR_NAME_CODE,
ROUTE
ROUTE,
DESTINATION,
ROUTE_DEST
)


Expand All @@ -30,12 +32,14 @@ async def validate_user_config(hass: core.HomeAssistant, data):
"""
name_code = data[NAME_CODE]
route = data[ROUTE]
dest = data[DESTINATION]

errors = ""
stop_code = None
stop_name = None
stop_gtfs = None
ret_route = None
ret_dest = None

# Check if there is a valid stop for the given name/code
try:
Expand All @@ -51,7 +55,8 @@ async def validate_user_config(hass: core.HomeAssistant, data):
STOP_CODE: None,
STOP_NAME: None,
STOP_GTFS: None,
ROUTE: None,
ROUTE: None,
DESTINATION: None,
ERROR: errors
}

Expand All @@ -66,21 +71,40 @@ async def validate_user_config(hass: core.HomeAssistant, data):
stop_name = stop_data.get("name", "")
stop_code = stop_data.get("code", "")
if stop_name != "" and stop_gtfs != "":
stop = stop_name
gtfs = stop_gtfs
if route.lower() != ALL:
## Specific route should be checked
## Ignore destination filter
if (route.lower() != ALL) or (dest.lower() != ALL):
routes = stop_data.get("routes", None)
if routes is not None:
for rt in routes:
rt_name = rt.get("shortName", "")
if rt_name != "":
if rt_name.lower() == route.lower():
ret_route = route
if route.lower() != ALL:
rt_name = rt.get("shortName", "")
if rt_name != "":
if rt_name.lower() == route.lower():
ret_route = route
break
else:
patterns = rt.get("patterns", None)
if patterns is not None:
break_loop = False
for pattern in patterns:
head_sign = pattern.get("headsign", "")
if head_sign != "":
if dest.lower() in head_sign.lower():
ret_dest = head_sign
break_loop = True
break

if break_loop:
break
else:
ret_route = route

if ret_route is None:
if (route.lower() != ALL) and (ret_route == None):
errors = "invalid_route"
else:
if (dest.lower() != ALL) and (ret_dest == None):
errors = "invalid_destination"
else:
_LOGGER.error("Name or gtfs is blank")
errors = "invalid_name_code"
Expand All @@ -99,8 +123,9 @@ async def validate_user_config(hass: core.HomeAssistant, data):
STOP_NAME: stop_name,
STOP_GTFS: stop_gtfs,
ROUTE: ret_route,
DESTINATION: ret_dest,
ERROR: errors
}
}


class HSLHRTConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
Expand All @@ -118,26 +143,30 @@ async def async_step_user(self, user_input=None):
if user_input is not None:

valid = await validate_user_config(self.hass, user_input)

await self.async_set_unique_id(
base_unique_id(valid[STOP_GTFS], valid[ROUTE])
base_unique_id(valid[STOP_GTFS], valid[ROUTE], valid[DESTINATION])
)
self._abort_if_unique_id_configured()

if valid.get(ERROR, "") == "":
title = f"{valid[STOP_NAME]}({valid[STOP_CODE]}) {valid[ROUTE]}"

title = ""
if valid[ROUTE] is not None:
title = f"{valid[STOP_NAME]}({valid[STOP_CODE]}) {valid[ROUTE]}"
elif valid[DESTINATION] is not None:
title = f"{valid[STOP_NAME]}({valid[STOP_CODE]}) {valid[DESTINATION]}"
else:
title = f"{valid[STOP_NAME]}({valid[STOP_CODE]}) ALL"
return self.async_create_entry(title=title, data=valid)
else:
reason = valid.get(ERROR, "Configuration Error!")
_LOGGER.error(reason)
return self.async_abort(reason=reason)

errors[DOMAIN] = valid[ERROR]

data_schema = vol.Schema(
{
vol.Required(NAME_CODE, default=""): str,
vol.Optional(ROUTE, default="ALL"): str
vol.Required(ROUTE, default="ALL"): str,
vol.Required(DESTINATION, default="ALL"): str
}
)

Expand Down
5 changes: 5 additions & 0 deletions custom_components/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
STOP_NAME = "stop_name"
STOP_GTFS = "stop_gtfs"
ROUTE = "route"
ROUTE_DEST = "route_destination"
DESTINATION = "destination"
ALL = "all"
ERROR = "err"

Expand Down Expand Up @@ -55,6 +57,9 @@
code
routes {
shortName
patterns {
headsign
}
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion custom_components/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,14 @@ def name(self):
"""Return the name of the sensor."""
if self.coordinator is not None:
if self.coordinator.route_data is not None:
return f"{self.coordinator.route_data['stop_name']}({self.coordinator.route_data['stop_code']}) {self.coordinator.route}"
ext = ""
if (self.coordinator.route is not None) and (self.coordinator.route != ALL):
ext = self.coordinator.route.upper()
elif (self.coordinator.dest is not None) and (self.coordinator.dest != ALL):
ext = self.coordinator.dest.upper()
else:
ext = ALL
return f"{self.coordinator.route_data[STOP_NAME]}({self.coordinator.route_data[STOP_CODE]}) {ext}"

return self._name

Expand Down
9 changes: 5 additions & 4 deletions custom_components/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"description": "HSL-HRT Configuration Parameters",
"title": "Helsinki Regional Transport",
"data": {
"name": "[%key:common::config_flow::data::name%]",
"namecode": "STOP Name / Code",
"route": "Route"
"user_name_code": "STOP Name / Code",
"route": "Route",
"destination": "Destination"
}
}
},
Expand All @@ -18,7 +18,8 @@
"abort": {
"already_configured": "Already configured stop/route",
"invalid_name_code": "Stop Name or Stop Code is invalid!",
"invalid_route": "Route is invalid!"
"invalid_route": "Route is invalid!",
"invalid_destination": "Destination is invalid!"
}
}
}
9 changes: 5 additions & 4 deletions custom_components/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"description": "HSL-HRT Configuration Parameters",
"title": "Helsinki Regional Transport",
"data": {
"name": "[%key:common::config_flow::data::name%]",
"namecode": "STOP Name / Code",
"route": "Route"
"user_name_code": "STOP Name / Code",
"route": "Route",
"destination": "Destination"
}
}
},
Expand All @@ -18,7 +18,8 @@
"abort": {
"already_configured": "Already configured stop/route",
"invalid_name_code": "Stop Name or Stop Code is invalid!",
"invalid_route": "Route is invalid!"
"invalid_route": "Route is invalid!",
"invalid_destination": "Destination is invalid!"
}
}
}

0 comments on commit cab51f3

Please sign in to comment.