Esempio n. 1
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the Pollen sensor."""
    name = config.get(CONF_NAME)
    sensors = config.get(CONF_SENSORS)
    state_as_string = config.get(CONF_STATE_AS_STRING)
    method = 'GET'
    payload = ''
    auth = ''
    verify_ssl = DEFAULT_VERIFY_SSL
    headers = {}

    rest = RestData(method, _ENDPOINT, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        _LOGGER.error("Unable to fetch data from Pollenkollen")
        return False

    devices = []

    for sensor in sensors:
        if 'days_to_track' in sensor:
            for day in range(int(sensor['days_to_track'])):
                for allergen in sensor['allergens']:
                    devices.append(
                        PollenkollSensor(rest, name, sensor, allergen,
                                         state_as_string, day))
        else:
            for allergen in sensor['allergens']:
                devices.append(
                    PollenkollSensor(rest, name, sensor, allergen,
                                     state_as_string))

    add_devices(devices, True)
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the PVOutput sensor."""
    name = config.get(CONF_NAME)
    sensors = config.get('sensors')
    method = 'GET'
    payload = ''
    auth = ''
    verify_ssl = DEFAULT_VERIFY_SSL
    headers = {}

    rest = RestData(method, _ENDPOINT, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        _LOGGER.error("Unable to fetch data from Pollenkollen")
        return False

    for sensor in sensors:
        if 'days_to_track' in sensor:
            i = 0
            while i <= sensor['days_to_track']:
                for allergen in sensor['allergens']:
                    add_devices([PollenkollSensor(rest, name, sensor, allergen, i)], True)
                i += 1
        else:
            for allergen in sensor['allergens']:
                add_devices([PollenkollSensor(rest, name, sensor, allergen, 0)], True)
Esempio n. 3
0
    def __init__(self, hass, config, add_sensors_callback):
        self._hass = hass
        self._sensors = {}
        self._add_sensors_callback = add_sensors_callback

        verify_ssl = True
        self._url = config.get(CONF_URL)
        self._rest = RestData('GET', self._url, '', '', '', verify_ssl)

        # query the latest data from Pool Math
        soup = self._fetch_latest_data()
        if soup is None:
            raise PlatformNotReady

        self._name = config.get(CONF_NAME)
        if self._name == None:
            self._name = DEFAULT_NAME

            # extract the pool name, if defined
            h1_span = soup.select('h1')
            if h1_span and h1_span[0]:
                pool_name = h1_span[0].string
                if pool_name != None:
                    self._name = f"{pool_name} {DEFAULT_NAME}"

        LOG.info(f"Creating Pool Math sensors for '{self._name}'")
        self._update_from_log_entries(soup)
Esempio n. 4
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Web scrape sensor."""
    name = config.get(CONF_NAME)
    resource = config.get(CONF_RESOURCE)
    method = 'GET'
    payload = None
    headers = config.get(CONF_HEADERS)
    verify_ssl = config.get(CONF_VERIFY_SSL)
    select = config.get(CONF_SELECT)
    attr = config.get(CONF_ATTR)
    index = config.get(CONF_INDEX)
    unit = config.get(CONF_UNIT_OF_MEASUREMENT)
    username = config.get(CONF_USERNAME)
    password = config.get(CONF_PASSWORD)
    value_template = config.get(CONF_VALUE_TEMPLATE)
    if value_template is not None:
        value_template.hass = hass

    if username and password:
        if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION:
            auth = HTTPDigestAuth(username, password)
        else:
            auth = HTTPBasicAuth(username, password)
    else:
        auth = None
    rest = RestData(method, resource, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        raise PlatformNotReady

    add_entities([
        ScrapeSensor(rest, name, select, attr, index, value_template, unit)],
                 True)
Esempio n. 5
0
class MoonPhaseHereAPI(object):
    """Get the latest data and update the states."""
    def __init__(self, app_id, app_code, zipcode):
        """Initialize the data object."""
        from homeassistant.components.rest.sensor import RestData

        resource = "{}app_id={}&app_code={}&zipcode={}".format(
            _ENDPOINT, app_id, app_code, zipcode)
        self._rest = RestData('GET', resource, None, None, None, False)
        self.data = None
        self.available = True
        self.update()

    @Throttle(MIN_TIME_BETWEEN_UPDATES)
    def update(self):
        """Get the latest data from Here."""
        try:
            self._rest.update()
            self.data = json.loads(self._rest.data)
            self._last_updated = dt_util.now().isoformat()
            _LOGGER.debug("Moon sensor updated")
            self.available = True
        except TypeError:
            _LOGGER.debug("Unable to fetch data from Here")
            self.available = False
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Doomsday Clock sensor."""
    name = config.get(CONF_NAME)
    resource = CONF_RESOURCE
    method = 'GET'
    selector = CONF_SELECTOR
    payload = headers = auth = None
    verify_ssl = False
    unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
    icon = config.get(CONF_ICON)
    value_template = config.get(CONF_VALUE_TEMPLATE)

    if value_template is not None:
        value_template.hass = hass

    rest = RestData(method, resource, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        _LOGGER.error("Unable to fetch URL: %s", resource)
        return False

    add_entities([
        DoomsdayClockSensor(rest, name, selector, unit_of_measurement, icon,
                            value_template)
    ], True)
Esempio n. 7
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the Web scrape sensor."""
    name = config.get(CONF_NAME)
    resource = config.get(CONF_RESOURCE)
    method = "GET"
    payload = None
    headers = config.get(CONF_HEADERS)
    verify_ssl = config.get(CONF_VERIFY_SSL)
    select = config.get(CONF_SELECT)
    attr = config.get(CONF_ATTR)
    index = config.get(CONF_INDEX)
    unit = config.get(CONF_UNIT_OF_MEASUREMENT)
    username = config.get(CONF_USERNAME)
    password = config.get(CONF_PASSWORD)
    value_template = config.get(CONF_VALUE_TEMPLATE)
    if value_template is not None:
        value_template.hass = hass

    if username and password:
        if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION:
            auth = HTTPDigestAuth(username, password)
        else:
            auth = HTTPBasicAuth(username, password)
    else:
        auth = None
    rest = RestData(method, resource, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        raise PlatformNotReady

    add_entities(
        [ScrapeSensor(rest, name, select, attr, index, value_template, unit)],
        True)
Esempio n. 8
0
    def __init__(self, api_key):
        """Initialize the data object."""
        from homeassistant.components.rest.sensor import RestData

        resource = "{}{}".format(_ENDPOINT, api_key)
        self._rest = RestData('GET', resource, None, None, None, False)
        self.data = None
        self.available = True
        self._rest.async_update()
Esempio n. 9
0
    def __init__(self, app_id, app_code, zipcode):
        """Initialize the data object."""
        from homeassistant.components.rest.sensor import RestData

        resource = "{}app_id={}&app_code={}&zipcode={}".format(
            _ENDPOINT, app_id, app_code, zipcode)
        self._rest = RestData('GET', resource, None, None, None, False)
        self.data = None
        self.available = True
        self.update()
Esempio n. 10
0
    def __init__(self, partregion_ids):
        """Initialize the data object."""
        resource = "https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json"

        self._rest = RestData('GET', resource, None, None, None, True)
        self._partregion_ids = partregion_ids
        self.last_update = None
        self.sensordata = {}
        self.api_id_to_descr = {}
        self.available = False
        self.update()
Esempio n. 11
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the sensor."""
    district_name = config.get(CONF_DISTRICT_NAME)

    rest = RestData(DEFAULT_METHOD, URL, None, None, None, DEFAULT_VERIFY_SSL)
    rest.update()
    if rest.data is None:
        raise PlatformNotReady

    # Must update the sensor now (including fetching the rest resource) to
    # ensure it's updating its state.
    add_entities([NswFireServiceFireDangerSensor(hass, rest, district_name)],
                 True)
Esempio n. 12
0
    def __init__(self, region_name):
        """Initialize the data object."""
        resource = "https://www.dwd.de/DWD/warnungen/warnapp_landkreise/json/warnings.json?jsonp=loadWarnings"

        # a User-Agent is necessary for this rest api endpoint (#29496)
        headers = {"User-Agent": HA_USER_AGENT}

        self._rest = RestData("GET", resource, None, headers, None, True)
        self.region_name = region_name
        self.region_id = None
        self.region_state = None
        self.data = None
        self.available = True
        self.update()
Esempio n. 13
0
    def __init__(self, region_name):
        """Initialize the data object."""
        resource = "{}{}{}?{}".format(
            'https://', 'www.dwd.de',
            '/DWD/warnungen/warnapp_landkreise/json/warnings.json',
            'jsonp=loadWarnings')

        self._rest = RestData('GET', resource, None, None, None, True)
        self.region_name = region_name
        self.region_id = None
        self.region_state = None
        self.data = None
        self.available = True
        self.update()
Esempio n. 14
0
    def setup_rest(self, endpoint, variables=None):
        payload = auth = headers = None
        verify_ssl = False
        method = 'GET'

        return RestData(method, endpoint.format(variables), auth, headers,
                        payload, verify_ssl)
Esempio n. 15
0
 def __init__(self, api_key, user_id):
     """Initialize the data object."""
     self.user_id = user_id
     self.available = True
     resource = "https://api.flatastic-app.com/index.php/api/chores"
     headers = {
         "Accept": "application/json, text/plain, */*",
         "X-Api-Key": api_key,
         "X-Api-Version": "2.0.0",
     }
     self._rest = RestData("GET", resource, None, headers, None, True)
     self.data = {
         "chore": None,
         "time_remaining": None,
     }
     self.user_chores = []
Esempio n. 16
0
async def async_setup_scanner(hass, config, async_see, discovery_info=None):
    """Validate the configuration and return a Traccar scanner."""
    method = 'GET'
    username = config.get(CONF_USERNAME)
    password = config.get(CONF_PASSWORD)
    json_attrs = config.get(CONF_JSON_ATTRS)
    force_update = config.get(CONF_FORCE_UPDATE)
    headers = None
    payload = None

    if username and password:
        if config.get(CONF_AUTHENTICATION) == HTTP_DIGEST_AUTHENTICATION:
            auth = HTTPDigestAuth(username, password)
        else:
            auth = HTTPBasicAuth(username, password)
    else:
        auth = None

    rest = RestData(method, config.get(CONF_RESOURCE), auth, headers, payload,
                    config.get(CONF_VERIFY_SSL))

    scanner = RestDeviceTracker(hass, rest, async_see, config.get(CONF_NAME),
                                config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL),
                                config.get(CONF_DEVICE),
                                config.get(CONF_JSON_ATTRS),
                                config.get(CONF_FORCE_UPDATE))

    return await scanner.async_init()
Esempio n. 17
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the sensor."""
    ip_address = config[CONF_IP_ADDRESS]
    password = config[CONF_PASSWORD]

    auth = HTTPBasicAuth(DEFAULT_USERNAME, password)
    url = URL_TEMPLATE.format(ip_address)

    rest = RestData(DEFAULT_METHOD, url, auth, None, None, False)
    rest.update()
    if rest.data is None:
        raise PlatformNotReady

    # Must update the sensor now (including fetching the rest resource) to
    # ensure it's updating its state.
    add_entities([NetgearCm500vModemConnectionStatus(
            hass, rest, ip_address)], True)
Esempio n. 18
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the PVOutput sensor."""
    name = config.get(CONF_NAME)
    api_key = config.get(CONF_API_KEY)
    system_id = config.get(CONF_SYSTEM_ID)
    method = "GET"
    payload = auth = None
    verify_ssl = DEFAULT_VERIFY_SSL
    headers = {"X-Pvoutput-Apikey": api_key, "X-Pvoutput-SystemId": system_id}

    rest = RestData(method, _ENDPOINT, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        _LOGGER.error("Unable to fetch data from PVOutput")
        return False

    add_entities([PvoutputSensor(rest, name)], True)
Esempio n. 19
0
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the Pollen sensor."""
    name = config.get(CONF_NAME)
    sensors = config.get(CONF_SENSORS)
    method = 'GET'
    payload = ''
    auth = ''
    verify_ssl = DEFAULT_VERIFY_SSL
    headers = {}

    rest = RestData(method, _ENDPOINT, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        _LOGGER.error("Unable to fetch data from Pollenkollen")
        return False

    for item in sensors:
        add_devices([PollenkollSensor(rest, name, item)], True)
Esempio n. 20
0
def setup_platform(hass, config, add_entities, discovery_info=None):
    """Set up the PVOutput sensor."""
    name = config.get(CONF_NAME)
    api_key = config.get(CONF_API_KEY)
    system_id = config.get(CONF_SYSTEM_ID)
    method = 'GET'
    payload = auth = None
    verify_ssl = DEFAULT_VERIFY_SSL
    headers = {
        'X-Pvoutput-Apikey': api_key,
        'X-Pvoutput-SystemId': system_id,
    }

    rest = RestData(method, _ENDPOINT, auth, headers, payload, verify_ssl)
    rest.update()

    if rest.data is None:
        _LOGGER.error("Unable to fetch data from PVOutput")
        return False

    add_entities([PvoutputSensor(rest, name)], True)
Esempio n. 21
0
class SectorPerfAPI(object):
    """Get the latest data and update the states."""
    def __init__(self, api_key):
        """Initialize the data object."""
        from homeassistant.components.rest.sensor import RestData

        resource = "{}{}".format(_ENDPOINT, api_key)
        self._rest = RestData('GET', resource, None, None, None, False)
        self.data = None
        self.available = True
        self._rest.async_update()

    @Throttle(MIN_TIME_BETWEEN_UPDATES)
    async def async_update(self):
        """Get the latest data from Alphavantage."""
        try:
            await self._rest.async_update()
            self.data = json.loads(self._rest.data)
            self.available = True
        except TypeError:
            _LOGGER.error("Unable to fetch data from Alphavantage")
            self.available = False
Esempio n. 22
0
class FlatasticAPI:
    """Get the latest data from Flatastic API."""

    def __init__(self, api_key, user_id):
        """Initialize the data object."""
        self.user_id = user_id
        self.available = True
        resource = "https://api.flatastic-app.com/index.php/api/chores"
        headers = {
            "Accept": "application/json, text/plain, */*",
            "X-Api-Key": api_key,
            "X-Api-Version": "2.0.0",
        }
        self._rest = RestData("GET", resource, None, headers, None, True)
        self.data = {
            "chore": None,
            "time_remaining": None,
        }
        self.user_chores = []

    @Throttle(SCAN_INTERVAL)
    def update(self):
        """Get the latest data from Flatastic."""
        try:
            self._rest.update()
            self.chores = json.loads(self._rest.data)
            # sort chores by their due date
            self.chores.sort(key=lambda chore: chore["timeLeftNext"])
            for chore in self.chores:
                if chore.get("currentUser") == self.user_id:
                    # self.user_chores.append(chore)
                    self.data["chore"] = chore.get("title")
                    self.data["time_remaining"] = int(chore.get("timeLeftNext") / 86400)
                    break
            # self.data["chore"] = data.get("temperature") / 10
            # self.data["time"] = datetime.fromtimestamp(timestamp / 1000).isoformat()
        except TypeError:
            _LOGGER.error("Unable to fetch data from Flatastic API")
            self.available = False
Esempio n. 23
0
    def __init__(self, region_name):
        """Initialize the data object."""
        resource = "{}{}{}?{}".format(
            'https://',
            'www.dwd.de',
            '/DWD/warnungen/warnapp_landkreise/json/warnings.json',
            'jsonp=loadWarnings'
        )

        self._rest = RestData('GET', resource, None, None, None, True)
        self.region_name = region_name
        self.region_id = None
        self.region_state = None
        self.data = None
        self.available = True
        self.update()
Esempio n. 24
0
async def add_sensors(hass,
                      config,
                      async_add_devices,
                      api_key,
                      fetch_interval,
                      number_of_sensors,
                      unit_of_measurement,
                      name,
                      update_name,
                      location,
                      max_journeys,
                      time_offset,
                      filter,
                      discovery_info=None):
    method = 'GET'
    payload = ''
    auth = None
    verify_ssl = DEFAULT_VERIFY_SSL
    headers = {}
    params = {}
    timeout = 5000
    time = None
    resource = _ENDPOINT + '&key=' + api_key + '&id=' + str(
        location) + '&maxJourneys=' + str(max_journeys)
    sensors = []
    helpers = []
    helper = 'helper_' + name
    base_resource = resource
    if time_offset:
        time = dateparser.parse("in " + str(time_offset) + " minutes")
        resource = resource + '&time=' + time.strftime(
            "%H:%M") + '&date=' + time.strftime('%Y-%m-%d')
    rest = RestData(hass, method, resource, auth, headers, params, payload,
                    verify_ssl, timeout)
    helpers.append(
        helperEntity(rest, helper, fetch_interval, time_offset, base_resource,
                     filter))
    async_add_devices(helpers, True)

    for i in range(0, number_of_sensors):
        entityName = name + '_' + str(i)
        sensors.append(
            entityRepresentation(hass, helper, entityName, i,
                                 number_of_sensors, unit_of_measurement,
                                 update_name, time_offset))
    async_add_devices(sensors, True)
Esempio n. 25
0
class DwdWeatherWarningsAPI:
    """Get the latest data and update the states."""
    def __init__(self, region_name):
        """Initialize the data object."""
        resource = "{}{}{}?{}".format(
            'https://', 'www.dwd.de',
            '/DWD/warnungen/warnapp_landkreise/json/warnings.json',
            'jsonp=loadWarnings')

        self._rest = RestData('GET', resource, None, None, None, True)
        self.region_name = region_name
        self.region_id = None
        self.region_state = None
        self.data = None
        self.available = True
        self.update()

    @Throttle(SCAN_INTERVAL)
    def update(self):
        """Get the latest data from the DWD-Weather-Warnings."""
        try:
            self._rest.update()

            json_string = self._rest.data[24:len(self._rest.data) - 2]
            json_obj = json.loads(json_string)

            data = {'time': json_obj['time']}

            for mykey, myvalue in {
                    'current': 'warnings',
                    'advance': 'vorabInformation'
            }.items():

                _LOGGER.debug("Found %d %s global DWD warnings",
                              len(json_obj[myvalue]), mykey)

                data['{}_warning_level'.format(mykey)] = 0
                my_warnings = []

                if self.region_id is not None:
                    # get a specific region_id
                    if self.region_id in json_obj[myvalue]:
                        my_warnings = json_obj[myvalue][self.region_id]

                else:
                    # loop through all items to find warnings, region_id
                    # and region_state for region_name
                    for key in json_obj[myvalue]:
                        my_region = json_obj[myvalue][key][0]['regionName']
                        if my_region != self.region_name:
                            continue
                        my_warnings = json_obj[myvalue][key]
                        my_state = json_obj[myvalue][key][0]['stateShort']
                        self.region_id = key
                        self.region_state = my_state
                        break

                # Get max warning level
                maxlevel = data['{}_warning_level'.format(mykey)]
                for event in my_warnings:
                    if event['level'] >= maxlevel:
                        data['{}_warning_level'.format(mykey)] = event['level']

                data['{}_warning_count'.format(mykey)] = len(my_warnings)
                data['{}_warnings'.format(mykey)] = my_warnings

                _LOGGER.debug("Found %d %s local DWD warnings",
                              len(my_warnings), mykey)

            self.data = data
            self.available = True
        except TypeError:
            _LOGGER.error("Unable to fetch data from DWD-Weather-Warnings")
            self.available = False
Esempio n. 26
0
class DwdWeatherWarningsAPI:
    """Get the latest data and update the states."""

    def __init__(self, region_name):
        """Initialize the data object."""
        resource = "{}{}{}?{}".format(
            'https://',
            'www.dwd.de',
            '/DWD/warnungen/warnapp_landkreise/json/warnings.json',
            'jsonp=loadWarnings'
        )

        self._rest = RestData('GET', resource, None, None, None, True)
        self.region_name = region_name
        self.region_id = None
        self.region_state = None
        self.data = None
        self.available = True
        self.update()

    @Throttle(SCAN_INTERVAL)
    def update(self):
        """Get the latest data from the DWD-Weather-Warnings."""
        try:
            self._rest.update()

            json_string = self._rest.data[24:len(self._rest.data) - 2]
            json_obj = json.loads(json_string)

            data = {'time': json_obj['time']}

            for mykey, myvalue in {
                    'current': 'warnings',
                    'advance': 'vorabInformation'
            }.items():

                _LOGGER.debug("Found %d %s global DWD warnings",
                              len(json_obj[myvalue]), mykey)

                data['{}_warning_level'.format(mykey)] = 0
                my_warnings = []

                if self.region_id is not None:
                    # get a specific region_id
                    if self.region_id in json_obj[myvalue]:
                        my_warnings = json_obj[myvalue][self.region_id]

                else:
                    # loop through all items to find warnings, region_id
                    # and region_state for region_name
                    for key in json_obj[myvalue]:
                        my_region = json_obj[myvalue][key][0]['regionName']
                        if my_region != self.region_name:
                            continue
                        my_warnings = json_obj[myvalue][key]
                        my_state = json_obj[myvalue][key][0]['stateShort']
                        self.region_id = key
                        self.region_state = my_state
                        break

                # Get max warning level
                maxlevel = data['{}_warning_level'.format(mykey)]
                for event in my_warnings:
                    if event['level'] >= maxlevel:
                        data['{}_warning_level'.format(mykey)] = event['level']

                data['{}_warning_count'.format(mykey)] = len(my_warnings)
                data['{}_warnings'.format(mykey)] = my_warnings

                _LOGGER.debug("Found %d %s local DWD warnings",
                              len(my_warnings), mykey)

            self.data = data
            self.available = True
        except TypeError:
            _LOGGER.error("Unable to fetch data from DWD-Weather-Warnings")
            self.available = False
Esempio n. 27
0
class DwdWeatherWarningsAPI:
    """Get the latest data and update the states."""
    def __init__(self, region_name):
        """Initialize the data object."""
        resource = "https://www.dwd.de/DWD/warnungen/warnapp_landkreise/json/warnings.json?jsonp=loadWarnings"

        # a User-Agent is necessary for this rest api endpoint (#29496)
        headers = {"User-Agent": HA_USER_AGENT}

        self._rest = RestData("GET", resource, None, headers, None, True)
        self.region_name = region_name
        self.region_id = None
        self.region_state = None
        self.data = None
        self.available = True
        self.update()

    @Throttle(SCAN_INTERVAL)
    def update(self):
        """Get the latest data from the DWD-Weather-Warnings."""
        try:
            self._rest.update()

            json_string = self._rest.data[24:len(self._rest.data) - 2]
            json_obj = json.loads(json_string)

            data = {"time": json_obj["time"]}

            for mykey, myvalue in {
                    "current": "warnings",
                    "advance": "vorabInformation",
            }.items():

                _LOGGER.debug("Found %d %s global DWD warnings",
                              len(json_obj[myvalue]), mykey)

                data[f"{mykey}_warning_level"] = 0
                my_warnings = []

                if self.region_id is not None:
                    # get a specific region_id
                    if self.region_id in json_obj[myvalue]:
                        my_warnings = json_obj[myvalue][self.region_id]

                else:
                    # loop through all items to find warnings, region_id
                    # and region_state for region_name
                    for key in json_obj[myvalue]:
                        my_region = json_obj[myvalue][key][0]["regionName"]
                        if my_region != self.region_name:
                            continue
                        my_warnings = json_obj[myvalue][key]
                        my_state = json_obj[myvalue][key][0]["stateShort"]
                        self.region_id = key
                        self.region_state = my_state
                        break

                # Get max warning level
                maxlevel = data[f"{mykey}_warning_level"]
                for event in my_warnings:
                    if event["level"] >= maxlevel:
                        data[f"{mykey}_warning_level"] = event["level"]

                data[f"{mykey}_warning_count"] = len(my_warnings)
                data[f"{mykey}_warnings"] = my_warnings

                _LOGGER.debug("Found %d %s local DWD warnings",
                              len(my_warnings), mykey)

            self.data = data
            self.available = True
        except TypeError:
            _LOGGER.error("Unable to fetch data from DWD-Weather-Warnings")
            self.available = False
Esempio n. 28
0
class PoolMathClient():
    def __init__(self, hass, config, add_sensors_callback):
        self._hass = hass
        self._sensors = {}
        self._add_sensors_callback = add_sensors_callback

        verify_ssl = True
        self._url = config.get(CONF_URL)
        self._rest = RestData('GET', self._url, '', '', '', verify_ssl)

        # query the latest data from Pool Math
        soup = self._fetch_latest_data()
        if soup is None:
            raise PlatformNotReady

        self._name = config.get(CONF_NAME)
        if self._name == None:
            self._name = DEFAULT_NAME

            # extract the pool name, if defined
            h1_span = soup.select('h1')
            if h1_span and h1_span[0]:
                pool_name = h1_span[0].string
                if pool_name != None:
                    self._name = f"{pool_name} {DEFAULT_NAME}"

        LOG.info(f"Creating Pool Math sensors for '{self._name}'")
        self._update_from_log_entries(soup)

    def _fetch_latest_data(self):
        """Fetch the latest log entries from the Pool Math service"""
        self._rest.update()
        result = self._rest.data
        if result is None:
            LOG.warn(f"Failed updating Pool Math data from {self._url}")
            return None
        soup = BeautifulSoup(result, 'html.parser')
        #LOG.debug("Raw data from %s: %s", self._url, soup)
        return soup

    def update(self):
        soup = self._fetch_latest_data()
        if not soup:
            return None
        return self._update_from_log_entries(soup)

    def get_sensor(self, sensor_type):
        sensor = self._sensors.get(sensor_type, None)
        if sensor:
            return sensor

        config = POOL_MATH_SENSOR_SETTINGS.get(sensor_type, None)
        if config is None:
            LOG.warning(
                f"Unknown Pool Math sensor '{sensor_type}' discovered at {self._url}"
            )
            return None

        name = self._name + ' ' + config['name']
        sensor = UpdatableSensor(self._hass, name, config)
        self._sensors[sensor_type] = sensor

        # register sensor with Home Assistant
        self._add_sensors_callback([sensor], True)
        return sensor

    def _update_from_log_entries(self, poolmath_soup):
        updated_sensors = {}
        latest_timestamp = None

        # Read back through all log entries and update any changed sensor states (since a given
        # log entry may only have a subset of sensor states)
        log_entries = poolmath_soup.find_all('div', class_='testLogCard')
        for log_entry in log_entries:
            log_fields = log_entry.select('.chiclet')
            LOG.debug("Pool Math log fields=%s", log_fields)

            if not latest_timestamp:
                # capture the timestamp for the most recent Pool Math log entry
                latest_timestamp = log_entry.find('time',
                                                  class_='timestamp timereal')

            # FIXME: improve parsing to be more robust to Pool Math changes
            for entry in log_fields:
                sensor_type = entry.contents[3].text.lower()
                if not sensor_type in updated_sensors:
                    state = entry.contents[1].text

                    sensor = self.get_sensor(sensor_type)
                    if sensor:
                        timestamp = log_entry.find(
                            'time', class_='timestamp timereal').text
                        if sensor.state != state:
                            LOG.info(
                                f"Pool Math returned updated {sensor_type}={state} (timestamp={timestamp})"
                            )
                        sensor.inject_state(state, timestamp)
                        updated_sensors[sensor_type] = sensor

        # record the most recent log entry's timestamp as the service's last updated timestamp
        self._timestamp = latest_timestamp
        return latest_timestamp

    @property
    def sensor_names(self):
        return self._sensors.keys()

    @property
    def latest_log_timestamp(self):
        return self._timestamp
Esempio n. 29
0
class DwdPollenAPI:
    """
    Get the latest data and update the states.

    Format of map sensordata:
    sensordata[<region_id>]['region_name']
    sensordata[<region_id>]['partregion_name']
    sensordata[<region_id>]['pollendata'][<pollen_name>]['today'|'today_mapped'|'tomorrow'|'tomorrow_mapped'|'dayafter_tomorrow'|'dayafter_tomorrow_mapped']
    """

    def __init__(self, partregion_ids):
        """Initialize the data object."""
        resource = "https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json"

        self._rest = RestData('GET', resource, None, None, None, True)
        self._partregion_ids = partregion_ids
        self.last_update = None
        self.sensordata = {}
        self.api_id_to_descr = {}
        self.available = False
        self.update()

    @Throttle(SCAN_INTERVAL)
    def update(self):
        """Get the latest pollen_name data from DWD open data site."""
        try:
            # Update DWD weather data by calling rest service
            self._rest.update()
            # Retrieve REST data from correspionding object
            rest_api_result = json.loads(self._rest.data)

            self.last_update = datetime.strptime(rest_api_result[REST_API_KEY_LAST_UPDATE], '%Y-%m-%d %H:%M Uhr')

            self.generate_api_id_to_descr_map(rest_api_result)

            # Iterate over all supplied partregions
            for partregion_data in rest_api_result[REST_API_KEY_CONTENT]:

                current_partregion_id = partregion_data[REST_API_KEY_PARTREGION_ID]
                if current_partregion_id == -1:
                    current_partregion_id = partregion_data[REST_API_KEY_REGION_ID]

                # Is the current partregion_id included in the ones we should parse?
                if current_partregion_id in self._partregion_ids:
                    self.sensordata[current_partregion_id] = {}
                    self.sensordata[current_partregion_id][SENSORDATA_REGION_NAME] = partregion_data[
                        REST_API_KEY_REGION_NAME]
                    self.sensordata[current_partregion_id][SENSORDATA_PARTREGION_NAME] = partregion_data[
                        REST_API_KEY_PARTREGION_NAME]

                    self.sensordata[current_partregion_id]['data'] = {}
                    self.calculateit(current_partregion_id, partregion_data[REST_API_KEY_POLLEN], 'today',
                                     self.last_update.date())
                    self.calculateit(current_partregion_id, partregion_data[REST_API_KEY_POLLEN], 'tomorrow',
                                     self.last_update.date() + timedelta(days=1))
                    self.calculateit(current_partregion_id, partregion_data[REST_API_KEY_POLLEN], 'dayafter_to',
                                     self.last_update.date() + timedelta(days=2))

            self.available = True
        except TypeError:
            _LOGGER.error("Unable to fetch pollen_name data from DWD opendata server")
            self.available = False

    def calculateit(self, current_partregion_id, pollendata, day, pollen_date):
        """
        Format:
            {
                "41": {
                    "region_name": "<region name>",
                    "partregion_name": "<partregion name>",
                    "data": {
                        "<pollen_date1>": {
                            "pollendata": {
                                "<polle1>": {
                                    "id": "<api ID>",
                                    "descr": "<api description of api ID>",
                                    "value": "<sensor value>"
                                },
                                "<polle2>": {
                                    "id": "<api ID>",
                                    "descr": "<api description of api ID>",
                                    "value": "<sensor value>"
                                }
                                [...]
                            },
                            "stats": {
                                "min": <minimum value>,
                                "max": <maximum value>,
                                "avg": <average value>
                            }
                        },
                        [...]
                    }
                }
            }
        """
        minimum = None
        # minimum = 6
        maximum = None
        # maximum = 0
        total_count = None
        # total_count = 0
        total_sum = None
        # total_sum = 0

        self.sensordata[current_partregion_id]['data'][pollen_date] = {}
        self.sensordata[current_partregion_id]['data'][pollen_date][SENSORDATA_POLLENDATA] = {}

        for pollen_name in pollendata:
            retrieved_pollendata = pollendata[pollen_name]
            internal_pollen_id = str(pollen_name).lower()
            self.sensordata[current_partregion_id]['data'][pollen_date][SENSORDATA_POLLENDATA][internal_pollen_id] = {}

            pollen_amount_api_id = retrieved_pollendata[day]
            pollen_amount_descr = self.api_id_to_descr[pollen_amount_api_id]
            pollen_amount_value = API_TO_HOMEASSISTANT_MAP[pollen_amount_api_id]

            self.sensordata[current_partregion_id]['data'][pollen_date][SENSORDATA_POLLENDATA][internal_pollen_id][
                'id'] = pollen_amount_api_id
            self.sensordata[current_partregion_id]['data'][pollen_date][SENSORDATA_POLLENDATA][internal_pollen_id][
                'descr'] = pollen_amount_descr
            self.sensordata[current_partregion_id]['data'][pollen_date][SENSORDATA_POLLENDATA][internal_pollen_id][
                'value'] = pollen_amount_value

            if pollen_amount_value is not None:
                minimum = pollen_amount_value if minimum is None else min(minimum, pollen_amount_value)
                maximum = pollen_amount_value if maximum is None else max(maximum, pollen_amount_value)
                total_count = 1 if total_count is None else total_count + 1
                total_sum = pollen_amount_value if total_sum is None else total_sum + pollen_amount_value

            _LOGGER.debug("Successfully retrieved pollen_name data for %s (ID %d).",
                          self.sensordata[current_partregion_id][SENSORDATA_PARTREGION_NAME],
                          current_partregion_id)

        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'] = {}
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_MIN] = {}
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_MIN]['value'] = minimum
        minimum_api_id = HOMEASSISTANT_TO_API_MAP[minimum]
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_MIN]['descr'] = self.api_id_to_descr[minimum_api_id]

        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_MAX] = {}
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_MAX]['value'] = maximum
        maximum_api_id = HOMEASSISTANT_TO_API_MAP[maximum]
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_MAX]['descr'] = self.api_id_to_descr[maximum_api_id]

        if total_count is None or total_sum is None or total_count <= 0:
            average = None
        else:
            average = total_sum / total_count
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_AVG] = {}
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_AVG]['value'] = average
        average_api_id = None if average is None else HOMEASSISTANT_TO_API_MAP[round(average, 0)]
        self.sensordata[current_partregion_id]['data'][pollen_date]['stats'][STAT_AVG]['descr'] = None if average_api_id is None else self.api_id_to_descr[average_api_id]

    def generate_api_id_to_descr_map(self, json_obj):
        legend_map = json_obj['legend']
        for key, value in legend_map.items():
            if not key.endswith('_desc'):
                self.api_id_to_descr[value] = legend_map["%s_desc" % key]

        self.api_id_to_descr['-1'] = 'n/a'

    def get_adjusted_day(self, day):
        today = datetime.now().date()
        last_update_day = self.last_update.date()
        offset = (today - last_update_day).days
        return DAY_ADJUSTMENTS[day][offset]

    def get_descr_for_value(self, value):
        if not value:
            return None
        api_id = HOMEASSISTANT_TO_API_MAP[value]
        if api_id in self.api_id_to_descr:
            return self.api_id_to_descr[api_id]
        else:
            return None