Webserver_Dashboard and basic functionality #1
|
@ -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)
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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" %}
|
||||
|
|
|
@ -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" %}
|
||||
|
|
|
@ -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>
|
|
@ -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" %}
|
||||
|
|
|
@ -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"
|
|
@ -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')
|
||||
|
||||
def startWebserver(port, translater, zones):
|
||||
|
||||
|
||||
app = Flask("Bewässerungssystem")
|
||||
nav = Navigation(app)
|
||||
|
||||
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)
|
||||
])
|
||||
])
|
||||
|
||||
#Example Route with pages:
|
||||
#@app.route('/gfg/<int:page>')
|
||||
#def gfg(page):
|
||||
# return render_template('gfg.html', page=page)
|
||||
#Example Route with pages:
|
||||
#@app.route('/gfg/<int:page>')
|
||||
#def gfg(page):
|
||||
# return render_template('gfg.html', page=page)
|
||||
|
||||
@app.route('/')
|
||||
def startPage():
|
||||
|
||||
@app.route('/')
|
||||
def startPage():
|
||||
return redirect(url_for('showDashboard'))
|
||||
|
||||
@app.route('/dashboard')
|
||||
def showDashboard():
|
||||
return render_template('dashboard.html')
|
||||
@app.route('/dashboard')
|
||||
def showDashboard():
|
||||
return render_template('dashboard.html', translater=translater, zones=zones)
|
||||
|
||||
@app.route('/zonen')
|
||||
def showZones():
|
||||
return render_template('zones.html')
|
||||
@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')
|
||||
|
||||
@app.route('/system')
|
||||
def showSystem():
|
||||
return render_template('system.html')
|
||||
@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)
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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{
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue