Skip to content

Commit ef55080

Browse files
authored
v0.17.4 Release Candidate (#337)
- Added new data provider (cflscoreboard) to support the Canadian Football League (beta)
1 parent d1e21b8 commit ef55080

29 files changed

Lines changed: 4680 additions & 229 deletions

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Real-time Sports Scores in Home Assistant
22

3-
This integration provides real-time scores for teams and athletes in multiple professional (NBA, NFL, NHL, MLB, MLS, and more), college (NCAA), and international (soccer, golf, tennis, racing, cricket) sports using the ESPN Scoreboard APIs, and creates a sensor with detailed data for the competition. Services exist to change and interact with the sensor.
3+
This integration provides real-time scores for teams and athletes in multiple professional (NBA, NFL, NHL, MLB, MLS, and more), college (NCAA), and international (soccer, golf, tennis, racing, cricket) sports using the ESPN Scoreboard and other APIs, and creates a sensor with detailed data for the competition. Services exist to change and interact with the sensor.
44

55
This integration can be used with the [ha-teamtracker-card](https://github.com/vasqued2/ha-teamtracker-card) to display the game information in the Home Assistant dashboard.
66

@@ -24,7 +24,7 @@ A small subset of the most popular teams/leagues have been pre-configured to sim
2424

2525
The remaining teams/leagues are still supported, however they require a couple extra steps to set up. This is referred to as configuring a Custom API.
2626

27-
There is also beta support for PWHL games through the hockeytech API. All non-ESPN APIs must be configured with a Custom API. Beta functionality may have defects or break in future releases.
27+
There is also beta support for other sports and leagues through non-ESPN APIs. All non-ESPN APIs must be configured with a Custom API. Beta functionality may have defects or break in future releases.
2828

2929
### Natively Supported (Pre-Configured) Sports / Leagues
3030

@@ -54,10 +54,11 @@ The [Custom APIs](https://github.com/vasqued2/ha-teamtracker?tab=readme-ov-file#
5454

5555
#### Sports / Leagues Supported by non-ESPN APIs
5656

57-
Custom APIs can be configured for the following leagues using HockeyTech APIs
57+
Custom APIs can be configured for the following leagues using Non-ESPN APIs. The data available may be limited.
5858

5959
| League | `sport_path` | `league_path` |
6060
| --- | --- | --- |
61+
| [Canadian Football League](https://chl.ca//) | cflscoreboard | pwhl |
6162
| [Professional Womens Hockey League](https://www.thepwhl.com/) | hockeytech | pwhl |
6263
| [Canadian Hockey League](https://chl.ca/) | hockeytech | chl |
6364
| [Ontario Hockey League](https://ontariohockeyleague.com/) | hockeytech | ohl |

custom_components/teamtracker/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
172172
if not domain_data:
173173
hass.services.async_remove(DOMAIN, SERVICE_NAME_CALL_API)
174174
BaseSportProvider.data_cache.clear()
175-
BaseSportProvider.all_team_cache.clear()
176175

177176
return unload_ok
178177

custom_components/teamtracker/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@
198198

199199
# Misc
200200
TEAM_ID = ""
201-
VERSION = "v0.17.3"
201+
VERSION = "v0.17.4"
202202
ISSUE_URL = "https://github.com/vasqued2/ha-teamtracker"
203203
DOMAIN = "teamtracker"
204204
COORDINATOR = "coordinator"

custom_components/teamtracker/coordinator.py

Lines changed: 6 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,10 @@
1515
CONF_LEAGUE_PATH,
1616
CONF_SPORT_PATH,
1717
CONF_TEAM_ID,
18-
DEFAULT_LOGO,
1918
DEFAULT_TIMEOUT,
2019
)
21-
from .models import TeamTrackerValues
2220
from .parser_factory import get_parser
23-
from .provider_base import BaseSportProvider
2421
from .provider_factory import get_provider
25-
from .utils import is_integer
2622

2723
_LOGGER = logging.getLogger(__name__)
2824

@@ -44,7 +40,7 @@ def __init__(self, hass, config, entry: ConfigEntry=None):
4440

4541
self.provider = get_provider(self.sport_path, self.league_path, self.team_id, self)
4642
self.parser = get_parser(self.provider.data_format)
47-
self.parser.setup(self.name, self.sport_path, self.league_id, self.team_id)
43+
self.parser.setup(self.name, self.sport_path, self.league_path, self.league_id, self.team_id)
4844

4945
self.update_interval = self.provider.DEFAULT_REFRESH_RATE
5046

@@ -92,22 +88,21 @@ def update_team_info(self, sport_path, league_path, team_id, conference_id=""):
9288
self.team_id = team_id
9389
self.conference_id = conference_id
9490

95-
self.parser.setup(self.name, self.sport_path, self.league_id, self.team_id)
91+
self.parser.setup(self.name, self.sport_path, self.league_path, self.league_id, self.team_id)
9692

9793

9894
#
9995
# DataUpdateCoordinator Call Tree
10096
#
101-
# _async_update_data() - Top-level method called from HA to update sensor, controls refresh rate
102-
# async_update_sport_data() - Provider method to return response from data provider (cached or real-time)
103-
# async_update_values() - Returns sensor values based on response returned by data provider
97+
# _async_update_data() - Top-level method called from HA to update sensor
98+
# Gets response from provider, parses it, and updates the refresh rate if appropriate
10499
#
105100
async def _async_update_data(self):
106101
"""Top-level method called from HA to update sensor, controls refresh rate."""
107102
async with timeout(DEFAULT_TIMEOUT):
108103
try:
109104
response = await self.provider.async_update_sport_data()
110-
values = await self.async_update_values(response)
105+
values = await self.parser.async_parse_response(response, self.get_lang())
111106

112107
# update the interval based on flag
113108
if values.private_fast_refresh:
@@ -125,89 +120,4 @@ async def _async_update_data(self):
125120
_LOGGER.debug("%s: Error type: %s", self.name, type(error).__name__)
126121
_LOGGER.debug("%s: Additional information: %s", self.name, str(error))
127122
raise UpdateFailed(error) from error
128-
return values
129-
130-
131-
#
132-
# async_update_values()
133-
#
134-
async def async_update_values(self, provider_response) -> TeamTrackerValues:
135-
"""Updates sensor values using data returned by API or in cache"""
136-
137-
data = provider_response["data"]
138-
url = provider_response["url"]
139-
timestamp = provider_response["timestamp"]
140-
141-
sensor_name = self.name
142-
league_id = self.league_id.upper()
143-
team_id = self.team_id.upper()
144-
lang = self.get_lang()
145-
146-
# Populate base values that do not need API data
147-
values = TeamTrackerValues()
148-
if self.sport_path.lower() == "hockeytech":
149-
values.sport = "hockey"
150-
else:
151-
values.sport = self.sport_path
152-
values.sport_path = self.sport_path
153-
values.league = league_id
154-
values.league_path = self.league_path
155-
values.league_logo = DEFAULT_LOGO
156-
values.team_abbr = team_id
157-
values.state = "NOT_FOUND"
158-
values.last_update = timestamp
159-
values.private_fast_refresh = False
160-
values.api_url = url
161-
values.api_message = None
162-
163-
# If there was an error (i.e. 404) w/ the API call...
164-
if data is None:
165-
values.api_message = "API error, no data returned"
166-
_LOGGER.warning(
167-
"%s: API did not return any data for team '%s'", sensor_name, team_id
168-
)
169-
return values
170-
171-
# When league_path is "all", parser needs league_map{} to do manual lookup
172-
league_map = {}
173-
if (self.league_path) == "all":
174-
cache_key = f"{self.sport_path}:{self.league_path}:{self.team_id}"
175-
team_cache = BaseSportProvider.all_team_cache.get(cache_key)
176-
if team_cache:
177-
league_map = team_cache.get("league_map", {})
178-
179-
# Parse the data returned from the API and get the values
180-
values = await self.parser.async_parse_response(
181-
values,
182-
data,
183-
league_map,
184-
lang,
185-
)
186-
187-
# "cache_flag" key only exists in cached data, so update the API message if appropriate
188-
if provider_response.get("cache_flag", False):
189-
if values.api_message:
190-
values.api_message = "Cached data: " + values.api_message
191-
else:
192-
values.api_message = "Cached data"
193-
194-
# If NOT_FOUND, try to get abbr w/ another API to make message easier to read
195-
if (values.state == "NOT_FOUND" and
196-
is_integer(team_id)
197-
):
198-
response = await self.provider.async_fetch_team_data(self.hass, self.sport_path, self.league_path)
199-
teams = response["data"]
200-
if teams:
201-
team_abbr = next(
202-
(team["abbreviation"] for team in teams if team["id"] == team_id),
203-
None,
204-
)
205-
else:
206-
team_abbr = None
207-
208-
values.team_id = team_id
209-
if team_abbr:
210-
values.team_abbr = team_abbr
211-
212-
return values
213-
123+
return values

custom_components/teamtracker/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"iot_class": "cloud_polling",
99
"issue_tracker": "https://github.com/vasqued2/ha-teamtracker/issues",
1010
"requirements": ["arrow", "aiofiles"],
11-
"version": "0.17.3"
11+
"version": "0.17.4"
1212
}

0 commit comments

Comments
 (0)