[#345] Rewritten sun plugin.

Closes: #345
This commit is contained in:
Fabio Manganiello 2024-05-20 02:01:40 +02:00
parent 86b4b14112
commit d0f781919d
Signed by: blacklight
GPG key ID: D90FBA7F76362774

View file

@ -1,9 +1,8 @@
import datetime import datetime
import time from typing import Dict, Optional
from typing import Optional
import requests import requests
from dateutil.tz import gettz, tzutc from dateutil.tz import gettz
from platypush.message.event.sun import SunriseEvent, SunsetEvent from platypush.message.event.sun import SunriseEvent, SunsetEvent
from platypush.plugins import RunnablePlugin, action from platypush.plugins import RunnablePlugin, action
@ -16,6 +15,7 @@ class SunPlugin(RunnablePlugin):
""" """
_base_url = 'https://api.sunrise-sunset.org/json' _base_url = 'https://api.sunrise-sunset.org/json'
_schema = SunEventsSchema()
_attr_to_event_class = { _attr_to_event_class = {
'sunrise': SunriseEvent, 'sunrise': SunriseEvent,
'sunset': SunsetEvent, 'sunset': SunsetEvent,
@ -32,66 +32,54 @@ class SunPlugin(RunnablePlugin):
def main(self): def main(self):
while not self.should_stop(): while not self.should_stop():
# noinspection PyUnresolvedReferences next_events = self._get_events()
next_events = self.get_events().output next_event = next(
next_events = sorted( iter(
[ sorted(
event_class( [
latitude=self.latitude, event_class(
longitude=self.longitude, latitude=self.latitude,
time=next_events[attr], 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 attr, event_class in self._attr_to_event_class.items() ),
if next_events.get(attr) None,
],
key=lambda t: t.time,
) )
for event in next_events: assert next_event is not None, 'No next event found'
# noinspection PyTypeChecker wait_secs = max(
dt = datetime.datetime.fromisoformat(event.time) 0, (next_event.time - datetime.datetime.now(tz=gettz())).seconds
while (not self.should_stop()) and ( )
dt > datetime.datetime.now(tz=gettz()) self.wait_stop(wait_secs)
):
time.sleep(1)
if dt <= datetime.datetime.now(tz=gettz()): if not self.should_stop():
self.bus.post(event) self._bus.post(next_event)
self.wait_stop(2)
@staticmethod @staticmethod
def _convert_time(t: str) -> datetime.datetime: def _convert_time(t: str) -> datetime.datetime:
now = datetime.datetime.now().replace( now = datetime.datetime.now(datetime.UTC).replace(microsecond=0)
tzinfo=gettz() dt = datetime.datetime.strptime(
) # lgtm [py/call-to-non-callable] f'{now.year}-{now.month:02d}-{now.day:02d} {t}',
dt = datetime.datetime.strptime(t, '%H:%M:%S %p') '%Y-%m-%d %I:%M:%S %p',
dt = datetime.datetime( ).replace(tzinfo=datetime.UTC)
year=now.year,
month=now.month,
day=now.day,
hour=dt.hour,
minute=dt.minute,
second=dt.second,
tzinfo=tzutc(),
)
if dt < now: if dt < now:
dt += datetime.timedelta(days=1) dt += datetime.timedelta(days=1)
return datetime.datetime.fromtimestamp(dt.timestamp(), tz=gettz()) return dt
@action def _get_events(
def get_events(
self, latitude: Optional[float] = None, longitude: Optional[float] = None self, latitude: Optional[float] = None, longitude: Optional[float] = None
) -> dict: ) -> Dict[str, datetime.datetime]:
"""
Return the next sun events.
:param latitude: Default latitude override.
:param longitude: Default longitude override.
:return: .. schema:: sun.SunEventsSchema
"""
response = ( response = (
requests.get( requests.get(
self._base_url, self._base_url,
timeout=10,
params={ params={
'lat': latitude or self.latitude, 'lat': latitude or self.latitude,
'lng': longitude or self.longitude, 'lng': longitude or self.longitude,
@ -101,11 +89,24 @@ class SunPlugin(RunnablePlugin):
.get('results', {}) .get('results', {})
) )
return {
attr: self._convert_time(t)
for attr, t in response.items()
if attr in self._schema.declared_fields
}
@action
def get_events(
self, latitude: Optional[float] = None, longitude: Optional[float] = None
) -> dict:
"""
Return the next sun events.
:param latitude: Override the default latitude.
:param longitude: Override the default longitude.
:return: .. schema:: sun.SunEventsSchema
"""
schema = SunEventsSchema() schema = SunEventsSchema()
return schema.dump( return dict(
{ schema.dump(self._get_events(latitude=latitude, longitude=longitude))
attr: self._convert_time(t)
for attr, t in response.items()
if attr in schema.declared_fields
}
) )