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