diff --git a/api_key.py b/api_key.py new file mode 100644 index 0000000000000000000000000000000000000000..dcb21d5d7fa039c47a7b1125b0fd79b6c5cf6d19 --- /dev/null +++ b/api_key.py @@ -0,0 +1 @@ +API_KEY = '[replace this string with your API key]' diff --git a/main.py b/main.py index 2a89e561ea4ed7272167b6e5e582fc69dcbe2ec8..a1ae0dcf1678554967c4ebbebc68cada3f4bf3f1 100644 --- a/main.py +++ b/main.py @@ -1,27 +1,83 @@ from kivy.app import App +from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label +from kivy.properties import ListProperty from kivy.logger import Logger +from datetime import datetime from json import dumps -from openmrs import RESTConnection +from api_key import API_KEY +from rest import RESTConnection + + +UNL_LATITUDE = 40.81750 +UNL_LONGITUDE = -96.701389 + + +def to_human_readable_time(timestamp): + return datetime.utcfromtimestamp(timestamp).strftime('%A %I:%M %p') + + +def to_celsius(kelvin): + return kelvin - 273.15 + + +def format_forecast_record(record): + try: + time = to_human_readable_time(record['dt']) + description = ', '.join(condition['description'] for condition in record['weather']) + temperature = to_celsius(record['main']['temp']) + humidity = record['main']['humidity'] + feels_like = to_celsius(record['main']['feels_like']) + return \ + f'{time}: {description}, {temperature:.1f} degrees, {humidity:.0f}% humidity, ' + \ + f'feels like {feels_like:.1f} degrees' + except KeyError: + return '[invalid forecast record]' + + +class Record(Label): + pass + + +class Records(BoxLayout): + records = ListProperty([]) + + def rebuild(self): + self.clear_widgets() + for record in self.records: + self.add_widget(Record(text=record)) + + def on_records(self, _, __): + self.rebuild() class RestApp(App): - def load_locations(self): - self.root.ids.results.clear_widgets() - openmrs_connection = RESTConnection('localhost', 8080, 'admin', 'Admin123') - openmrs_connection.send_request('location', None, None, self.on_locations_loaded, - self.on_locations_not_loaded, self.on_locations_not_loaded) + records = ListProperty([]) + + def load_records(self): + self.records = [] + connection = RESTConnection('api.agromonitoring.com', 443, '/agro/1.0') + connection.send_request( + 'weather/forecast', + { + 'appid': API_KEY, + 'lat': UNL_LATITUDE, + 'lon': UNL_LONGITUDE, + }, + None, + self.on_records_loaded, + self.on_records_not_loaded, + self.on_records_not_loaded + ) - def on_locations_loaded(self, _, response): + def on_records_loaded(self, _, response): print(dumps(response, indent=4, sort_keys=True)) - results_layout = self.root.ids.results - for result in response['results']: - results_layout.add_widget(Label(text=result['display'])) + self.records = [format_forecast_record(record) for record in response] - def on_locations_not_loaded(self, _, error): - self.root.ids.results.add_widget(Label(text='[Failed to load locations]')) + def on_records_not_loaded(self, _, error): + self.records = ['[Failed to load records]'] Logger.error(f'{self.__class__.__name__}: {error}') diff --git a/rest.kv b/rest.kv index 8f7f17995135310529e381038b47118fba15f9d1..96678b06f3e1632a317427d2cc35b1bde188197c 100644 --- a/rest.kv +++ b/rest.kv @@ -1,8 +1,18 @@ BoxLayout: orientation: 'vertical' - BoxLayout: - id: results - orientation: 'vertical' + ScrollView: + Records: + records: app.records Button: - text: 'Load Locations' - on_press: app.load_locations() + text: 'Load Records' + size_hint: (1.0, 0.25) + on_press: app.load_records() + +<Records>: + orientation: 'vertical' + size_hint: (1.0, None) + height: sum(child.height for child in self.children) + +<Record>: + text_size: self.size + halign: 'center' diff --git a/openmrs.py b/rest.py similarity index 60% rename from openmrs.py rename to rest.py index 6cc768aed47945f16090b20b96ffcc7c0a146fb8..5ab6cf6bceb072d0a65ab9586c19db9c0619ecf9 100644 --- a/openmrs.py +++ b/rest.py @@ -1,28 +1,26 @@ -from kivy.network.urlrequest import UrlRequest - import base64 import json -try: - from urllib import quote -except ImportError: - from urllib.parse import quote + +from kivy.network.urlrequest import UrlRequest +from urllib.parse import quote class RESTConnection: - def __init__(self, authority, port, username, password): + def __init__(self, authority, port, root_path, username=None, password=None): self.authority = authority self.port = port - credentials = f'{username}:{password}' - credentials = base64.standard_b64encode(credentials.encode('UTF8')).decode('UTF8') + self.root_path = root_path self.headers = { - 'Authorization': f'Basic {credentials}', 'Content-type': 'application/json', } + if username is not None and password is not None: + credentials = base64.standard_b64encode(f'{username}:{password}'.encode('UTF8')).decode('UTF8') + self.headers['Authorization'] = f'Basic {credentials}' def construct_url(self, resource, get_parameters=None): - get_parameters = '&'.join(f'{quote(str(key))}={quote(str(value))}' for key, value in get_parameters.items()) \ + parameter_string = '&'.join(f'{quote(str(key))}={quote(str(value))}' for key, value in get_parameters.items()) \ if get_parameters is not None else '' - return f'http://{self.authority}:{self.port}/openmrs/ws/rest/v1/{resource}?{get_parameters}' + return f'https://{self.authority}:{self.port}{self.root_path}/{resource}?{parameter_string}' def send_request_by_url(self, url, post_parameters, on_success, on_failure, on_error): UrlRequest(url, req_headers=self.headers,