Source code for pyowm.alertapi30.trigger

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pyowm.commons.exceptions
from pyowm.alertapi30.alert import Alert
from pyowm.alertapi30.condition import Condition
from pyowm.alertapi30.enums import AlertChannelsEnum
from pyowm.utils import formatting
from pyowm.utils.geo import GeometryBuilder


[docs] class Trigger: """ Object representing a the check if a set of weather conditions are met on a given geographical area: each condition is a rule on the value of a given weather parameter (eg. humidity, temperature, etc). Whenever a condition from a `Trigger` is met, the OWM API crates an alert and binds it to the the `Trigger`. A `Trigger` is the local proxy for the corresponding entry on the OWM API, therefore it can get ouf of sync as time goes by and conditions are met: it's up to you to "refresh" the local trigger by using a `pyowm.utils.alertapi30.AlertManager` instance. :param start_after_millis: how many milliseconds after the trigger creation the trigger begins to be checked :type start_after_millis: int :param end_after_millis: how many milliseconds after the trigger creation the trigger ends to be checked :type end_after_millis: int :param alerts: the `Alert` objects representing the alerts that have been fired for this `Trigger` so far. Defaults to `None` :type alerts: list of `pyowm.utils.alertapi30.Alert` instances :param conditions: the `Condition` objects representing the set of checks to be done on weather variables :type conditions: list of `pyowm.utils.alertapi30.Condition` instances :param area: the geographic are over which conditions are checked: it can be composed by multiple geoJSON types :type area: list of geoJSON types :param alert_channels: the alert channels through which alerts originating from this `Trigger` can be consumed. Defaults to OWM API polling :type alert_channels: list of `pyowm.utils.alertapi30.AlertChannel` instances :param id: optional unique ID for this `Trigger` instance :type id: str :returns: a *Trigger* instance :raises: *ValueError* when start or end epochs are `None` or when end precedes start or when conditions or area are empty collections """ def __init__(self, start_after_millis, end_after_millis, conditions, area, alerts=None, alert_channels=None, id=None): assert start_after_millis is not None assert end_after_millis is not None assert isinstance(start_after_millis, int) assert isinstance(end_after_millis, int) if start_after_millis > end_after_millis: raise ValueError("Error: trigger start time must precede trigger end time") self.start_after_millis = start_after_millis self.end_after_millis = end_after_millis assert conditions is not None if len(conditions) == 0: raise ValueError('A trigger must contain at least one condition: you provided none') self.conditions = conditions assert area is not None if len(area) == 0: raise ValueError('The area for a trigger must contain at least one geoJSON type: you provided none') self.area = area if alerts is None or len(alerts) == 0: self.alerts = [] else: self.alerts = alerts if alert_channels is None or len(alert_channels) == 0: self.alert_channels = [AlertChannelsEnum.OWM_API_POLLING] else: self.alert_channels = alert_channels self.id = id
[docs] def get_alerts(self): """ Returns all of the alerts for this `Trigger` :return: a list of `Alert` objects """ return self.alerts
[docs] def get_alert(self, alert_id): """ Returns the `Alert` of this `Trigger` having the specified ID :param alert_id: str, the ID of the alert :return: `Alert` instance """ for alert in self.alerts: if alert.id == alert_id: return alert return None
[docs] def get_alerts_since(self, timestamp): """ Returns all the `Alert` objects of this `Trigger` that were fired since the specified timestamp. :param timestamp: time object representing the point in time since when alerts have to be fetched :type timestamp: int, ``datetime.datetime`` or ISO8601-formatted string :return: list of `Alert` instances """ unix_timestamp = formatting.to_UNIXtime(timestamp) return [alert for alert in self.alerts if alert.last_update >= unix_timestamp]
[docs] def get_alerts_on(self, weather_param): """ Returns all the `Alert` objects of this `Trigger` that refer to the specified weather parameter (eg. 'temp', 'pressure', etc.). The allowed weather params are the ones enumerated by class `pyowm.alertapi30.enums.WeatherParametersEnum` :param weather_param: str, values in `pyowm.alertapi30.enums.WeatherParametersEnum` :return: list of `Alert` instances """ result = [] for alert in self.alerts: for met_condition in alert.met_conditions: if met_condition['condition'].weather_param == weather_param: result.append(alert) break return result
[docs] @classmethod def from_dict(cls, the_dict): if the_dict is None: raise pyowm.commons.exceptions.ParseAPIResponseError('Data is None') try: # trigger id trigger_id = the_dict.get('_id', None) # start timestamp start_dict = the_dict['time_period']['start'] expr = start_dict['expression'] if expr != 'after': raise ValueError('Invalid time expression: "%s" on start timestamp. Only: "after" is supported' % expr) start = start_dict['amount'] # end timestamp end_dict = the_dict['time_period']['end'] expr = end_dict['expression'] if expr != 'after': raise ValueError('Invalid time expression: "%s" on end timestamp. Only: "after" is supported' % expr) end = end_dict['amount'] # conditions conditions = [Condition.from_dict(c) for c in the_dict['conditions']] # alerts alerts_dict = the_dict['alerts'] alerts = list() for key in alerts_dict: alert_id = key alert_data = alerts_dict[alert_id] alert_last_update = alert_data['last_update'] alert_met_conds = [] for c in alert_data['conditions']: if isinstance(c['current_value'], int): cv = c['current_value'] else: cv = c['current_value']['min'] item = dict(current_value=cv, condition=Condition.from_dict(c['condition'])) alert_met_conds.append(item) alert_coords = alert_data['coordinates'] alert = Alert(alert_id, trigger_id, alert_met_conds, alert_coords, last_update=alert_last_update) alerts.append(alert) # area area_list = the_dict['area'] area = [GeometryBuilder.build(a_dict) for a_dict in area_list] # alert channels alert_channels = None # defaulting except ValueError as e: raise pyowm.commons.exceptions.ParseAPIResponseError( 'Impossible to parse JSON: %s' % e ) except KeyError as e: raise pyowm.commons.exceptions.ParseAPIResponseError( 'Impossible to parse JSON: %s' % e ) return Trigger(start, end, conditions, area=area, alerts=alerts, alert_channels=alert_channels, id=trigger_id)
[docs] def to_dict(self): return { "start_after_millis": self.start_after_millis, "end_after_millis": self.end_after_millis, "conditions": [c.to_dict() for c in self.conditions], "area": [g.to_dict() for g in self.area], "alerts": [alert.to_dict() for alert in self.alerts], "alert_channels": [ac.to_dict() for ac in self.alert_channels], "id": self.id }
def __repr__(self): return "<%s.%s - id=%s, start_after_mills=%s, end_after_mills=%s, alerts=%s>" % ( __name__, self.__class__.__name__, self.id if self.id is not None else 'None', self.start_after_millis, self.end_after_millis, str(len(self.alerts)))