From f83bb077c16533c2a5209c0e059782ba40ae809c Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Tue, 10 Aug 2021 20:06:41 +0200 Subject: [PATCH 01/13] feat: Crawling and parsing of vaccination data See #2 --- .../__init__.py | 2 +- .../crawler.py | 134 ++++++++++++++---- .../home_assistant_covid19_augsburg/main.py | 5 +- tests/test_example.py | 3 +- 4 files changed, 111 insertions(+), 33 deletions(-) diff --git a/custom_components/home_assistant_covid19_augsburg/__init__.py b/custom_components/home_assistant_covid19_augsburg/__init__.py index f578184..6263d32 100644 --- a/custom_components/home_assistant_covid19_augsburg/__init__.py +++ b/custom_components/home_assistant_covid19_augsburg/__init__.py @@ -69,7 +69,7 @@ async def get_coordinator(hass: HomeAssistant): async def async_get_data() -> IncidenceData: crawler = CovidCrawler(hass) - return await crawler.crawl() + return await crawler.crawl_incidence() hass.data[DOMAIN] = DataUpdateCoordinator( hass, diff --git a/custom_components/home_assistant_covid19_augsburg/crawler.py b/custom_components/home_assistant_covid19_augsburg/crawler.py index 92dcd1d..5c9a190 100644 --- a/custom_components/home_assistant_covid19_augsburg/crawler.py +++ b/custom_components/home_assistant_covid19_augsburg/crawler.py @@ -15,6 +15,32 @@ def parse_num(s, t=int): return 0 +def parse_date( + day: int, month: str, year=datetime.datetime.now().year +) -> datetime.date: + """Parse a German medium-form date, e.g. 17. August into a datetime.date""" + months = [ + "Januar", + "Februar", + "März", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember", + ] + date = datetime.date( + year=int(year), + month=1 + months.index(month), + day=parse_num(day), + ) + return date + + @dataclass class IncidenceData: location: str @@ -26,37 +52,51 @@ class IncidenceData: num_dead: int = 0 +@dataclass +class VaccinationData: + date: str + + total_vaccinations: int = 0 + num_vaccinated_once: int = 0 + num_vaccinated_full: int = 0 + + ratio_vaccinated_once: float = 0.0 + ratio_vaccinated_full: float = 0.0 + + class CovidCrawlerBase(ABC): @abstractmethod - def crawl(self) -> IncidenceData: + def crawl_incidence(self) -> IncidenceData: + pass + + @abstractmethod + def crawl_vaccination(self) -> VaccinationData: pass class CovidCrawler(CovidCrawlerBase): def __init__(self, hass=None) -> None: - self.url = ( - "https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/fallzahlen" - ) self.hass = hass - async def crawl(self) -> IncidenceData: + async def crawl_incidence(self) -> IncidenceData: """ Fetch COVID-19 infection data from the target website. """ _log.info("Fetching COVID-19 data update") + url = ( + "https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/fallzahlen" + ) if self.hass: from homeassistant.helpers import aiohttp_client - result = await aiohttp_client.async_get_clientsession(self.hass).get( - self.url - ) + result = await aiohttp_client.async_get_clientsession(self.hass).get(url) soup = BeautifulSoup(await result.text(), "html.parser") else: import requests - result = requests.get(self.url) + result = requests.get(url) if not result.ok: result.raise_for_status() soup = BeautifulSoup(result.text, "html.parser") @@ -79,27 +119,7 @@ class CovidCrawler(CovidCrawlerBase): if not matches: raise ValueError(f"Could not extract date from scraped web page, {text=}") - months = [ - "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, - ) + date = parse_date(matches.group(1), matches.group(2)) _log.debug(f"Parsed date: {date}") match = match.find_next_sibling(class_="frame--type-textpic") @@ -130,3 +150,57 @@ class CovidCrawler(CovidCrawlerBase): _log.debug(f"Result data: {result}") return result + + async def crawl_vaccination(self) -> VaccinationData: + _log.info("Fetching COVID-19 vaccination data update") + url = "https://www.augsburg.de/umwelt-sozgcoiales/gesundheit/coronavirus/impfzentrum" + container_id = "c1088140" + + if self.hass: + from homeassistant.helpers import aiohttp_client + + result = await aiohttp_client.async_get_clientsession(self.hass).get(url) + soup = BeautifulSoup(await result.text(), "html.parser") + else: + import requests + + result = requests.get(url) + if not result.ok: + result.raise_for_status() + soup = BeautifulSoup(result.text, "html.parser") + + result = soup.find(id=container_id) + text = re.sub(r"\s+", " ", result.text) + regexes = [ + r"(?P\d+[.]\d+) Impfdosen", + r"Weitere (?P\d+[.]\d+) Personen haben die Erstimpfung erhalten", + r"(?P\d+[.]\d+) Personen sind bereits vollständig geimpft", + ] + values = {} + for r in regexes: + matches = re.search(r, text) + if not matches: + continue + values.update( + { + k: parse_num(v.replace(".", "")) + for k, v in matches.groupdict().items() + } + ) + + matches = re.search(r"Stand (?P\d+)\. (?P\w+) (?P\d+)", text) + if not matches: + raise ValueError(f"Could not extract date from scraped web page, {text=}") + + values["date"] = parse_date(**matches.groupdict()).strftime("%Y-%m-%d") + result = VaccinationData(**values) + + # Total population in Augsburg as of 2020 + # https://www.augsburg.de/fileadmin/user_upload/buergerservice_rathaus/rathaus/statisiken_und_geodaten/statistiken/Monitoring/Demografiemonitoring_der_Stadt_Augsburg_2021.pdf + population = 299021 + + result.ratio_vaccinated_full = result.num_vaccinated_full / population + result.ratio_vaccinated_once = result.num_vaccinated_once / population + _log.debug(f"Result data: {result}") + + return result diff --git a/custom_components/home_assistant_covid19_augsburg/main.py b/custom_components/home_assistant_covid19_augsburg/main.py index 422e50e..4783013 100644 --- a/custom_components/home_assistant_covid19_augsburg/main.py +++ b/custom_components/home_assistant_covid19_augsburg/main.py @@ -3,7 +3,10 @@ from .crawler import CovidCrawler async def main(): crawler = CovidCrawler() - result = await crawler.crawl() + # result = await crawler.crawl() + # print(result) + + result = await crawler.crawl_vaccination() print(result) diff --git a/tests/test_example.py b/tests/test_example.py index b2f43a8..e08bf7d 100644 --- a/tests/test_example.py +++ b/tests/test_example.py @@ -3,5 +3,6 @@ TODO: Remove once other tests have been added. """ + def test_example(): - assert True + assert True From 70fa0619d46623f173b2c8f2e30746cfeafc150f Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Tue, 10 Aug 2021 20:11:14 +0200 Subject: [PATCH 02/13] fix: Simply HTTP error handling --- .../home_assistant_covid19_augsburg/crawler.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/custom_components/home_assistant_covid19_augsburg/crawler.py b/custom_components/home_assistant_covid19_augsburg/crawler.py index 5c9a190..e77d4dc 100644 --- a/custom_components/home_assistant_covid19_augsburg/crawler.py +++ b/custom_components/home_assistant_covid19_augsburg/crawler.py @@ -97,8 +97,7 @@ class CovidCrawler(CovidCrawlerBase): import requests result = requests.get(url) - if not result.ok: - result.raise_for_status() + result.raise_for_status() soup = BeautifulSoup(result.text, "html.parser") match = soup.find(class_="frame--type-textpic") @@ -153,7 +152,9 @@ class CovidCrawler(CovidCrawlerBase): async def crawl_vaccination(self) -> VaccinationData: _log.info("Fetching COVID-19 vaccination data update") - url = "https://www.augsburg.de/umwelt-sozgcoiales/gesundheit/coronavirus/impfzentrum" + url = ( + "https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/impfzentrum" + ) container_id = "c1088140" if self.hass: @@ -165,8 +166,7 @@ class CovidCrawler(CovidCrawlerBase): import requests result = requests.get(url) - if not result.ok: - result.raise_for_status() + result.raise_for_status() soup = BeautifulSoup(result.text, "html.parser") result = soup.find(id=container_id) From b6184be32ff62ec72954c1d2adba980609f1cb52 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Tue, 10 Aug 2021 20:11:23 +0200 Subject: [PATCH 03/13] fix: Enable commented out code --- custom_components/home_assistant_covid19_augsburg/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/home_assistant_covid19_augsburg/main.py b/custom_components/home_assistant_covid19_augsburg/main.py index 4783013..32b5c30 100644 --- a/custom_components/home_assistant_covid19_augsburg/main.py +++ b/custom_components/home_assistant_covid19_augsburg/main.py @@ -3,8 +3,8 @@ from .crawler import CovidCrawler async def main(): crawler = CovidCrawler() - # result = await crawler.crawl() - # print(result) + result = await crawler.crawl_incidence() + print(result) result = await crawler.crawl_vaccination() print(result) From 2f73be90106a51fbca02b12ce701512359e45f8e Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 08:12:48 +0200 Subject: [PATCH 04/13] chore: Refactor duplicated HTTP fetching code --- .../crawler.py | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/custom_components/home_assistant_covid19_augsburg/crawler.py b/custom_components/home_assistant_covid19_augsburg/crawler.py index e77d4dc..a977d8b 100644 --- a/custom_components/home_assistant_covid19_augsburg/crawler.py +++ b/custom_components/home_assistant_covid19_augsburg/crawler.py @@ -78,16 +78,9 @@ class CovidCrawler(CovidCrawlerBase): def __init__(self, hass=None) -> None: self.hass = hass - async def crawl_incidence(self) -> IncidenceData: - """ - Fetch COVID-19 infection data from the target website. - """ + async def _fetch(self, url: str) -> str: + """Fetch a URL, using either the current Home Assistant instance or requests""" - _log.info("Fetching COVID-19 data update") - - url = ( - "https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/fallzahlen" - ) if self.hass: from homeassistant.helpers import aiohttp_client @@ -99,6 +92,19 @@ class CovidCrawler(CovidCrawlerBase): result = requests.get(url) result.raise_for_status() soup = BeautifulSoup(result.text, "html.parser") + return soup + + async def crawl_incidence(self) -> IncidenceData: + """ + Fetch COVID-19 infection data from the target website. + """ + + _log.info("Fetching COVID-19 data update") + + url = ( + "https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/fallzahlen" + ) + soup = await self._fetch(url) match = soup.find(class_="frame--type-textpic") text = match.p.text @@ -155,20 +161,9 @@ class CovidCrawler(CovidCrawlerBase): url = ( "https://www.augsburg.de/umwelt-soziales/gesundheit/coronavirus/impfzentrum" ) + soup = await self._fetch(url) + container_id = "c1088140" - - if self.hass: - from homeassistant.helpers import aiohttp_client - - result = await aiohttp_client.async_get_clientsession(self.hass).get(url) - soup = BeautifulSoup(await result.text(), "html.parser") - else: - import requests - - result = requests.get(url) - result.raise_for_status() - soup = BeautifulSoup(result.text, "html.parser") - result = soup.find(id=container_id) text = re.sub(r"\s+", " ", result.text) regexes = [ From 559a4631408de86082e7d3883f6389b4fd3bdc18 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 08:28:24 +0200 Subject: [PATCH 05/13] feat: Add new entity for vaccination data to Home Asssistant integration --- .../__init__.py | 7 ++- .../home_assistant_covid19_augsburg/sensor.py | 61 ++++++++++++++++--- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/custom_components/home_assistant_covid19_augsburg/__init__.py b/custom_components/home_assistant_covid19_augsburg/__init__.py index 6263d32..bb9fe06 100644 --- a/custom_components/home_assistant_covid19_augsburg/__init__.py +++ b/custom_components/home_assistant_covid19_augsburg/__init__.py @@ -67,9 +67,12 @@ async def get_coordinator(hass: HomeAssistant): if DOMAIN in hass.data: return hass.data[DOMAIN] - async def async_get_data() -> IncidenceData: + async def async_get_data() -> dict: crawler = CovidCrawler(hass) - return await crawler.crawl_incidence() + return { + "incidence": await crawler.crawl_incidence(), + "vaccination": await crawler.crawl_vaccination(), + } hass.data[DOMAIN] = DataUpdateCoordinator( hass, diff --git a/custom_components/home_assistant_covid19_augsburg/sensor.py b/custom_components/home_assistant_covid19_augsburg/sensor.py index 516b50c..558022b 100644 --- a/custom_components/home_assistant_covid19_augsburg/sensor.py +++ b/custom_components/home_assistant_covid19_augsburg/sensor.py @@ -1,3 +1,5 @@ +from dataclasses import asdict + from homeassistant.helpers.entity import Entity from . import get_coordinator @@ -41,18 +43,59 @@ class CoronaAugsburgSensor(Entity): @property def state(self): - return self.coordinator.data.incidence + return self.coordinator.data["incidence"].incidence @property def device_state_attributes(self): - return { - "date": self.coordinator.data.date, - "incidence": self.coordinator.data.incidence, - "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, - } + data = self.coordinator.data["incidence"] + return asdict(data) + + 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) + + +class CoronaAugsburgVaccinationSensor(Entity): + """Representation of vaccination data for the city of Augsburg""" + + def __init__(self, coordinator): + """Initialize sensor.""" + self.coordinator = coordinator + self._name = "COVID-19 Vaccinations Augsburg" + self._state = None + + @property + def available(self): + return self.coordinator.last_update_success and 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 "" + + @property + def state(self): + return self.coordinator.data["vaccination"].total_vaccinations + + @property + def device_state_attributes(self): + data = self.coordinator.data["vaccination"] + return asdict(data) async def async_added_to_hass(self): """When entity is added to hass.""" From 403efb937b94b95c5481df6dc42f36ce02de711f Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 08:32:51 +0200 Subject: [PATCH 06/13] feat(CI): Add HACS validation step to Github Actions --- .github/workflows/python-app.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 6f78ce1..bd494d9 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -50,3 +50,12 @@ jobs: - name: Test with pytest run: | poetry run pytest + + validate: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v2" + - name: HACS validation + uses: "hacs/action@main" + with: + category: "integration" From 216775e68f31bc78350a85bfec5b8fe3bd78d244 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 08:39:56 +0200 Subject: [PATCH 07/13] fix: Fix and disable some HACS validations --- .github/workflows/python-app.yml | 1 + custom_components/home_assistant_covid19_augsburg/manifest.json | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index bd494d9..6015b08 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -59,3 +59,4 @@ jobs: uses: "hacs/action@main" with: category: "integration" + ignore: brands wheels diff --git a/custom_components/home_assistant_covid19_augsburg/manifest.json b/custom_components/home_assistant_covid19_augsburg/manifest.json index 852918e..a2f3599 100644 --- a/custom_components/home_assistant_covid19_augsburg/manifest.json +++ b/custom_components/home_assistant_covid19_augsburg/manifest.json @@ -4,6 +4,7 @@ "version": "0.1.0", "config_flow": true, "documentation": "https://github.com/AdrianoKF/home-assistant-covid19-augsburg", + "issue_tracker": "https://github.com/AdrianoKF/home-assistant-covid19-augsburg/issues", "requirements": ["beautifulsoup4==4.8.2"], "dependencies": [], "codeowners": ["@AdrianoKF"] From 025a6475dd4636a74f92a3c0f9bbd5dab769821d Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 08:52:56 +0200 Subject: [PATCH 08/13] fix: Actually add vaccination entity to integratoin --- .../home_assistant_covid19_augsburg/__init__.py | 2 +- .../home_assistant_covid19_augsburg/sensor.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/custom_components/home_assistant_covid19_augsburg/__init__.py b/custom_components/home_assistant_covid19_augsburg/__init__.py index bb9fe06..a331f13 100644 --- a/custom_components/home_assistant_covid19_augsburg/__init__.py +++ b/custom_components/home_assistant_covid19_augsburg/__init__.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from homeassistant.core import HomeAssistant from .const import DOMAIN -from .crawler import CovidCrawler, IncidenceData +from .crawler import CovidCrawler _LOGGER = logging.getLogger(__name__) diff --git a/custom_components/home_assistant_covid19_augsburg/sensor.py b/custom_components/home_assistant_covid19_augsburg/sensor.py index 558022b..2307bb7 100644 --- a/custom_components/home_assistant_covid19_augsburg/sensor.py +++ b/custom_components/home_assistant_covid19_augsburg/sensor.py @@ -9,7 +9,12 @@ 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([CoronaAugsburgSensor(coordinator)]) + async_add_entities( + [ + CoronaAugsburgSensor(coordinator), + CoronaAugsburgVaccinationSensor(coordinator), + ] + ) class CoronaAugsburgSensor(Entity): From 573f91e2f965f99fb674aa31b64ca3fabc633374 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 09:47:20 +0200 Subject: [PATCH 09/13] chore: Bump manifest version --- custom_components/home_assistant_covid19_augsburg/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/home_assistant_covid19_augsburg/manifest.json b/custom_components/home_assistant_covid19_augsburg/manifest.json index a2f3599..23b2084 100644 --- a/custom_components/home_assistant_covid19_augsburg/manifest.json +++ b/custom_components/home_assistant_covid19_augsburg/manifest.json @@ -1,7 +1,7 @@ { "domain": "covid19_augsburg", "name": "COVID-19 Augsburg", - "version": "0.1.0", + "version": "1.1.0", "config_flow": true, "documentation": "https://github.com/AdrianoKF/home-assistant-covid19-augsburg", "issue_tracker": "https://github.com/AdrianoKF/home-assistant-covid19-augsburg/issues", From f385ee3a5affe36ea5560d0c8b2cf30d2b24d44b Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 10:07:00 +0200 Subject: [PATCH 10/13] fix: Return vaccination percentage instead of ratio --- custom_components/home_assistant_covid19_augsburg/crawler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/home_assistant_covid19_augsburg/crawler.py b/custom_components/home_assistant_covid19_augsburg/crawler.py index a977d8b..5ff4fce 100644 --- a/custom_components/home_assistant_covid19_augsburg/crawler.py +++ b/custom_components/home_assistant_covid19_augsburg/crawler.py @@ -194,8 +194,8 @@ class CovidCrawler(CovidCrawlerBase): # https://www.augsburg.de/fileadmin/user_upload/buergerservice_rathaus/rathaus/statisiken_und_geodaten/statistiken/Monitoring/Demografiemonitoring_der_Stadt_Augsburg_2021.pdf population = 299021 - result.ratio_vaccinated_full = result.num_vaccinated_full / population - result.ratio_vaccinated_once = result.num_vaccinated_once / population + result.ratio_vaccinated_full = result.num_vaccinated_full / population * 100 + result.ratio_vaccinated_once = result.num_vaccinated_once / population * 100 _log.debug(f"Result data: {result}") return result From 903a512f99b9ef8beebd0713a3d55bb03fbcb762 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 10:21:34 +0200 Subject: [PATCH 11/13] docs: Update readme --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 343add6..746aa9e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ ## Adding to your dashboard -You can add an overview of the current infection numbers to your dashboard using the [multiple-entity-row](https://github.com/benct/lovelace-multiple-entity-row) card: +You can add an overview of the current infection and vaccination numbers to your dashboard +using the [multiple-entity-row](https://github.com/benct/lovelace-multiple-entity-row) card: ```yaml type: entities @@ -24,4 +25,23 @@ entities: secondary_info: attribute: incidence unit: cases/100k + - type: custom:multiple-entity-row + entity: sensor.covid_19_vaccinations_augsburg + entities: + - attribute: ratio_vaccinated_once + name: Once + format: precision1 + unit: '%' + - attribute: num_vaccinated_full + name: Fully + format: precision1 + unit: '%' + - attribute: total_vaccinations + name: Total doses + show_state: false + icon: mdi:biohazard + name: COVID-19 Vaccinations + secondary_info: + attribute: date + format: date ``` From 92e99e03ef4c3438b7fbc4645f7eefae1a8f08d8 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 10:26:18 +0200 Subject: [PATCH 12/13] feat: Include ratio of at-least-once vaccinated persons --- custom_components/home_assistant_covid19_augsburg/crawler.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/custom_components/home_assistant_covid19_augsburg/crawler.py b/custom_components/home_assistant_covid19_augsburg/crawler.py index 5ff4fce..36c1eb6 100644 --- a/custom_components/home_assistant_covid19_augsburg/crawler.py +++ b/custom_components/home_assistant_covid19_augsburg/crawler.py @@ -62,6 +62,7 @@ class VaccinationData: ratio_vaccinated_once: float = 0.0 ratio_vaccinated_full: float = 0.0 + ratio_vaccinated_total: float = 0.0 class CovidCrawlerBase(ABC): @@ -196,6 +197,9 @@ class CovidCrawler(CovidCrawlerBase): result.ratio_vaccinated_full = result.num_vaccinated_full / population * 100 result.ratio_vaccinated_once = result.num_vaccinated_once / population * 100 + result.ratio_vaccinated_total = ( + result.ratio_vaccinated_once + result.ratio_vaccinated_full + ) _log.debug(f"Result data: {result}") return result From d2e8f77725c55ff76ce68cac52620d4087cc0340 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Wed, 11 Aug 2021 10:26:48 +0200 Subject: [PATCH 13/13] docs: Update readme --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 746aa9e..d55175a 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,14 @@ entities: name: Once format: precision1 unit: '%' - - attribute: num_vaccinated_full + - attribute: ratio_vaccinated_full name: Fully format: precision1 unit: '%' - - attribute: total_vaccinations - name: Total doses + - attribute: ratio_vaccinated_total + name: Total + format: precision1 + unit: '%' show_state: false icon: mdi:biohazard name: COVID-19 Vaccinations