Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for ovos api service and caching #2

Merged
merged 6 commits into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions skill/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
from .intent import WeatherIntent
from .weather import CURRENT, DAILY, DailyWeather, HOURLY, WeatherReport
from .util import LocationNotFoundError
from .ovosbackend import OVOSApiBackend
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
67 changes: 63 additions & 4 deletions skill/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@
provided, precluding us from having to do the conversions.

"""
import os
from mycroft.api import Api
from .weather import WeatherReport
from .ovosbackend import OVOSApiBackend
from json_database import JsonStorageXDG
import threading

OPEN_WEATHER_MAP_LANGUAGES = (
"af",
Expand Down Expand Up @@ -83,6 +87,8 @@ class OpenWeatherMapApi(Api):
def __init__(self):
super().__init__(path="owm")
self.language = "en"
self.localbackend = OVOSApiBackend()
self.cache_response_location = JsonStorageXDG("skill-weather-response-cache")

def get_weather_for_coordinates(
self, measurement_system: str, latitude: float, longitude: float
Expand All @@ -101,11 +107,64 @@ def get_weather_for_coordinates(
lon=longitude,
units=measurement_system
)
api_request = dict(path="/onecall", query=query_parameters)
response = self.request(api_request)
local_weather = WeatherReport(response)

self.clear_cache_timer()
if self.check_if_cached_weather_exist(latitude, longitude):
response = self.get_cached_weather_results(latitude, longitude)
local_weather = WeatherReport(response)
else:
try:
api_request = dict(path="/onecall", query=query_parameters)
response = self.request(api_request)
weather_cache_response = {'lat': latitude, 'lon': longitude, 'response': response}
print(weather_cache_response)
self.cache_weather_results(weather_cache_response)
local_weather = WeatherReport(response)
except:
response = self.localbackend.get_report_for_weather_onecall_type(query=query_parameters)
weather_cache_response = {'lat': latitude, 'lon': longitude, 'response': response}
print(weather_cache_response)
self.cache_weather_results(weather_cache_response)
local_weather = WeatherReport(response)

return local_weather

def cache_weather_results(self, weather_response):
cache_response = {'lat': weather_response["lat"], 'lon': weather_response["lon"], 'response': weather_response["response"]}
if "caches" in self.cache_response_location:
cache_responses = self.cache_response_location["caches"]
else:
cache_responses = []

if cache_response not in cache_responses:
cache_responses.append(cache_response)

self.cache_response_location["caches"] = cache_responses
self.cache_response_location.store()

def check_if_cached_weather_exist(self, latitude, longitude):
if "caches" in self.cache_response_location:
cache_responses = self.cache_response_location["caches"]
for cache_response in cache_responses:
if cache_response["lat"] == latitude and cache_response["lon"] == longitude:
return True
else:
return False
else:
return False

def get_cached_weather_results(self, latitude, longitude):
if "caches" in self.cache_response_location:
cache_responses = self.cache_response_location["caches"]
for cache_response in cache_responses:
if cache_response["lat"] == latitude and cache_response["lon"] == longitude:
return cache_response["response"]

def clear_cache_timer(self):
if "caches" in self.cache_response_location:
threading.Timer(900, self.clear_cache).start()

def clear_cache(self):
os.remove(self.cache_response_location.path)

def set_language_parameter(self, language_config: str):
"""
Expand Down
49 changes: 49 additions & 0 deletions skill/ovosbackend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import json
import requests
from json_database import JsonStorageXDG


class OVOSApiBackend:

def __init__(self) -> None:
self.uuid_storage = JsonStorageXDG("ovos_api_uuid")
self.token_storage = JsonStorageXDG("ovos_api_token")

def register_device(self):
if self.check_if_uuid_exists():
return
else:
created_challenge = requests.get('https://api.openvoiceos.com/create_challenge')
challenge_response = created_challenge.json()
register_device = requests.get('https://api.openvoiceos.com/register_device/' + challenge_response['challenge'] + '/' + challenge_response['secret'])
register_device_uuid = challenge_response['challenge']
self.uuid_storage['uuid'] = register_device_uuid
self.uuid_storage.store()

def check_if_uuid_exists(self):
if "uuid" in self.uuid_storage:
return True
return False

def get_session_challenge(self):
session_challenge_request = requests.get('https://api.openvoiceos.com/get_session_challenge')
session_challenge_response = session_challenge_request.json()
self.token_storage["challenge"] = session_challenge_response['challenge']
self.token_storage.store()

def get_uuid(self):
return self.uuid_storage.get("uuid", "")

def get_session_token(self):
return self.token_storage.get("challenge", "")

def get_report_for_weather_onecall_type(self, query: dict):
self.register_device()
self.get_session_challenge()

headers = {'session_challenge': self.get_session_token(), 'backend': 'OWM'}
print(headers)
reqdata = {"lat": query.get("lat"), "lon": query.get("lon"), "units": query.get("units"), "lang": query.get("lang")}
onecall_weather_request = requests.post('https://api.openvoiceos.com/weather/onecall_weather_report/' + self.get_uuid(), data=reqdata, headers=headers)
onecall_weather_response = onecall_weather_request.text
return json.loads(onecall_weather_response)
3 changes: 3 additions & 0 deletions skill/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ class WeatherReport:
"""Full representation of the data returned by the Open Weather Maps One Call API"""

def __init__(self, report):
print("Printing Report")
print(report)
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved

timezone = report["timezone"]
self.current = CurrentWeather(report["current"], timezone)
self.hourly = [HourlyWeather(hour, timezone) for hour in report["hourly"]]
Expand Down