From a12304664f002b0907e789f512fb52c19b4b296d Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Sep 2022 13:00:57 -0700 Subject: [PATCH 1/8] feat: convert team colors to RGB color lists --- custom_components/nfl/sensor.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/custom_components/nfl/sensor.py b/custom_components/nfl/sensor.py index 8b22f17..34cc72a 100644 --- a/custom_components/nfl/sensor.py +++ b/custom_components/nfl/sensor.py @@ -164,7 +164,7 @@ def extra_state_attributes(self): attrs["team_record"] = self.coordinator.data["team_record"] attrs["team_homeaway"] = self.coordinator.data["team_homeaway"] attrs["team_logo"] = self.coordinator.data["team_logo"] - attrs["team_colors"] = self.coordinator.data["team_colors"] + attrs["team_colors"] = self.team_colors(self.coordinator.data["team_colors"]) attrs["team_score"] = self.coordinator.data["team_score"] attrs["team_win_probability"] = self.coordinator.data["team_win_probability"] attrs["team_timeouts"] = self.coordinator.data["team_timeouts"] @@ -174,7 +174,7 @@ def extra_state_attributes(self): attrs["opponent_record"] = self.coordinator.data["opponent_record"] attrs["opponent_homeaway"] = self.coordinator.data["opponent_homeaway"] attrs["opponent_logo"] = self.coordinator.data["opponent_logo"] - attrs["opponent_colors"] = self.coordinator.data["opponent_colors"] + attrs["opponent_colors"] = self.team_colors(self.coordinator.data["opponent_colors"]) attrs["opponent_score"] = self.coordinator.data["opponent_score"] attrs["opponent_win_probability"] = self.coordinator.data["opponent_win_probability"] attrs["opponent_timeouts"] = self.coordinator.data["opponent_timeouts"] @@ -186,3 +186,14 @@ def extra_state_attributes(self): def available(self) -> bool: """Return if entity is available.""" return self.coordinator.last_update_success + + def team_colors(self, colors) -> tuple: + colors = []] + color_list = colors.split(",") + colors.append(self.hex_to_rgb(color_list[0])) + colors.append(self.hex_to_rgb(color_list[1])) + return tuple(colors) + + def hex_to_rgb(hexa): + hexa = hexa.lstrip("#") + return list(int(hexa[i:i+2], 16) for i in (0, 2, 4)) \ No newline at end of file From 6f0802c4551fb9120cd056f1e431a52fea525a59 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Sep 2022 13:02:11 -0700 Subject: [PATCH 2/8] linting --- custom_components/nfl/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/nfl/sensor.py b/custom_components/nfl/sensor.py index 34cc72a..b502ec3 100644 --- a/custom_components/nfl/sensor.py +++ b/custom_components/nfl/sensor.py @@ -188,7 +188,7 @@ def available(self) -> bool: return self.coordinator.last_update_success def team_colors(self, colors) -> tuple: - colors = []] + colors = [] color_list = colors.split(",") colors.append(self.hex_to_rgb(color_list[0])) colors.append(self.hex_to_rgb(color_list[1])) From 4086a212be21b41dbc6584435606ea3e2c0a5706 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Sep 2022 14:58:55 -0700 Subject: [PATCH 3/8] colors is a list --- custom_components/nfl/sensor.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/custom_components/nfl/sensor.py b/custom_components/nfl/sensor.py index b502ec3..7d2912d 100644 --- a/custom_components/nfl/sensor.py +++ b/custom_components/nfl/sensor.py @@ -187,12 +187,10 @@ def available(self) -> bool: """Return if entity is available.""" return self.coordinator.last_update_success - def team_colors(self, colors) -> tuple: - colors = [] - color_list = colors.split(",") - colors.append(self.hex_to_rgb(color_list[0])) - colors.append(self.hex_to_rgb(color_list[1])) - return tuple(colors) + def team_colors(self, colors) -> list: + colors[0] = self.hex_to_rgb(colors[0]) + colors[1] = self.hex_to_rgb(colors[1]) + return colors def hex_to_rgb(hexa): hexa = hexa.lstrip("#") From 805634a045ddaa51fb136ed04f1002552724ad79 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Sep 2022 15:14:30 -0700 Subject: [PATCH 4/8] fix colors being none --- custom_components/nfl/sensor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/custom_components/nfl/sensor.py b/custom_components/nfl/sensor.py index 7d2912d..cdb5ba2 100644 --- a/custom_components/nfl/sensor.py +++ b/custom_components/nfl/sensor.py @@ -188,6 +188,9 @@ def available(self) -> bool: return self.coordinator.last_update_success def team_colors(self, colors) -> list: + if colors is None: + return None + _LOGGER.debug("Colors: %s", colors[0]) colors[0] = self.hex_to_rgb(colors[0]) colors[1] = self.hex_to_rgb(colors[1]) return colors From b0748901588c91172f6a9a16468492af35a55cc4 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Sep 2022 15:59:42 -0700 Subject: [PATCH 5/8] formatting --- custom_components/__init__.py | 1 - custom_components/nfl/__init__.py | 329 +++++++++++++++++++-------- custom_components/nfl/config_flow.py | 66 +++--- custom_components/nfl/sensor.py | 21 +- 4 files changed, 283 insertions(+), 134 deletions(-) diff --git a/custom_components/__init__.py b/custom_components/__init__.py index fab6099..9d18c38 100644 --- a/custom_components/__init__.py +++ b/custom_components/__init__.py @@ -1,2 +1 @@ """For testing""" - diff --git a/custom_components/nfl/__init__.py b/custom_components/nfl/__init__.py index 2b51dfd..1f68f5e 100644 --- a/custom_components/nfl/__init__.py +++ b/custom_components/nfl/__init__.py @@ -1,4 +1,5 @@ """ NFL Team Status """ +import asyncio import logging from datetime import timedelta import arrow @@ -41,6 +42,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ) hass.data.setdefault(DOMAIN, {}) + entry.add_update_listener(update_listener) + if entry.unique_id is not None: hass.config_entries.async_update_entry(entry, unique_id=None) @@ -50,9 +53,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Setup the data coordinator coordinator = AlertsDataUpdateCoordinator( - hass, - entry.data, - entry.data.get(CONF_TIMEOUT) + hass, entry.data, entry.data.get(CONF_TIMEOUT) ) # Fetch initial data so we have data when entities subscribe @@ -66,41 +67,66 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: return True -async def async_unload_entry(hass, config_entry): +async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: """Handle removal of an entry.""" - try: - await hass.config_entries.async_forward_entry_unload(config_entry, "sensor") - _LOGGER.info("Successfully removed sensor from the " + DOMAIN + " integration") - except ValueError: - pass - return True + _LOGGER.debug("Attempting to unload entities from the %s integration", DOMAIN) + + unload_ok = all( + await asyncio.gather( + *[ + hass.config_entries.async_forward_entry_unload(config_entry, platform) + for platform in PLATFORMS + ] + ) + ) + + if unload_ok: + _LOGGER.debug("Successfully removed entities from the %s integration", DOMAIN) + hass.data[DOMAIN].pop(config_entry.entry_id) + + return unload_ok -async def update_listener(hass, entry): + +async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> None: """Update listener.""" - entry.data = entry.options - await hass.config_entries.async_forward_entry_unload(entry, "sensor") - hass.async_add_job(hass.config_entries.async_forward_entry_setup(entry, "sensor")) + + _LOGGER.debug("Attempting to reload entities from the %s integration", DOMAIN) + + if config_entry.data == config_entry.options: + _LOGGER.debug("No changes detected not reloading entities.") + return + + new_data = config_entry.options.copy() + + hass.config_entries.async_update_entry( + entry=config_entry, + data=new_data, + ) + + await hass.config_entries.async_reload(config_entry.entry_id) + async def async_migrate_entry(hass, config_entry): - """Migrate an old config entry.""" - version = config_entry.version + """Migrate an old config entry.""" + version = config_entry.version - # 1-> 2: Migration format - if version == 1: - _LOGGER.debug("Migrating from version %s", version) - updated_config = config_entry.data.copy() + # 1-> 2: Migration format + if version == 1: + _LOGGER.debug("Migrating from version %s", version) + updated_config = config_entry.data.copy() - if CONF_TIMEOUT not in updated_config.keys(): - updated_config[CONF_TIMEOUT] = DEFAULT_TIMEOUT + if CONF_TIMEOUT not in updated_config.keys(): + updated_config[CONF_TIMEOUT] = DEFAULT_TIMEOUT - if updated_config != config_entry.data: - hass.config_entries.async_update_entry(config_entry, data=updated_config) + if updated_config != config_entry.data: + hass.config_entries.async_update_entry(config_entry, data=updated_config) - config_entry.version = 2 - _LOGGER.debug("Migration to version %s complete", config_entry.version) + config_entry.version = 2 + _LOGGER.debug("Migration to version %s complete", config_entry.version) + + return True - return True class AlertsDataUpdateCoordinator(DataUpdateCoordinator): """Class to manage fetching NFL data.""" @@ -130,7 +156,6 @@ async def _async_update_data(self): except Exception as error: raise UpdateFailed(error) from error return data - async def update_game(config) -> dict: @@ -141,6 +166,7 @@ async def update_game(config) -> dict: data = await async_get_state(config) return data + async def async_get_state(config) -> dict: """Query API for status.""" @@ -158,28 +184,47 @@ async def async_get_state(config) -> dict: found_team = False if data is not None: for event in data["events"]: - #_LOGGER.debug("Looking at this event: %s" % event) + # _LOGGER.debug("Looking at this event: %s" % event) if team_id in event["shortName"]: _LOGGER.debug("Found event; parsing data.") found_team = True - team_index = 0 if event["competitions"][0]["competitors"][0]["team"]["abbreviation"] == team_id else 1 - oppo_index = abs((team_index-1)) + team_index = ( + 0 + if event["competitions"][0]["competitors"][0]["team"][ + "abbreviation" + ] + == team_id + else 1 + ) + oppo_index = abs((team_index - 1)) values["state"] = event["status"]["type"]["state"].upper() values["date"] = event["date"] values["kickoff_in"] = arrow.get(event["date"]).humanize() values["venue"] = event["competitions"][0]["venue"]["fullName"] - values["location"] = "%s, %s" % (event["competitions"][0]["venue"]["address"]["city"], event["competitions"][0]["venue"]["address"]["state"]) + values["location"] = "%s, %s" % ( + event["competitions"][0]["venue"]["address"]["city"], + event["competitions"][0]["venue"]["address"]["state"], + ) try: - values["tv_network"] = event["competitions"][0]["broadcasts"][0]["names"][0] + values["tv_network"] = event["competitions"][0]["broadcasts"][0][ + "names" + ][0] except: values["tv_network"] = None - if event["status"]["type"]["state"].lower() in ['pre']: # odds only exist pre-game + if event["status"]["type"]["state"].lower() in [ + "pre" + ]: # odds only exist pre-game values["odds"] = event["competitions"][0]["odds"][0]["details"] - values["overunder"] = event["competitions"][0]["odds"][0]["overUnder"] + values["overunder"] = event["competitions"][0]["odds"][0][ + "overUnder" + ] else: values["odds"] = None values["overunder"] = None - if event["status"]["type"]["state"].lower() in ['pre', 'post']: # could use status.completed == true as well + if event["status"]["type"]["state"].lower() in [ + "pre", + "post", + ]: # could use status.completed == true as well values["possession"] = None values["last_play"] = None values["down_distance_text"] = None @@ -192,78 +237,169 @@ async def async_get_state(config) -> dict: else: values["quarter"] = event["status"]["period"] values["clock"] = event["status"]["displayClock"] - values["last_play"] = event["competitions"][0]["situation"]["lastPlay"]["text"] + values["last_play"] = event["competitions"][0]["situation"][ + "lastPlay" + ]["text"] try: - values["down_distance_text"] = event["competitions"][0]["situation"]["downDistanceText"] + values["down_distance_text"] = event["competitions"][0][ + "situation" + ]["downDistanceText"] except: values["down_distance_text"] = None try: - values["possession"] = event["competitions"][0]["situation"]["possession"] + values["possession"] = event["competitions"][0]["situation"][ + "possession" + ] except: values["possession"] = None - if event["competitions"][0]["competitors"][team_index]["homeAway"] == "home": - values["team_timeouts"] = event["competitions"][0]["situation"]["homeTimeouts"] - values["opponent_timeouts"] = event["competitions"][0]["situation"]["awayTimeouts"] + if ( + event["competitions"][0]["competitors"][team_index]["homeAway"] + == "home" + ): + values["team_timeouts"] = event["competitions"][0]["situation"][ + "homeTimeouts" + ] + values["opponent_timeouts"] = event["competitions"][0][ + "situation" + ]["awayTimeouts"] try: - values["team_win_probability"] = event["competitions"][0]["situation"]["lastPlay"]["probability"]["homeWinPercentage"] - values["opponent_win_probability"] = event["competitions"][0]["situation"]["lastPlay"]["probability"]["awayWinPercentage"] + values["team_win_probability"] = event["competitions"][0][ + "situation" + ]["lastPlay"]["probability"]["homeWinPercentage"] + values["opponent_win_probability"] = event["competitions"][ + 0 + ]["situation"]["lastPlay"]["probability"][ + "awayWinPercentage" + ] except: values["team_win_probability"] = None values["opponent_win_probability"] = None else: - values["team_timeouts"] = event["competitions"][0]["situation"]["awayTimeouts"] - values["opponent_timeouts"] = event["competitions"][0]["situation"]["homeTimeouts"] + values["team_timeouts"] = event["competitions"][0]["situation"][ + "awayTimeouts" + ] + values["opponent_timeouts"] = event["competitions"][0][ + "situation" + ]["homeTimeouts"] try: - values["team_win_probability"] = event["competitions"][0]["situation"]["lastPlay"]["probability"]["awayWinPercentage"] - values["opponent_win_probability"] = event["competitions"][0]["situation"]["lastPlay"]["probability"]["homeWinPercentage"] + values["team_win_probability"] = event["competitions"][0][ + "situation" + ]["lastPlay"]["probability"]["awayWinPercentage"] + values["opponent_win_probability"] = event["competitions"][ + 0 + ]["situation"]["lastPlay"]["probability"][ + "homeWinPercentage" + ] except: values["team_win_probability"] = None values["opponent_win_probability"] = None - values["team_abbr"] = event["competitions"][0]["competitors"][team_index]["team"]["abbreviation"] - values["team_id"] = event["competitions"][0]["competitors"][team_index]["team"]["id"] - values["team_name"] = event["competitions"][0]["competitors"][team_index]["team"]["shortDisplayName"] + values["team_abbr"] = event["competitions"][0]["competitors"][ + team_index + ]["team"]["abbreviation"] + values["team_id"] = event["competitions"][0]["competitors"][team_index][ + "team" + ]["id"] + values["team_name"] = event["competitions"][0]["competitors"][ + team_index + ]["team"]["shortDisplayName"] try: - values["team_record"] = event["competitions"][0]["competitors"][team_index]["records"][0]["summary"] + values["team_record"] = event["competitions"][0]["competitors"][ + team_index + ]["records"][0]["summary"] except: values["team_record"] = None - values["team_homeaway"] = event["competitions"][0]["competitors"][team_index]["homeAway"] - values["team_logo"] = event["competitions"][0]["competitors"][team_index]["team"]["logo"] + values["team_homeaway"] = event["competitions"][0]["competitors"][ + team_index + ]["homeAway"] + values["team_logo"] = event["competitions"][0]["competitors"][ + team_index + ]["team"]["logo"] try: - values["team_colors"] = [''.join(('#',event["competitions"][0]["competitors"][team_index]["team"]["color"])), - ''.join(('#',event["competitions"][0]["competitors"][team_index]["team"]["alternateColor"]))] + values["team_colors"] = [ + "".join( + ( + "#", + event["competitions"][0]["competitors"][team_index][ + "team" + ]["color"], + ) + ), + "".join( + ( + "#", + event["competitions"][0]["competitors"][team_index][ + "team" + ]["alternateColor"], + ) + ), + ] except: - if team_id == 'NFC': - values["team_colors"] = ['#013369','#013369'] - if team_id == 'AFC': - values["team_colors"] = ['#D50A0A','#D50A0A'] - values["team_score"] = event["competitions"][0]["competitors"][team_index]["score"] - values["opponent_abbr"] = event["competitions"][0]["competitors"][oppo_index]["team"]["abbreviation"] - values["opponent_id"] = event["competitions"][0]["competitors"][oppo_index]["team"]["id"] - values["opponent_name"] = event["competitions"][0]["competitors"][oppo_index]["team"]["shortDisplayName"] + if team_id == "NFC": + values["team_colors"] = ["#013369", "#013369"] + if team_id == "AFC": + values["team_colors"] = ["#D50A0A", "#D50A0A"] + values["team_score"] = event["competitions"][0]["competitors"][ + team_index + ]["score"] + values["opponent_abbr"] = event["competitions"][0]["competitors"][ + oppo_index + ]["team"]["abbreviation"] + values["opponent_id"] = event["competitions"][0]["competitors"][ + oppo_index + ]["team"]["id"] + values["opponent_name"] = event["competitions"][0]["competitors"][ + oppo_index + ]["team"]["shortDisplayName"] try: - values["opponent_record"] = event["competitions"][0]["competitors"][oppo_index]["records"][0]["summary"] + values["opponent_record"] = event["competitions"][0]["competitors"][ + oppo_index + ]["records"][0]["summary"] except: values["opponent_record"] = None - values["opponent_homeaway"] = event["competitions"][0]["competitors"][oppo_index]["homeAway"] - values["opponent_logo"] = event["competitions"][0]["competitors"][oppo_index]["team"]["logo"] + values["opponent_homeaway"] = event["competitions"][0]["competitors"][ + oppo_index + ]["homeAway"] + values["opponent_logo"] = event["competitions"][0]["competitors"][ + oppo_index + ]["team"]["logo"] try: - values["opponent_colors"] = [''.join(('#',event["competitions"][0]["competitors"][oppo_index]["team"]["color"])), - ''.join(('#',event["competitions"][0]["competitors"][oppo_index]["team"]["alternateColor"]))] + values["opponent_colors"] = [ + "".join( + ( + "#", + event["competitions"][0]["competitors"][oppo_index][ + "team" + ]["color"], + ) + ), + "".join( + ( + "#", + event["competitions"][0]["competitors"][oppo_index][ + "team" + ]["alternateColor"], + ) + ), + ] except: - if team_id == 'AFC': - values["opponent_colors"] = ['#013369','#013369'] - if team_id == 'NFC': - values["opponent_colors"] = ['#D50A0A','#D50A0A'] - values["opponent_score"] = event["competitions"][0]["competitors"][oppo_index]["score"] + if team_id == "AFC": + values["opponent_colors"] = ["#013369", "#013369"] + if team_id == "NFC": + values["opponent_colors"] = ["#D50A0A", "#D50A0A"] + values["opponent_score"] = event["competitions"][0]["competitors"][ + oppo_index + ]["score"] values["last_update"] = arrow.now().format(arrow.FORMAT_W3C) values["private_fast_refresh"] = False - + # Never found the team. Either a bye or a post-season condition if not found_team: - _LOGGER.debug("Did not find a game with for the configured team. Checking if it's a bye week.") + _LOGGER.debug( + "Did not find a game with for the configured team. Checking if it's a bye week." + ) found_bye = False values = await async_clear_states(config) - try: # look for byes in regular season + try: # look for byes in regular season for bye_team in data["week"]["teamsOnBye"]: if team_id.lower() == bye_team["abbreviation"].lower(): _LOGGER.debug("Bye week confirmed.") @@ -271,38 +407,47 @@ async def async_get_state(config) -> dict: values["team_abbr"] = bye_team["abbreviation"] values["team_name"] = bye_team["shortDisplayName"] values["team_logo"] = bye_team["logo"] - values["state"] = 'BYE' + values["state"] = "BYE" values["last_update"] = arrow.now().format(arrow.FORMAT_W3C) if found_bye == False: - _LOGGER.debug("Team not found in active games or bye week list. Have you missed the playoffs?") - values["team_abbr"] = None - values["team_name"] = None - values["team_logo"] = None - values["state"] = 'NOT_FOUND' - values["last_update"] = arrow.now().format(arrow.FORMAT_W3C) + _LOGGER.debug( + "Team not found in active games or bye week list. Have you missed the playoffs?" + ) + values["team_abbr"] = None + values["team_name"] = None + values["team_logo"] = None + values["state"] = "NOT_FOUND" + values["last_update"] = arrow.now().format(arrow.FORMAT_W3C) except: - _LOGGER.debug("Team not found in active games or bye week list. Have you missed the playoffs?") + _LOGGER.debug( + "Team not found in active games or bye week list. Have you missed the playoffs?" + ) values["team_abbr"] = None values["team_name"] = None values["team_logo"] = None - values["state"] = 'NOT_FOUND' + values["state"] = "NOT_FOUND" values["last_update"] = arrow.now().format(arrow.FORMAT_W3C) - if values["state"] == 'PRE' and ((arrow.get(values["date"])-arrow.now()).total_seconds() < 1200): - _LOGGER.debug("Event is within 20 minutes, setting refresh rate to 5 seconds.") + if values["state"] == "PRE" and ( + (arrow.get(values["date"]) - arrow.now()).total_seconds() < 1200 + ): + _LOGGER.debug( + "Event is within 20 minutes, setting refresh rate to 5 seconds." + ) values["private_fast_refresh"] = True - elif values["state"] == 'IN': + elif values["state"] == "IN": _LOGGER.debug("Event in progress, setting refresh rate to 5 seconds.") values["private_fast_refresh"] = True - elif values["state"] in ['POST', 'BYE']: + elif values["state"] in ["POST", "BYE"]: _LOGGER.debug("Event is over, setting refresh back to 10 minutes.") values["private_fast_refresh"] = False return values + async def async_clear_states(config) -> dict: """Clear all state attributes""" - + values = {} # Reset values values = { @@ -336,7 +481,7 @@ async def async_clear_states(config) -> dict: "opponent_win_probability": None, "opponent_timeouts": None, "last_update": None, - "private_fast_refresh": False + "private_fast_refresh": False, } return values diff --git a/custom_components/nfl/config_flow.py b/custom_components/nfl/config_flow.py index bf989a1..ffe12e5 100644 --- a/custom_components/nfl/config_flow.py +++ b/custom_components/nfl/config_flow.py @@ -50,40 +50,40 @@ async def _get_team_list(self): """Return list of team acronyms""" team_list = [ - 'ARI', - 'ATL', - 'BAL', - 'BUF', - 'CAR', - 'CHI', - 'CIN', - 'CLE', - 'DAL', - 'DEN', - 'DET', - 'GB', - 'HOU', - 'IND', - 'JAX', - 'KC', - 'LAC', - 'LAR', - 'LV', - 'MIA', - 'MIN', - 'NE', - 'NO', - 'NYG', - 'NYJ', - 'PHI', - 'PIT', - 'SEA', - 'SF', - 'TB', - 'TEN', - 'WSH' + "ARI", + "ATL", + "BAL", + "BUF", + "CAR", + "CHI", + "CIN", + "CLE", + "DAL", + "DEN", + "DET", + "GB", + "HOU", + "IND", + "JAX", + "KC", + "LAC", + "LAR", + "LV", + "MIA", + "MIN", + "NE", + "NO", + "NYG", + "NYJ", + "PHI", + "PIT", + "SEA", + "SF", + "TB", + "TEN", + "WSH", ] - + _LOGGER.debug("Team list: %s", team_list) return team_list diff --git a/custom_components/nfl/sensor.py b/custom_components/nfl/sensor.py index cdb5ba2..c9413d0 100644 --- a/custom_components/nfl/sensor.py +++ b/custom_components/nfl/sensor.py @@ -174,9 +174,13 @@ def extra_state_attributes(self): attrs["opponent_record"] = self.coordinator.data["opponent_record"] attrs["opponent_homeaway"] = self.coordinator.data["opponent_homeaway"] attrs["opponent_logo"] = self.coordinator.data["opponent_logo"] - attrs["opponent_colors"] = self.team_colors(self.coordinator.data["opponent_colors"]) + attrs["opponent_colors"] = self.team_colors( + self.coordinator.data["opponent_colors"] + ) attrs["opponent_score"] = self.coordinator.data["opponent_score"] - attrs["opponent_win_probability"] = self.coordinator.data["opponent_win_probability"] + attrs["opponent_win_probability"] = self.coordinator.data[ + "opponent_win_probability" + ] attrs["opponent_timeouts"] = self.coordinator.data["opponent_timeouts"] attrs["last_update"] = self.coordinator.data["last_update"] @@ -187,14 +191,15 @@ def available(self) -> bool: """Return if entity is available.""" return self.coordinator.last_update_success - def team_colors(self, colors) -> list: + def team_colors(self, colors) -> tuple: if colors is None: return None + color_list = [] _LOGGER.debug("Colors: %s", colors[0]) - colors[0] = self.hex_to_rgb(colors[0]) - colors[1] = self.hex_to_rgb(colors[1]) - return colors + color_list.append(list(self.hex_to_rgb(colors[0]))) + color_list.append(list(self.hex_to_rgb(colors[1]))) + return color_list - def hex_to_rgb(hexa): + def hex_to_rgb(self, hexa) -> tuple: hexa = hexa.lstrip("#") - return list(int(hexa[i:i+2], 16) for i in (0, 2, 4)) \ No newline at end of file + return tuple(int(hexa[i : i + 2], 16) for i in (0, 2, 4)) From d4dd6218569d0d2d667c007104ad3415d8862076 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Sep 2022 16:01:17 -0700 Subject: [PATCH 6/8] update coordinator class name --- custom_components/nfl/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/nfl/__init__.py b/custom_components/nfl/__init__.py index 1f68f5e..1e5d2ee 100644 --- a/custom_components/nfl/__init__.py +++ b/custom_components/nfl/__init__.py @@ -52,7 +52,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ent_reg.async_update_entity(entity.entity_id, new_unique_id=entry.entry_id) # Setup the data coordinator - coordinator = AlertsDataUpdateCoordinator( + coordinator = NFLDataUpdateCoordinator( hass, entry.data, entry.data.get(CONF_TIMEOUT) ) @@ -128,7 +128,7 @@ async def async_migrate_entry(hass, config_entry): return True -class AlertsDataUpdateCoordinator(DataUpdateCoordinator): +class NFLDataUpdateCoordinator(DataUpdateCoordinator): """Class to manage fetching NFL data.""" def __init__(self, hass, config, the_timeout: int): From 83596dda2b05ba422be4263a3367574a190ed0c1 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Sep 2022 16:29:42 -0700 Subject: [PATCH 7/8] fix reconfigure flow --- custom_components/nfl/config_flow.py | 31 +++++++++++++++------------- custom_components/nfl/sensor.py | 4 ++-- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/custom_components/nfl/config_flow.py b/custom_components/nfl/config_flow.py index ffe12e5..4a43bd1 100644 --- a/custom_components/nfl/config_flow.py +++ b/custom_components/nfl/config_flow.py @@ -2,13 +2,13 @@ from __future__ import annotations import logging -from typing import Any +from typing import Any, Dict, Optional import aiohttp import voluptuous as vol from homeassistant import config_entries from homeassistant.const import CONF_NAME -from homeassistant.core import callback +from homeassistant.core import HomeAssistant, callback from homeassistant.data_entry_flow import FlowResult from .const import ( @@ -28,25 +28,30 @@ _LOGGER = logging.getLogger(__name__) -def _get_schema(hass: Any, user_input: list, default_dict: list) -> Any: +def _get_schema( + hass: HomeAssistant, + user_input: Optional[Dict[str, Any]], + default_dict: Dict[str, Any], + entry_id: str = None +) -> vol.Schema: """Gets a schema using the default_dict as a backup.""" if user_input is None: user_input = {} - def _get_default(key): + def _get_default(key: str, fallback_default: Any = None) -> None: """Gets default value for key.""" - return user_input.get(key, default_dict.get(key)) + return user_input.get(key, default_dict.get(key, fallback_default)) return vol.Schema( { - vol.Required(CONF_TEAM_ID, default=_get_default(CONF_TEAM_ID)): str, - vol.Optional(CONF_NAME, default=_get_default(CONF_NAME)): str, - vol.Optional(CONF_TIMEOUT, default=_get_default(CONF_TIMEOUT)): int, + vol.Required(CONF_TEAM_ID, default=_get_default(CONF_TEAM_ID,_get_team_list())): str, + vol.Optional(CONF_NAME, default=_get_default(CONF_NAME, DEFAULT_NAME)): str, + vol.Optional(CONF_TIMEOUT, default=_get_default(CONF_TIMEOUT, DEFAULT_TIMEOUT)): int, } ) -async def _get_team_list(self): +def _get_team_list() -> list: """Return list of team acronyms""" team_list = [ @@ -112,7 +117,7 @@ def __init__(self): async def async_step_user(self, user_input={}): """Handle a flow initialized by the user.""" self._errors = {} - self._team_list = await _get_team_list(self) + self._team_list = _get_team_list() if user_input is not None: self._data.update(user_input) @@ -147,14 +152,12 @@ class NFLScoresOptionsFlow(config_entries.OptionsFlow): def __init__(self, config_entry): """Initialize.""" self.config = config_entry - self._data = dict(config_entry.options) self._errors = {} async def async_step_init(self, user_input=None): """Manage options.""" if user_input is not None: - self._data.update(user_input) - return self.async_create_entry(title="", data=self._data) + return self.async_create_entry(title="", data=user_input) return await self._show_options_form(user_input) async def _show_options_form(self, user_input): @@ -162,6 +165,6 @@ async def _show_options_form(self, user_input): return self.async_show_form( step_id="init", - data_schema=_get_schema(self.hass, user_input, self._data), + data_schema=_get_schema(self.hass, user_input, self.config.data), errors=self._errors, ) diff --git a/custom_components/nfl/sensor.py b/custom_components/nfl/sensor.py index c9413d0..e87c3cc 100644 --- a/custom_components/nfl/sensor.py +++ b/custom_components/nfl/sensor.py @@ -9,7 +9,7 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util import slugify -from . import AlertsDataUpdateCoordinator +from . import NFLDataUpdateCoordinator from .const import ( ATTRIBUTION, @@ -44,7 +44,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= config.data = config # Setup the data coordinator - coordinator = AlertsDataUpdateCoordinator( + coordinator = NFLDataUpdateCoordinator( hass, config, config[CONF_TIMEOUT], From 6bf1bebb3c979851ac75b096a19c34774e4c680a Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 28 Sep 2022 11:32:50 -0700 Subject: [PATCH 8/8] add rgb changes as new attribute --- custom_components/nfl/sensor.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/custom_components/nfl/sensor.py b/custom_components/nfl/sensor.py index e87c3cc..1e4b3fc 100644 --- a/custom_components/nfl/sensor.py +++ b/custom_components/nfl/sensor.py @@ -164,7 +164,8 @@ def extra_state_attributes(self): attrs["team_record"] = self.coordinator.data["team_record"] attrs["team_homeaway"] = self.coordinator.data["team_homeaway"] attrs["team_logo"] = self.coordinator.data["team_logo"] - attrs["team_colors"] = self.team_colors(self.coordinator.data["team_colors"]) + attrs["team_colors"] = self.coordinator.data["team_colors"] + attrs["team_colors_rbg"] = self.team_colors(self.coordinator.data["team_colors"]) attrs["team_score"] = self.coordinator.data["team_score"] attrs["team_win_probability"] = self.coordinator.data["team_win_probability"] attrs["team_timeouts"] = self.coordinator.data["team_timeouts"] @@ -174,7 +175,8 @@ def extra_state_attributes(self): attrs["opponent_record"] = self.coordinator.data["opponent_record"] attrs["opponent_homeaway"] = self.coordinator.data["opponent_homeaway"] attrs["opponent_logo"] = self.coordinator.data["opponent_logo"] - attrs["opponent_colors"] = self.team_colors( + attrs["opponent_colors"] = self.coordinator.data["opponent_colors"] + attrs["opponent_colors_rgb"] = self.team_colors( self.coordinator.data["opponent_colors"] ) attrs["opponent_score"] = self.coordinator.data["opponent_score"]