- Login Added. Default Password is „beer“

- Several UI Adjustments - still work in progress
- New API Method to add custom JavaScript to CraftBeerPi
- Global Action Buttons added
- Register new Web Modules for complete custom UI
This commit is contained in:
Manuel83
2017-09-24 15:10:45 +02:00
parent 42ed9f02af
commit 813b2f0035
22 changed files with 354 additions and 139 deletions
+8
View File
@@ -87,6 +87,9 @@ class StepAPI(BaseAPI):
return func
return real_decorator
class ActorAPI(BaseAPI):
key = "actor_types"
@@ -150,6 +153,8 @@ class CoreAPI(BaseAPI):
self.cbpi.cache["init"] = []
self.cbpi.cache["js"] = {}
self.cbpi.cache["background"] = []
self.cbpi.cache["web_menu"] =[]
def init(self):
self.cbpi.cache["init"] = sorted(self.cbpi.cache["init"], key=lambda k: k['order'])
@@ -173,6 +178,9 @@ class CoreAPI(BaseAPI):
def add_js(self, name, file):
self.cbpi.cache["js"][name] = file
def add_menu_link(self, name, path):
self.cbpi.cache["web_menu"].append(dict(name=name, path=path))
def initializer(self, order=0, **options):
def decorator(f):
self.cbpi.cache.get("init").append({"function": f, "order": order})
+2 -1
View File
@@ -246,4 +246,5 @@ class Step(Base):
self.__dirty = True
super(Step, self).__setattr__(name, value)
else:
super(Step, self).__setattr__(name, value)
super(Step, self).__setattr__(name, value)
+7 -1
View File
@@ -1,5 +1,7 @@
from flask import request, json
from flask_classy import route, FlaskView
from flask_login import login_required
from modules.core.core import cbpi
@@ -9,6 +11,7 @@ class BaseView(FlaskView):
cache_key = None
api = cbpi
@login_required
@route('/<int:id>', methods=["GET"])
def getOne(self, id):
if self.api.cache.get(self.cache_key) is not None:
@@ -16,6 +19,7 @@ class BaseView(FlaskView):
else:
return json.dumps(self.model.get_one(id))
@login_required
@route('/', methods=["GET"])
def getAll(self):
if self.api.cache.get(self.cache_key) is not None:
@@ -30,6 +34,7 @@ class BaseView(FlaskView):
def _post_post_callback(self, m):
pass
@login_required
@route('/', methods=["POST"])
def post(self):
@@ -50,7 +55,7 @@ class BaseView(FlaskView):
def _post_put_callback(self, m):
pass
@login_required
@route('/<int:id>', methods=["PUT"])
def put(self, id):
data = request.json
@@ -78,6 +83,7 @@ class BaseView(FlaskView):
def _post_delete_callback(self, id):
pass
@login_required
@route('/<int:id>', methods=["DELETE"])
def delete(self, id):
if self.api.cache.get(self.cache_key) is not None:
+53 -1
View File
@@ -7,6 +7,7 @@ from datetime import datetime
from functools import wraps, update_wrapper
from importlib import import_module
from time import localtime, strftime
import time
from flask import Flask, redirect, json, g, make_response
from flask_socketio import SocketIO
@@ -17,6 +18,7 @@ from modules.core.basetypes import Sensor, Actor
from modules.database.dbmodel import Kettle
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
try:
@@ -109,6 +111,12 @@ class ActorCore(object):
print e
return False
def toggle(self, id):
if self.cbpi.cache.get("actors").get(id).state == 0:
self.on(id)
else:
self.off(id)
def power(self, id, power):
try:
actor = self.cbpi.cache["actors"].get(int(id))
@@ -121,6 +129,20 @@ class ActorCore(object):
print e
return False
def action(self, id, method):
self.cbpi.cache.get("actors").get(id).instance.__getattribute__(method)()
def toggle_timeout(self, id, seconds):
def toggle( id, seconds):
self.cbpi.cache.get("actors").get(int(id)).timer = int(time.time()) + int(seconds)
self.toggle(int(id))
self.cbpi.sleep(seconds)
self.cbpi.cache.get("actors").get(int(id)).timer = None
self.toggle(int(id))
job = self.cbpi._socketio.start_background_task(target=toggle, id=id, seconds=seconds)
def get_state(self, actor_id):
print actor_id
print self.cbpi
@@ -183,6 +205,10 @@ class SensorCore(object):
with open(filename, "a") as file:
file.write(msg)
def action(self, id, method):
self.cbpi.cache.get("sensors").get(id).instance.__getattribute__(method)()
class BrewingCore(object):
def __init__(self, cbpi):
@@ -207,6 +233,32 @@ class BrewingCore(object):
self.cbpi.emit("SET_KETTLE_TARGET_TEMP", id=id, temp=temp)
def toggle_automatic(self, id):
kettle = self.cbpi.cache.get("kettle")[id]
if kettle.state is False:
# Start controller
if kettle.logic is not None:
cfg = kettle.config.copy()
cfg.update(dict(api=cbpi, kettle_id=kettle.id, heater=kettle.heater, sensor=kettle.sensor))
instance = self.get_controller(kettle.logic).get("class")(**cfg)
instance.init()
kettle.instance = instance
def run(instance):
instance.run()
t = self.cbpi._socketio.start_background_task(target=run, instance=instance)
kettle.state = not kettle.state
self.cbpi.ws_emit("UPDATE_KETTLE", cbpi.cache.get("kettle").get(id))
self.cbpi.emit("KETTLE_CONTROLLER_STARTED", id=id)
else:
# Stop controller
kettle.instance.stop()
kettle.state = not kettle.state
self.cbpi.ws_emit("UPDATE_KETTLE", cbpi.cache.get("kettle").get(id))
self.cbpi.emit("KETTLE_CONTROLLER_STOPPED", id=id)
class FermentationCore(object):
def __init__(self, cbpi):
self.cbpi = cbpi
@@ -313,7 +365,7 @@ class CraftBeerPI(object):
return cfg.value
def emit(self, key, **kwargs):
print key, kwargs
if self.eventbus.get(key) is not None:
for value in self.eventbus[key]:
if value["async"] is False:
+44
View File
@@ -0,0 +1,44 @@
import sqlite3
import os
from modules.core.core import cbpi
from modules.core.db import get_db
def execute_file(curernt_version, data):
if curernt_version >= data["version"]:
cbpi._app.logger.info("SKIP DB FILE: %s" % data["file"])
return
try:
with sqlite3.connect("craftbeerpi.db") as conn:
with open('./update/%s' % data["file"], 'r') as f:
d = f.read()
sqlCommands = d.split(";")
cur = conn.cursor()
for s in sqlCommands:
cur.execute(s)
cur.execute("INSERT INTO schema_info (version,filename) values (?,?)", (data["version"], data["file"]))
conn.commit()
except sqlite3.OperationalError as err:
print "EXCEPT"
print err
@cbpi.addon.core.initializer(order=-9999)
def init(cbpi):
with cbpi._app.app_context():
conn = get_db()
cur = conn.cursor()
current_version = None
try:
cur.execute("SELECT max(version) as m FROM schema_info")
m = cur.fetchone()
current_version = m["m"]
except:
pass
result = []
for filename in os.listdir("./update"):
print filename
if filename.endswith(".sql"):
d = {"version": int(filename[:filename.index('_')]), "file": filename}
result.append(d)
execute_file(current_version, d)
-36
View File
@@ -1,36 +0,0 @@
import flask_login
from modules.core.core import cbpi, addon
class User(flask_login.UserMixin):
pass
@addon.core.initializer(order=0)
def log(cbpi):
cbpi._login_manager = flask_login.LoginManager()
cbpi._login_manager.init_app(cbpi._app)
@cbpi._app.route('/login', methods=['GET', 'POST'])
def login():
user = User()
user.id = "manuel"
flask_login.login_user(user)
return "OK"
@cbpi._app.route('/logout')
def logout():
flask_login.logout_user()
return 'Logged out'
@cbpi._login_manager.user_loader
def user_loader(email):
if email not in cbpi.cache["users"]:
return
user = User()
user.id = email
return user
@cbpi._login_manager.unauthorized_handler
def unauthorized_handler():
return 'Unauthorized :-('