Webserver_Dashboard and basic functionality #1

Merged
Roman_Schenk merged 12 commits from Webserver_Layout into master 2022-08-23 20:28:05 +02:00
13 changed files with 413 additions and 74 deletions
Showing only changes of commit 62a17bc63d - Show all commits

15
FileIO/__init__.py Normal file
View File

@ -0,0 +1,15 @@
from Zone import Zone
def loadZones():
zones = []
for i in range(12):
zones.append(Zone(i+1, "Zone " + str(i+1), 90, 10, True, False))
return zones
if __name__ == "__main__":
zones = loadZones()
for zone in zones:
print(zone.name)

View File

@ -2,8 +2,28 @@
<html lang="de"> <html lang="de">
<head> <head>
<link rel="stylesheet" href="../static/Styles/main.css"> <link rel="stylesheet" href="../static/Styles/main.css">
<link rel="stylesheet" href="../static/Styles/dashboard.css">
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Bewässerungssystem</title> <title>{{ translater.getTranslation("Irrigation") }}{{ translater.getTranslation("system") }}</title>
<style>
@media screen and (min-width: 2051px){
#content{
grid-template-rows: repeat( {{ (zones|length / 3) + 1 }} , minmax(150px, auto));
}
}
@media screen and (max-width: 2050px) and (min-width: 1351px){
#content{
grid-template-rows: repeat( {{ (zones|length / 2) + 1 }} , minmax(150px, auto));
}
}
@media screen and (max-width: 1350px){
#content{
grid-template-rows: repeat( {{ zones|length }} , minmax(150px, auto));
}
}
</style>
</head> </head>
<body> <body>
{% include "header.html" %} {% include "header.html" %}
@ -11,43 +31,67 @@
<main> <main>
<h2>Dashboard</h2> <h2>{{ translater.getTranslation("Dashboard") }}</h2>
<div> <div id="content">
<p> {% for zone in zones %}
Lorem, ipsum dolor sit amet consectetur adipisicing elit. <div id="zone_{{ zone.number }}" class="zone">
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti. <a href="/zones/{{ zone.number}}">
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe! <h3>{{ zone.name }}</h3>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. </a>
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti. <table>
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe! <tbody>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. <tr>
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti. <td class="icon">
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe! <span class="outer_dot">
</p> <span class="inner_icon {{ 'dot_green' if zone.state else 'dot_red' }}"></span>
<p> </span>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. </td>
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti. <td class="property">{{ translater.getTranslation("state") }}:</td>
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe! <td class="value">
</p> <p class="state">{{ translater.getTranslation("switched on") if zone.state else translater.getTranslation("switched off") }}</p>
<p> <p class="on_off" href="">{{ translater.getTranslation("turn off") if zone.state else translater.getTranslation("turn on") }}</p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. </td>
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe! </tr>
</p> <tr>
<p> <td class="icon">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. <span class="outer_dot">
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti. <p class="inner_icon">{{'A' if zone.autoMode else 'M'}}</p>
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe! </span>
</p> </td>
<p> <td class="property">{{ translater.getTranslation("operating mode") }}:</td>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. <td class="value">{{translater.getTranslation("automatic mode") if zone.autoMode else translater.getTranslation("manual mode")}}</td>
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti. </tr>
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe! <tr>
</p> <td class="icon">
<span class="outer_dot">
<span class="inner_icon {{ 'dot_green' if(zone.actualValue >= zone.setValue) else 'dot_red' }}"></span>
</span>
</td>
<td class="property">{{ translater.getTranslation("actual humidity") }}:</td>
<td class="value">{{ zone.actualValue}}</td>
</tr>
<tr>
<td class="icon">
</td>
<td class="property">{{ translater.getTranslation("desired humidity") }}:</td>
<td class="value">{{ zone.setValue }}</td>
</tr>
</tbody>
</table>
<p class="zone_number">{{ zone.number }}</p>
</div>
{% endfor %}
</div> </div>
</main> </main>
<p><br><br></p>
</body> </body>
</html> </html>

View File

@ -3,7 +3,6 @@
<head> <head>
<link rel="stylesheet" href="../static/Styles/header.css"> <link rel="stylesheet" href="../static/Styles/header.css">
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Bewässerungssystem</title>
</head> </head>
<body> <body>
<header> <header>
@ -20,12 +19,12 @@
</nav> </nav>
<div class="heading"> <div class="heading">
<img src="../static/img/header/wassertropfen.png" alt="Tropfen" class="title-img"> <img src="../static/img/header/wassertropfen.png" alt="" class="title-img">
<h1>Bewässerungs-<br>system</h1> <h1>{{ translater.getTranslation("Irrigation") }}-<br>{{ translater.getTranslation("system") }}</h1>
</div> </div>
<img src="../static/img/header/blumenbeet.jpg" alt="Blumenbeet" class="header-img"> <img src="../static/img/header/blumenbeet.jpg" alt="" class="header-img">
</header> </header>
</body> </body>

View File

@ -3,7 +3,7 @@
<head> <head>
<link rel="stylesheet" href="../static/Styles/main.css"> <link rel="stylesheet" href="../static/Styles/main.css">
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Bewässerungssystem</title> <title>{{ translater.getTranslation("Irrigation") }}{{ translater.getTranslation("system") }}</title>
</head> </head>
<body> <body>
{% include "header.html" %} {% include "header.html" %}

View File

@ -3,7 +3,7 @@
<head> <head>
<link rel="stylesheet" href="../static/Styles/main.css"> <link rel="stylesheet" href="../static/Styles/main.css">
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Bewässerungssystem</title> <title>{{ translater.getTranslation("Irrigation") }}{{ translater.getTranslation("system") }}</title>
</head> </head>
<body> <body>
{% include "header.html" %} {% include "header.html" %}

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="de">
<head>
<link rel="stylesheet" href="../static/Styles/main.css">
<meta charset="UTF-8">
<title>{{ translater.getTranslation("Irrigation") }}{{ translater.getTranslation("system") }}</title>
</head>
<body>
{% include "header.html" %}
<main>
<h2>Zone</h2>
<div>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe!
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe!
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe!
</p>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe!
</p>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe!
</p>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe!
</p>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Sed excepturi quod dicta temporibus eveniet corporis incidunt molestiae, laborum deleniti.
Molestiae architecto quod veritatis laudantium aliquid aperiam earum quia voluptates saepe!
</p>
</div>
</main>
</body>
</html>

View File

@ -3,7 +3,7 @@
<head> <head>
<link rel="stylesheet" href="../static/Styles/main.css"> <link rel="stylesheet" href="../static/Styles/main.css">
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Bewässerungssystem</title> <title>{{ translater.getTranslation("Irrigation") }}{{ translater.getTranslation("system") }}</title>
</head> </head>
<body> <body>
{% include "header.html" %} {% include "header.html" %}

38
Webserver/Translater.py Normal file
View File

@ -0,0 +1,38 @@
from enum import Enum
class Language(Enum):
ENGLISH = 1
GERMAN = 2
class Translater:
def __init__(self, language):
self.language = language
self.dict_german = { "Irrigation": "Bewässerungs",
"system": "system",
"Dashboard": "Startseite",
"irrigation zones": "Bewässerungszonen",
"blocking times": "Sperrzeiten",
"system settings": "Systemeinstellungen",
"Zone": "Zone",
"state": "Status",
"operating mode": "Betriebsmodus",
"actual humidity": "momentane Feuchtigkeit",
"desired humidity": "gewünschte Feuchtigkeit",
"switched on": "eingeschaltet",
"switched off": "ausgeschaltet",
"turn on": "einschalten",
"turn off": "ausschalten",
"manual mode": "Handbetrieb",
"automatic mode": "Automatikbetrieb",
"switch to manual mode": "Auf Handbetrieb umstellen",
"switch to automatic mode": "Auf Automatikbetrieb umstellen",
}
def getTranslation(self, english_String):
match self.language:
case Language.ENGLISH:
return english_String
case Language.GERMAN:
return self.dict_german[english_String]
case _:
return "no translations for these language"

View File

@ -1,41 +1,59 @@
from flask import Flask, render_template, request, redirect, url_for from flask import Flask, render_template, request, redirect, url_for
from flask_navigation import Navigation from flask_navigation import Navigation
from FileIO import loadZones
from Translater import Translater, Language
from Zone import getZone
app = Flask("Bewässerungssystem")
nav = Navigation(app)
nav.Bar('top', [
nav.Item('Dashboard', 'showDashboard'),
nav.Item('Bewässerungszonen', 'showZones'),
nav.Item('Sperrzeiteneinstellung', 'showTimes'),
nav.Item('Systemeinestellungen', 'showSystem')
#nav.Item('Gfg', 'gfg', {'page': 5}), #(example with pages)
])
#Example Route with pages: def startWebserver(port, translater, zones):
#@app.route('/gfg/<int:page>')
#def gfg(page):
# return render_template('gfg.html', page=page)
@app.route('/')
def startPage():
return redirect(url_for('showDashboard'))
@app.route('/dashboard') app = Flask("Bewässerungssystem")
def showDashboard(): nav = Navigation(app)
return render_template('dashboard.html')
@app.route('/zonen') nav.Bar('top', [
def showZones(): nav.Item(translater.getTranslation('Dashboard'), 'showDashboard'),
return render_template('zones.html') nav.Item(translater.getTranslation('irrigation zones'), 'showZones'),
nav.Item(translater.getTranslation('blocking times'), 'showTimes'),
nav.Item(translater.getTranslation('system settings'), 'showSystem')
#nav.Item('Gfg', 'gfg', {'page': 5}), #(example with pages)
])
@app.route('/times') #Example Route with pages:
def showTimes(): #@app.route('/gfg/<int:page>')
return render_template('times.html') #def gfg(page):
# return render_template('gfg.html', page=page)
@app.route('/system')
def showSystem(): @app.route('/')
return render_template('system.html') def startPage():
return redirect(url_for('showDashboard'))
@app.route('/dashboard')
def showDashboard():
return render_template('dashboard.html', translater=translater, zones=zones)
@app.route('/zones')
@app.route('/zones/<zoneNumber>')
def showZones(zoneNumber=False):
if(zoneNumber):
return render_template('zone.html', translater=translater, zone=getZone(zones, zoneNumber))
else:
return render_template('zones.html', translater=translater, zones=zones)
@app.route('/times')
def showTimes():
return render_template('times.html', translater=translater)
@app.route('/system')
def showSystem():
return render_template('system.html', translater=translater)
app.run(debug=True, port=port)
if __name__ == "__main__": if __name__ == "__main__":
app.run(debug=True, port=80) zones = loadZones()
translater = Translater(Language.ENGLISH)
startWebserver(80, translater, zones)

View File

@ -0,0 +1,141 @@
#content{
display: grid;
grid-template-columns: repeat(3, 1fr);
/* grid-template-rows: repeat( {{ zones|length }} , minmax(150px, auto)); moved to content div to use jinja */
grid-gap: 30px;
margin: 0 auto;
}
.zone{
position: relative;
background: green;
color: white;
font-size: larger;
padding-left: 30px;
padding-bottom: 30px;
padding-right: 30px;
}
.zone a{
color: inherit;
text-decoration: inherit;
}
.zone:hover{
animation: scale 0.5s linear 0.0s normal both;
}
@keyframes scale{
0% {transform: scale3d(100%, 100%, 100%);}
100% {transform: scale3d(107%, 120%, 100%);}
}
.zone h3{
padding-top: 25px;
padding-bottom: 25px;
}
.zone_number{
position: absolute;
top: 15px;
right: 30px;;
}
.zone table{
table-layout: auto;
width: 100%;
}
td.icon{
text-align: left;
width: 30px;
}
td.property{
text-align: left;
}
td.value{
text-align: left;
position: relative;
}
.state{
display: inline;
}
.on_off{
display: none;
color: green;
position: absolute;
background: #bbb;
padding-right: 50px;
padding-left: 5px;
top: -15px;
left: 0px;
z-index: 1;
}
.state:hover + .on_off, .on_off:hover{
display: inline;
}
.outer_dot {
height: 30px;
width: 30px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
margin-right: 10px;
z-index: 1;
}
.inner_icon{
color: black;
font-size: 16px;
font-weight: bold;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
height: 15px;
width: 15px;
margin-left: 7.5px;
margin-top: 7.5px;
border-radius: 50%;
display: inline-block;
z-index: 2;
}
.dot_green {
background-color: green;
}
.dot_red {
background-color: red;
}
@media screen and (min-width: 2051px){
.zone:nth-child(even){
background: blue;
}
}
@media screen and (max-width: 2050px) and (min-width: 1351px){
#content{
grid-template-columns: repeat(2, 1fr);
}
.zone:nth-child(4n){
background: blue;
}
.zone:nth-child(4n+1){
background: blue;
}
}
@media screen and (max-width: 1350px){
#content{
grid-template-columns: repeat(1, 1fr);
}
.zone{
max-width: 600px;
}
.zone:nth-child(even){
background: blue;
}
}

View File

@ -4,13 +4,14 @@ header{
position: sticky; position: sticky;
left: 0px; left: 0px;
top: 0px; top: 0px;
z-index: 20;
} }
nav{ nav{
z-index: 1; z-index: 21;
position: absolute; position: absolute;
top: 0px; top: 0px;
right: 20px; right: 25px;
} }
nav ul li{ nav ul li{
@ -21,13 +22,13 @@ nav ul li a{
white-space: nowrap; white-space: nowrap;
text-decoration: none; text-decoration: none;
color: white; color: white;
background-color: green; background-color: blue;
padding: 5px; padding: 5px;
margin: 10px; margin: 10px;
} }
nav ul li a:hover{ nav ul li a:hover{
background-color: darkgreen; background-color: darkblue;
} }
.active{ .active{

View File

@ -4,3 +4,9 @@ main{
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
h2{
font-family: "Century Gothic", CenturyGothic, AppleGothic, sans-serif;
text-transform: uppercase;
margin-bottom: 2em;
}

25
Zone.py Normal file
View File

@ -0,0 +1,25 @@
class Zone:
def __init__(self, number=0, name="", actualValue="100", setValue="0", autoMode=False, state=False):
self.number = number
self.name = name
self.actualValue = actualValue
self.setValue = setValue
self.autoMode = autoMode #False = manual, True = automatic
self.state = state #True = off, True = on
def refreshStatus(self):
if(self.AutoMode):
if(self.actualValue < self.setValue):
self.state = True
else:
self.state = False
def getStatus(self):
self.refreshStatus()
return self.state
def getZone(zones, number):
for zone in zones:
if(zone.number == number):
return zone