diff --git a/FileIO/__init__.py b/FileIO/__init__.py index 6b53a7f..0c6ff54 100644 --- a/FileIO/__init__.py +++ b/FileIO/__init__.py @@ -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) \ No newline at end of file + 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 diff --git a/SystemSettings.py b/SystemSettings.py new file mode 100644 index 0000000..0ca6a50 --- /dev/null +++ b/SystemSettings.py @@ -0,0 +1,6 @@ + + +class SystemSettings: + def __init__(self, dataDir="/Data", multiZoneIrrigation=False): + self.dataDir = dataDir + self.multiZoneIrrigation = multiZoneIrrigation \ No newline at end of file diff --git a/Webserver/Templates/dashboard.html b/Webserver/Templates/dashboard.html index 8f58116..c657192 100644 --- a/Webserver/Templates/dashboard.html +++ b/Webserver/Templates/dashboard.html @@ -66,18 +66,18 @@ - + {{ translater.getTranslation("actual humidity") }}: - {{ zone.actualValue}} + {{ zone.actualHumidity}} {{ translater.getTranslation("desired humidity") }}: - {{ zone.setValue }} + {{ zone.desiredHumidity }} diff --git a/Webserver/__init__.py b/Webserver/__init__.py index 27f411e..d71fa3b 100644 --- a/Webserver/__init__.py +++ b/Webserver/__init__.py @@ -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/') - #def gfg(page): + # Example Route with pages: + # @app.route('/gfg/') + # def gfg(page): # return render_template('gfg.html', page=page) - @app.route('/') def startPage(): return redirect(url_for('showDashboard')) + @app.route('/action///') + 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/') 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) \ No newline at end of file diff --git a/Zone.py b/Zone.py index 43b5fa4..457f84f 100644 --- a/Zone.py +++ b/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 \ No newline at end of file + 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() + + diff --git a/ZoneManager.py b/ZoneManager.py new file mode 100644 index 0000000..eb3fc7f --- /dev/null +++ b/ZoneManager.py @@ -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) \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..5a46f41 --- /dev/null +++ b/main.py @@ -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") \ No newline at end of file