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 id="content">
{% for zone in zones %}
<div id="zone_{{ zone.number }}" class="zone">
<a href="/zones/{{ zone.number}}">
<h3>{{ zone.name }}</h3>
</a>
<table>
<tbody>
<tr>
<td class="icon">
<span class="outer_dot">
<span class="inner_icon {{ 'dot_green' if zone.state else 'dot_red' }}"></span>
</span>
</td>
<td class="property">{{ translater.getTranslation("state") }}:</td>
<td class="value">
<p class="state">{{ translater.getTranslation("switched on") if zone.state else translater.getTranslation("switched off") }}</p>
<p class="on_off" href="">{{ translater.getTranslation("turn off") if zone.state else translater.getTranslation("turn on") }}</p>
</td>
</tr>
<tr>
<td class="icon">
<span class="outer_dot">
<p class="inner_icon">{{'A' if zone.autoMode else 'M'}}</p>
</span>
</td>
<td class="property">{{ translater.getTranslation("operating mode") }}:</td>
<td class="value">{{translater.getTranslation("automatic mode") if zone.autoMode else translater.getTranslation("manual mode")}}</td>
</tr>
<tr>
<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>
<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> </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,14 +1,22 @@
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
def startWebserver(port, translater, zones):
app = Flask("Bewässerungssystem") app = Flask("Bewässerungssystem")
nav = Navigation(app) nav = Navigation(app)
nav.Bar('top', [ nav.Bar('top', [
nav.Item('Dashboard', 'showDashboard'), nav.Item(translater.getTranslation('Dashboard'), 'showDashboard'),
nav.Item('Bewässerungszonen', 'showZones'), nav.Item(translater.getTranslation('irrigation zones'), 'showZones'),
nav.Item('Sperrzeiteneinstellung', 'showTimes'), nav.Item(translater.getTranslation('blocking times'), 'showTimes'),
nav.Item('Systemeinestellungen', 'showSystem') nav.Item(translater.getTranslation('system settings'), 'showSystem')
#nav.Item('Gfg', 'gfg', {'page': 5}), #(example with pages) #nav.Item('Gfg', 'gfg', {'page': 5}), #(example with pages)
]) ])
@ -17,25 +25,35 @@ nav.Bar('top', [
#def gfg(page): #def gfg(page):
# return render_template('gfg.html', page=page) # return render_template('gfg.html', page=page)
@app.route('/') @app.route('/')
def startPage(): def startPage():
return redirect(url_for('showDashboard')) return redirect(url_for('showDashboard'))
@app.route('/dashboard') @app.route('/dashboard')
def showDashboard(): def showDashboard():
return render_template('dashboard.html') 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('/zonen')
def showZones():
return render_template('zones.html')
@app.route('/times') @app.route('/times')
def showTimes(): def showTimes():
return render_template('times.html') return render_template('times.html', translater=translater)
@app.route('/system') @app.route('/system')
def showSystem(): def showSystem():
return render_template('system.html') 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