From eb2d4f89d753b772173473ac098d05305f509994 Mon Sep 17 00:00:00 2001 From: Agustinefe Date: Wed, 3 Jan 2024 20:00:16 -0300 Subject: [PATCH 1/6] Fetch data from weather api --- src/data_packet.py | 37 +++++++++++++++++++++++++++++++++---- src/main.py | 2 ++ src/requirements.txt | 2 ++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 src/requirements.txt diff --git a/src/data_packet.py b/src/data_packet.py index e14bb44..e85e923 100644 --- a/src/data_packet.py +++ b/src/data_packet.py @@ -1,4 +1,34 @@ import random as rnd +import requests as req +from requests import Response +from dotenv import load_dotenv +from os import environ +from typing import Optional, Tuple +import math + + +load_dotenv() + +def fetch_temperature_and_humidity(location: str) -> Tuple[int, int]: + + base_params = { + "q": location, + "APPID": environ['WEATHER_API_KEY'] + } + res: Response = req.get(environ["WEATHER_API_URL"], params=base_params) + + if not res.ok: + raise Exception("Could fetch temperature and humidity from weather API") + + result = res.json() + temperature = int(result["main"]["temp"] - 273.15) + humidity = result["main"]["humidity"] + + return temperature, humidity + + + + ''' Creates a data packet with simulated data, validating the data before that. @@ -39,14 +69,13 @@ def create_packet(temperature: float = None, humidity: float = None, light: floa - - ''' -def generate_data(): +def generate_data(location = "Pilar, AR") -> Tuple[int, int, int, int]: #TODO - temperature = rnd.randint(-5, 30) - humidity = rnd.randint(0, 100) + temperature, humidity = fetch_temperature_and_humidity(location) light = rnd.randint(0, 400) watering = rnd.randint(0, 100) - return temperature, humidity, light, watering + return temperature, humidity, light, watering ''' Compares the current packet and the last sent packet, based in the deviations. diff --git a/src/main.py b/src/main.py index 8b3dad0..5f1f3fc 100644 --- a/src/main.py +++ b/src/main.py @@ -28,12 +28,14 @@ def simulate_packets(config): # TODO: Send packet to the RabbitMQ queue logging.info(f"Packet sent: {current_packet}") + last_sent_packet = current_packet except Exception as err: logging.warning(err) finally: + print(current_packet) time.sleep(config["packet_period"]) diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..8804ab6 --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,2 @@ +requests +python-dotenv \ No newline at end of file From 9f41bfff4ec7177feec49e28d581099c812fc112 Mon Sep 17 00:00:00 2001 From: Agustinefe Date: Sun, 7 Jan 2024 20:07:32 -0300 Subject: [PATCH 2/6] Add simulator to fetch light --- src/data_packet.py | 130 +++++++++++++++++++++++++++++---------------- src/main.py | 3 +- 2 files changed, 86 insertions(+), 47 deletions(-) diff --git a/src/data_packet.py b/src/data_packet.py index e85e923..d9ed5fc 100644 --- a/src/data_packet.py +++ b/src/data_packet.py @@ -3,14 +3,15 @@ from requests import Response from dotenv import load_dotenv from os import environ -from typing import Optional, Tuple +from typing import Tuple +from datetime import datetime import math - load_dotenv() + def fetch_temperature_and_humidity(location: str) -> Tuple[int, int]: - + base_params = { "q": location, "APPID": environ['WEATHER_API_KEY'] @@ -18,8 +19,10 @@ def fetch_temperature_and_humidity(location: str) -> Tuple[int, int]: res: Response = req.get(environ["WEATHER_API_URL"], params=base_params) if not res.ok: - raise Exception("Could fetch temperature and humidity from weather API") - + raise Exception( + "Could fetch temperature and humidity from weather API" + ) + result = res.json() temperature = int(result["main"]["temp"] - 273.15) humidity = result["main"]["humidity"] @@ -27,32 +30,59 @@ def fetch_temperature_and_humidity(location: str) -> Tuple[int, int]: return temperature, humidity +def solar_irradiation_simulator(x): + x += 14 + x *= (math.pi / 6) + x = math.sin(x) + x += 1 + x *= 500 + return x +def fetch_solar_irradiation(): + current_hour = datetime.now() + x = current_hour.hour + ( + 60 * current_hour.minute + current_hour.second + ) / 3600 -''' -Creates a data packet with simulated data, validating the data before that. + return round(solar_irradiation_simulator(x)) -If all the parameters are empty, returns None. Else, return a dictionary with the data. +def create_packet(temperature: float = None, + humidity: float = None, + light: float = None, + watering: float = None): + ''' + Creates a data packet with simulated data, validating the data before that. + + If all the parameters are empty, returns None. Else, return a dictionary + with the data. + + + Constraints: + - Humidity and Watering should be between 0 and 100, since they are + percentages. + - Light has to be positive or 0. + ''' -Constraints: -- Humidity and Watering should be between 0 and 100, since they are percentages. -- Light has to be positive or 0. -''' -def create_packet(temperature: float = None, humidity: float = None, light: float = None, watering: float = None): if not (temperature and humidity and light and watering): return None - + if humidity < 0 or humidity > 100: - raise Exception(f"Humidity has to be between 0 and 100. Current value: {humidity}") - + raise Exception( + f"Humidity has to be between 0 and 100. Current value: {humidity}" + ) + if watering < 0 or watering > 100: - raise Exception(f"Watering has to be between 0 and 100. Current value: {watering}") - + raise Exception( + f"Watering has to be between 0 and 100. Current value: {watering}" + ) + if light < 0: - raise Exception(f"Light has to be positive or 0. Current value: {light}") - + raise Exception( + f"Light has to be positive or 0. Current value: {light}" + ) + return { "temperature": temperature, "humidity": humidity, @@ -61,40 +91,48 @@ def create_packet(temperature: float = None, humidity: float = None, light: floa } -''' -Generates the parameters data: temperature, humidity, light and watering. +def generate_data(location="Pilar, AR") -> Tuple[int, int, int, int]: + ''' + Generates the parameters data: temperature, humidity, light and watering. + + [Describe the criteria of every parameter here] + - + - + - + ''' + # TODO -[Describe the criteria of every parameter here] -- -- -- -''' -def generate_data(location = "Pilar, AR") -> Tuple[int, int, int, int]: - #TODO temperature, humidity = fetch_temperature_and_humidity(location) - light = rnd.randint(0, 400) + light = fetch_solar_irradiation() watering = rnd.randint(0, 100) return temperature, humidity, light, watering -''' -Compares the current packet and the last sent packet, based in the deviations. - -If any parameter differs enough from the last sent packet, then the packet -must be sent. - -In other words: if (|current[parameter] - last_sent[parameter]| > deviations[parameter]), return True. -Else, return False - -If there is no last_sent, then the current must be sent. -Types: -- current: {temperature: float, humidity: float, light: float, watering: float} -- last_sent: {temperature: float, humidity: float, light: float, watering: float} -- deviations: {temperature: float, humidity: float, light: float, watering: float} -''' def current_packet_differs_from_last_sent(current, last_sent, deviations): - #TODO + ''' + Compares the current packet and the last sent packet, + based in the deviations. + + If any parameter differs enough from the last sent packet, then the packet + must be sent. + + In other words: + if (|current[parameter] - last_sent[parameter]| > deviations[parameter]), + return True. + Else, return False + + If there is no last_sent, then the current must be sent. + + Types: + - current: {temperature: float, humidity: float, light: float, + watering: float} + - last_sent: {temperature: float, humidity: float, light: float, + watering: float} + - deviations: {temperature: float, humidity: float, light: float, + watering: float} + ''' + # TODO if not last_sent: return True diff --git a/src/main.py b/src/main.py index 5f1f3fc..f873143 100644 --- a/src/main.py +++ b/src/main.py @@ -9,7 +9,8 @@ - Enviar paquete a la queue. ''' -import time, random +import time +import random import logging from data_packet import generate_data, create_packet, current_packet_differs_from_last_sent From 4146e1e3abf7e07a49964c177ee6dec0666e7112 Mon Sep 17 00:00:00 2001 From: Agustinefe Date: Sun, 7 Jan 2024 20:09:01 -0300 Subject: [PATCH 3/6] Fix light in night hours@ --- src/data_packet.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/data_packet.py b/src/data_packet.py index d9ed5fc..5d65373 100644 --- a/src/data_packet.py +++ b/src/data_packet.py @@ -31,6 +31,9 @@ def fetch_temperature_and_humidity(location: str) -> Tuple[int, int]: def solar_irradiation_simulator(x): + if x < 7 or x > 19: + return 0 + x += 14 x *= (math.pi / 6) x = math.sin(x) From 1bc273bceddf3aefd7ecc4932e8bd90bf21cd264 Mon Sep 17 00:00:00 2001 From: Agustinefe Date: Sun, 7 Jan 2024 20:25:00 -0300 Subject: [PATCH 4/6] Add watering simulator --- src/data_packet.py | 41 ++++++++++++++++++++++++++++++----------- src/main.py | 3 +-- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/data_packet.py b/src/data_packet.py index 5d65373..c76aed1 100644 --- a/src/data_packet.py +++ b/src/data_packet.py @@ -29,6 +29,12 @@ def fetch_temperature_and_humidity(location: str) -> Tuple[int, int]: return temperature, humidity +def get_decimal_hour(): + current_hour = datetime.now() + return current_hour.hour + ( + 60 * current_hour.minute + current_hour.second + ) / 3600 + def solar_irradiation_simulator(x): if x < 7 or x > 19: @@ -43,18 +49,28 @@ def solar_irradiation_simulator(x): def fetch_solar_irradiation(): - current_hour = datetime.now() - x = current_hour.hour + ( - 60 * current_hour.minute + current_hour.second - ) / 3600 - + x = get_decimal_hour() return round(solar_irradiation_simulator(x)) -def create_packet(temperature: float = None, - humidity: float = None, - light: float = None, - watering: float = None): +def watering_simulator(x): + x %= 6 + x /= 6 + x *= 100 + x = 100 - x + return x + + +def fetch_watering(): + x = get_decimal_hour() + return round(watering_simulator(x)) + + + +def create_packet(temperature: int = None, + humidity: int = None, + light: int = None, + watering: int = None): ''' Creates a data packet with simulated data, validating the data before that. @@ -68,7 +84,10 @@ def create_packet(temperature: float = None, - Light has to be positive or 0. ''' - if not (temperature and humidity and light and watering): + if not (temperature is not None + and humidity is not None + and light is not None + and watering is not None): return None if humidity < 0 or humidity > 100: @@ -107,7 +126,7 @@ def generate_data(location="Pilar, AR") -> Tuple[int, int, int, int]: temperature, humidity = fetch_temperature_and_humidity(location) light = fetch_solar_irradiation() - watering = rnd.randint(0, 100) + watering = fetch_watering() return temperature, humidity, light, watering diff --git a/src/main.py b/src/main.py index f873143..5f1f3fc 100644 --- a/src/main.py +++ b/src/main.py @@ -9,8 +9,7 @@ - Enviar paquete a la queue. ''' -import time -import random +import time, random import logging from data_packet import generate_data, create_packet, current_packet_differs_from_last_sent From 7a0df3ca518376a11f27cbffedd108e60525eb28 Mon Sep 17 00:00:00 2001 From: Agustinefe Date: Sun, 7 Jan 2024 20:27:11 -0300 Subject: [PATCH 5/6] Fix linter issues --- src/data_packet.py | 3 +-- src/main.py | 34 ++++++++++++++++++++-------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/data_packet.py b/src/data_packet.py index c76aed1..738599b 100644 --- a/src/data_packet.py +++ b/src/data_packet.py @@ -1,4 +1,3 @@ -import random as rnd import requests as req from requests import Response from dotenv import load_dotenv @@ -29,6 +28,7 @@ def fetch_temperature_and_humidity(location: str) -> Tuple[int, int]: return temperature, humidity + def get_decimal_hour(): current_hour = datetime.now() return current_hour.hour + ( @@ -66,7 +66,6 @@ def fetch_watering(): return round(watering_simulator(x)) - def create_packet(temperature: int = None, humidity: int = None, light: int = None, diff --git a/src/main.py b/src/main.py index 5f1f3fc..6b74588 100644 --- a/src/main.py +++ b/src/main.py @@ -9,41 +9,46 @@ - Enviar paquete a la queue. ''' -import time, random +import time +import random import logging -from data_packet import generate_data, create_packet, current_packet_differs_from_last_sent +from data_packet import generate_data, create_packet +from data_packet import current_packet_differs_from_last_sent + def simulate_packets(config): last_sent_packet = None while True: try: temperature, humidity, light, watering = generate_data() - current_packet = create_packet(temperature, humidity, light, watering) - + current_packet = create_packet( + temperature, humidity, light, watering + ) + if not current_packet: continue - if current_packet_differs_from_last_sent(current_packet, last_sent_packet, config["deviations"]): + if current_packet_differs_from_last_sent(current_packet, + last_sent_packet, + config["deviations"]): # TODO: Send packet to the RabbitMQ queue logging.info(f"Packet sent: {current_packet}") - - last_sent_packet = current_packet - except Exception as err: logging.warning(err) finally: print(current_packet) time.sleep(config["packet_period"]) - -''' -Reads the config file. At this moment, it is mocked. -''' + def read_config_file(path): - #TODO + ''' + Reads the config file. At this moment, it is mocked. + ''' + + # TODO return { "packet_period": 1, "device_id": str(random.getrandbits(128)), @@ -52,8 +57,9 @@ def read_config_file(path): "humidity": 5, "light": 25, "watering": 5 + } } -} + if __name__ == '__main__': logging.basicConfig(level=logging.INFO) From b1a5eab533e37d37c798b305692e9d2a4e418290 Mon Sep 17 00:00:00 2001 From: Agustinefe Date: Fri, 19 Jan 2024 17:45:20 -0300 Subject: [PATCH 6/6] HAN-6: rewrite condition to return a null packet --- src/data_packet.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/data_packet.py b/src/data_packet.py index 16a90ba..692c871 100644 --- a/src/data_packet.py +++ b/src/data_packet.py @@ -82,10 +82,7 @@ def create_packet(temperature: int = None, - Light has to be positive or 0. ''' - if not (temperature is not None - and humidity is not None - and light is not None - and watering is not None): + if temperature is None and humidity is None and light is None and watering is None: return None if humidity < 0 or humidity > 100: