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">
<head>
<link rel="stylesheet" href="../static/Styles/main.css">
<link rel="stylesheet" href="../static/Styles/dashboard.css">
<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>
<body>
{% include "header.html" %}
@ -11,43 +31,67 @@
<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>
</main>
<p><br><br></p>
</body>
</html>

View File

@ -3,7 +3,6 @@
<head>
<link rel="stylesheet" href="../static/Styles/header.css">
<meta charset="UTF-8">
<title>Bewässerungssystem</title>
</head>
<body>
<header>
@ -20,12 +19,12 @@
</nav>
<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>
<img src="../static/img/header/blumenbeet.jpg" alt="Blumenbeet" class="header-img">
<img src="../static/img/header/blumenbeet.jpg" alt="" class="header-img">
</header>
</body>

View File

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

View File

@ -3,7 +3,7 @@
<head>
<link rel="stylesheet" href="../static/Styles/main.css">
<meta charset="UTF-8">
<title>Bewässerungssystem</title>
<title>{{ translater.getTranslation("Irrigation") }}{{ translater.getTranslation("system") }}</title>
</head>
<body>
{% 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>
<link rel="stylesheet" href="../static/Styles/main.css">
<meta charset="UTF-8">
<title>Bewässerungssystem</title>
<title>{{ translater.getTranslation("Irrigation") }}{{ translater.getTranslation("system") }}</title>
</head>
<body>
{% 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_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:
#@app.route('/gfg/<int:page>')
#def gfg(page):
# return render_template('gfg.html', page=page)
def startWebserver(port, translater, zones):
@app.route('/')
def startPage():
return redirect(url_for('showDashboard'))
@app.route('/dashboard')
def showDashboard():
return render_template('dashboard.html')
app = Flask("Bewässerungssystem")
nav = Navigation(app)
@app.route('/zonen')
def showZones():
return render_template('zones.html')
nav.Bar('top', [
nav.Item(translater.getTranslation('Dashboard'), 'showDashboard'),
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')
def showTimes():
return render_template('times.html')
#Example Route with pages:
#@app.route('/gfg/<int:page>')
#def gfg(page):
# return render_template('gfg.html', page=page)
@app.route('/system')
def showSystem():
return render_template('system.html')
@app.route('/')
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__":
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;
left: 0px;
top: 0px;
z-index: 20;
}
nav{
z-index: 1;
z-index: 21;
position: absolute;
top: 0px;
right: 20px;
right: 25px;
}
nav ul li{
@ -21,13 +22,13 @@ nav ul li a{
white-space: nowrap;
text-decoration: none;
color: white;
background-color: green;
background-color: blue;
padding: 5px;
margin: 10px;
}
nav ul li a:hover{
background-color: darkgreen;
background-color: darkblue;
}
.active{

View File

@ -4,3 +4,9 @@ main{
margin-left: 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