feat: Implement HA sensor to expose data

This commit is contained in:
Adrian Rumpold
2021-06-18 17:17:28 +02:00
parent 5ba354c86d
commit 975b7666e2
2 changed files with 107 additions and 9 deletions

View File

@@ -11,6 +11,12 @@ from homeassistant import aiohttp_client
_log = logging.getLogger(__name__) _log = logging.getLogger(__name__)
def parse_num(s, t=int):
if len(s):
return t(s.replace(".", "").replace(",", "."))
return 0
@dataclass @dataclass
class IncidenceData: class IncidenceData:
location: str location: str
@@ -29,7 +35,7 @@ class CovidCrawlerBase(ABC):
class CovidCrawler(CovidCrawlerBase): class CovidCrawler(CovidCrawlerBase):
def __init__(self, hass) -> None: def __init__(self, hass=None) -> None:
self.url = ( self.url = (
"https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/fallzahlen" "https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/fallzahlen"
) )
@@ -42,10 +48,18 @@ class CovidCrawler(CovidCrawlerBase):
_log.info("Fetching COVID-19 data update") _log.info("Fetching COVID-19 data update")
locale.setlocale(locale.LC_ALL, "de_DE.utf8") if self.hass:
result = await aiohttp_client.async_get_clientsession(self.hass).get(
self.url
)
soup = BeautifulSoup(await result.text(), "html.parser")
else:
import requests
result = await aiohttp_client.async_get_clientsession(self.hass).get(self.url) result = requests.get(self.url)
soup = BeautifulSoup(await result.text(), features="html.parser") if not result.ok:
result.raise_for_status()
soup = BeautifulSoup(result.text, "html.parser")
match = soup.find(class_="frame--type-textpic") match = soup.find(class_="frame--type-textpic")
text = match.p.text text = match.p.text
@@ -55,16 +69,35 @@ class CovidCrawler(CovidCrawlerBase):
if not matches: if not matches:
raise ValueError("Could not extract incidence from scraped web page") raise ValueError("Could not extract incidence from scraped web page")
incidence = locale.atof(matches.group(1)) incidence = parse_num(matches.group(1), t=float)
_log.debug(f"Parsed incidence: {incidence}") _log.debug(f"Parsed incidence: {incidence}")
text = match.h2.text text = match.h2.text
matches = re.search(r"\((\d+\. \w+)\)", text) matches = re.search(r"\((\d+)\. (\w+)\)", text)
if not matches: if not matches:
raise ValueError("Could not extract date from scraped web page") raise ValueError("Could not extract date from scraped web page")
date = datetime.datetime.strptime(matches.group(1), "%d. %B") months = [
date = date.replace(year=datetime.datetime.now().year).date() "Januar",
"Februar",
"März",
"April",
"Mai",
"Juni",
"Juli",
"August",
"September",
"Oktober",
"November",
"Dezember",
]
day = parse_num(matches.group(1))
month_name = matches.group(2)
date = datetime.date(
year=datetime.datetime.now().year,
month=1 + months.index(month_name),
day=day,
)
_log.debug(f"Parsed date: {date}") _log.debug(f"Parsed date: {date}")
match = match.find_next_sibling(class_="frame--type-textpic") match = match.find_next_sibling(class_="frame--type-textpic")
@@ -83,7 +116,10 @@ class CovidCrawler(CovidCrawlerBase):
if not matches: if not matches:
continue continue
cases.update( cases.update(
{k: int(v.replace(".", "")) for k, v in matches.groupdict().items()} {
k: parse_num(v.replace(".", ""))
for k, v in matches.groupdict().items()
}
) )
result = IncidenceData("Augsburg", incidence, date, **cases) result = IncidenceData("Augsburg", incidence, date, **cases)

View File

@@ -0,0 +1,62 @@
from home_assistant_covid19_augsburg import get_coordinator
from homeassistant.helpers.entity import Entity
async def async_setup_entry(hass, _, async_add_entities):
"""Defer sensor setup to the shared sensor module."""
coordinator = await get_coordinator(hass)
async_add_entities([CoronaHessenSensor(coordinator)])
class CoronaHessenSensor(Entity):
"""Representation of a county with Corona cases."""
def __init__(self, coordinator):
"""Initialize sensor."""
self.coordinator = coordinator
self._name = "Coronavirus Augsburg"
self._state = None
@property
def available(self):
return self.coordinator.last_update_success in self.coordinator.data
@property
def name(self):
return self._name
@property
def unique_id(self):
return self._name
@property
def icon(self):
return "mdi:biohazard"
@property
def unit_of_measurement(self):
return "people"
@property
def state(self):
return self.coordinator.data.total_cases
@property
def device_state_attributes(self):
return {
"date": self.coordinator.data.date,
"total_cases": self.coordinator.data.total_cases,
"num_dead": self.coordinator.data.num_dead,
"num_recovered": self.coordinator.data.num_recovered,
"num_infected": self.coordinator.data.num_infected,
"incidence": self.coordinator.data.incidence,
}
async def async_added_to_hass(self):
"""When entity is added to hass."""
self.coordinator.async_add_listener(self.async_write_ha_state)
async def async_will_remove_from_hass(self):
"""When entity will be removed from hass."""
self.coordinator.async_remove_listener(self.async_write_ha_state)