Webserver_Dashboard and basic functionality #1
|
@ -1,15 +1,12 @@
|
|||
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
|
||||
|
||||
class FileIO:
|
||||
def __init__(self, systemSettings):
|
||||
self.systemSettings = systemSettings
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
zones = loadZones()
|
||||
for zone in zones:
|
||||
print(zone.name)
|
||||
def loadZones(self):
|
||||
zones = []
|
||||
for i in range(12):
|
||||
zones.append(Zone(number=i+1, name="Zone " + str(i+1), actualHumidity=100, desiredHumidity=0, autoMode=False, state=False, setState=0, endTimeSetState=0, planedDuration=0))
|
||||
return zones
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
|
||||
class SystemSettings:
|
||||
def __init__(self, dataDir="/Data", multiZoneIrrigation=False):
|
||||
self.dataDir = dataDir
|
||||
self.multiZoneIrrigation = multiZoneIrrigation
|
|
@ -66,18 +66,18 @@
|
|||
<tr>
|
||||
<td class="icon">
|
||||
<span class="outer_dot">
|
||||
<span class="inner_icon {{ 'dot_green' if(zone.actualValue >= zone.setValue) else 'dot_red' }}"></span>
|
||||
<span class="inner_icon {{ 'dot_green' if(zone.actualHumidity >= zone.desiredHumidity) else 'dot_red' }}"></span>
|
||||
</span>
|
||||
</td>
|
||||
<td class="property">{{ translater.getTranslation("actual humidity") }}:</td>
|
||||
<td class="value">{{ zone.actualValue}}</td>
|
||||
<td class="value">{{ zone.actualHumidity}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="icon">
|
||||
|
||||
</td>
|
||||
<td class="property">{{ translater.getTranslation("desired humidity") }}:</td>
|
||||
<td class="value">{{ zone.setValue }}</td>
|
||||
<td class="value">{{ zone.desiredHumidity }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
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
|
||||
from Webserver.Translater import Translater, Language
|
||||
from Zone import Zone
|
||||
|
||||
|
||||
def startWebserver(port, zoneManager):
|
||||
translater_EN = Translater(Language.ENGLISH)
|
||||
translater_DE = Translater(Language.GERMAN)
|
||||
translater = translater_EN
|
||||
|
||||
def startWebserver(port, translater, zones):
|
||||
|
||||
|
||||
app = Flask("Bewässerungssystem")
|
||||
app = Flask("Bewässerungssystem", template_folder="Webserver/templates", static_folder="Webserver/static")
|
||||
nav = Navigation(app)
|
||||
|
||||
nav.Bar('top', [
|
||||
|
@ -17,31 +17,56 @@ def startWebserver(port, translater, zones):
|
|||
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)
|
||||
# nav.Item('Gfg', 'gfg', {'page': 5}), #(example with pages)
|
||||
])
|
||||
|
||||
#Example Route with pages:
|
||||
#@app.route('/gfg/<int:page>')
|
||||
#def gfg(page):
|
||||
# Example Route with pages:
|
||||
# @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('/action/<command>/<index_str>/<value_str>')
|
||||
def executeAction(command=False, index_str=False, value_str=False):
|
||||
sucess = False
|
||||
index = int(index_str)
|
||||
value = int(value_str)
|
||||
match command:
|
||||
case "switch_zone_on":
|
||||
if (index and value):
|
||||
zoneManager.switchZoneIndexState(zoneIndex=index, state=True, duration=value)
|
||||
case "switch_zone_off":
|
||||
if (index and value):
|
||||
zoneManager.switchZoneIndexState(zoneIndex=index, state=False, duration=value)
|
||||
case "switch_zone_mode":
|
||||
if (index and value):
|
||||
zone = zoneManager.getZone(index)
|
||||
match value:
|
||||
case "automatic":
|
||||
zone.switchMode(autoMode=True)
|
||||
case "manual":
|
||||
zone.switchMode(autoMode=False)
|
||||
case "set_desired_humidity":
|
||||
if (index and value):
|
||||
zone = zoneManager.getZone(index)
|
||||
zone.desiredHumidity = value
|
||||
|
||||
return render_template('action.html', translater=translater, zones=zoneManager.zones)
|
||||
|
||||
@app.route('/dashboard')
|
||||
def showDashboard():
|
||||
return render_template('dashboard.html', translater=translater, zones=zones)
|
||||
return render_template('dashboard.html', translater=translater, zones=zoneManager.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))
|
||||
if (zoneNumber):
|
||||
return render_template('zone.html', translater=translater, zone=zoneManager.getZone(zoneNumber))
|
||||
else:
|
||||
return render_template('zones.html', translater=translater, zones=zones)
|
||||
|
||||
return render_template('zones.html', translater=translater, zones=zoneManager.zones)
|
||||
|
||||
@app.route('/times')
|
||||
def showTimes():
|
||||
|
@ -52,8 +77,3 @@ def startWebserver(port, translater, zones):
|
|||
return render_template('system.html', translater=translater)
|
||||
|
||||
app.run(debug=True, port=port)
|
||||
|
||||
if __name__ == "__main__":
|
||||
zones = loadZones()
|
||||
translater = Translater(Language.ENGLISH)
|
||||
startWebserver(80, translater, zones)
|
91
Zone.py
91
Zone.py
|
@ -1,25 +1,84 @@
|
|||
import time
|
||||
|
||||
|
||||
class Zone:
|
||||
def __init__(self, number=0, name="", actualValue="100", setValue="0", autoMode=False, state=False):
|
||||
def __init__(self, number=0, name="", actualHumidity="100", desiredHumidity="0", autoMode=False, state=False, setState=0, endTimeSetState=0, planedDuration=0):
|
||||
self.number = number
|
||||
self.name = name
|
||||
self.actualValue = actualValue
|
||||
self.setValue = setValue
|
||||
self.actualHumidity = actualHumidity
|
||||
self.desiredHumidity = desiredHumidity
|
||||
self.autoMode = autoMode #False = manual, True = automatic
|
||||
self.state = state #True = off, True = on
|
||||
self.state = state #True = on, False = off
|
||||
self.setState = setState #0=default, 1=turned off for time, 2=turned on for time, 3=command in pipeline
|
||||
self.endTimeSetState = endTimeSetState
|
||||
self.planedDuration = planedDuration
|
||||
|
||||
def timeOver(self):
|
||||
return time.time() > self.endTimeSetState
|
||||
|
||||
def refreshStatus(self):
|
||||
if(self.AutoMode):
|
||||
if(self.actualValue < self.setValue):
|
||||
self.state = True
|
||||
else:
|
||||
def refreshStateAutomode(self):
|
||||
match self.setState:
|
||||
case 0:
|
||||
if(self.desiredHumidity > self.actualHumidity):
|
||||
self.state = True
|
||||
else:
|
||||
self.state = False
|
||||
case 1:
|
||||
if(self.timeOver()):
|
||||
self.setState = 0
|
||||
self.refreshStateAutomode()
|
||||
else:
|
||||
self.state = False
|
||||
case 2:
|
||||
if (self.timeOver()):
|
||||
self.setState = 0
|
||||
self.refreshStateAutomode()
|
||||
else:
|
||||
self.state = True
|
||||
case 3:
|
||||
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
|
||||
def refreshStateManualmode(self):
|
||||
if(self.setState > 0):
|
||||
match self.setState:
|
||||
case 1:
|
||||
if(self.timeOver()):
|
||||
self.setState = 0
|
||||
self.state = False
|
||||
case 2:
|
||||
if (self.timeOver()):
|
||||
self.setState = 0
|
||||
self.state = False
|
||||
else:
|
||||
self.state = True
|
||||
case 3:
|
||||
self.state = False
|
||||
|
||||
|
||||
def refreshState(self):
|
||||
if(self.autoMode):
|
||||
self.refreshStateAutomode()
|
||||
else:
|
||||
self.refreshStateManualmode()
|
||||
|
||||
def switchMode(self, autoMode):
|
||||
if(self.autoMode != autoMode):
|
||||
self.autoMode = autoMode
|
||||
self.state = False
|
||||
self.refreshState()
|
||||
|
||||
def switchState(self, state, duration, instant):
|
||||
if(instant):
|
||||
if(not state):
|
||||
self.setState = 1
|
||||
else:
|
||||
self.setState = 2
|
||||
self.endTimeSetState = time.time() + duration
|
||||
else:
|
||||
if(state):
|
||||
self.setState = 3
|
||||
self.planedDuration = duration
|
||||
self.refreshState()
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
from FileIO import FileIO
|
||||
|
||||
class ZoneManager:
|
||||
def __init__(self, systemSettings, fileIO):
|
||||
self.systemSettings = systemSettings
|
||||
self.fileIO = FileIO
|
||||
self.zones = fileIO.loadZones()
|
||||
self.pipeLine = []
|
||||
|
||||
def getZone(self, number):
|
||||
for zone in self.zones:
|
||||
if(zone.number == number):
|
||||
return zone
|
||||
|
||||
def addIrrigationJob(self, job):
|
||||
self.pipeLine.append(job)
|
||||
|
||||
def isAnyZoneBusy(self):
|
||||
for zone in self.zones:
|
||||
if(zone.state):
|
||||
return True
|
||||
return False
|
||||
|
||||
def switchZoneState(self, zone, state, duration, instant=False):
|
||||
if(instant or self.systemSettings.multiZoneIrrigation):
|
||||
zone.switchState(state=state, duration=duration, instant=True)
|
||||
else:
|
||||
self.addIrrigationJob(IrrigationJob(zone, duration))
|
||||
|
||||
def switchZoneIndexState(self, zoneIndex, state, duration, instant=False):
|
||||
zone = self.getZone(zoneIndex)
|
||||
self.switchZoneState(zone, state, duration, instant)
|
||||
|
||||
def refreshStates(self):
|
||||
for zone in self.zones:
|
||||
zone.refreshState()
|
||||
|
||||
def processPipeline(self):
|
||||
if(len(self.pipeLine) > 0 and (not self.isAnyZoneBusy())):
|
||||
irrigationJob = self.pipeLine[0]
|
||||
irrigationJob.process()
|
||||
self.pipeLine.pop(0)
|
||||
|
||||
def cronJobs(self):
|
||||
self.refreshStates()
|
||||
self.processPipeline()
|
||||
|
||||
|
||||
|
||||
|
||||
class IrrigationJob:
|
||||
def __init__(self, zone, duration=0):
|
||||
self.zone = zone
|
||||
self.duration = duration
|
||||
self.zone.switchState(state=True, duration=duration, instant=False)
|
||||
|
||||
def process(self):
|
||||
self.zone.switchState(state=True, duration=self.duration, instant=True)
|
|
@ -0,0 +1,12 @@
|
|||
from Webserver import startWebserver
|
||||
from ZoneManager import ZoneManager
|
||||
from SystemSettings import SystemSettings
|
||||
from FileIO import FileIO
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
systemSettings = SystemSettings(dataDir="/Data", multiZoneIrrigation=True)
|
||||
fileIO = FileIO(systemSettings)
|
||||
zoneManager = ZoneManager(systemSettings=systemSettings, fileIO=fileIO)
|
||||
startWebserver(port=80, zoneManager=zoneManager)
|
||||
print("webserver started")
|
Loading…
Reference in New Issue