From f5bc152a2db0c4ab5dd00174c7e2a6017fc486e2 Mon Sep 17 00:00:00 2001 From: cs171062 Date: Sun, 24 Jan 2021 15:54:06 +0000 Subject: [PATCH] Upload files to '' atmos commit --- atmos-device.py | 116 +++++++++++++++++++++++++++++++++++++++ atmos-server.py | 123 ++++++++++++++++++++++++++++++++++++++++++ gmail_credentials.txt | 3 ++ logo.png | Bin 0 -> 4319 bytes webapp.html | 66 +++++++++++++++++++++++ 5 files changed, 308 insertions(+) create mode 100644 atmos-device.py create mode 100644 atmos-server.py create mode 100644 gmail_credentials.txt create mode 100644 logo.png create mode 100644 webapp.html diff --git a/atmos-device.py b/atmos-device.py new file mode 100644 index 0000000..da5b26c --- /dev/null +++ b/atmos-device.py @@ -0,0 +1,116 @@ +import math +import random +import sched, time +import socket, pickle +from threading import Timer + + +class Conditions: + def __init__(self): + self.temperature = random.uniform(25.0, 38.0) + self.air_humidity = random.uniform(0.2, 0.6) + self.soil_humidity = random.uniform(0.2, 0.6) + self.air_speed = random.randint(16, 30) + + def new_conditions(self): + self.temperature = random.uniform(25.0, 38.0) + self.air_humidity = random.uniform(0.2, 0.6) + self.soil_humidity = random.uniform(0.2, 0.6) + self.air_speed = random.randint(16,30) + return self + + +#function that calculates if the differnce between the values exceeds 10% +def calculate_difference(previous, current): + if abs((previous - current) / previous) > 0.1: + return True + else: + return False + +#function that decides if the new measurements need to be sent over the server +def needs_send(previous, current): + if (calculate_difference(previous.temperature, current.temperature) or + calculate_difference(previous.air_humidity, current.air_humidity) or + calculate_difference(previous.soil_humidity, current.soil_humidity) or + calculate_difference(previous.air_speed, current.air_speed)) : + return True + +#copy function +def copy(obj1, obj2): + obj1.temperature = obj2.temperature + obj1.air_humidity = obj2.air_humidity + obj1.soil_humidity = obj2.soil_humidity + obj1.air_speed = obj2.air_speed + +#function that checks if data has been sent in 5 minutes +def send_is_true(data_sent, current_conditions): + if data_sent == True: + pass + else: + print("Data has not been sent for 5 minutes\n") + print("Sending current data") + my_pickled_object = pickle.dumps(current_conditions) + s.send(my_pickled_object) + + +#socket connection +s = socket.socket() +port = 3125 +s.connect(('localhost', port)) + +#initializing conditions objects +counter = 0 +previous_conditions = Conditions() +current_conditions = Conditions() + +#initializing scheduler +f = sched.scheduler(time.time, time.sleep) + +#initializing data for time checker +data_sent = False +t = Timer(300.0, send_is_true) +t.start() + +def send_data(sc, counter, previous_conditions, current_conditions, data_sent): + if counter == 0: #is this first time sending? + previous_conditions = previous_conditions.new_conditions() + + elif counter == 1: #data sets are over 1 + current_conditions = current_conditions.new_conditions() + + else: + copy(previous_conditions, current_conditions) + current_conditions = current_conditions.new_conditions() + + if counter != 0: #will print data to console when we have > 1 conditions + print("\n\n---" + str(counter) + "---") + print("\nPrevious temperature: " + str(int(previous_conditions.temperature)) + " Celcius") + print("Current temperature: " + str(int(current_conditions.temperature)) + " Celcius\n\n") + print(f"Previous soil humidity: " + str(int(previous_conditions.soil_humidity*100)) + " %") + print(f"Current soil humidity: " + str(int(current_conditions.soil_humidity*100)) + " %\n\n") + print(f"Previous air humidity: " + str(int(previous_conditions.air_humidity*100)) + "%") + print(f"Current air humidity: " + str(int(current_conditions.air_humidity*100)) + "%\n\n") + print("Previous air speed: " + str(previous_conditions.air_speed) + " km/h") + print("Current air speed: " + str(current_conditions.air_speed) + " km/h\n\n") + + + if needs_send(previous_conditions, current_conditions): + print("It needs to be send.") + my_pickled_object = pickle.dumps(current_conditions) + data_sent = True + s.send(my_pickled_object) + + else: + print("It doesn't need to be send.") + + counter += 1 + f.enter(30, 1, send_data, (sc,counter, previous_conditions, current_conditions, data_sent)) + +f.enter(30, 1, send_data, (f,counter, previous_conditions, current_conditions, data_sent)) +f.run() + +s.close() + + + + diff --git a/atmos-server.py b/atmos-server.py new file mode 100644 index 0000000..49e1ecc --- /dev/null +++ b/atmos-server.py @@ -0,0 +1,123 @@ +import socket +import pickle +import time +import sys +from influxdb import InfluxDBClient +import yagmail + +class Conditions: + def __init__(self): + self.temperature = None + self.air_humidity = None + self.soil_humidity = None + self.air_speed = None + +def calculate_dif(temp, percentage): + temp.sort() + if (temp[4] - temp[0]) / temp[0] >= percentage: + return True + else: + return False + +def gmail_send(code): + + with open("gmail_credentials.txt") as f: + data = f.readlines() + + username = data[0].strip('\n') + password = data[1].strip('\n') + receiver = data[2].strip('\n') + + yag = yagmail.SMTP(username, password) + temperature_content = "Attention! Atmos weather device detected a radical change of temperature. Please check the enviroment." + humidity_content = "Attention! Atmos weather device detected a radical change of air humidity. Please check the enviroment." + subject = "Atmos Urgent Notification" + + if code == 1: + yag.send(receiver, subject, temperature_content) + else: + yag.send(receiver, subject, humidity_content) + + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +port = 3125 +s.bind(('0.0.0.0', port)) +print ('Socket binded to port 3125') + +s.listen(3) +print ('socket is listening') + +c, addr = s.accept() +print ('Got connection from ' + str(addr) + ' \n') + +client = InfluxDBClient(host='localhost', port=8086) +databases = client.get_list_database() +exists = False + +for i in databases: + if('atmos' in i['name']): + exists = True + +if(exists): + client.switch_database('atmos') + print("Switched to 'atmos' database\n") +else: + client.create_database('atmos') + print("Created database 'atmos'\n") + client.switch_database('atmos') + + +received = 0 +temperature_array = [] +airhumidity_array = [] + +while True: + + unpickled_object = pickle.loads(c.recv(4096)) + received += 1 + + temperature_array.append(unpickled_object.temperature) + airhumidity_array.append(unpickled_object.air_humidity) + + if(received == 5 ): + is_temp = calculate_dif(temperature_array, 0.4) + is_hum = calculate_dif(airhumidity_array, -0.5) + + if is_temp: + print("\nTemperature critical difference!!!") + print("Will now send notification email.\n") + gmail_send(1) + if is_hum: + print("\nHumidity critical difference!!!") + print("Will now send notification email.\n") + gmail_send(2) + + #resetting values + temperature_array.clear() + airhumidity_array.clear() + received = 0 + + json_body = [ + { + "measurement": "tablePython", + "tags": { + "location": "Athens" + }, + "fields": { + "temperature": str(int(unpickled_object.temperature)), + "soil_humidity": str(int(unpickled_object.soil_humidity*100)), + "air_humidity": str(int(unpickled_object.air_humidity*100)), + "air_speed": str(unpickled_object.air_speed) + } + } + ] + + client.write_points(json_body) + + print("Current temperature: " + str(int(unpickled_object.temperature)) + " Celcius") + print("Current soil humidity: " + str(int(unpickled_object.soil_humidity*100)) + " %") + print("Current air humidity: " + str(int(unpickled_object.air_humidity*100)) + "%") + print("Current air speed: " + str(unpickled_object.air_speed) + " km/h\n") + + +c.close() \ No newline at end of file diff --git a/gmail_credentials.txt b/gmail_credentials.txt new file mode 100644 index 0000000..265f7c2 --- /dev/null +++ b/gmail_credentials.txt @@ -0,0 +1,3 @@ +username +password +receiver's mail diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4231f7997000a5d807437d09ee073b27d64fd06a GIT binary patch literal 4319 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 RgQo<*@UroxO0-kd{{SB!`!E0i literal 0 HcmV?d00001 diff --git a/webapp.html b/webapp.html new file mode 100644 index 0000000..41d859f --- /dev/null +++ b/webapp.html @@ -0,0 +1,66 @@ + + +ATMOS + + + + + + + + + + + + +
+
+ HOME + ABOUT + PHOTOS + CONTACT +
+
+ + +
+ +
+

ATMOS

+
+ + +
+

Live data generated from ATMOS weather device

+
+ +
+
+ +
+ + + + + +

Voliotis Ioannis Alexandros for IoT Lab 2021, UNIWA

+ +
+ + + + + +