cs171062
4 years ago
5 changed files with 308 additions and 0 deletions
@ -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() |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -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() |
@ -0,0 +1,3 @@ |
|||||
|
username |
||||
|
password |
||||
|
receiver's mail |
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,66 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<title>ATMOS</title> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> |
||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Montserrat"> |
||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> |
||||
|
<style> |
||||
|
body, h1,h2,h3,h4,h5,h6 {font-family: "Montserrat", sans-serif} |
||||
|
.w3-row-padding img {margin-bottom: 12px} |
||||
|
/* Set the width of the sidebar to 120px */ |
||||
|
.w3-sidebar {width: 120px;background: rgb(255, 255, 255);} |
||||
|
/* Add a left margin to the "page content" that matches the width of the sidebar (120px) */ |
||||
|
#main {margin-left: 120px} |
||||
|
/* Remove margins from "page content" on small screens */ |
||||
|
@media only screen and (max-width: 600px) {#main {margin-left: 0}} |
||||
|
</style> |
||||
|
<body class="w3-black"> |
||||
|
|
||||
|
<!-- Icon Bar (Sidebar - hidden on small screens) --> |
||||
|
<nav class="w3-sidebar w3-bar-block w3-small w3-hide-small w3-center"> |
||||
|
<!-- Avatar image in top left corner --> |
||||
|
<img src="logo.png" style="width:100%"> |
||||
|
</nav> |
||||
|
|
||||
|
<!-- Navbar on small screens (Hidden on medium and large screens) --> |
||||
|
<div class="w3-top w3-hide-large w3-hide-medium" id="myNavbar"> |
||||
|
<div class="w3-bar w3-black w3-opacity w3-hover-opacity-off w3-center w3-small"> |
||||
|
<a href="#" class="w3-bar-item w3-button" style="width:25% !important">HOME</a> |
||||
|
<a href="#about" class="w3-bar-item w3-button" style="width:25% !important">ABOUT</a> |
||||
|
<a href="#photos" class="w3-bar-item w3-button" style="width:25% !important">PHOTOS</a> |
||||
|
<a href="#contact" class="w3-bar-item w3-button" style="width:25% !important">CONTACT</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Page Content --> |
||||
|
<div class="w3-padding-large" id="main"> |
||||
|
<!-- Header/Home --> |
||||
|
<header class="w3-container w3-padding-32 w3-center w3-black" id="home"> |
||||
|
<h1 class="w3-jumbo"><span class="w3-hide-small">ATMOS</span></h1> |
||||
|
</header> |
||||
|
|
||||
|
<!-- About Section --> |
||||
|
<div class="w3-content w3-justify w3-text-grey w3-padding-64" id="about"> |
||||
|
<h2 class="w3-text-light-grey">Live data generated from ATMOS weather device</h2> |
||||
|
<hr style="width:200px" class="w3-opacity"> |
||||
|
<iframe src="http://localhost:3000/d-solo/rOJrXyBMz/atmos-monitor?orgId=1&refresh=30s&panelId=2" width="1200" height="550" frameborder="0"></iframe> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- Footer --> |
||||
|
<footer class="w3-content w3-padding-64 w3-text-grey w3-xlarge"> |
||||
|
<i></i> |
||||
|
<i</i> |
||||
|
<i></i> |
||||
|
<i></i> |
||||
|
<i></i> |
||||
|
<p class="w3-medium">Voliotis Ioannis Alexandros for IoT Lab 2021, UNIWA<a></p> |
||||
|
<!-- End footer --> |
||||
|
</footer> |
||||
|
|
||||
|
<!-- END PAGE CONTENT --> |
||||
|
</div> |
||||
|
|
||||
|
</body> |
||||
|
</html> |
Loading…
Reference in new issue