First Version

This commit is contained in:
Manuel83
2017-06-11 17:12:22 +02:00
parent b03966562c
commit 58e927b0bf
57 changed files with 8540 additions and 1 deletions
+306
View File
@@ -0,0 +1,306 @@
import time
from flask import request
from flask_classy import route
from modules import DBModel, cbpi, get_db
from modules.core.baseview import BaseView
class Fermenter(DBModel):
__fields__ = ["name", "brewname", "sensor", "sensor2", "sensor3", "heater", "cooler", "logic", "config", "target_temp"]
__table_name__ = "fermenter"
__json_fields__ = ["config"]
class FermenterStep(DBModel):
__fields__ = ["name", "days", "hours", "minutes", "temp", "direction", "order", "state", "start", "end", "timer_start", "fermenter_id"]
__table_name__ = "fermenter_step"
@classmethod
def get_by_fermenter_id(cls, id):
cur = get_db().cursor()
cur.execute("SELECT * FROM %s WHERE fermenter_id = ?" % cls.__table_name__,(id,))
result = []
for r in cur.fetchall():
result.append(cls(r))
return result
@classmethod
def get_max_order(cls,id):
cur = get_db().cursor()
cur.execute("SELECT max(fermenter_step.'order') as 'order' FROM %s WHERE fermenter_id = ?" % cls.__table_name__, (id,))
r = cur.fetchone()
return r.get("order")
@classmethod
def update_state(cls, id, state):
cur = get_db().cursor()
cur.execute("UPDATE %s SET state = ? WHERE id =?" % cls.__table_name__, (state, id))
get_db().commit()
@classmethod
def update_timer(cls, id, timer):
cur = get_db().cursor()
cur.execute("UPDATE %s SET timer_start = ? WHERE id =?" % cls.__table_name__, (timer, id))
get_db().commit()
@classmethod
def get_by_state(cls, state):
cur = get_db().cursor()
cur.execute("SELECT * FROM %s WHERE state = ?" % cls.__table_name__, state)
r = cur.fetchone()
if r is not None:
return cls(r)
else:
return None
@classmethod
def reset_all_steps(cls,id):
cur = get_db().cursor()
cur.execute("UPDATE %s SET state = 'I', start = NULL, end = NULL, timer_start = NULL WHERE fermenter_id = ?" % cls.__table_name__, (id,))
get_db().commit()
class FermenterView(BaseView):
model = Fermenter
cache_key = "fermenter"
def post_post_callback(self, m):
m.state = False
m.steps = []
@route('/<int:id>/targettemp/<temp>', methods=['POST'])
def postTargetTemp(self, id, temp):
if temp is None or not temp:
return ('', 500)
id = int(id)
temp = float(temp)
cbpi.cache.get(self.cache_key)[id].target_temp = float(temp)
self.model.update(**self.api.cache.get(self.cache_key)[id].__dict__)
cbpi.emit("UPDATE_FERMENTER_TARGET_TEMP", {"id": id, "target_temp": temp})
return ('', 204)
@route('/<int:id>/brewname', methods=['POST'])
def postBrewName(self, id):
data = request.json
brewname = data.get("brewname")
cbpi.cache.get(self.cache_key)[id].brewname = brewname
self.model.update(**self.api.cache.get(self.cache_key)[id].__dict__)
cbpi.emit("UPDATE_FERMENTER_BREWNAME", {"id": id, "brewname": brewname})
return ('', 204)
@classmethod
def post_init_callback(cls, obj):
obj.steps = FermenterStep.get_by_fermenter_id(obj.id)
obj.state = False
@route('/<int:id>/step', methods=['POST'])
def postStep(self, id):
data = request.json
order_max = FermenterStep.get_max_order(id)
order = order_max + 1 if order_max is not None else 1
data["order"] = order
data["days"] = 0 if data["days"] == "" else data["days"]
data["hours"] = 0 if data["hours"] == "" else data["hours"]
data["minutes"] = 0 if data["minutes"] == "" else data["minutes"]
data["temp"] = 0 if data["temp"] == "" else data["temp"]
data["state"] = "I"
data["name"] = "NO NAME" if data["name"] == "" else data["name"]
f = FermenterStep.insert(**data)
cbpi.cache.get(self.cache_key)[id].steps.append(f)
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
return ('', 204)
@route('/<int:id>/step/<int:stepid>', methods=["PUT"])
def putStep(self, id, stepid):
data = request.json
# Select modal
data["id"] = stepid
data["fermenter_id"] = id
data["days"] = 0 if data["days"] == "" else data["days"]
data["hours"] = 0 if data["hours"] == "" else data["hours"]
data["minutes"] = 0 if data["minutes"] == "" else data["minutes"]
for s in cbpi.cache.get(self.cache_key)[id].steps:
if s.id == stepid:
s.__dict__.update(**data)
FermenterStep.update(**s.__dict__)
break
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
return ('', 204)
@route('/<int:id>/step/<int:stepid>', methods=["DELETE"])
def deleteStep(self, id, stepid):
for idx, s in enumerate(cbpi.cache.get(self.cache_key)[id].steps):
if s.id == stepid:
del cbpi.cache.get(self.cache_key)[id].steps[idx]
FermenterStep.delete(s.id)
break
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
return ('', 204)
@route('/<int:id>/start', methods=['POST'])
def start_fermentation(self, id):
active = None
for idx, s in enumerate(cbpi.cache.get(self.cache_key)[id].steps):
if s.state == 'A':
active = s
break
inactive = None
for idx, s in enumerate(cbpi.cache.get(self.cache_key)[id].steps):
if s.state == 'I':
inactive = s
break
if active is not None:
active.state = 'D'
active.end = time.time()
FermenterStep.update(**active.__dict__)
del cbpi.cache["fermenter_task"][id]
if inactive is not None:
fermenter = self.get_fermenter(inactive.fermenter_id)
current_temp = cbpi.get_sensor_value(int(fermenter.sensor))
inactive.state = 'A'
inactive.start = time.time()
inactive.direction = "C" if current_temp >= inactive.temp else "H"
FermenterStep.update(**inactive.__dict__)
self.postTargetTemp(id, inactive.temp)
cbpi.cache["fermenter_task"][id] = inactive
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
return ('', 204)
@route('/<int:id>/reset', methods=["POST"])
def reset(self, id):
FermenterStep.reset_all_steps(id)
cbpi.cache[self.cache_key][id].steps = FermenterStep.get_by_fermenter_id(id)
if id in cbpi.cache["fermenter_task"]:
del cbpi.cache["fermenter_task"][id]
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
return ('', 204)
@route('/<int:id>/automatic', methods=['POST'])
def toggle(self, id):
fermenter = cbpi.cache.get(self.cache_key)[id]
try:
if fermenter.state is False:
# Start controller
if fermenter.logic is not None:
cfg = fermenter.config.copy()
cfg.update(
dict(api=cbpi, fermenter_id=fermenter.id, heater=fermenter.heater, sensor=fermenter.sensor))
instance = cbpi.get_fermentation_controller(fermenter.logic).get("class")(**cfg)
instance.init()
fermenter.controller_instance = instance
def run(instance):
instance.run()
t = cbpi.socketio.start_background_task(target=run, instance=instance)
fermenter.state = not fermenter.state
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key).get(id))
else:
# Stop controller
fermenter.controller_instance.stop()
fermenter.state = not fermenter.state
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key).get(id))
except Exception as e:
cbpi.notify("Toogle Fementer Controller failed", "Pleae check the %s configuration" % fermenter.name,
type="danger", timeout=None)
return ('', 500)
return ('', 204)
def get_fermenter(self, id):
return cbpi.cache["fermenter"].get(id)
def target_temp_reached(self,id, step):
timestamp = time.time()
days = step.days * 24 * 60 * 60
hours = step.hours * 60 * 60
minutes = step.minutes * 60
target_time = days + hours + minutes + timestamp
FermenterStep.update_timer(step.id, target_time)
step.timer_start = target_time
cbpi.emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id])
def check_step(self):
for key, value in cbpi.cache["fermenter_task"].iteritems():
try:
fermenter = self.get_fermenter(key)
current_temp = current_temp = cbpi.get_sensor_value(int(fermenter.sensor))
if value.timer_start is None:
if value.direction == "H" :
if current_temp >= value.temp:
self.target_temp_reached(key,value)
else:
if current_temp <= value.temp:
self.target_temp_reached(key, value)
else:
if time.time() >= value.timer_start:
self.start_fermentation(key)
else:
pass
except Exception as e:
pass
@cbpi.backgroundtask(key="read_target_temps_fermenter", interval=5)
def read_target_temps():
"""
background process that reads all passive sensors in interval of 1 second
:return: None
"""
result = {}
for key, value in cbpi.cache.get("fermenter").iteritems():
cbpi.save_to_file(key, value.target_temp, prefix="fermenter")
instance = FermenterView()
@cbpi.backgroundtask(key="fermentation_task", interval=1)
def execute_fermentation_step():
with cbpi.app.app_context():
instance.check_step()
def init_active_steps():
'''
active_steps = FermenterStep.query.filter_by(state='A')
for a in active_steps:
db.session.expunge(a)
cbpi.cache["fermenter_task"][a.fermenter_id] = a
'''
@cbpi.initalizer(order=1)
def init(cbpi):
print "INITIALIZE CONFIG MODULE"
FermenterView.register(cbpi.app, route_base='/api/fermenter')
FermenterView.init_cache()