[#345] Rewritten `sun` plugin.
continuous-integration/drone/push Build is passing Details

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
1 changed files with 55 additions and 54 deletions

View File

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