Weather Alert API¶
You can use the OWM API to create triggers.
Each trigger represents the check if a set of conditions on certain weather parameter values are met over certain geographic areas.
Whenever a condition is met, an alert is fired and stored, and can be retrieved by polling the API.
OWM website technical reference¶
A full example first¶
Hands-on! This is a full example of how to use the Alert API. Check further for details about the involved object types.
from pyowm import OWM
from pyowm.utils import geo
from pyowm.alertapi30.enums import WeatherParametersEnum, OperatorsEnum, AlertChannelsEnum
from pyowm.alertapi30.condition import Condition
# obtain an AlertManager instance
owm = OWM('apikey')
am = owm.alert_manager()
# -- areas --
geom_1 = geo.Point(lon, lat) # available types: Point, MultiPoint, Polygon, MultiPolygon
geom_1.geojson()
'''
{
"type": "Point",
"coordinates":[ lon, lat ]
}
'''
geom_2 = geo.MultiPolygon([[lon1, lat1], [lon2, lat2], [lon3, lat3], [lon1, lat1]]
[[lon7, lat7], [lon8, lat8], [lon9, lat9], [lon7, lat7]])
# -- conditions --
condition_1 = Condition(WeatherParametersEnum.TEMPERATURE,
OperatorsEnum.GREATER_THAN,
313.15) # kelvin
condition_2 = Condition(WeatherParametersEnum.CLOUDS,
OperatorsEnum.EQUAL,
80) # clouds % coverage
# -- triggers --
# create a trigger
trigger = am.create_trigger(start_after_millis_=355000, end_after_millis=487000,
conditions=[condition_1, condition_2],
area=[geom_1, geom_2],
alert_channel=AlertChannelsEnum.OWM_API)
# read all triggers
triggers_list = am.get_triggers()
# read one named trigger
trigger_2 = am.get_trigger('trigger_id')
# update a trigger
am.update_trigger(trigger_2)
# delete a trigger
am.delete_trigger(trigger_2)
# -- alerts --
# retrieved from the local parent Trigger obj...
alerts_list = trigger.get_alerts()
alerts_list = trigger.get_alerts_since('2018-01-09T23:07:24Z') # useful for polling alerts
alerts_list = trigger.get_alerts_on(WeatherParametersEnum.TEMPERATURE)
alert = trigger.get_alert('alert_id')
# ...or retrieved from the remote API
alerts_list_alternate = am.get_alerts_for(trigger)
alert_alternate = am.get_alert('alert_id')
# delete all or one alert
am.delete_all_alerts_for(trigger)
am.delete_alert_for(trigger, alert)
Alert API object model¶
This is the Alert API object model:
- Trigger: collection of alerts to be met over specified areas and within a specified time frame according to specified weather params conditions
- Condition: rule for matching a weather measurement with a specified threshold
- Alert: whenever a condition is met, an alert is created (or updated) and can be polled to verify when it has been met and what the actual weather param value was.
- Area: geographic area over which the trigger is checked
- AlertChannel: as OWM plans to add push-oriented alert channels (eg. push notifications), we need to encapsulate this into a specific class
and then you have an AlertManager class that you will need to instantiate to operatively interact with the Alert API
Area¶
The area describes the geographic boundaries over which a trigger is evaluated. Don’t be mislead by the term “area”: this can refer also to a specific geopoint or a set of them, besides - of course - polygons and set of polygons.
Any of the geometry subtypes found in pyowm.utils.geo
module (point, multipoint, polygon, multipolygon) are fine to use.
Example:
from pyowm.utils import geo
point = geo.Point(20.8, 30.9) # available geometry types: Point, MultiPoint, Polygon, MultiPolygon
point.geojson()
'''
{
"type": "Point",
"coordinates":[ 20.8, 30.9 ]
}
'''
Defining complex geometries is sometimes difficult, but in most cases you just need to set triggers upon cities: that’s
why we’ve added a method to the pyowm.weatherapi25.cityidregistry.CityIDRegistry
registry that returns the geopoints
that correspond to one or more named cities:
import pyowm
owm = pyowm.OWM('your-API-key')
reg = owm.city_id_registry()
geopoints = reg.geopoints_for('London', country='GB')
But still some very spread cities (think of London,GB or Los Angeles,CA) exist and therefore approximating a city to a single point is not accurate at all: that’s why we’ve added a nice method to get a squared polygon that is circumscribed to the circle having a specified geopoint as its centre. This makes it possible to easily get polygons to cover large squared areas and you would only need to specify the radius of the circle. Let’s do it for London,GB in example:
geopoints = reg.geopoints_for('London', country='GB')
centre = geopoints[0] # the list has only 1 geopoint
square_polygon = centre.bounding_square_polygon(inscribed_circle_radius_km=12) # radius of the inscribed circle in kms (defaults to: 10)
Please, notice that if you specify big values for the radius you need to take care about the projection of geographic coordinates on a proper geoid: this means that if you don’t, the polygon will only approximate a square.
Topology is set out as stated by GeoJSON
Moreover, there is a useful factory for Areas: pyowm.utils.geo.GeometryBuilder.build()
, that you can use to turn a geoJSON standard
dictionary into the corresponding topology type:
from pyowm.utils.geo import GeometryBuilder
the_dict = {
"type": "Point",
"coordinates": [53, 37]
}
geom = GeometryBuilder.build(the_dict)
type(geom) # <pyowm.utils.geo.Point>
You can bind multiple pyowm.utils.geo
geometry types to a Trigger: a list of such geometries is considered to be
the area on which conditions of a Trigger are checked.
Condition¶
A condition is a numeric rule to be checked on a named weather variable. Something like:
- VARIABLE X IS GREATER THAN AMOUNT_1
- VARIABLE Y IS EQUAL TO AMOUNT_2
- VARIABLE Z IS DIFFERENT FROM AMOUNT_3
GREATER, EQUAL TO, DIFFERENT FROM
are called comparison expressions or operators; VARIABLE X, Y, Z
are
called target parameters.
Each condition is then specified by:
- target_param: weather parameter to be checked. Can be:
temp, pressure, humidity, wind_speed, wind_direction, clouds
. - expression: str, operator for the comparison. Can be:
$gt
, $gte, $lt, $lte, $eq, $ne` - amount: number, the comparison value
Conditions are bound to Triggers, as they are set on Trigger instantiation.
As Conditions can be only set on a limited number of weather variables and can be expressed only through a closed set of
comparison operators, convenient enumerators are offered in module pyowm.alertapi30.enums
:
WeatherParametersEnum
–> what weather variable to set this condition onOperatorsEnum
–> what comparison operator to use on the weather parameter
Use enums so that you don’t have to remember the syntax of operators and weather params that is specific to the OWM Alert API. Here is how you use them:
from pyowm.alertapi30 import enums
enums.WeatherParametersEnum.items() # [('TEMPERATURE', 'temp'), ('WIND_SPEED', 'wind_speed'), ... ]
enums.WeatherParametersEnum.TEMPERATURE # 'temp'
enums.WeatherParametersEnum.WIND_SPEED # 'wind_speed'
enums.OperatorsEnum.items() # [('GREATER_THAN', '$gt'), ('NOT_EQUAL', '$ne'), ... ]
enums.OperatorsEnum.GREATER_THAN # '$gt'
enums.OperatorsEnum.NOT_EQUAL # '$ne'
Here is an example of conditions:
from pyowm.alertapi30.condition import Condition
from pyowm.alertapi30 import enums
# this condition checks if the temperature is bigger than 313.15 Kelvin degrees
condition = Condition(enums.WeatherParametersEnum.TEMPERATURE,
enums.OperatorsEnum.GREATER_THAN,
313.15)
Remember that each Condition is checked by the OWM Alert API on the geographic area that you need to specify!
You can bind multiple pyowm.alertapi30.condition.Condition
objects to a Trigger: each Alert will be fired when
a specific Condition is met on the area.
Alert¶
As said, whenever one or more conditions are met on a certain area, an alert is fired (this means that “the trigger triggers”)
If the condition then keeps on being met, more and more alerts will be spawned by the OWM Alert API. You can retrieve such alerts by polling the OWM API (see below about how to do it).
Each alert is represented by PyOWM as a pyowm.alertapi30.alert.Alert
instance, having:
- a unique identifier
- timestamp of firing
- a link back to the unique identifier of the parent
pyowm.alertapi30.trigger.Trigger
object instance - the list of met conditions (each one being a dict containing the
Condition
object and the weather parameter value that actually made the condition true) - the geocoordinates where the condition has been met (they belong to the area that had been specified for the Trigger)
Example:
from pyowm.alertapi30.condition import Condition
from pyowm.alertapi30 import enums
from pyowm.alertapi30.alert import Alert
condition = Condition(enums.WeatherParametersEnum.TEMPERATURE,
enums.OperatorsEnum.GREATER_THAN,
356.15)
alert = Alert('alert-id', # alert id
'parent-trigger-id', # parent trigger's id
[{ # list of met conditions
"current_value": 326.4,
"condition": condition
}],
{"lon": 37, "lat": 53}, # coordinates
1481802100000 # fired on
)
As you see, you’re not meant to create alerts, but PyOWM is supposed to create them for you as they are fired by the OWM API.
AlertChannel¶
Something that OWM envisions, but still does not offer. Possibly, when you will setup a trigger you shall also specify
the channels you want to be notified on: that’s why we’ve added a reference to a list of AlertChannel
instances
directly on the Trigger objects (the list now only points to the default channel)
A useful enumerator is offered in module pyowm.alertapi30.enums
: AlertChannelsEnum
(says what channels should the alerts
delivered to)
As of today, the default AlertChannel
is: AlertChannelsEnum.OWM_API_POLLING
, and is the only one available.
Trigger¶
As said, each trigger represents the check if a set of conditions on certain weather parameter values are met over certain geographic areas.
A Trigger is the local proxy for the corresponding entry on the OWM API: Triggers can be operated through
pyowm.alertapi30.alertmanager.AlertManager
instances.
Each Trigger has these attributes:
- start_after_millis: with respect to the time when the trigger will be created on the Alert API, how many milliseconds after should it begin to be checked for conditions matching
- end_after_millis: with respect to the time when the trigger will be created on the Alert API, how many milliseconds after should it end to be checked for conditions matching
- alerts: a list of
pyowm.alertapi30.alert.Alert
instances, which are the alerts that the trigger has fired so far - conditions: a list of
pyowm.alertapi30.condition.Condition
instances - area: a list of
pyowm.utils.geo.Geometry
instances, representing the geographic area on which the trigger’s conditions need to be checked - alertChannels: list of
pyowm.alertapi30.alert.AlertChannel
objects, representing which channels this trigger is notifying to
Notes on trigger’s time period
By design, PyOWM will only use the after
operator to communicate time periods for Triggers to the Alert API.
will send them to the API using the after
operator.
The millisecond start/end deltas will be calculated with respect to the time when the Trigger record is created on the
Alert API using pyowm.alertapi30.alertmanager.AlertManager.create_trigger
AlertManager¶
The OWM main entry point object allows you to get an instance of an pyowm.alertapi30.alert_manager.AlertManager
object:
use it to interact with the Alert API and create/read/update/delete triggers and read/delete the related alerts.
Here is how to instantiate an AlertManager
:
from pyowm import OWM
owm = OWM(API_Key='my-API-key')
am = owm.alert_manager()
Then you can do some nice things with it:
- create a trigger
- read all of your triggers
- read a named trigger
- modify a named trigger
- delete a named trigger
- read all the alerts fired by a named trigger
- read a named alert
- delete a named alert
- delete all of the alerts for a named trigger