Browse Source

changes

master
cse242017107 11 months ago
parent
commit
45a170e9c6
  1. 236
      coordinator/src/new_coordinator.py
  2. 237
      project.adoc
  3. 911
      project.html

236
coordinator/src/new_coordinator.py

@ -1,236 +0,0 @@
import requests
import time
import json
import os
"""
waitTime = [0, 0, 0, 0]
serviceTime = [20, 20, 20, 20]
trafficLightState = [0, 0, 0, 0]
while True:
os.system("clear")
res = requests.get("http://cloud_computing_project_api:8080/sensors/read")
sensors = json.loads(res.text)
sum = [0, 0, 0, 0]
weight = [0, 0, 0, 0]
for i in range(4):
for j in range(5):
print(sensors[i*5+j]["value"])
for i in range(4):
for j in range(5):
sensorValue = sensors[i*5+j]["value"]
sum[i] += sensorValue
priority = 0
prioritySet = False
for i in range(4):
#weight[i] = sum[i] * (1 + waitTime[i] / 40 + 10 / serviceTime[i])
weight[i] = sum[i] * (1 + waitTime[i] / 40 + 20 / serviceTime[i])
if(weight[i] != 0):
prioritySet = True
if(weight[i] > weight[priority]):
priority = i
print("weight[" + str(i) + "]= " + str([weight[i]]))
if not prioritySet:
if trafficLightState[0] == 1 or trafficLightState[1] == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=11000&redLight=0&orangeLight=1&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=21000&redLight=0&orangeLight=1&greenLight=0")
time.sleep(6)
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=11000&redLight=1&orangeLight=0&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=21000&redLight=1&orangeLight=0&greenLight=0")
trafficLightState[0] = 0
trafficLightState[1] = 0
elif trafficLightState[2] == 1 or trafficLightState[3] == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=31000&redLight=0&orangeLight=1&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=41000&redLight=0&orangeLight=1&greenLight=0")
time.sleep(6)
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=31000&redLight=1&orangeLight=0&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=41000&redLight=1&orangeLight=0&greenLight=0")
trafficLightState[2] = 0
trafficLightState[3] = 0
elif priority == 0 or priority == 1:
if trafficLightState[2] == 1 or trafficLightState[3] == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=31000&redLight=0&orangeLight=1&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=41000&redLight=0&orangeLight=1&greenLight=0")
time.sleep(6)
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=31000&redLight=1&orangeLight=0&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=41000&redLight=1&orangeLight=0&greenLight=0")
trafficLightState[2] = 0
trafficLightState[3] = 0
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=11000&redLight=0&orangeLight=0&greenLight=1")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=21000&redLight=0&orangeLight=0&greenLight=1")
trafficLightState[0] = 1
trafficLightState[1] = 1
serviceTime[0] = 1
serviceTime[1] = 1
elif trafficLightState[0] == 0 or trafficLightState[1] == 0:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=11000&redLight=0&orangeLight=0&greenLight=1")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=21000&redLight=0&orangeLight=0&greenLight=1")
trafficLightState[0] = 1
trafficLightState[1] = 1
serviceTime[0] = 1
serviceTime[1] = 1
elif priority == 2 or priority == 3:
if trafficLightState[0] == 1 or trafficLightState[1] == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=11000&redLight=0&orangeLight=1&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=21000&redLight=0&orangeLight=1&greenLight=0")
time.sleep(6)
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=11000&redLight=1&orangeLight=0&greenLight=0")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=21000&redLight=1&orangeLight=0&greenLight=0")
trafficLightState[0] = 0
trafficLightState[1] = 0
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=31000&redLight=0&orangeLight=0&greenLight=1")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=41000&redLight=0&orangeLight=0&greenLight=1")
trafficLightState[2] = 1
trafficLightState[3] = 1
serviceTime[2] = 1
serviceTime[3] = 1
elif trafficLightState[2] == 0 or trafficLightState[3] == 0:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=31000&redLight=0&orangeLight=0&greenLight=1")
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=41000&redLight=0&orangeLight=0&greenLight=1")
trafficLightState[2] = 1
trafficLightState[3] = 1
serviceTime[2] = 1
serviceTime[3] = 1
time.sleep(1)
for i in range(4):
if trafficLightState[i] == 0 and weight != 0:
waitTime[i] += 1
serviceTime[i] = 20
elif trafficLightState[i] == 1:
waitTime[i] = 0
serviceTime[i] += 1
else:
waitTime[i] = 0
serviceTime[i] = 20
"""
class Lane:
def __init__(self, ID):
self.ID = ID
self.weight = 0
self.waitTime = 0
self.serviceTime = 20
self.trafficLightState = 0
Lanes = [Lane(11000), Lane(21000), Lane(31000), Lane(41000), Lane(12000), Lane(22000), Lane(32000), Lane(42000)]
secondSelections = [[4, 1, 6], [5, 0, 7], [6, 3, 5], [7, 2, 4], [0, 5, 3], [1, 4, 2], [2, 7, 0], [3, 6, 1]]
while True:
os.system("clear")
res = requests.get("http://cloud_computing_project_api:8080/sensors/read")
sensorValues = json.loads(res.text)
sum = [0, 0, 0, 0, 0, 0, 0, 0]
for i in range(8):
for j in range(5):
#print(sensorValues[i*5+j]["value"])
sum[i] += sensorValues[i*5+j]["value"]
print("")
firstPriority = 0
secondPriority = 0
firstPrioritySet = False
secondPrioritySet = False
togglingOrangeLight = False
for i in range(8):
Lanes[i].weight = sum[i] * (1 + Lanes[i].waitTime / 40 + 20 / Lanes[i].serviceTime)
if(Lanes[i].weight != 0):
firstPrioritySet = True
if(Lanes[i].weight > Lanes[firstPriority].weight):
firstPriority = i
print("weight[" + str(i) + "]= " + str(Lanes[i].weight))
if firstPrioritySet:
secondPriority = secondSelections[firstPriority][0]
if Lanes[secondPriority].weight != 0:
secondPrioritySet = True
for i in range(1, 3):
if Lanes[secondSelections[firstPriority][i]].weight > Lanes[secondPriority].weight:
secondPriority = secondSelections[firstPriority][i]
secondPrioritySet = True
for i in range(8):
if i != firstPriority and ((not secondPrioritySet) or i != secondPriority) and Lanes[i].trafficLightState == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=" + str(Lanes[i].ID) +"&redLight=0&orangeLight=1&greenLight=0")
togglingOrangeLight = True
if togglingOrangeLight:
#time.sleep(6)
time.sleep(12)
for i in range(8):
if i != firstPriority and ((not secondPrioritySet) or i != secondPriority) and Lanes[i].trafficLightState == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=" + str(Lanes[i].ID) +"&redLight=1&orangeLight=0&greenLight=0")
Lanes[i].trafficLightState = 0
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=" + str(Lanes[firstPriority].ID) +"&redLight=0&orangeLight=0&greenLight=1")
Lanes[firstPriority].trafficLightState = 1
Lanes[firstPriority].serviceTime = 1
if secondPrioritySet:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=" + str(Lanes[secondPriority].ID) +"&redLight=0&orangeLight=0&greenLight=1")
Lanes[secondPriority].trafficLightState = 1
Lanes[secondPriority].serviceTime = 1
else:
for i in range(8):
if Lanes[i].trafficLightState == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=" + str(Lanes[i].ID) +"&redLight=0&orangeLight=1&greenLight=0")
togglingOrangeLight = True
if togglingOrangeLight:
#time.sleep(6)
time.sleep(12)
for i in range(8):
if Lanes[i].trafficLightState == 1:
requests.get("http://cloud_computing_project_api:8080/traffic_lights/update?road=" + str(Lanes[i].ID) +"&redLight=1&orangeLight=0&greenLight=0")
Lanes[i].trafficLightState = 0
time.sleep(1)
for i in range(8):
if Lanes[i].trafficLightState == 0 and Lanes[i].weight != 0:
Lanes[i].waitTime += 1
Lanes[i].serviceTime = 20
elif Lanes[i].trafficLightState == 1:
Lanes[i].waitTime = 0
Lanes[i].serviceTime += 1
else:
Lanes[i].waitTime = 0
Lanes[i].serviceTime = 20

237
project.adoc

@ -0,0 +1,237 @@
= Υπολογιστική Νέφους και Υπηρεσίες - Εργασία Εξαμήνου
Καραβίδας Γεώργιος cse242017107@uniwa.gr - Θεοδωρόπουλος Διονύσιος cs171208@uniwa.gr
:toc: right
:toc-title: Πίνακας περιεχομένων
:toclevels: 4
:source-highlighter: highlightk
:icons: font
:sectnums:
{empty} +
== Περιγραφή Εφαρμογής
=== Γενική Περιγραφή
Σκοπός της εφαρμογής είναι η προσομοίωση ενός έξυπνου οδικού δικτύου σε περιβάλλον docker. Στόχος του έξυπνου οδικού δικτύου είναι η ελαχιστοποίηση της συμφόρησης
ρυθμίζοντας κατάλληλα τους φωτεινούς σηματοδότες λαμβάνοντας υπόψιν τις θέσεις των οχημάτων μέσω των αισθητήρων κίνησης. Τα κύρια στοιχεία του οδικού δικτύου(φωτεινοί
σηματοδότες, αισθητήρες κίνησης, οχήματα) προσομοιώνονται μέσω εκτέλεσης προγράμματος σε ξεχωριστό container. Για την αποθήκευση της τρέχουσας κατάστασης των κύριων στοιχείων
του οδικού δικτύου δημιουργείται container το οποίο εκτελεί μία υπηρεσία διαχείρησης βάσεων δεδομένων και για την ανάγνωση/εγγραφή από/στις βάσεις δεδομένων δημιουργείται
container το οποίο θέτει σε λειτουργία ένα REST API παρέχοντας κατάλληλα URI's. Ένα πρόγραμμα συντονιστής ρυθμίζει την κατάσταση των φωτεινών σηματοδότων με βάση
τις τιμές των αισθητήρων και ένας web server παρέχει μία ιστοσελίδα στον χρήστη μέσω της οποίας μπορεί να εισάγει νέα οχήματα και να παρατηρεί την κατάσταση του έξυπνου
οδικού δικτύου. Τέλος ένα πρόγραμμα Node js εκτελείται στο επίπεδο του host(εκτός docker) και δημιουργεί containers ανάλογα με την είσοδο του χρήστη μέσω της web εφαρμογής.
Συνολικά δημιουργούνται 52 containers κατά την εκκίνηση της εφαρμογής:
* 1 container για το σύστημα διαχείρησης βάσεων δεδομένων
* 1 container για το REST API
* 8 containers για τους φωτεινούς σηματοδότες
* 40 containers για τους αισθητήρες κίνησης
* 1 container για τον κόμβο συντονιστή
* 1 container για τον web server
Κατά την διάρκεια εκτέλεσης της εφαρμογής μπορούν να δημιουργηθούν containers ανάλογα με την είσοδο του χρήστη μέσω της web εφαρμογής για την προσομοίωση των οχημάτων. Τα
container των οχημάτων σταματάνε όταν το όχημα φτάσει στον προορισμό του.
=== Τοπολογία Οδικού Δικτύου
Η τοπολογία που σχεδιάστηκε για την αναπαράσταση του οδικού δικτύου είναι η ακόλουθη(οι φωτεινοί σηματοδότες σχεδιάζονται στην web εφαρμογή)
image::web_server/src/images/street.png[]
Η τοπολογία του οδικού δικτύου σχεδιάστηκε με τέτοιο τρόπο ώστε κάθε όχημα να μπορεί να καταλήξει από οποιαδήποτε κατεύθυνση εκκίνησης(Ανατολικά, Δυτικά, Βόρεια, Νότια) σε
οποιαδήποτε κατεύθυνση προορισμού. Για αυτόν τον λόγο η τοπολογία αποτελείται από τέσσερις δρόμους με κάθε δρόμο να αποτελείται από τρεις λωρίδες. Κατά σύμβαση τα οχήματα
που θέλουν να κινηθούν ευθεία τοποθετούνται στην μεσαία λωρίδα κατά την άφιξη τους. Αντίστοιχα τα οχήματα που θέλουν να κινηθούν αριστερά τοποθετούνται στην αριστερή λωρίδα
και τα οχήματα που θέλουν να κινηθούν δεξιά τοποθετούνται στην δεξία λωρίδα. Επομένως σύμφωνα με τον τρόπο που έχει σχεδιαστεί η τοπολογία, στις δεξιές λωρίδες μπορεί να τοποθετηθεί
παλλόμενο φανάρι καθώς δεν υπάρχει κίνδυνος σύγκρουσης με οχήματα που ακολουθούν διαφορετική πορεία. Για αυτό τον λόγο στις δεξιές λωρίδες των δρόμων δεν τοποθετούνται αισθητήρες
κίνησης(κάνοντας την εφαρμογή πιο ελαφριά από απόψη επεξεργαστικής ισχύς) και δεν δημιουργείται container για την προσομοίωση του φωτεινού σηματοδότη καθώς δεν μεταβάλλεται η κατάσταση
του. Η αναπαράσταση των παλλόμενων φαναριών γίνεται μόνο στην web εφαρμογή.
Για τις ανάγκες προσομοίωσης των αισθητήρων κίνησης και των οχημάτων, το οδικό δίκτυο έχει χωριστεί σε διακριτές τιμές που αντιστοιχούν σε φυσικές θέσεις. Κάθε φυσική θέση αντιστοιχεί σε
ένα πενταψήφιο αριθμό με το πρώτο most significant digit του αριθμού να καθορίζει τον δρόμο και το δεύτερο most significant digit να καθορίζει την λωρίδα στην οποία αντιστοιχεί η θέση.
Τα 3 least singificant digits του αριθμού καθορίζουν που βρίσκεται η θέση στην συγκεκριμένη λωρίδα. Επομένως οι διακριτές τιμές του οδικού δικτύου διαμορφώνονται ως εξής:
* Οι θέσεις 11000 έως 11170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Δυτικά προς Ανατολικά(προχωρόντας ευθεία)
* Οι θέσεις 12000 έως 12170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου
* Οι θέσεις 13000 έως 13170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου
{empty} +
* Οι θέσεις 21000 έως 21170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Ανατολικά προς Δυτικά(προχωρόντας ευθεία)
* Οι θέσεις 22000 έως 22170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου
* Οι θέσεις 23000 έως 23170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου
{empty} +
* Οι θέσεις 31000 έως 31170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Βόρεια προς Νότια(προχωρόντας ευθεία)
* Οι θέσεις 32000 έως 32170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου
* Οι θέσεις 33000 έως 33170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου
{empty} +
* Οι θέσεις 41000 έως 41170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Νότια προς Βόρεια(προχωρόντας ευθεία)
* Οι θέσεις 42000 έως 42170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου
* Οι θέσεις 43000 έως 43170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου
{empty} +
Τα οχήματα τοποθετούνται σε μία θέση αναλόγα με το σημείο εκκίνησης και προχωράνε αυξάνοντας την θέση τους αφού λάβουν υπόψιν τα οχήματα που βρίσκονται μπροστά τους, την
κατάσταση του φωτεινού σηματοδότη αν βρίσκονται σε μεσαία ή αριστερή λωρίδα και τον προορισμό τους. Στα οχήματα η τιμή της θέσης συμβολίζει το που ξεκινάει το όχημα ως φυσικό
αντικείμενο και για αυτόν τον λόγο θεωρείται ότι κάθε όχημα καταλαμβάνει συνολικά 9 θέσεις ξεκινώντας από την τρέχουσα τιμή της θέσης του(π.χ. ένα όχημα με τρέχουσα θέση την 11000
θεωρείται ότι καταλαμβάνει τις θέσεις 11000-11008). Για κάθε όχημα ορίζεται το σημείο εκκίνησης και το σημείο προορισμού με βάση τις κατευθύνσεις που εισάγονται από τον χρήστη
μέσω της web εφαρμογής. Ακολουθούν οι 12 πορείες που μπορεί να ακολουθήσει ένα όχημα:
* Κατεύθυνση Εκκίνησης: Δυτικά, Κατεύθυνση Προορισμού: Ανατολικά | Σημείο(Θέση) Εκκίνησης: 11000, Σημείο Προορισμού: 11170
* Κατεύθυνση Εκκίνησης: Δυτικά, Κατεύθυνση Προορισμού: Βόρεια | Σημείο Εκκίνησης: 12000, Σημείο Προορισμού: 42170
* Κατεύθυνση Εκκίνησης: Δυτικά, Κατεύθυνση Προορισμού: Νότια | Σημείο Εκκίνησης: 13000, Σημείο Προορισμού: 33170
{empty} +
* Κατεύθυνση Εκκίνησης: Ανατολικά, Κατεύθυνση Προορισμού: Δυτικά | Σημείο Εκκίνησης: 21000, Σημείο Προορισμού: 21170
* Κατεύθυνση Εκκίνησης: Ανατολικά, Κατεύθυνση Προορισμού: Νότια | Σημείο Εκκίνησης: 22000, Σημείο Προορισμού: 32170
* Κατεύθυνση Εκκίνησης: Ανατολικά, Κατεύθυνση Προορισμού: Βόρεια |Σημείο Εκκίνησης: 23000, Σημείο Προορισμού: 43170
{empty} +
* Κατεύθυνση Εκκίνησης: Βόρεια, Κατεύθυνση Προορισμού: Νότια | Σημείο Εκκίνησης: 31000, Σημείο Προορισμού: 31170
* Κατεύθυνση Εκκίνησης: Βόρεια, Κατεύθυνση Προορισμού: Ανατολικά | Σημείο Εκκίνησης: 32000, Σημείο Προορισμού: 12170
* Κατεύθυνση Εκκίνησης: Βόρεια, Κατεύθυνση Προορισμού: Δυτικά | Σημείο Εκκίνησης: 33000, Σημείο Προορισμού: 23170
{empty} +
* Κατεύθυνση Εκκίνησης: Νότια, Κατεύθυνση Προορισμού: Βόρεια | Σημείο Εκκίνησης: 41000, Σημείο Προορισμού: 41170
* Κατεύθυνση Εκκίνησης: Νότια, Κατεύθυνση Προορισμού: Δυτικά | Σημείο Εκκίνησης: 42000, Σημείο Προορισμού: 22170
* Κατεύθυνση Εκκίνησης: Νότια, Κατεύθυνση Προορισμού: Ανατολικά | Σημείο Εκκίνησης: 43000, Σημείο Προορισμού: 13170
{empty} +
Οι αισθητήρες κίνησης τοποθετούνται σε μία συγκεκριμένη σταθερή θέση πριν από το φωτεινό σηματοδότη της λωρίδας τους. Σε κάθε λωρίδα τοποθετούνται πέντε αισθητήρες στη σειρά για την ανίχνευση πέντε οχημάτων.
Οι αισθητήρες λειτουργούν συμμετρικά σε σχέση με τα οχήματα. Επομένως ένα αισθητήρας καλύπτει ένα εύρος 9 τιμών από την θέση του και 8 θέσεις πριν. Για να γίνει πιο κατανοητός ο τρόπος σχεδιασμού, έστω ένας αισθητήρας
που βρίσκεται στη θέση 11008 και ένα όχημα που βρίσκεται στην θέση 11000. Στην συγκεκριμένη περίπτωση ο αισθητήρας ανιχνεύει το όχημα καθώς οι μπροστά ρόδες του οχήματος βρίσκονται πάνω από τον αισθητήρα. Στην συνέχεια
το όχημα κινείται και βρίσκεται πλέον στην θέση 11008. Σε αυτήν την περίπτωση ο αισθητήρας ανιχνεύει πάλι το όχημα καθώς οι πίσω ρόδες του οχήματος βρίσκονται πάνω από τον αισθητήρα. Τέλος το όχημα κινείται λίγο ακόμα και
βρίσκεται πλέον στην θέση 11009. Σε αυτό το σενάριο ο αισθητήρας που βρίσκεται στην θέση 11008 δεν ανιχνεύει το όχημα καθώς τον έχει προσπεράσει. Οι αισθητήρες κίνησης έχουν τοποθετηθεί με τέτοιο τρόπο έτσι ώστε όταν ένα
όχημα προσπερνάει έναν αισθητήρα να βρίσκεται στο εύρος τιμών ανίχνευσης του επόμενου. Ακολουθούν οι θέσεις αισθητήρων για τις μεσαίες και αριστερές λωρίδες των δρόμων:
* Λωρίδα 11000: 11008 11017 11026 11035 11044
* Λωρίδα 12000: 12008 12017 12026 12035 12044
* Λωρίδα 21000: 21008 21017 21026 21035 21044
* Λωρίδα 22000: 22008 22017 22026 22035 22044
* Λωρίδα 31000: 31008 31017 31026 31035 31044
* Λωρίδα 32000: 32008 32017 32026 32035 32044
* Λωρίδα 41000: 41008 41017 41026 41035 41044
* Λωρίδα 42000: 42008 42017 42026 42035 42044
{empty} +
Οι φωτεινοί σηματοδότες αντιστοιχούν σε μία λωρίδα(είτε μεσαία είτε αριστερή). Η τρέχουσα κατάσταση τους καθορίζεται από τον κόμβο συντονιστή ο οποίος έχει καθολική εικόνα του οδικού
δικτύου.
== Υλοποίηση Κόμβων Εφαρμογής
Όλοι οι κόμβοι της εφαρμογής εκτός από τον entry handler εκτελούνται ως container στο περιβάλλον docker. Όλα τα containers εκτός από το container που εκτελεί την υπηρεσία
διαχείρσης βάσεων δεδομένων βασίζονται στο αντίστοιχο Dockerfile. Εκτελώντας το script εκκίνησης της εφαρμογής(start.sh) δημιουργούνται τα εξής docker images για τους αντίστοιχους
κόμβους, μεταφέροντας τα κατάλληλα αρχεία:
* Κόμβος REST API -> cloud_computing_project_api
* Κόμβοι Φωτεινού Σηματοδότη -> cloud_computing_project_traffic_light
* Κόμβοι Αισθητήρων Κίνησης -> cloud_computing_project_sensor
* Κόμβοι Οχημάτων -> cloud_computing_project_vehicle
* Κόμβος Συντονιστή -> cloud_computing_project_coordinator
* Κόμβος web_server -> cloud_computing_project_web_server
=== Κόμβος Διαχείρησης Βάσεων Δεδομένων
Ο κόμβος διαχείρησης βάσεων δεδομένων αποτελεί ένα microservice το οποίο τρέχει MongoDB. Στην MongoDB δημιουργούνται οι βάσεις δεδομένων traffic_lights_db, sensors_db και vehicles_db στις οποίες αποθηκεύεται η
τρέχουσα κατάσταση των φαναριών, των αισθητήρων κίνησης και των οχημάτων αντίστοιχα. Για την ανάγνωση και εγγραφή δεδομένων στην MongoDB τα προγράμματα δεν πραγματοποιούν απευθείας σύνδεση αλλά
πραγματοποιούν αιτήματα στο REST API. Επομένως η MongoDB κατά την διάρκεια εκτέλεσης της εφαρμογής επικοινωνεί μόνο με το REST API.
=== Κόμβος REST API
Το REST API της εφαρμογής τοποθετείται ανάμεσα στη Βάση Δεδομένων και τους υπόλοιπους κόμβους. Αποτελεί εφαρμογή Node js και για την υλοποίηση του χρησιμοποιήθηκαν τα modules mongodb, cors και express. Μέσω του module
mongodb πραγματοποιείται η σύνδεση στη βάση δεδομένων καθώς και η ανάγνωση/εγγραφή δεδομένων από/σε αυτή. Το module cors ενεργοποιεί το cross origin resource sharing έτσι ώστε η web εφαρμογή να μπορεί να διαβάσει
δεδομένα για την τρέχουσα κατάσταση των στοιχείων του έξυπνου οδικού δικτύου και να τα αναπαραστήσει. Η εφαρμογή Node js παρέχει κατάλληλα URI's στους υπόλοιπους κόμβους μέσω του module express το οποίο αποτελεί web
framework. Τα URI's της εφαρμογής Node js είναι τα εξής:
* /:database/subscribe
Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "sensors_db", "vehicles_db". Οι κόμβοι στέλνουν αίτημα στο συγκεκριμένο URI όταν εκκινείται το πρόγραμμα τους για να καταγραφούν ως οντότηα στην
στην κατάλληλη βάση δεδομένων. Ως απάντηση επιστρέφεται το ID που τους ορίστηκε στην βάση δεδομένων. Στην συνέχεια του προγράμματος τους οι κόμβοι μπορούν να χρησιμοποιήσουν το συγκεκριμένο ID για να πραγματοποιήσουν
διάφορες ενέργειες όπως να ενημερώσουν την βάση για την τρέχουσα κατάσταση τους.
{empty} +
* /:database/update
Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "sensors_db", "vehicles_db". Οι κόμβοι στέλνουν αίτημα στο συγκεκριμένο URI για να ενημερώσουν την τρέχουσα κατάσταση τους. Ο κόμβος συντοντιστής
συγκεκριμένα ρυθμίζει την κατάσταση των φαναριών χρησιμοποιώντας μέσω αυτού το URI.
{empty} +
* "/:database/read"
Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "sensors_db", "vehicles_db". Οι κόμβοι στέλνουν αίτημα στο συγκεκριμένο URI για να ενημερωθούν για την τρέχουσα κατάσταση των στοιχείων του οδικού
δικτύου. Ο κόμβος συντονιστής διαβάζει τις τιμές των αισθητήρων για να καθορίσει ποια λωρίδα πρέπει να αποκτήσει προτεραιότητα.
{empty} +
* "/:database/discover"
Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "vehicles_db". Το συγκεκριμένο URI χρησιμοποιείται μόνο από τους κόμβους αισθητήρων. Οι αισθητήρες πραγματοποιούν αιτήματα στο URI για να αντιληφθούν αν υπάρχει κάποιο
όχημα στο εύρος θέσεων που καλύπτουν.
{empty} +
* "/:database/look"
Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "vehicles_db". Το συγκεκριμένο URI χρησιμοποιείται μόνο από τους κόμβους οχημάτων. Τα οχήματα πραγματοποιούν αιτήματα στο URI για να αντιληφθούν
αν υπάρχει κάποιο σταματημένο όχημα μπροστά τους και πρέπει να σταματήσουν. Επίσης ελέγχουν την κατάσταση του φωτεινού σηματοδότη της λωρίδας στην οποία βρίσκονται για να αποφασίσουν αν θα πρέπει να περάσουν ή να σταματήσουν.
{empty} +
* "/:database/delete"
Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "vehicles_db". Το συγκεκριμένο URI χρησιμοποιείται μόνο από τους κόμβους οχημάτων. Τα οχήματα που φτάνουν στον προορισμό τους πραγματοποιούν αίτημα
στο URI έτσι ώστε να διαγραφεί η εγγραφή που τους αντιστοιχεί στη βάση δεδομένων πριν σταματήσει το container.
{empty} +
=== Κόμβοι Φωτεινού Σηματοδότη
Οι κόμβοι φωτεινού σηματοδότη έχουν υλοποιηθεί σε python. Κατά την εκκίνηση του container ορίζεται ως command line argument η λωρίδα στην οποία τοποθετείται ο φωτεινός σηματοδότης. Στην συγκεκριμένη εφαρμογή οι κόμβοι
δεν πραγματοποιούν κάτι άλλο πέρα από το να διαβάζουν την τιμή της τρέχουσας κατάστασης τους, την οποία ορίζει ο κόμβος συντονιστής. Σε μια υλοποίηση στον πραγματικό κόσμο, το ενσωματομένο σύστημα του φωτεινού σηματοδότη
θα έπρεπε να πραγματοποιήσει τις κατάλληλες ενέργειες σε επίπεδο υλικού με βάση την καινούργια του κατάσταση.
=== Κόμβοι Αισθητήρων Κίνησης
Οι κόμβοι αισθητήρων κίνησης έχουν υλοποιηθεί σε python. Κατά την εκκίνηση του container ορίζεται ως command line argument η θέση στην οποία τοποθετείται ο αισθητήρας. Οι αισθητήρες πραγματοποιούν αίτημα στο REST API κάθε 100 ms
για να μάθουν αν βρίσκεται κάποιο όχημα στο εύρος θέσεων που καλύπτουν. Σε περίπτωση που αλλάξει η τιμή του αισθητήρα, ενημερώνει την εγγραφή του στην βάση δεδομένων "sensors_db" με κατάλληλο αίτημα στο REST API.
=== Κόμβοι Οχημάτων
Οι κόμβοι οχημάτων έχουν υλοποιηθεί σε python. Κατά την εκκίνηση του container ορίζονται ως command line arguments το σημείο εκκίνησης και το σημείο προορισμού του οχήματος(μέσω της web εφαρμογής). Τα οχήματα ελέγχουν κάθε 200 ms
αν μπορούν να προχωρήσουν αυξάνοντας την θέση τους κατά 1 με βάση τα δεδομένα που λαμβάνουν μέσω αιτημάτων στο REST API. Για να καθορίσουν αν μπορούν να πραγματοποιήσουν την κίνηση λαμβάνουν υπόψιν τα οχήματα που βρίσκονται μπροστά τους και
την κατάσταση του φωτεινού σηματοδότη αν βρίσκονται σε μεσαία ή αριστερή λωρίδα. Επίσης ελέγχουν αν θα πρέπει να μεταβάλλουν την θέση τους κατάλληλα για να εισέλθουν σε διαφορετική λωρίδα-δρόμο μετά την πραγματοποίηση στροφής. Αφού φτάσουν στον προορισμό
τους, τα οχήματα πραγματοποιούν αίτημα στο REST API έτσι ώστε να διαγραφεί η εγγραφή που τους αντιστοιχεί στη βάση δεδομένων πριν σταματήσει το container.
=== Κόμβος Συντονιστή
Ο κόμβος συντονιστής έχει υλοποιηθεί σε python. Ο ρόλος του κόμβου συντονιστή είναι να ρυθμίζει κατάλληλα τους φωτεινούς σηματοδότες έτσι ώστε να ελαχιστοποιείται η συμφόρηση στο έξυπνο οδικό δίκτυο. Κάθε δευτερόλεπτο ο συντονιστής διαβάζει τις τιμές
των αισθητήρων μέσω κατάλληλου αιτήματος στο REST API. Στην συνέχεια υπολογίζει το άθροισμα των αισθητήρων κάθε λωρίδας και ορίζει μία τιμή προτεραιότητας σε κάθε λωρίδα λαμβάνοντας υπόψιν το άθροισμα των αισθητήρων, το χρόνο αναμονής των οχημάτων σε κόκκινο φανάρι
και πριν από πόσο χρόνο άναψε πράσινο σε μία λωρίδα(αν είναι στην συγκεκριμένη κατάσταση ο φωτεινός σηματοδότης). Με αυτόν τον τρόπο ορίζεται ο φωτεινός σηματοδότης με τη πρώτη προτεραιότητα ο οποίος θα πρέπει να μεταβεί σε κατάταση πράσινου. Στην συνέχεια
υπολογίζεται η λωρίδα με την δεύτερη μεγαλύτερη προτεραιότητα. Για τον υπολογισμό της δεύτερης μεγαλύτερης προτεραιότητας λαμβάνονται υπόψιν μόνο οι τρεις λωρίδες για τις οποίες δεν υπάρχει η πιθανότητα σύγκρουσης με την λωρίδα η οποία έχει την πρώτη προτεραιότητα.
Σε περίπτωση που μία λωρίδα δεν έχει την πρώτη ή την δεύτερη προτεραιότητα και το φανάρι της είναι σε κατάσταση πράσινο, το φανάρι της μεταβαίνει σε κατάσταση πορτοκαλί και ένας μετρητής ξεκινάει να μετράει αντίστροφα. Όταν ο μετρητής γίνει 0 το φανάρι της λωρίδας
μεταβαίνει σε κατάσταση κόκκινο. Στο πρόγραμμα πραγματοποιούνται οι κατάλληλοι έλεγχει έτσι ώστε να μην αλλάζουν τα φανάρια την κατάσταση τους σε πράσινο όταν υπάρχουν 2 φανάρια που βρίσκονται σε κατάσταση πορτοκαλί. Αυτό συμβαίνει για να αποφευχθούν τυχόν συγκρούσεις
καθώς ενδέχεται κάποια οχήματα να μην έχουν προλάβει να περάσουν από την διασταύρωση.
=== Κόμβος Web Server
Ο κόμβος web server έχει υλοποιηθεί με nginx. Παρέχει μία web εφαρμογή στην διεύθυνση 127.0.0.1/8080 όπου ο χρήστης μπορεί να εισάγει νέα οχήματα στο έξυπνο οδικό δίκτυο και να παρατηρεί την κατάσταση του.
=== Κόμβος Entry Handler
Ο κόμβος entry handler αποτελεί ένα πρόγραμμα Node js το οποίο τρέχει στο επίπεδο του host(εκτός docker) και αναμένει αιτήματα από την web εφαρμογή με σκοπό να δημιουργεί containers οχημάτων
με βάση τις επιλογές του χρήστη. Τα containers που δημιουργούνται από το Node js πρόγραμμα εισάγονται στο ίδιο δίκτυο με τα υπόλοιπα containers που έχουν δημιουργηθεί κατά την εκκίνηση
της εφαρμογής.

911
project.html

@ -0,0 +1,911 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.8">
<meta name="author" content="Καραβίδας Γεώργιος cse242017107@uniwa.gr - Θεοδωρόπουλος Διονύσιος cs171208@uniwa.gr">
<title>Υπολογιστική Νέφους και Υπηρεσίες - Εργασία Εξαμήνου</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Uncomment @import statement below to use as custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite::before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
*:not(pre)>code.nobreak{word-wrap:normal}
*:not(pre)>code.nowrap{white-space:nowrap}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock pre.nowrap,.literalblock pre.nowrap pre,.listingblock pre.nowrap,.listingblock pre.nowrap pre{white-space:pre;word-wrap:normal}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #dddddf}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt,.quoteblock .quoteblock{margin:0 0 1.25em;padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
table.tableblock{max-width:100%;border-collapse:separate}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot,table.frame-ends{border-width:1px 0}
table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body class="article toc2 toc-right">
<div id="header">
<h1>Υπολογιστική Νέφους και Υπηρεσίες - Εργασία Εξαμήνου</h1>
<div class="details">
<span id="author" class="author">Καραβίδας Γεώργιος cse242017107@uniwa.gr - Θεοδωρόπουλος Διονύσιος cs171208@uniwa.gr</span><br>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Πίνακας περιεχομένων</div>
<ul class="sectlevel1">
<li><a href="#_περιγραφή_εφαρμογής">1. Περιγραφή Εφαρμογής</a>
<ul class="sectlevel2">
<li><a href="#_γενική_περιγραφή">1.1. Γενική Περιγραφή</a></li>
<li><a href="#_τοπολογία_οδικού_δικτύου">1.2. Τοπολογία Οδικού Δικτύου</a></li>
</ul>
</li>
<li><a href="#_υλοποίηση_κόμβων_εφαρμογής">2. Υλοποίηση Κόμβων Εφαρμογής</a>
<ul class="sectlevel2">
<li><a href="#_κόμβος_διαχείρησης_βάσεων_δεδομένων">2.1. Κόμβος Διαχείρησης Βάσεων Δεδομένων</a></li>
<li><a href="#_κόμβος_rest_api">2.2. Κόμβος REST API</a></li>
<li><a href="#_κόμβοι_φωτεινού_σηματοδότη">2.3. Κόμβοι Φωτεινού Σηματοδότη</a></li>
<li><a href="#_κόμβοι_αισθητήρων_κίνησης">2.4. Κόμβοι Αισθητήρων Κίνησης</a></li>
<li><a href="#_κόμβοι_οχημάτων">2.5. Κόμβοι Οχημάτων</a></li>
<li><a href="#_κόμβος_συντονιστή">2.6. Κόμβος Συντονιστή</a></li>
<li><a href="#_κόμβος_web_server">2.7. Κόμβος Web Server</a></li>
<li><a href="#_κόμβος_entry_handler">2.8. Κόμβος Entry Handler</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><br></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_περιγραφή_εφαρμογής">1. Περιγραφή Εφαρμογής</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_γενική_περιγραφή">1.1. Γενική Περιγραφή</h3>
<div class="paragraph">
<p>Σκοπός της εφαρμογής είναι η προσομοίωση ενός έξυπνου οδικού δικτύου σε περιβάλλον docker. Στόχος του έξυπνου οδικού δικτύου είναι η ελαχιστοποίηση της συμφόρησης
ρυθμίζοντας κατάλληλα τους φωτεινούς σηματοδότες λαμβάνοντας υπόψιν τις θέσεις των οχημάτων μέσω των αισθητήρων κίνησης. Τα κύρια στοιχεία του οδικού δικτύου(φωτεινοί
σηματοδότες, αισθητήρες κίνησης, οχήματα) προσομοιώνονται μέσω εκτέλεσης προγράμματος σε ξεχωριστό container. Για την αποθήκευση της τρέχουσας κατάστασης των κύριων στοιχείων
του οδικού δικτύου δημιουργείται container το οποίο εκτελεί μία υπηρεσία διαχείρησης βάσεων δεδομένων και για την ανάγνωση/εγγραφή από/στις βάσεις δεδομένων δημιουργείται
container το οποίο θέτει σε λειτουργία ένα REST API παρέχοντας κατάλληλα URI&#8217;s. Ένα πρόγραμμα συντονιστής ρυθμίζει την κατάσταση των φωτεινών σηματοδότων με βάση
τις τιμές των αισθητήρων και ένας web server παρέχει μία ιστοσελίδα στον χρήστη μέσω της οποίας μπορεί να εισάγει νέα οχήματα και να παρατηρεί την κατάσταση του έξυπνου
οδικού δικτύου. Τέλος ένα πρόγραμμα Node js εκτελείται στο επίπεδο του host(εκτός docker) και δημιουργεί containers ανάλογα με την είσοδο του χρήστη μέσω της web εφαρμογής.
Συνολικά δημιουργούνται 52 containers κατά την εκκίνηση της εφαρμογής:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>1 container για το σύστημα διαχείρησης βάσεων δεδομένων</p>
</li>
<li>
<p>1 container για το REST API</p>
</li>
<li>
<p>8 containers για τους φωτεινούς σηματοδότες</p>
</li>
<li>
<p>40 containers για τους αισθητήρες κίνησης</p>
</li>
<li>
<p>1 container για τον κόμβο συντονιστή</p>
</li>
<li>
<p>1 container για τον web server</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Κατά την διάρκεια εκτέλεσης της εφαρμογής μπορούν να δημιουργηθούν containers ανάλογα με την είσοδο του χρήστη μέσω της web εφαρμογής για την προσομοίωση των οχημάτων. Τα
container των οχημάτων σταματάνε όταν το όχημα φτάσει στον προορισμό του.</p>
</div>
</div>
<div class="sect2">
<h3 id="_τοπολογία_οδικού_δικτύου">1.2. Τοπολογία Οδικού Δικτύου</h3>
<div class="paragraph">
<p>Η τοπολογία που σχεδιάστηκε για την αναπαράσταση του οδικού δικτύου είναι η ακόλουθη(οι φωτεινοί σηματοδότες σχεδιάζονται στην web εφαρμογή)</p>
</div>
<div class="imageblock">
<div class="content">
<img src="web_server/src/images/street.png" alt="street">
</div>
</div>
<div class="paragraph">
<p>Η τοπολογία του οδικού δικτύου σχεδιάστηκε με τέτοιο τρόπο ώστε κάθε όχημα να μπορεί να καταλήξει από οποιαδήποτε κατεύθυνση εκκίνησης(Ανατολικά, Δυτικά, Βόρεια, Νότια) σε
οποιαδήποτε κατεύθυνση προορισμού. Για αυτόν τον λόγο η τοπολογία αποτελείται από τέσσερις δρόμους με κάθε δρόμο να αποτελείται από τρεις λωρίδες. Κατά σύμβαση τα οχήματα
που θέλουν να κινηθούν ευθεία τοποθετούνται στην μεσαία λωρίδα κατά την άφιξη τους. Αντίστοιχα τα οχήματα που θέλουν να κινηθούν αριστερά τοποθετούνται στην αριστερή λωρίδα
και τα οχήματα που θέλουν να κινηθούν δεξιά τοποθετούνται στην δεξία λωρίδα. Επομένως σύμφωνα με τον τρόπο που έχει σχεδιαστεί η τοπολογία, στις δεξιές λωρίδες μπορεί να τοποθετηθεί
παλλόμενο φανάρι καθώς δεν υπάρχει κίνδυνος σύγκρουσης με οχήματα που ακολουθούν διαφορετική πορεία. Για αυτό τον λόγο στις δεξιές λωρίδες των δρόμων δεν τοποθετούνται αισθητήρες
κίνησης(κάνοντας την εφαρμογή πιο ελαφριά από απόψη επεξεργαστικής ισχύς) και δεν δημιουργείται container για την προσομοίωση του φωτεινού σηματοδότη καθώς δεν μεταβάλλεται η κατάσταση
του. Η αναπαράσταση των παλλόμενων φαναριών γίνεται μόνο στην web εφαρμογή.</p>
</div>
<div class="paragraph">
<p>Για τις ανάγκες προσομοίωσης των αισθητήρων κίνησης και των οχημάτων, το οδικό δίκτυο έχει χωριστεί σε διακριτές τιμές που αντιστοιχούν σε φυσικές θέσεις. Κάθε φυσική θέση αντιστοιχεί σε
ένα πενταψήφιο αριθμό με το πρώτο most significant digit του αριθμού να καθορίζει τον δρόμο και το δεύτερο most significant digit να καθορίζει την λωρίδα στην οποία αντιστοιχεί η θέση.
Τα 3 least singificant digits του αριθμού καθορίζουν που βρίσκεται η θέση στην συγκεκριμένη λωρίδα. Επομένως οι διακριτές τιμές του οδικού δικτύου διαμορφώνονται ως εξής:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Οι θέσεις 11000 έως 11170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Δυτικά προς Ανατολικά(προχωρόντας ευθεία)</p>
</li>
<li>
<p>Οι θέσεις 12000 έως 12170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου</p>
</li>
<li>
<p>Οι θέσεις 13000 έως 13170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Οι θέσεις 21000 έως 21170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Ανατολικά προς Δυτικά(προχωρόντας ευθεία)</p>
</li>
<li>
<p>Οι θέσεις 22000 έως 22170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου</p>
</li>
<li>
<p>Οι θέσεις 23000 έως 23170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Οι θέσεις 31000 έως 31170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Βόρεια προς Νότια(προχωρόντας ευθεία)</p>
</li>
<li>
<p>Οι θέσεις 32000 έως 32170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου</p>
</li>
<li>
<p>Οι θέσεις 33000 έως 33170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Οι θέσεις 41000 έως 41170 αντιστοιχούν στην μεσαία λωρίδα του δρόμου που τα οχήματα κινούνται από Νότια προς Βόρεια(προχωρόντας ευθεία)</p>
</li>
<li>
<p>Οι θέσεις 42000 έως 42170 αντιστοιχούν στην αριστερή λωρίδα του ίδιου δρόμου</p>
</li>
<li>
<p>Οι θέσεις 43000 έως 43170 αντιστοιχούν στην δεξιά λωρίδα του ίδιου δρόμου</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="paragraph">
<p>Τα οχήματα τοποθετούνται σε μία θέση αναλόγα με το σημείο εκκίνησης και προχωράνε αυξάνοντας την θέση τους αφού λάβουν υπόψιν τα οχήματα που βρίσκονται μπροστά τους, την
κατάσταση του φωτεινού σηματοδότη αν βρίσκονται σε μεσαία ή αριστερή λωρίδα και τον προορισμό τους. Στα οχήματα η τιμή της θέσης συμβολίζει το που ξεκινάει το όχημα ως φυσικό
αντικείμενο και για αυτόν τον λόγο θεωρείται ότι κάθε όχημα καταλαμβάνει συνολικά 9 θέσεις ξεκινώντας από την τρέχουσα τιμή της θέσης του(π.χ. ένα όχημα με τρέχουσα θέση την 11000
θεωρείται ότι καταλαμβάνει τις θέσεις 11000-11008). Για κάθε όχημα ορίζεται το σημείο εκκίνησης και το σημείο προορισμού με βάση τις κατευθύνσεις που εισάγονται από τον χρήστη
μέσω της web εφαρμογής. Ακολουθούν οι 12 πορείες που μπορεί να ακολουθήσει ένα όχημα:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Κατεύθυνση Εκκίνησης: Δυτικά, Κατεύθυνση Προορισμού: Ανατολικά | Σημείο(Θέση) Εκκίνησης: 11000, Σημείο Προορισμού: 11170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Δυτικά, Κατεύθυνση Προορισμού: Βόρεια | Σημείο Εκκίνησης: 12000, Σημείο Προορισμού: 42170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Δυτικά, Κατεύθυνση Προορισμού: Νότια | Σημείο Εκκίνησης: 13000, Σημείο Προορισμού: 33170</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Κατεύθυνση Εκκίνησης: Ανατολικά, Κατεύθυνση Προορισμού: Δυτικά | Σημείο Εκκίνησης: 21000, Σημείο Προορισμού: 21170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Ανατολικά, Κατεύθυνση Προορισμού: Νότια | Σημείο Εκκίνησης: 22000, Σημείο Προορισμού: 32170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Ανατολικά, Κατεύθυνση Προορισμού: Βόρεια |Σημείο Εκκίνησης: 23000, Σημείο Προορισμού: 43170</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Κατεύθυνση Εκκίνησης: Βόρεια, Κατεύθυνση Προορισμού: Νότια | Σημείο Εκκίνησης: 31000, Σημείο Προορισμού: 31170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Βόρεια, Κατεύθυνση Προορισμού: Ανατολικά | Σημείο Εκκίνησης: 32000, Σημείο Προορισμού: 12170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Βόρεια, Κατεύθυνση Προορισμού: Δυτικά | Σημείο Εκκίνησης: 33000, Σημείο Προορισμού: 23170</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>Κατεύθυνση Εκκίνησης: Νότια, Κατεύθυνση Προορισμού: Βόρεια | Σημείο Εκκίνησης: 41000, Σημείο Προορισμού: 41170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Νότια, Κατεύθυνση Προορισμού: Δυτικά | Σημείο Εκκίνησης: 42000, Σημείο Προορισμού: 22170</p>
</li>
<li>
<p>Κατεύθυνση Εκκίνησης: Νότια, Κατεύθυνση Προορισμού: Ανατολικά | Σημείο Εκκίνησης: 43000, Σημείο Προορισμού: 13170</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="paragraph">
<p>Οι αισθητήρες κίνησης τοποθετούνται σε μία συγκεκριμένη σταθερή θέση πριν από το φωτεινό σηματοδότη της λωρίδας τους. Σε κάθε λωρίδα τοποθετούνται πέντε αισθητήρες στη σειρά για την ανίχνευση πέντε οχημάτων.
Οι αισθητήρες λειτουργούν συμμετρικά σε σχέση με τα οχήματα. Επομένως ένα αισθητήρας καλύπτει ένα εύρος 9 τιμών από την θέση του και 8 θέσεις πριν. Για να γίνει πιο κατανοητός ο τρόπος σχεδιασμού, έστω ένας αισθητήρας
που βρίσκεται στη θέση 11008 και ένα όχημα που βρίσκεται στην θέση 11000. Στην συγκεκριμένη περίπτωση ο αισθητήρας ανιχνεύει το όχημα καθώς οι μπροστά ρόδες του οχήματος βρίσκονται πάνω από τον αισθητήρα. Στην συνέχεια
το όχημα κινείται και βρίσκεται πλέον στην θέση 11008. Σε αυτήν την περίπτωση ο αισθητήρας ανιχνεύει πάλι το όχημα καθώς οι πίσω ρόδες του οχήματος βρίσκονται πάνω από τον αισθητήρα. Τέλος το όχημα κινείται λίγο ακόμα και
βρίσκεται πλέον στην θέση 11009. Σε αυτό το σενάριο ο αισθητήρας που βρίσκεται στην θέση 11008 δεν ανιχνεύει το όχημα καθώς τον έχει προσπεράσει. Οι αισθητήρες κίνησης έχουν τοποθετηθεί με τέτοιο τρόπο έτσι ώστε όταν ένα
όχημα προσπερνάει έναν αισθητήρα να βρίσκεται στο εύρος τιμών ανίχνευσης του επόμενου. Ακολουθούν οι θέσεις αισθητήρων για τις μεσαίες και αριστερές λωρίδες των δρόμων:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Λωρίδα 11000: 11008 11017 11026 11035 11044</p>
</li>
<li>
<p>Λωρίδα 12000: 12008 12017 12026 12035 12044</p>
</li>
<li>
<p>Λωρίδα 21000: 21008 21017 21026 21035 21044</p>
</li>
<li>
<p>Λωρίδα 22000: 22008 22017 22026 22035 22044</p>
</li>
<li>
<p>Λωρίδα 31000: 31008 31017 31026 31035 31044</p>
</li>
<li>
<p>Λωρίδα 32000: 32008 32017 32026 32035 32044</p>
</li>
<li>
<p>Λωρίδα 41000: 41008 41017 41026 41035 41044</p>
</li>
<li>
<p>Λωρίδα 42000: 42008 42017 42026 42035 42044</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="paragraph">
<p>Οι φωτεινοί σηματοδότες αντιστοιχούν σε μία λωρίδα(είτε μεσαία είτε αριστερή). Η τρέχουσα κατάσταση τους καθορίζεται από τον κόμβο συντονιστή ο οποίος έχει καθολική εικόνα του οδικού
δικτύου.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_υλοποίηση_κόμβων_εφαρμογής">2. Υλοποίηση Κόμβων Εφαρμογής</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Όλοι οι κόμβοι της εφαρμογής εκτός από τον entry handler εκτελούνται ως container στο περιβάλλον docker. Όλα τα containers εκτός από το container που εκτελεί την υπηρεσία
διαχείρσης βάσεων δεδομένων βασίζονται στο αντίστοιχο Dockerfile. Εκτελώντας το script εκκίνησης της εφαρμογής(start.sh) δημιουργούνται τα εξής docker images για τους αντίστοιχους
κόμβους, μεταφέροντας τα κατάλληλα αρχεία:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Κόμβος REST API &#8594; cloud_computing_project_api</p>
</li>
<li>
<p>Κόμβοι Φωτεινού Σηματοδότη &#8594; cloud_computing_project_traffic_light</p>
</li>
<li>
<p>Κόμβοι Αισθητήρων Κίνησης &#8594; cloud_computing_project_sensor</p>
</li>
<li>
<p>Κόμβοι Οχημάτων &#8594; cloud_computing_project_vehicle</p>
</li>
<li>
<p>Κόμβος Συντονιστή &#8594; cloud_computing_project_coordinator</p>
</li>
<li>
<p>Κόμβος web_server &#8594; cloud_computing_project_web_server</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="_κόμβος_διαχείρησης_βάσεων_δεδομένων">2.1. Κόμβος Διαχείρησης Βάσεων Δεδομένων</h3>
<div class="paragraph">
<p>Ο κόμβος διαχείρησης βάσεων δεδομένων αποτελεί ένα microservice το οποίο τρέχει MongoDB. Στην MongoDB δημιουργούνται οι βάσεις δεδομένων traffic_lights_db, sensors_db και vehicles_db στις οποίες αποθηκεύεται η
τρέχουσα κατάσταση των φαναριών, των αισθητήρων κίνησης και των οχημάτων αντίστοιχα. Για την ανάγνωση και εγγραφή δεδομένων στην MongoDB τα προγράμματα δεν πραγματοποιούν απευθείας σύνδεση αλλά
πραγματοποιούν αιτήματα στο REST API. Επομένως η MongoDB κατά την διάρκεια εκτέλεσης της εφαρμογής επικοινωνεί μόνο με το REST API.</p>
</div>
</div>
<div class="sect2">
<h3 id="_κόμβος_rest_api">2.2. Κόμβος REST API</h3>
<div class="paragraph">
<p>Το REST API της εφαρμογής τοποθετείται ανάμεσα στη Βάση Δεδομένων και τους υπόλοιπους κόμβους. Αποτελεί εφαρμογή Node js και για την υλοποίηση του χρησιμοποιήθηκαν τα modules mongodb, cors και express. Μέσω του module
mongodb πραγματοποιείται η σύνδεση στη βάση δεδομένων καθώς και η ανάγνωση/εγγραφή δεδομένων από/σε αυτή. Το module cors ενεργοποιεί το cross origin resource sharing έτσι ώστε η web εφαρμογή να μπορεί να διαβάσει
δεδομένα για την τρέχουσα κατάσταση των στοιχείων του έξυπνου οδικού δικτύου και να τα αναπαραστήσει. Η εφαρμογή Node js παρέχει κατάλληλα URI&#8217;s στους υπόλοιπους κόμβους μέσω του module express το οποίο αποτελεί web
framework. Τα URI&#8217;s της εφαρμογής Node js είναι τα εξής:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>/:database/subscribe</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "sensors_db", "vehicles_db". Οι κόμβοι στέλνουν αίτημα στο συγκεκριμένο URI όταν εκκινείται το πρόγραμμα τους για να καταγραφούν ως οντότηα στην
στην κατάλληλη βάση δεδομένων. Ως απάντηση επιστρέφεται το ID που τους ορίστηκε στην βάση δεδομένων. Στην συνέχεια του προγράμματος τους οι κόμβοι μπορούν να χρησιμοποιήσουν το συγκεκριμένο ID για να πραγματοποιήσουν
διάφορες ενέργειες όπως να ενημερώσουν την βάση για την τρέχουσα κατάσταση τους.</p>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>/:database/update</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "sensors_db", "vehicles_db". Οι κόμβοι στέλνουν αίτημα στο συγκεκριμένο URI για να ενημερώσουν την τρέχουσα κατάσταση τους. Ο κόμβος συντοντιστής
συγκεκριμένα ρυθμίζει την κατάσταση των φαναριών χρησιμοποιώντας μέσω αυτού το URI.</p>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>"/:database/read"</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "sensors_db", "vehicles_db". Οι κόμβοι στέλνουν αίτημα στο συγκεκριμένο URI για να ενημερωθούν για την τρέχουσα κατάσταση των στοιχείων του οδικού
δικτύου. Ο κόμβος συντονιστής διαβάζει τις τιμές των αισθητήρων για να καθορίσει ποια λωρίδα πρέπει να αποκτήσει προτεραιότητα.</p>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>"/:database/discover"</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "vehicles_db". Το συγκεκριμένο URI χρησιμοποιείται μόνο από τους κόμβους αισθητήρων. Οι αισθητήρες πραγματοποιούν αιτήματα στο URI για να αντιληφθούν αν υπάρχει κάποιο
όχημα στο εύρος θέσεων που καλύπτουν.</p>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>"/:database/look"</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "traffic_lights_db", "vehicles_db". Το συγκεκριμένο URI χρησιμοποιείται μόνο από τους κόμβους οχημάτων. Τα οχήματα πραγματοποιούν αιτήματα στο URI για να αντιληφθούν
αν υπάρχει κάποιο σταματημένο όχημα μπροστά τους και πρέπει να σταματήσουν. Επίσης ελέγχουν την κατάσταση του φωτεινού σηματοδότη της λωρίδας στην οποία βρίσκονται για να αποφασίσουν αν θα πρέπει να περάσουν ή να σταματήσουν.</p>
</div>
<div class="paragraph">
<p><br></p>
</div>
<div class="ulist">
<ul>
<li>
<p>"/:database/delete"</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Οι τιμές που μπορεί να πάρει η παράμετρος database είναι "vehicles_db". Το συγκεκριμένο URI χρησιμοποιείται μόνο από τους κόμβους οχημάτων. Τα οχήματα που φτάνουν στον προορισμό τους πραγματοποιούν αίτημα
στο URI έτσι ώστε να διαγραφεί η εγγραφή που τους αντιστοιχεί στη βάση δεδομένων πριν σταματήσει το container.</p>
</div>
<div class="paragraph">
<p><br></p>
</div>
</div>
<div class="sect2">
<h3 id="_κόμβοι_φωτεινού_σηματοδότη">2.3. Κόμβοι Φωτεινού Σηματοδότη</h3>
<div class="paragraph">
<p>Οι κόμβοι φωτεινού σηματοδότη έχουν υλοποιηθεί σε python. Κατά την εκκίνηση του container ορίζεται ως command line argument η λωρίδα στην οποία τοποθετείται ο φωτεινός σηματοδότης. Στην συγκεκριμένη εφαρμογή οι κόμβοι
δεν πραγματοποιούν κάτι άλλο πέρα από το να διαβάζουν την τιμή της τρέχουσας κατάστασης τους, την οποία ορίζει ο κόμβος συντονιστής. Σε μια υλοποίηση στον πραγματικό κόσμο, το ενσωματομένο σύστημα του φωτεινού σηματοδότη
θα έπρεπε να πραγματοποιήσει τις κατάλληλες ενέργειες σε επίπεδο υλικού με βάση την καινούργια του κατάσταση.</p>
</div>
</div>
<div class="sect2">
<h3 id="_κόμβοι_αισθητήρων_κίνησης">2.4. Κόμβοι Αισθητήρων Κίνησης</h3>
<div class="paragraph">
<p>Οι κόμβοι αισθητήρων κίνησης έχουν υλοποιηθεί σε python. Κατά την εκκίνηση του container ορίζεται ως command line argument η θέση στην οποία τοποθετείται ο αισθητήρας. Οι αισθητήρες πραγματοποιούν αίτημα στο REST API κάθε 100 ms
για να μάθουν αν βρίσκεται κάποιο όχημα στο εύρος θέσεων που καλύπτουν. Σε περίπτωση που αλλάξει η τιμή του αισθητήρα, ενημερώνει την εγγραφή του στην βάση δεδομένων "sensors_db" με κατάλληλο αίτημα στο REST API.</p>
</div>
</div>
<div class="sect2">
<h3 id="_κόμβοι_οχημάτων">2.5. Κόμβοι Οχημάτων</h3>
<div class="paragraph">
<p>Οι κόμβοι οχημάτων έχουν υλοποιηθεί σε python. Κατά την εκκίνηση του container ορίζονται ως command line arguments το σημείο εκκίνησης και το σημείο προορισμού του οχήματος(μέσω της web εφαρμογής). Τα οχήματα ελέγχουν κάθε 200 ms
αν μπορούν να προχωρήσουν αυξάνοντας την θέση τους κατά 1 με βάση τα δεδομένα που λαμβάνουν μέσω αιτημάτων στο REST API. Για να καθορίσουν αν μπορούν να πραγματοποιήσουν την κίνηση λαμβάνουν υπόψιν τα οχήματα που βρίσκονται μπροστά τους και
την κατάσταση του φωτεινού σηματοδότη αν βρίσκονται σε μεσαία ή αριστερή λωρίδα. Επίσης ελέγχουν αν θα πρέπει να μεταβάλλουν την θέση τους κατάλληλα για να εισέλθουν σε διαφορετική λωρίδα-δρόμο μετά την πραγματοποίηση στροφής. Αφού φτάσουν στον προορισμό
τους, τα οχήματα πραγματοποιούν αίτημα στο REST API έτσι ώστε να διαγραφεί η εγγραφή που τους αντιστοιχεί στη βάση δεδομένων πριν σταματήσει το container.</p>
</div>
</div>
<div class="sect2">
<h3 id="_κόμβος_συντονιστή">2.6. Κόμβος Συντονιστή</h3>
<div class="paragraph">
<p>Ο κόμβος συντονιστής έχει υλοποιηθεί σε python. Ο ρόλος του κόμβου συντονιστή είναι να ρυθμίζει κατάλληλα τους φωτεινούς σηματοδότες έτσι ώστε να ελαχιστοποιείται η συμφόρηση στο έξυπνο οδικό δίκτυο. Κάθε δευτερόλεπτο ο συντονιστής διαβάζει τις τιμές
των αισθητήρων μέσω κατάλληλου αιτήματος στο REST API. Στην συνέχεια υπολογίζει το άθροισμα των αισθητήρων κάθε λωρίδας και ορίζει μία τιμή προτεραιότητας σε κάθε λωρίδα λαμβάνοντας υπόψιν το άθροισμα των αισθητήρων, το χρόνο αναμονής των οχημάτων σε κόκκινο φανάρι
και πριν από πόσο χρόνο άναψε πράσινο σε μία λωρίδα(αν είναι στην συγκεκριμένη κατάσταση ο φωτεινός σηματοδότης). Με αυτόν τον τρόπο ορίζεται ο φωτεινός σηματοδότης με τη πρώτη προτεραιότητα ο οποίος θα πρέπει να μεταβεί σε κατάταση πράσινου. Στην συνέχεια
υπολογίζεται η λωρίδα με την δεύτερη μεγαλύτερη προτεραιότητα. Για τον υπολογισμό της δεύτερης μεγαλύτερης προτεραιότητας λαμβάνονται υπόψιν μόνο οι τρεις λωρίδες για τις οποίες δεν υπάρχει η πιθανότητα σύγκρουσης με την λωρίδα η οποία έχει την πρώτη προτεραιότητα.
Σε περίπτωση που μία λωρίδα δεν έχει την πρώτη ή την δεύτερη προτεραιότητα και το φανάρι της είναι σε κατάσταση πράσινο, το φανάρι της μεταβαίνει σε κατάσταση πορτοκαλί και ένας μετρητής ξεκινάει να μετράει αντίστροφα. Όταν ο μετρητής γίνει 0 το φανάρι της λωρίδας
μεταβαίνει σε κατάσταση κόκκινο. Στο πρόγραμμα πραγματοποιούνται οι κατάλληλοι έλεγχει έτσι ώστε να μην αλλάζουν τα φανάρια την κατάσταση τους σε πράσινο όταν υπάρχουν 2 φανάρια που βρίσκονται σε κατάσταση πορτοκαλί. Αυτό συμβαίνει για να αποφευχθούν τυχόν συγκρούσεις
καθώς ενδέχεται κάποια οχήματα να μην έχουν προλάβει να περάσουν από την διασταύρωση.</p>
</div>
</div>
<div class="sect2">
<h3 id="_κόμβος_web_server">2.7. Κόμβος Web Server</h3>
<div class="paragraph">
<p>Ο κόμβος web server έχει υλοποιηθεί με nginx. Παρέχει μία web εφαρμογή στην διεύθυνση 127.0.0.1/8080 όπου ο χρήστης μπορεί να εισάγει νέα οχήματα στο έξυπνο οδικό δίκτυο και να παρατηρεί την κατάσταση του.</p>
</div>
</div>
<div class="sect2">
<h3 id="_κόμβος_entry_handler">2.8. Κόμβος Entry Handler</h3>
<div class="paragraph">
<p>Ο κόμβος entry handler αποτελεί ένα πρόγραμμα Node js το οποίο τρέχει στο επίπεδο του host(εκτός docker) και αναμένει αιτήματα από την web εφαρμογή με σκοπό να δημιουργεί containers οχημάτων
με βάση τις επιλογές του χρήστη. Τα containers που δημιουργούνται από το Node js πρόγραμμα εισάγονται στο ίδιο δίκτυο με τα υπόλοιπα containers που έχουν δημιουργηθεί κατά την εκκίνηση
της εφαρμογής.</p>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2023-06-13 14:41:38 +0300
</div>
</div>
</body>
</html>
Loading…
Cancel
Save