mirror of
https://github.com/jdejaegh/irm-kmi-ha.git
synced 2025-06-27 03:35:56 +02:00
107 lines
3.4 KiB
Python
107 lines
3.4 KiB
Python
import logging
|
|
import xml.etree.ElementTree as ET
|
|
from typing import List
|
|
|
|
from custom_components.irm_kmi.const import POLLEN_NAMES
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
class PollenParser:
|
|
def __init__(
|
|
self,
|
|
xml_string: str
|
|
):
|
|
self._xml = xml_string
|
|
|
|
@staticmethod
|
|
def _validate_svg(elements: List[ET.Element]) -> bool:
|
|
x_values = {"rectgreen": 80,
|
|
"rectyellow": 95,
|
|
"rectorange": 110,
|
|
"rectred": 125,
|
|
"rectpurple": 140}
|
|
for e in elements:
|
|
if e.attrib.get('id', '') in x_values.keys():
|
|
try:
|
|
if float(e.attrib.get('x', '0')) != x_values.get(e.attrib.get('id')):
|
|
return False
|
|
except ValueError:
|
|
return False
|
|
return True
|
|
|
|
@staticmethod
|
|
def get_default_data() -> dict:
|
|
return {k.lower(): 'none' for k in POLLEN_NAMES}
|
|
|
|
@staticmethod
|
|
def get_option_values() -> List[str]:
|
|
return ['active', 'green', 'yellow', 'orange', 'red', 'purple', 'none']
|
|
|
|
@staticmethod
|
|
def _extract_elements(root) -> List[ET.Element]:
|
|
elements = []
|
|
for child in root:
|
|
elements.append(child)
|
|
elements.extend(PollenParser._extract_elements(child))
|
|
return elements
|
|
|
|
@staticmethod
|
|
def _dot_to_color_value(dot: ET.Element) -> str:
|
|
|
|
try:
|
|
cx = float(dot.attrib.get('cx'))
|
|
except ValueError:
|
|
return 'none'
|
|
|
|
if cx > 155:
|
|
return 'none'
|
|
elif cx > 140:
|
|
return 'purple'
|
|
elif cx > 125:
|
|
return 'red'
|
|
elif cx > 110:
|
|
return 'orange'
|
|
elif cx > 95:
|
|
return 'yellow'
|
|
elif cx > 80:
|
|
return 'green'
|
|
else:
|
|
return 'none'
|
|
|
|
def get_pollen_data(self) -> dict:
|
|
pollen_data = self.get_default_data()
|
|
try:
|
|
root = ET.fromstring(self._xml)
|
|
except ET.ParseError:
|
|
_LOGGER.warning("Could not parse SVG pollen XML")
|
|
return pollen_data
|
|
|
|
elements: List[ET.Element] = self._extract_elements(root)
|
|
|
|
if not self._validate_svg(elements):
|
|
_LOGGER.warning("Could not validate SVG pollen data")
|
|
return pollen_data
|
|
|
|
pollens = [e for e in elements if 'tspan' in e.tag and e.text in POLLEN_NAMES]
|
|
active = [e for e in elements if 'tspan' in e.tag and e.text == 'active']
|
|
dots = [e for e in elements if 'ellipse' in e.tag
|
|
and 'fill:#ffffff' in e.attrib.get('style', '')
|
|
and 3 == float(e.attrib.get('rx', '0'))]
|
|
|
|
for pollen in pollens:
|
|
try:
|
|
y = float(pollen.attrib.get('y'))
|
|
if y in [float(e.attrib.get('y')) for e in active]:
|
|
pollen_data[pollen.text.lower()] = 'active'
|
|
else:
|
|
dot = [d for d in dots if y - 3 <= float(d.attrib.get('cy', '0')) <= y + 3]
|
|
if len(dot) == 1:
|
|
dot = dot[0]
|
|
pollen_data[pollen.text.lower()] = self._dot_to_color_value(dot)
|
|
except ValueError | NameError:
|
|
_LOGGER.warning("Skipped some data in the pollen SVG")
|
|
|
|
_LOGGER.debug(f"Pollen data: {pollen_data}")
|
|
return pollen_data
|
|
|