forked from platypush/platypush
87 lines
3 KiB
Python
87 lines
3 KiB
Python
import datetime
|
|
import time
|
|
from typing import Optional
|
|
|
|
import requests
|
|
from dateutil.tz import gettz, tzutc
|
|
|
|
from platypush.message.event.sun import SunriseEvent, SunsetEvent
|
|
from platypush.plugins import RunnablePlugin, action
|
|
from platypush.schemas.sun import SunEventsSchema
|
|
|
|
|
|
class SunPlugin(RunnablePlugin):
|
|
"""
|
|
Plugin to get sunset/sunrise events and info for a certain location.
|
|
|
|
Triggers:
|
|
|
|
* :class:`platypush.message.event.sun.SunriseEvent` on sunrise.
|
|
* :class:`platypush.message.event.sun.SunsetEvent` on sunset.
|
|
|
|
"""
|
|
_base_url = 'https://api.sunrise-sunset.org/json'
|
|
_attr_to_event_class = {
|
|
'sunrise': SunriseEvent,
|
|
'sunset': SunsetEvent,
|
|
}
|
|
|
|
def __init__(self, latitude: float, longitude: float, **kwargs):
|
|
"""
|
|
:param latitude: Default latitude.
|
|
:param longitude: Default longitude.
|
|
"""
|
|
super().__init__(**kwargs)
|
|
self.latitude = latitude
|
|
self.longitude = longitude
|
|
|
|
def main(self):
|
|
while not self.should_stop():
|
|
# noinspection PyUnresolvedReferences
|
|
next_events = self.get_events().output
|
|
next_events = sorted([
|
|
event_class(latitude=self.latitude, longitude=self.longitude, time=next_events[attr])
|
|
for attr, event_class in self._attr_to_event_class.items()
|
|
if next_events.get(attr)
|
|
], key=lambda t: t.time)
|
|
|
|
for event in next_events:
|
|
# noinspection PyTypeChecker
|
|
dt = datetime.datetime.fromisoformat(event.time)
|
|
while (not self.should_stop()) and (dt > datetime.datetime.now(tz=gettz())):
|
|
time.sleep(1)
|
|
|
|
if dt <= datetime.datetime.now(tz=gettz()):
|
|
self.bus.post(event)
|
|
|
|
@staticmethod
|
|
def _convert_time(t: str) -> datetime.datetime:
|
|
now = datetime.datetime.now().replace(tzinfo=gettz()) # lgtm [py/call-to-non-callable]
|
|
dt = datetime.datetime.strptime(t, '%H:%M:%S %p')
|
|
dt = datetime.datetime(year=now.year, month=now.month, day=now.day,
|
|
hour=dt.hour, minute=dt.minute, second=dt.second, tzinfo=tzutc())
|
|
|
|
if dt < now:
|
|
dt += datetime.timedelta(days=1)
|
|
return datetime.datetime.fromtimestamp(dt.timestamp(), tz=gettz())
|
|
|
|
@action
|
|
def get_events(self, latitude: Optional[float] = None, longitude: Optional[float] = None) -> dict:
|
|
"""
|
|
Return the next sun events.
|
|
|
|
:param latitude: Default latitude override.
|
|
:param longitude: Default longitude override.
|
|
:return: .. schema:: sun.SunEventsSchema
|
|
"""
|
|
response = requests.get(self._base_url, params={
|
|
'lat': latitude or self.latitude,
|
|
'lng': longitude or self.longitude,
|
|
}).json().get('results', {})
|
|
|
|
schema = SunEventsSchema()
|
|
return schema.dump({
|
|
attr: self._convert_time(t)
|
|
for attr, t in response.items()
|
|
if attr in schema.declared_fields.keys()
|
|
})
|