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 0000000..4231f79 Binary files /dev/null and b/logo.png differ 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

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