- Action Button with Parameter - Actor Action with Parameter - Sensor Action with Parametercore_refactoring
| @@ -0,0 +1,4 @@ | |||||
| from modules.core.core import CraftBeerPI, Addon | |||||
| cbpi = CraftBeerPI() | |||||
| cbpi.addon = Addon(cbpi) | |||||
| @@ -1,6 +1,8 @@ | |||||
| import json | import json | ||||
| from flask import request | |||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| class ActionView(FlaskView): | class ActionView(FlaskView): | ||||
| @@ -15,9 +17,10 @@ class ActionView(FlaskView): | |||||
| 200: | 200: | ||||
| description: action invoked | description: action invoked | ||||
| """ | """ | ||||
| data = request.json | |||||
| self.cbpi.cache["actions"][action]["function"](self.cbpi) | |||||
| obj = self.cbpi.cache["actions"][action]["class"](self.cbpi) | |||||
| obj.execute(**data) | |||||
| return ('',204) | return ('',204) | ||||
| @cbpi.addon.core.initializer() | @cbpi.addon.core.initializer() | ||||
| @@ -28,4 +31,4 @@ def init(cbpi): | |||||
| :return: None | :return: None | ||||
| """ | """ | ||||
| ActionView.cbpi = cbpi | ActionView.cbpi = cbpi | ||||
| ActionView.register(cbpi._app, route_base='/api/action') | |||||
| ActionView.register(cbpi.web, route_base='/api/action') | |||||
| @@ -1,14 +1,16 @@ | |||||
| import time | import time | ||||
| from flask import request | |||||
| from flask_classy import route | from flask_classy import route | ||||
| from flask_login import login_required | from flask_login import login_required | ||||
| from modules.core.db import DBModel | from modules.core.db import DBModel | ||||
| from modules.core.core import cbpi | |||||
| from modules.core.baseview import BaseView | |||||
| from modules import cbpi | |||||
| from modules.core.baseview import RestApi | |||||
| from modules.database.dbmodel import Actor | from modules.database.dbmodel import Actor | ||||
| class ActorView(BaseView): | |||||
| class ActorView(RestApi): | |||||
| model = Actor | model = Actor | ||||
| cache_key = "actors" | cache_key = "actors" | ||||
| @@ -121,7 +123,7 @@ class ActorView(BaseView): | |||||
| def toggleTimeJob(self, id, t): | def toggleTimeJob(self, id, t): | ||||
| self.api.cache.get("actors").get(int(id)).timer = int(time.time()) + int(t) | self.api.cache.get("actors").get(int(id)).timer = int(time.time()) + int(t) | ||||
| self.toggle(int(id)) | self.toggle(int(id)) | ||||
| self.api._socketio.sleep(t) | |||||
| self.api.sleep(t) | |||||
| self.api.cache.get("actors").get(int(id)).timer = None | self.api.cache.get("actors").get(int(id)).timer = None | ||||
| self.toggle(int(id)) | self.toggle(int(id)) | ||||
| @@ -179,13 +181,18 @@ class ActorView(BaseView): | |||||
| 200: | 200: | ||||
| description: Actor Action called | description: Actor Action called | ||||
| """ | """ | ||||
| self.api.actor.action(id, method) | |||||
| data = request.json | |||||
| if data: | |||||
| cbpi.actor.action(id, method, **data) | |||||
| else: | |||||
| cbpi.actor.action(id, method) | |||||
| return ('', 204) | return ('', 204) | ||||
| @cbpi.addon.core.initializer(order=1000) | @cbpi.addon.core.initializer(order=1000) | ||||
| def init(cbpi): | def init(cbpi): | ||||
| ActorView.register(cbpi._app, route_base='/api/actor') | |||||
| ActorView.register(cbpi.web, route_base='/api/actor') | |||||
| ActorView.init_cache() | ActorView.init_cache() | ||||
| #cbpi.init_actors() | #cbpi.init_actors() | ||||
| @@ -1,15 +1,37 @@ | |||||
| from modules.core.baseapi import Buzzer | from modules.core.baseapi import Buzzer | ||||
| from modules.core.basetypes import Actor, KettleController, FermenterController | from modules.core.basetypes import Actor, KettleController, FermenterController | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from modules.core.proptypes import Property | |||||
| @cbpi.addon.actor.type("Dummy Actor") | @cbpi.addon.actor.type("Dummy Actor") | ||||
| class Dummy(Actor): | class Dummy(Actor): | ||||
| @cbpi.addon.actor.action("WOHOO") | |||||
| def myaction(self): | |||||
| print "WOOHOO" | |||||
| pass | |||||
| # Decorator to create a parameter based action | |||||
| @cbpi.addon.actor.action("Run until Temp reached", parameters={"t": Property.Text(label="Target Temp")}) | |||||
| def check_sensor_value(self, t=1): | |||||
| def check(api, id, value): | |||||
| ''' | |||||
| Background Prozess which checks the sensor value every second | |||||
| :param api: | |||||
| :param id: | |||||
| :param value: | |||||
| :return: | |||||
| ''' | |||||
| while api.sensor.get_value(1) < value: | |||||
| api.sleep(1) | |||||
| api.actor.off(id) | |||||
| target_value = int(t) | |||||
| # Create notificaiton | |||||
| self.api.notify(headline="Waiting", message="Waiting for temp %s" % target_value) | |||||
| # Switch actor on | |||||
| self.api.actor.on(self.id, 100) | |||||
| # Start Background task | |||||
| self.api.start_background_task(check, self.api, id=self.id, value=target_value) | |||||
| def on(self, power=100): | def on(self, power=100): | ||||
| ''' | ''' | ||||
| @@ -17,11 +39,10 @@ class Dummy(Actor): | |||||
| :param power: int value between 0 - 100 | :param power: int value between 0 - 100 | ||||
| :return: | :return: | ||||
| ''' | ''' | ||||
| print "ON" | |||||
| print "ID %s ON" % self.id | |||||
| def off(self): | def off(self): | ||||
| print "OFF" | |||||
| print "ID %s OFF" % self.id | |||||
| @cbpi.addon.kettle.controller() | @cbpi.addon.kettle.controller() | ||||
| @@ -29,7 +50,7 @@ class MyController(KettleController): | |||||
| def run(self): | def run(self): | ||||
| while self.is_running(): | while self.is_running(): | ||||
| print "HALLO" | |||||
| self.sleep(1) | self.sleep(1) | ||||
| @@ -49,6 +70,7 @@ def init(cbpi): | |||||
| class MyBuzzer(Buzzer): | class MyBuzzer(Buzzer): | ||||
| def beep(self): | def beep(self): | ||||
| print "BEEEEEP" | |||||
| pass | pass | ||||
| cbpi.buzzer = MyBuzzer() | cbpi.buzzer = MyBuzzer() | ||||
| @@ -3,11 +3,12 @@ import os | |||||
| from os.path import join | from os.path import join | ||||
| from modules.core.basetypes import Actor, Sensor | |||||
| from modules.core.core import cbpi | |||||
| from modules.core.basetypes import Actor, Sensor, Action | |||||
| from modules import cbpi | |||||
| from modules.core.proptypes import Property | from modules.core.proptypes import Property | ||||
| import random | import random | ||||
| @cbpi.addon.sensor.type("Dummy Sensor") | @cbpi.addon.sensor.type("Dummy Sensor") | ||||
| class Dummy(Sensor): | class Dummy(Sensor): | ||||
| @@ -21,10 +22,15 @@ class Dummy(Sensor): | |||||
| else: | else: | ||||
| self.unit = "°F" | self.unit = "°F" | ||||
| @cbpi.addon.sensor.action("WOHOO") | |||||
| def myaction(self): | |||||
| @cbpi.addon.sensor.action(label="Set Dummy Temp", parameters={ | |||||
| "p1":Property.Select(label="Temp",options=[1,2,3]), | |||||
| }) | |||||
| def myaction(self, p1): | |||||
| self.text = p1 | |||||
| self.update_value(int(p1)) | |||||
| self.api.notify(headline="WOHOO", message="HALLO") | |||||
| def execute(self): | def execute(self): | ||||
| while True: | while True: | ||||
| @@ -34,14 +40,28 @@ class Dummy(Sensor): | |||||
| pass | pass | ||||
| self.api.sleep(5) | self.api.sleep(5) | ||||
| @cbpi.addon.core.action(key="clear", label="Clear all Logs") | |||||
| def woohoo(cbpi): | |||||
| dir = "./logs" | |||||
| test = os.listdir(dir) | |||||
| @cbpi.addon.core.action(name="Delete All Logs") | |||||
| class ParameterAction(Action): | |||||
| p1 = Property.Number("P1", configurable=True, description="Target Temperature of Mash Step", unit="C") | |||||
| p2 = Property.Number("P2", configurable=True, description="Target Temperature of Mash Step", unit="C") | |||||
| def execute(self, p1, p2, **kwargs): | |||||
| for i in range(5): | |||||
| cbpi.sleep(1) | |||||
| cbpi.notify(headline="Woohoo", message="%s %s" % (p1, p2)) | |||||
| @cbpi.addon.core.action(name="Delete All Logs") | |||||
| class DeleteAllLogs(Action): | |||||
| def execute(self, **kwargs): | |||||
| dir = "./logs" | |||||
| test = os.listdir(dir) | |||||
| for item in test: | |||||
| for item in test: | |||||
| if item.endswith(".log"): | |||||
| os.remove(join(dir, item)) | |||||
| cbpi.notify(headline="Logs Deleted",message="All Logs Cleared") | |||||
| if item.endswith(".log"): | |||||
| os.remove(join(dir, item)) | |||||
| cbpi.notify(headline="Logs Deleted", message="All Logs Cleared") | |||||
| @@ -1,5 +1,5 @@ | |||||
| from modules.core.basetypes import Step | from modules.core.basetypes import Step | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from modules.core.proptypes import Property | from modules.core.proptypes import Property | ||||
| import time | import time | ||||
| @@ -18,7 +18,7 @@ class Dummy(Step): | |||||
| time = Property.Text(label="Text", configurable=True, description="WOHOOO") | time = Property.Text(label="Text", configurable=True, description="WOHOOO") | ||||
| def execute(self): | def execute(self): | ||||
| #print self.text | |||||
| pass | pass | ||||
| def reset(self): | def reset(self): | ||||
| @@ -36,8 +36,8 @@ class MashStep(Step): | |||||
| Just put the decorator @cbpi.step on top of a method | Just put the decorator @cbpi.step on top of a method | ||||
| ''' | ''' | ||||
| # Properties | # Properties | ||||
| temp = Property.Number("Temperature", configurable=True, description="Target Temperature of Mash Step") | |||||
| kettle = Property.Kettle("Kettle", description="Kettle in which the mashing takes place") | |||||
| temp = Property.Number("Temperature", configurable=True, description="Target Temperature of Mash Step", unit="C") | |||||
| kettle = Property.Kettle("Kettle", description="Kettle in which the mashing takes place" ) | |||||
| timer = Property.Number("Timer in Minutes", configurable=True, description="Timer is started when the target temperature is reached") | timer = Property.Number("Timer in Minutes", configurable=True, description="Timer is started when the target temperature is reached") | ||||
| def init(self): | def init(self): | ||||
| @@ -79,6 +79,7 @@ class MashStep(Step): | |||||
| # Check if timer finished and go to next step | # Check if timer finished and go to next step | ||||
| if self.is_timer_finished() == True: | if self.is_timer_finished() == True: | ||||
| self.api.beep() | |||||
| self.notify("Mash Step Completed!", "Starting the next step", timeout=None) | self.notify("Mash Step Completed!", "Starting the next step", timeout=None) | ||||
| self.next() | self.next() | ||||
| @@ -243,3 +244,5 @@ class BoilStep(Step): | |||||
| if self.is_timer_finished() == True: | if self.is_timer_finished() == True: | ||||
| self.notify("Boil Step Completed!", "Starting the next step", timeout=None) | self.notify("Boil Step Completed!", "Starting the next step", timeout=None) | ||||
| self.next() | self.next() | ||||
| @@ -2,7 +2,7 @@ import time | |||||
| from thread import start_new_thread | from thread import start_new_thread | ||||
| from modules.core.baseapi import Buzzer | from modules.core.baseapi import Buzzer | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| try: | try: | ||||
| import RPi.GPIO as GPIO | import RPi.GPIO as GPIO | ||||
| @@ -16,19 +16,19 @@ class GPIOBuzzer(Buzzer): | |||||
| def __init__(self, gpio): | def __init__(self, gpio): | ||||
| try: | try: | ||||
| cbpi._app.logger.info("INIT BUZZER NOW GPIO%s" % gpio) | |||||
| cbpi.web.logger.info("INIT BUZZER NOW GPIO%s" % gpio) | |||||
| self.gpio = int(gpio) | self.gpio = int(gpio) | ||||
| GPIO.setmode(GPIO.BCM) | GPIO.setmode(GPIO.BCM) | ||||
| GPIO.setup(self.gpio, GPIO.OUT) | GPIO.setup(self.gpio, GPIO.OUT) | ||||
| self.state = True | self.state = True | ||||
| cbpi._app.logger.info("BUZZER SETUP OK") | |||||
| cbpi.web.logger.info("BUZZER SETUP OK") | |||||
| except Exception as e: | except Exception as e: | ||||
| cbpi._app.logger.info("BUZZER EXCEPTION %s" % str(e)) | |||||
| cbpi.web.logger.info("BUZZER EXCEPTION %s" % str(e)) | |||||
| self.state = False | self.state = False | ||||
| def beep(self): | def beep(self): | ||||
| if self.state is False: | if self.state is False: | ||||
| cbpi._app.logger.error("BUZZER not working") | |||||
| cbpi.web.logger.error("BUZZER not working") | |||||
| return | return | ||||
| def play(sound): | def play(sound): | ||||
| @@ -2,13 +2,13 @@ import time | |||||
| from flask import json, request | from flask import json, request | ||||
| from flask_classy import route | from flask_classy import route | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from modules.core.db import DBModel | from modules.core.db import DBModel | ||||
| from modules.core.baseview import BaseView | |||||
| from modules.core.baseview import RestApi | |||||
| from modules.database.dbmodel import Config | from modules.database.dbmodel import Config | ||||
| class ConfigView(BaseView): | |||||
| class ConfigView(RestApi): | |||||
| model = Config | model = Config | ||||
| cache_key = "config" | cache_key = "config" | ||||
| @@ -77,7 +77,7 @@ class ConfigView(BaseView): | |||||
| @classmethod | @classmethod | ||||
| def init_cache(cls): | def init_cache(cls): | ||||
| with cls.api._app.app_context(): | |||||
| with cls.api.web.app_context(): | |||||
| cls.api.cache[cls.cache_key] = {} | cls.api.cache[cls.cache_key] = {} | ||||
| for key, value in cls.model.get_all().iteritems(): | for key, value in cls.model.get_all().iteritems(): | ||||
| cls.post_init_callback(value) | cls.post_init_callback(value) | ||||
| @@ -85,5 +85,5 @@ class ConfigView(BaseView): | |||||
| @cbpi.addon.core.initializer(order=0) | @cbpi.addon.core.initializer(order=0) | ||||
| def init(cbpi): | def init(cbpi): | ||||
| ConfigView.register(cbpi._app, route_base='/api/config') | |||||
| ConfigView.register(cbpi.web, route_base='/api/config') | |||||
| ConfigView.init_cache() | ConfigView.init_cache() | ||||
| @@ -22,6 +22,9 @@ class BaseAPI(object): | |||||
| except: | except: | ||||
| doc = "" | doc = "" | ||||
| if self.cbpi.cache.get(key) is None: | |||||
| self.cbpi.cache[key] = {} | |||||
| self.cbpi.logger.debug(name) | |||||
| self.cbpi.cache.get(key)[name] = {"name": name, "class": cls, "description":doc, "properties": [], "actions": []} | self.cbpi.cache.get(key)[name] = {"name": name, "class": cls, "description":doc, "properties": [], "actions": []} | ||||
| self.cbpi.cache.get(key)[name].update(options) | self.cbpi.cache.get(key)[name].update(options) | ||||
| members = [attr for attr in dir(tmpObj) if not callable(getattr(tmpObj, attr)) and not attr.startswith("__")] | members = [attr for attr in dir(tmpObj) if not callable(getattr(tmpObj, attr)) and not attr.startswith("__")] | ||||
| @@ -29,23 +32,39 @@ class BaseAPI(object): | |||||
| t = tmpObj.__getattribute__(m) | t = tmpObj.__getattribute__(m) | ||||
| if isinstance(t, Property.Number): | if isinstance(t, Property.Number): | ||||
| self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "number", "configurable": t.configurable, "description": t.description, "default_value": t.default_value}) | |||||
| self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "number", "configurable": t.configurable, "description": t.description, "default_value": t.default_value, "unit": t.unit}) | |||||
| elif isinstance(t, Property.Text): | elif isinstance(t, Property.Text): | ||||
| self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "text", "required": t.required, "configurable": t.configurable, "description": t.description, "default_value": t.default_value}) | self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "text", "required": t.required, "configurable": t.configurable, "description": t.description, "default_value": t.default_value}) | ||||
| elif isinstance(tmpObj.__getattribute__(m), Property.Select): | |||||
| elif isinstance(t, Property.Select): | |||||
| self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "select", "configurable": True, "options": t.options, "description": t.description}) | self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "select", "configurable": True, "options": t.options, "description": t.description}) | ||||
| elif isinstance(tmpObj.__getattribute__(m), Property.Actor): | |||||
| elif isinstance(t, Property.Actor): | |||||
| self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "actor", "configurable": True, "description": t.description}) | self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "actor", "configurable": True, "description": t.description}) | ||||
| elif isinstance(tmpObj.__getattribute__(m), Property.Sensor): | |||||
| elif isinstance(t, Property.Sensor): | |||||
| self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "sensor", "configurable": True, "description": t.description}) | self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "sensor", "configurable": True, "description": t.description}) | ||||
| elif isinstance(tmpObj.__getattribute__(m), Property.Kettle): | |||||
| elif isinstance(t, Property.Kettle): | |||||
| self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": True, "description": t.description}) | self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": True, "description": t.description}) | ||||
| for method_name, method in cls.__dict__.iteritems(): | for method_name, method in cls.__dict__.iteritems(): | ||||
| if hasattr(method, "action"): | if hasattr(method, "action"): | ||||
| label = method.__getattribute__("label") | label = method.__getattribute__("label") | ||||
| self.cbpi.cache.get(key)[name]["actions"].append({"method": method_name, "label": label}) | |||||
| parameters = method.__getattribute__("parameters") | |||||
| props = [] | |||||
| if parameters is not None: | |||||
| for k, t in parameters.iteritems(): | |||||
| if isinstance(t, Property.Number): | |||||
| props.append({"name": k, "label": t.label, "type": "number", "configurable": t.configurable, "description": t.description, "default_value": t.default_value, "unit": t.unit}) | |||||
| elif isinstance(t, Property.Text): | |||||
| props.append({"name": k, "label": t.label, "type": "text", "required": t.required, "configurable": t.configurable, "description": t.description, "default_value": t.default_value}) | |||||
| elif isinstance(t, Property.Select): | |||||
| props.append({"name": k, "label": t.label, "type": "select", "configurable": True, "options": t.options, "description": t.description}) | |||||
| elif isinstance(t, Property.Actor): | |||||
| props.append({"name": k, "label": t.label, "type": "actor", "configurable": True, "description": t.description}) | |||||
| elif isinstance(t, Property.Sensor): | |||||
| props.append({"name": k, "label": t.label, "type": "sensor", "configurable": True, "description": t.description}) | |||||
| elif isinstance(t, Property.Kettle): | |||||
| props.append({"name": k, "label": t.label, "type": "kettle", "configurable": True, "description": t.description}) | |||||
| self.cbpi.cache.get(key)[name]["actions"].append({"method": method_name, "label": label, "properties":props }) | |||||
| return cls | return cls | ||||
| @@ -59,9 +78,11 @@ class SensorAPI(BaseAPI): | |||||
| return f | return f | ||||
| return decorator | return decorator | ||||
| def action(self, label): | |||||
| def action(self, label, parameters=None): | |||||
| def real_decorator(func): | def real_decorator(func): | ||||
| func.action = True | func.action = True | ||||
| func.parameters = parameters | |||||
| func.label = label | func.label = label | ||||
| return func | return func | ||||
| return real_decorator | return real_decorator | ||||
| @@ -80,10 +101,11 @@ class StepAPI(BaseAPI): | |||||
| return f | return f | ||||
| return decorator | return decorator | ||||
| def action(self, label): | |||||
| def action(self, label, parameters=None): | |||||
| def real_decorator(func): | def real_decorator(func): | ||||
| func.action = True | func.action = True | ||||
| func.label = label | func.label = label | ||||
| func.parameters = parameters | |||||
| return func | return func | ||||
| return real_decorator | return real_decorator | ||||
| @@ -100,10 +122,11 @@ class ActorAPI(BaseAPI): | |||||
| return f | return f | ||||
| return decorator | return decorator | ||||
| def action(self, label): | |||||
| def action(self, label, parameters=None): | |||||
| def real_decorator(func): | def real_decorator(func): | ||||
| func.action = True | func.action = True | ||||
| func.label = label | func.label = label | ||||
| func.parameters = parameters | |||||
| return func | return func | ||||
| return real_decorator | return real_decorator | ||||
| @@ -119,10 +142,11 @@ class KettleAPI(BaseAPI): | |||||
| return f | return f | ||||
| return decorator | return decorator | ||||
| def action(self, label): | |||||
| def action(self, label, parameters=None): | |||||
| def real_decorator(func): | def real_decorator(func): | ||||
| func.action = True | func.action = True | ||||
| func.label = label | func.label = label | ||||
| func.parameters = parameters | |||||
| return func | return func | ||||
| return real_decorator | return real_decorator | ||||
| @@ -136,10 +160,11 @@ class FermenterAPI(BaseAPI): | |||||
| return f | return f | ||||
| return decorator | return decorator | ||||
| def action(self, label): | |||||
| def action(self, label, parameters=None): | |||||
| def real_decorator(func): | def real_decorator(func): | ||||
| func.action = True | func.action = True | ||||
| func.label = label | func.label = label | ||||
| func.parameters = parameters | |||||
| return func | return func | ||||
| return real_decorator | return real_decorator | ||||
| @@ -156,7 +181,6 @@ class CoreAPI(BaseAPI): | |||||
| self.cbpi.cache["web_menu"] =[] | self.cbpi.cache["web_menu"] =[] | ||||
| def init(self): | def init(self): | ||||
| self.cbpi.cache["init"] = sorted(self.cbpi.cache["init"], key=lambda k: k['order']) | self.cbpi.cache["init"] = sorted(self.cbpi.cache["init"], key=lambda k: k['order']) | ||||
| for value in self.cbpi.cache.get("init"): | for value in self.cbpi.cache.get("init"): | ||||
| @@ -168,12 +192,17 @@ class CoreAPI(BaseAPI): | |||||
| try: | try: | ||||
| method(self.cbpi) | method(self.cbpi) | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.cbpi._socketio.sleep(interval) | |||||
| self.cbpi.logger.error(e) | |||||
| self.cbpi.sleep(interval) | |||||
| for value in self.cbpi.cache.get("background"): | for value in self.cbpi.cache.get("background"): | ||||
| t = self.cbpi._socketio.start_background_task(target=job, interval=value.get("interval"), method=value.get("function")) | |||||
| t = self.cbpi.start_background_task(target=job, interval=value.get("interval"), method=value.get("function")) | |||||
| def action(self, **options): | |||||
| def decorator(f): | |||||
| BaseAPI.parseProps(self, "actions", f) | |||||
| return f | |||||
| return decorator | |||||
| def add_js(self, name, file): | def add_js(self, name, file): | ||||
| self.cbpi.cache["js"][name] = file | self.cbpi.cache["js"][name] = file | ||||
| @@ -187,15 +216,7 @@ class CoreAPI(BaseAPI): | |||||
| return f | return f | ||||
| return decorator | return decorator | ||||
| def action(self, key, label, **options): | |||||
| def decorator(f): | |||||
| self.cbpi.cache.get("actions")[key] = {"label": label, "function": f} | |||||
| return f | |||||
| return decorator | |||||
| def backgroundjob(self, key, interval, **options): | |||||
| def backgroundtask(self, key, interval, **options): | |||||
| def decorator(f): | def decorator(f): | ||||
| self.cbpi.cache.get("background").append({"function": f, "key": key, "interval": interval}) | self.cbpi.cache.get("background").append({"function": f, "key": key, "interval": interval}) | ||||
| return f | return f | ||||
| @@ -220,5 +241,20 @@ class CoreAPI(BaseAPI): | |||||
| class Buzzer(object): | class Buzzer(object): | ||||
| def beep(): | |||||
| pass | |||||
| def beep(self): | |||||
| pass | |||||
| class Addon(object): | |||||
| def __init__(self, cbpi): | |||||
| self.step = StepAPI(cbpi) | |||||
| self.actor = ActorAPI(cbpi) | |||||
| self.sensor = SensorAPI(cbpi) | |||||
| self.kettle = KettleAPI(cbpi) | |||||
| self.fermenter = FermenterAPI(cbpi) | |||||
| self.core = CoreAPI(cbpi) | |||||
| def init(self): | |||||
| self.core.init() | |||||
| self.step.init() | |||||
| self.actor.init() | |||||
| self.sensor.init() | |||||
| @@ -12,11 +12,15 @@ class Base(object): | |||||
| self.value = None | self.value = None | ||||
| self.__dirty = False | self.__dirty = False | ||||
| class Action(Base): | |||||
| def execute(self): | |||||
| pass | |||||
| class Actor(Base): | class Actor(Base): | ||||
| @classmethod | @classmethod | ||||
| def init_global(cls): | def init_global(cls): | ||||
| pass | pass | ||||
| def init(self): | def init(self): | ||||
| @@ -68,9 +72,6 @@ class Sensor(Base): | |||||
| print "EXECUTE" | print "EXECUTE" | ||||
| pass | pass | ||||
| class ControllerBase(object): | class ControllerBase(object): | ||||
| __dirty = False | __dirty = False | ||||
| __running = False | __running = False | ||||
| @@ -271,7 +272,6 @@ class Step(Base, Timer): | |||||
| def set_target_temp(self, temp, id=None): | def set_target_temp(self, temp, id=None): | ||||
| temp = float(temp) | temp = float(temp) | ||||
| try: | try: | ||||
| if id is None: | if id is None: | ||||
| self.api.emit("SET_TARGET_TEMP", id=self.kettle_id, temp=temp) | self.api.emit("SET_TARGET_TEMP", id=self.kettle_id, temp=temp) | ||||
| @@ -281,7 +281,6 @@ class Step(Base, Timer): | |||||
| self.api.notify("Faild to set Target Temp", "", type="warning") | self.api.notify("Faild to set Target Temp", "", type="warning") | ||||
| def get_kettle_temp(self, id=None): | def get_kettle_temp(self, id=None): | ||||
| id = int(id) | id = int(id) | ||||
| if id is None: | if id is None: | ||||
| @@ -294,6 +293,8 @@ class Step(Base, Timer): | |||||
| def reset_dirty(self): | def reset_dirty(self): | ||||
| self.__dirty = False | self.__dirty = False | ||||
| def notify(self, headline, messsage, timeout=None): | |||||
| self.api.notify(headline, messsage, timeout) | |||||
| def __setattr__(self, name, value): | def __setattr__(self, name, value): | ||||
| if name != "_StepBase__dirty" and name in self.managed_fields: | if name != "_StepBase__dirty" and name in self.managed_fields: | ||||
| @@ -2,10 +2,10 @@ from flask import request, json | |||||
| from flask_classy import route, FlaskView | from flask_classy import route, FlaskView | ||||
| from flask_login import login_required | from flask_login import login_required | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| class BaseView(FlaskView): | |||||
| class RestApi(FlaskView): | |||||
| as_array = False | as_array = False | ||||
| cache_key = None | cache_key = None | ||||
| @@ -39,7 +39,7 @@ class BaseView(FlaskView): | |||||
| def post(self): | def post(self): | ||||
| data = request.json | data = request.json | ||||
| self.api._app.logger.info("INSERT Model %s", self.model.__name__) | |||||
| self.api.web.logger.info("INSERT Model %s", self.model.__name__) | |||||
| self._pre_post_callback(data) | self._pre_post_callback(data) | ||||
| m = self.model.insert(**data) | m = self.model.insert(**data) | ||||
| if self.api.cache.get(self.cache_key) is not None: | if self.api.cache.get(self.cache_key) is not None: | ||||
| @@ -101,7 +101,7 @@ class BaseView(FlaskView): | |||||
| @classmethod | @classmethod | ||||
| def init_cache(cls): | def init_cache(cls): | ||||
| with cls.api._app.app_context(): | |||||
| with cls.api.web.app_context(): | |||||
| if cls.model.__as_array__ is True: | if cls.model.__as_array__ is True: | ||||
| cls.api.cache[cls.cache_key] = [] | cls.api.cache[cls.cache_key] = [] | ||||
| @@ -22,7 +22,6 @@ from modules.database.dbmodel import Kettle | |||||
| class ComplexEncoder(json.JSONEncoder): | class ComplexEncoder(json.JSONEncoder): | ||||
| def default(self, obj): | def default(self, obj): | ||||
| try: | try: | ||||
| if isinstance(obj, DBModel): | if isinstance(obj, DBModel): | ||||
| return obj.__dict__ | return obj.__dict__ | ||||
| elif isinstance(obj, Actor): | elif isinstance(obj, Actor): | ||||
| @@ -33,31 +32,11 @@ class ComplexEncoder(json.JSONEncoder): | |||||
| return obj() | return obj() | ||||
| else: | else: | ||||
| return None | return None | ||||
| return None | return None | ||||
| except TypeError as e: | except TypeError as e: | ||||
| pass | pass | ||||
| return None | return None | ||||
| class Addon(object): | |||||
| def __init__(self, cbpi): | |||||
| self.step = StepAPI(cbpi) | |||||
| self.actor = ActorAPI(cbpi) | |||||
| self.sensor = SensorAPI(cbpi) | |||||
| self.kettle = KettleAPI(cbpi) | |||||
| self.fermenter = FermenterAPI(cbpi) | |||||
| self.core = CoreAPI(cbpi) | |||||
| def init(self): | |||||
| self.core.init() | |||||
| self.step.init() | |||||
| self.actor.init() | |||||
| self.sensor.init() | |||||
| # self.kettle.init() | |||||
| # self.fermenter.init() | |||||
| class ActorCore(object): | class ActorCore(object): | ||||
| key = "actor_types" | key = "actor_types" | ||||
| @@ -82,8 +61,7 @@ class ActorCore(object): | |||||
| actor.power = 100 | actor.power = 100 | ||||
| self.cbpi.emit("INIT_ACTOR", id=id) | self.cbpi.emit("INIT_ACTOR", id=id) | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.cbpi._app.logger.error(e) | |||||
| self.cbpi.web.logger.error(e) | |||||
| def stop_one(self, id): | def stop_one(self, id): | ||||
| self.cbpi.cache["actors"][id]["instance"].stop() | self.cbpi.cache["actors"][id]["instance"].stop() | ||||
| @@ -99,7 +77,7 @@ class ActorCore(object): | |||||
| self.cbpi.emit("SWITCH_ACTOR_ON", id=id, power=power) | self.cbpi.emit("SWITCH_ACTOR_ON", id=id, power=power) | ||||
| return True | return True | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.cbpi.logger.error(e) | |||||
| return False | return False | ||||
| def off(self, id): | def off(self, id): | ||||
| @@ -111,7 +89,7 @@ class ActorCore(object): | |||||
| self.cbpi.emit("SWITCH_ACTOR_OFF", id=id) | self.cbpi.emit("SWITCH_ACTOR_OFF", id=id) | ||||
| return True | return True | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.cbpi.logger.error(e) | |||||
| return False | return False | ||||
| def toggle(self, id): | def toggle(self, id): | ||||
| @@ -129,11 +107,11 @@ class ActorCore(object): | |||||
| self.cbpi.emit("SWITCH_ACTOR_POWER_CHANGE", id=id, power=power) | self.cbpi.emit("SWITCH_ACTOR_POWER_CHANGE", id=id, power=power) | ||||
| return True | return True | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.cbpi.logger.error(e) | |||||
| return False | return False | ||||
| def action(self, id, method): | |||||
| self.cbpi.cache.get("actors").get(id).instance.__getattribute__(method)() | |||||
| def action(self, id, method, **data): | |||||
| self.cbpi.cache.get("actors").get(id).instance.__getattribute__(method)(**data) | |||||
| def toggle_timeout(self, id, seconds): | def toggle_timeout(self, id, seconds): | ||||
| @@ -182,7 +160,7 @@ class SensorCore(object): | |||||
| except Exception as e: | except Exception as e: | ||||
| print "ERROR" | print "ERROR" | ||||
| self.cbpi._app.logger.error(e) | |||||
| self.cbpi.web.logger.error(e) | |||||
| def stop_one(self, id): | def stop_one(self, id): | ||||
| @@ -206,12 +184,12 @@ class SensorCore(object): | |||||
| with open(filename, "a") as file: | with open(filename, "a") as file: | ||||
| file.write(msg) | file.write(msg) | ||||
| def action(self, id, method): | |||||
| self.cbpi.cache.get("sensors").get(id).instance.__getattribute__(method)() | |||||
| def action(self, id, method, **data): | |||||
| self.cbpi.cache.get("sensors").get(id).instance.__getattribute__(method)(**data) | |||||
| class BrewingCore(object): | class BrewingCore(object): | ||||
| def __init__(self, cbpi): | def __init__(self, cbpi): | ||||
| self.cbpi = cbpi | self.cbpi = cbpi | ||||
| self.cbpi.cache["step_types"] = {} | self.cbpi.cache["step_types"] = {} | ||||
| @@ -240,7 +218,7 @@ class BrewingCore(object): | |||||
| # Start controller | # Start controller | ||||
| if kettle.logic is not None: | if kettle.logic is not None: | ||||
| cfg = kettle.config.copy() | cfg = kettle.config.copy() | ||||
| cfg.update(dict(api=cbpi, kettle_id=kettle.id, heater=kettle.heater, sensor=kettle.sensor)) | |||||
| cfg.update(dict(api=self.cbpi, kettle_id=kettle.id, heater=kettle.heater, sensor=kettle.sensor)) | |||||
| instance = self.get_controller(kettle.logic).get("class")(**cfg) | instance = self.get_controller(kettle.logic).get("class")(**cfg) | ||||
| instance.init() | instance.init() | ||||
| kettle.instance = instance | kettle.instance = instance | ||||
| @@ -250,13 +228,13 @@ class BrewingCore(object): | |||||
| t = self.cbpi._socketio.start_background_task(target=run, instance=instance) | t = self.cbpi._socketio.start_background_task(target=run, instance=instance) | ||||
| kettle.state = not kettle.state | kettle.state = not kettle.state | ||||
| self.cbpi.ws_emit("UPDATE_KETTLE", cbpi.cache.get("kettle").get(id)) | |||||
| self.cbpi.ws_emit("UPDATE_KETTLE", self.cbpi.cache.get("kettle").get(id)) | |||||
| self.cbpi.emit("KETTLE_CONTROLLER_STARTED", id=id) | self.cbpi.emit("KETTLE_CONTROLLER_STARTED", id=id) | ||||
| else: | else: | ||||
| # Stop controller | # Stop controller | ||||
| kettle.instance.stop() | kettle.instance.stop() | ||||
| kettle.state = not kettle.state | kettle.state = not kettle.state | ||||
| self.cbpi.ws_emit("UPDATE_KETTLE", cbpi.cache.get("kettle").get(id)) | |||||
| self.cbpi.ws_emit("UPDATE_KETTLE", self.cbpi.cache.get("kettle").get(id)) | |||||
| self.cbpi.emit("KETTLE_CONTROLLER_STOPPED", id=id) | self.cbpi.emit("KETTLE_CONTROLLER_STOPPED", id=id) | ||||
| @@ -270,28 +248,50 @@ class FermentationCore(object): | |||||
| return self.cbpi.cache["fermentation_controller_types"].get(name) | return self.cbpi.cache["fermentation_controller_types"].get(name) | ||||
| class Logger(object): | |||||
| def __init__(self, cbpi): | |||||
| self.cbpi = cbpi | |||||
| def error(self, msg, *args, **kwargs): | |||||
| self.cbpi.web.logger.error(msg, *args, **kwargs) | |||||
| def info(self, msg, *args, **kwargs): | |||||
| self.cbpi.web.logger.info(msg, *args, **kwargs) | |||||
| def debug(self, msg, *args, **kwargs): | |||||
| self.cbpi.web.logger.debug(msg, *args, **kwargs) | |||||
| def warning(self, msg, *args, **kwargs): | |||||
| self.cbpi.web.logger.warning(msg, *args, **kwargs) | |||||
| class CraftBeerPI(object): | class CraftBeerPI(object): | ||||
| cache = {} | cache = {} | ||||
| eventbus = {} | eventbus = {} | ||||
| def __init__(self): | def __init__(self): | ||||
| FORMAT = '%(asctime)-15s - %(levelname)s - %(message)s' | |||||
| logging.basicConfig(filename='./logs/app.log', level=logging.INFO, format=FORMAT) | |||||
| self.cache["messages"] = [] | self.cache["messages"] = [] | ||||
| self.cache["version"] = "3.1" | self.cache["version"] = "3.1" | ||||
| self.modules = {} | |||||
| FORMAT = '%(asctime)-15s - %(levelname)s - %(message)s' | |||||
| logging.basicConfig(filename='./logs/app.log', level=logging.INFO, format=FORMAT) | |||||
| logging.getLogger('socketio').setLevel(logging.ERROR) | |||||
| logging.getLogger('engineio').setLevel(logging.ERROR) | |||||
| self.web = Flask(__name__) | |||||
| self.logger = Logger(self) | |||||
| self.logger.info("###Startup CraftBeerPi %s ###" % self.cache.get("version")) | |||||
| self.web.secret_key = 'Cr4ftB33rP1' | |||||
| self.web.json_encoder = ComplexEncoder | |||||
| self._socketio = SocketIO(self.web, json=json, logging=False) | |||||
| self.modules = {} | |||||
| self.addon = Addon(self) | self.addon = Addon(self) | ||||
| self.actor = ActorCore(self) | self.actor = ActorCore(self) | ||||
| self.sensor = SensorCore(self) | self.sensor = SensorCore(self) | ||||
| self.brewing = BrewingCore(self) | self.brewing = BrewingCore(self) | ||||
| self.fermentation = FermentationCore(self) | self.fermentation = FermentationCore(self) | ||||
| self._app = Flask(__name__) | |||||
| self._app.secret_key = 'Cr4ftB33rP1' | |||||
| self._app.json_encoder = ComplexEncoder | |||||
| self._socketio = SocketIO(self._app, json=json, logging=False) | |||||
| @self._app.route('/') | |||||
| @self.web.route('/') | |||||
| def index(): | def index(): | ||||
| return redirect('ui') | return redirect('ui') | ||||
| @@ -303,11 +303,11 @@ class CraftBeerPI(object): | |||||
| self.actor.init() | self.actor.init() | ||||
| self.beep() | self.beep() | ||||
| try: | try: | ||||
| port = int(cbpi.get_config_parameter('port', '5000')) | |||||
| port = int(self.get_config_parameter('port', '5000')) | |||||
| except ValueError: | except ValueError: | ||||
| port = 5000 | port = 5000 | ||||
| print port | |||||
| self._socketio.run(self._app, host='0.0.0.0', port=port) | |||||
| self._socketio.run(self.web, host='0.0.0.0', port=port) | |||||
| def beep(self): | def beep(self): | ||||
| self.buzzer.beep() | self.buzzer.beep() | ||||
| @@ -315,6 +315,10 @@ class CraftBeerPI(object): | |||||
| def sleep(self, seconds): | def sleep(self, seconds): | ||||
| self._socketio.sleep(seconds) | self._socketio.sleep(seconds) | ||||
| def start_background_task(self, target, *args, **kwargs): | |||||
| self._socketio.start_background_task(target, *args, **kwargs) | |||||
| def notify(self, headline, message, type="success", timeout=5000): | def notify(self, headline, message, type="success", timeout=5000): | ||||
| msg = {"id": str(uuid.uuid1()), "type": type, "headline": headline, "message": message, "timeout": timeout} | msg = {"id": str(uuid.uuid1()), "type": type, "headline": headline, "message": message, "timeout": timeout} | ||||
| self.ws_emit("NOTIFY", msg) | self.ws_emit("NOTIFY", msg) | ||||
| @@ -324,10 +328,10 @@ class CraftBeerPI(object): | |||||
| def __init_db(self, ): | def __init_db(self, ): | ||||
| with self._app.app_context(): | |||||
| with self.web.app_context(): | |||||
| db = self.get_db() | db = self.get_db() | ||||
| try: | try: | ||||
| with self._app.open_resource('../../config/schema.sql', mode='r') as f: | |||||
| with self.web.open_resource('../../config/schema.sql', mode='r') as f: | |||||
| db.cursor().executescript(f.read()) | db.cursor().executescript(f.read()) | ||||
| db.commit() | db.commit() | ||||
| except Exception as e: | except Exception as e: | ||||
| @@ -373,7 +377,7 @@ class CraftBeerPI(object): | |||||
| def set_config_parameter(self, name, value): | def set_config_parameter(self, name, value): | ||||
| from modules.config import Config | from modules.config import Config | ||||
| with self._app.app_context(): | |||||
| with self.web.app_context(): | |||||
| update_data = {"name": name, "value": value} | update_data = {"name": name, "value": value} | ||||
| self.cache.get("config")[name].__dict__.update(**update_data) | self.cache.get("config")[name].__dict__.update(**update_data) | ||||
| c = Config.update(**update_data) | c = Config.update(**update_data) | ||||
| @@ -381,7 +385,6 @@ class CraftBeerPI(object): | |||||
| def emit(self, key, **kwargs): | def emit(self, key, **kwargs): | ||||
| if self.eventbus.get(key) is not None: | if self.eventbus.get(key) is not None: | ||||
| for value in self.eventbus[key]: | for value in self.eventbus[key]: | ||||
| if value["async"] is False: | if value["async"] is False: | ||||
| @@ -400,6 +403,3 @@ class CraftBeerPI(object): | |||||
| self.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None) | self.notify("Failed to load plugin %s " % filename, str(e), type="danger", timeout=None) | ||||
| cbpi = CraftBeerPI() | |||||
| addon = cbpi.addon | |||||
| @@ -1,11 +1,11 @@ | |||||
| import sqlite3 | import sqlite3 | ||||
| import os | import os | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from modules.core.db import get_db | from modules.core.db import get_db | ||||
| def execute_file(curernt_version, data): | def execute_file(curernt_version, data): | ||||
| if curernt_version >= data["version"]: | if curernt_version >= data["version"]: | ||||
| cbpi._app.logger.info("SKIP DB FILE: %s" % data["file"]) | |||||
| cbpi.web.logger.info("SKIP DB FILE: %s" % data["file"]) | |||||
| return | return | ||||
| try: | try: | ||||
| with sqlite3.connect("craftbeerpi.db") as conn: | with sqlite3.connect("craftbeerpi.db") as conn: | ||||
| @@ -18,14 +18,13 @@ def execute_file(curernt_version, data): | |||||
| cur.execute("INSERT INTO schema_info (version,filename) values (?,?)", (data["version"], data["file"])) | cur.execute("INSERT INTO schema_info (version,filename) values (?,?)", (data["version"], data["file"])) | ||||
| conn.commit() | conn.commit() | ||||
| except sqlite3.OperationalError as err: | |||||
| print err | |||||
| except sqlite3.OperationalError as e: | |||||
| cbpi.logger.error(e) | |||||
| @cbpi.addon.core.initializer(order=-9999) | @cbpi.addon.core.initializer(order=-9999) | ||||
| def init(cbpi): | def init(cbpi): | ||||
| with cbpi._app.app_context(): | |||||
| with cbpi.web.app_context(): | |||||
| conn = get_db() | conn = get_db() | ||||
| cur = conn.cursor() | cur = conn.cursor() | ||||
| current_version = None | current_version = None | ||||
| @@ -16,6 +16,7 @@ class Property(object): | |||||
| self.configurable = configurable | self.configurable = configurable | ||||
| self.default_value = default_value | self.default_value = default_value | ||||
| self.description = description | self.description = description | ||||
| self.unit = unit | |||||
| class Text(PropertyType): | class Text(PropertyType): | ||||
| def __init__(self, label, configurable=False, required=False, default_value="", description=""): | def __init__(self, label, configurable=False, required=False, default_value="", description=""): | ||||
| @@ -44,5 +45,6 @@ class Property(object): | |||||
| def __init__(self, label, description=""): | def __init__(self, label, description=""): | ||||
| PropertyType.__init__(self) | PropertyType.__init__(self) | ||||
| self.label = label | self.label = label | ||||
| self.unit = "" | |||||
| self.configurable = True | self.configurable = True | ||||
| self.description = description | self.description = description | ||||
| @@ -1,11 +1,11 @@ | |||||
| from flask import Blueprint | from flask import Blueprint | ||||
| from modules.core.core import cbpi, addon | |||||
| from modules import cbpi | |||||
| from flask_swagger import swagger | from flask_swagger import swagger | ||||
| from flask import json | from flask import json | ||||
| from flask import Blueprint | from flask import Blueprint | ||||
| @addon.core.initializer(order=22) | |||||
| @cbpi.addon.core.initializer(order=22) | |||||
| def web(cbpi): | def web(cbpi): | ||||
| s = Blueprint('web_view', __name__, template_folder='templates', static_folder='static') | s = Blueprint('web_view', __name__, template_folder='templates', static_folder='static') | ||||
| @@ -16,4 +16,4 @@ def web(cbpi): | |||||
| cbpi.addon.core.add_menu_link("JQuery View", "/web_view") | cbpi.addon.core.add_menu_link("JQuery View", "/web_view") | ||||
| cbpi._app.register_blueprint(s, url_prefix='/web_view') | |||||
| cbpi.web.register_blueprint(s, url_prefix='/web_view') | |||||
| @@ -1,11 +1,11 @@ | |||||
| from flask import Blueprint | from flask import Blueprint | ||||
| from modules.core.core import cbpi, addon | |||||
| from modules import cbpi | |||||
| from flask_swagger import swagger | from flask_swagger import swagger | ||||
| from flask import json | from flask import json | ||||
| from flask import Blueprint | from flask import Blueprint | ||||
| @addon.core.initializer(order=22) | |||||
| @cbpi.addon.core.initializer(order=22) | |||||
| def web(cbpi): | def web(cbpi): | ||||
| s = Blueprint('webviewreact', __name__, template_folder='templates', static_folder='static') | s = Blueprint('webviewreact', __name__, template_folder='templates', static_folder='static') | ||||
| @@ -16,4 +16,4 @@ def web(cbpi): | |||||
| cbpi.addon.core.add_menu_link("ReactJS View", "/webviewreact") | cbpi.addon.core.add_menu_link("ReactJS View", "/webviewreact") | ||||
| cbpi._app.register_blueprint(s, url_prefix='/webviewreact') | |||||
| cbpi.web.register_blueprint(s, url_prefix='/webviewreact') | |||||
| @@ -1,9 +1,9 @@ | |||||
| from modules.core.core import cbpi, addon | |||||
| from modules import cbpi | |||||
| from flask_swagger import swagger | from flask_swagger import swagger | ||||
| from flask import json | from flask import json | ||||
| from flask import Blueprint | from flask import Blueprint | ||||
| @addon.core.initializer(order=22) | |||||
| @cbpi.addon.core.initializer(order=22) | |||||
| def hello(cbpi): | def hello(cbpi): | ||||
| s = Blueprint('react', __name__, template_folder='templates', static_folder='static') | s = Blueprint('react', __name__, template_folder='templates', static_folder='static') | ||||
| @@ -14,10 +14,10 @@ def hello(cbpi): | |||||
| @s.route('/swagger.json', methods=["GET"]) | @s.route('/swagger.json', methods=["GET"]) | ||||
| def spec(): | def spec(): | ||||
| swag = swagger(cbpi._app) | |||||
| swag = swagger(cbpi.web) | |||||
| swag['info']['version'] = "3.0" | swag['info']['version'] = "3.0" | ||||
| swag['info']['title'] = "CraftBeerPi" | swag['info']['title'] = "CraftBeerPi" | ||||
| return json.dumps(swag) | return json.dumps(swag) | ||||
| cbpi.addon.core.add_menu_link("Swagger API", "/swagger") | cbpi.addon.core.add_menu_link("Swagger API", "/swagger") | ||||
| cbpi._app.register_blueprint(s, url_prefix='/swagger') | |||||
| cbpi.web.register_blueprint(s, url_prefix='/swagger') | |||||
| @@ -2,13 +2,13 @@ import time | |||||
| from flask import request | from flask import request | ||||
| from flask_classy import route | from flask_classy import route | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from modules.core.db import get_db, DBModel | from modules.core.db import get_db, DBModel | ||||
| from modules.core.baseview import BaseView | |||||
| from modules.core.baseview import RestApi | |||||
| from modules.database.dbmodel import Fermenter, FermenterStep | from modules.database.dbmodel import Fermenter, FermenterStep | ||||
| class FermenterView(BaseView): | |||||
| class FermenterView(RestApi): | |||||
| model = Fermenter | model = Fermenter | ||||
| cache_key = "fermenter" | cache_key = "fermenter" | ||||
| @@ -212,10 +212,9 @@ class FermenterView(BaseView): | |||||
| cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id]) | cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id]) | ||||
| def check_step(self): | def check_step(self): | ||||
| print "CHECK STEP" | |||||
| print cbpi.cache["fermenter_task"] | |||||
| for key, value in cbpi.cache["fermenter_task"].iteritems(): | for key, value in cbpi.cache["fermenter_task"].iteritems(): | ||||
| print value | |||||
| try: | try: | ||||
| fermenter = self.get_fermenter(key) | fermenter = self.get_fermenter(key) | ||||
| current_temp = current_temp = cbpi.sensor.get_value(int(fermenter.sensor)) | current_temp = current_temp = cbpi.sensor.get_value(int(fermenter.sensor)) | ||||
| @@ -236,11 +235,11 @@ class FermenterView(BaseView): | |||||
| else: | else: | ||||
| pass | pass | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.api.looger.error(e) | |||||
| pass | pass | ||||
| @cbpi.addon.core.backgroundjob(key="read_target_temps_fermenter", interval=5) | |||||
| @cbpi.addon.core.backgroundtask(key="read_target_temps_fermenter", interval=5) | |||||
| def read_target_temps(cbpi): | def read_target_temps(cbpi): | ||||
| """ | """ | ||||
| background process that reads all passive sensors in interval of 1 second | background process that reads all passive sensors in interval of 1 second | ||||
| @@ -253,9 +252,9 @@ def read_target_temps(cbpi): | |||||
| instance = FermenterView() | instance = FermenterView() | ||||
| @cbpi.addon.core.backgroundjob(key="fermentation_task", interval=1) | |||||
| @cbpi.addon.core.backgroundtask(key="fermentation_task", interval=1) | |||||
| def execute_fermentation_step(cbpi): | def execute_fermentation_step(cbpi): | ||||
| with cbpi._app.app_context(): | |||||
| with cbpi.web.app_context(): | |||||
| instance.check_step() | instance.check_step() | ||||
| @@ -268,5 +267,5 @@ def init_active_steps(): | |||||
| def init(cbpi): | def init(cbpi): | ||||
| cbpi.cache["fermenter_task"] = {} | cbpi.cache["fermenter_task"] = {} | ||||
| FermenterView.register(cbpi._app, route_base='/api/fermenter') | |||||
| FermenterView.register(cbpi.web, route_base='/api/fermenter') | |||||
| FermenterView.init_cache() | FermenterView.init_cache() | ||||
| @@ -1,11 +1,11 @@ | |||||
| from flask import request | from flask import request | ||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from modules.core.core import cbpi | |||||
| from modules.core.baseview import BaseView | |||||
| from modules import cbpi | |||||
| from modules.core.baseview import RestApi | |||||
| from modules.core.db import DBModel | from modules.core.db import DBModel | ||||
| from modules.database.dbmodel import Kettle | from modules.database.dbmodel import Kettle | ||||
| class KettleView(BaseView): | |||||
| class KettleView(RestApi): | |||||
| model = Kettle | model = Kettle | ||||
| cache_key = "kettle" | cache_key = "kettle" | ||||
| @@ -228,7 +228,7 @@ def set_target_temp(id, temp): | |||||
| ''' | ''' | ||||
| KettleView().postTargetTemp(id,temp) | KettleView().postTargetTemp(id,temp) | ||||
| @cbpi.addon.core.backgroundjob(key="read_target_temps", interval=5) | |||||
| @cbpi.addon.core.backgroundtask(key="read_target_temps", interval=5) | |||||
| def read_target_temps(api): | def read_target_temps(api): | ||||
| """ | """ | ||||
| background process that reads all passive sensors in interval of 1 second | background process that reads all passive sensors in interval of 1 second | ||||
| @@ -241,5 +241,5 @@ def read_target_temps(api): | |||||
| @cbpi.addon.core.initializer() | @cbpi.addon.core.initializer() | ||||
| def init(cbpi): | def init(cbpi): | ||||
| KettleView.api = cbpi | KettleView.api = cbpi | ||||
| KettleView.register(cbpi._app, route_base='/api/kettle') | |||||
| KettleView.register(cbpi.web, route_base='/api/kettle') | |||||
| KettleView.init_cache() | KettleView.init_cache() | ||||
| @@ -1,18 +1,19 @@ | |||||
| import flask_login | import flask_login | ||||
| from flask import request | from flask import request | ||||
| from modules.core.core import cbpi, addon | |||||
| from modules import cbpi | |||||
| class User(flask_login.UserMixin): | class User(flask_login.UserMixin): | ||||
| pass | pass | ||||
| @addon.core.initializer(order=0) | |||||
| @cbpi.addon.core.initializer(order=0) | |||||
| def log(cbpi): | def log(cbpi): | ||||
| cbpi._login_manager = flask_login.LoginManager() | cbpi._login_manager = flask_login.LoginManager() | ||||
| cbpi._login_manager.init_app(cbpi._app) | |||||
| @cbpi._app.route('/login', methods=['POST']) | |||||
| cbpi._login_manager.init_app(cbpi.web) | |||||
| @cbpi.web.route('/login', methods=['POST']) | |||||
| def login(): | def login(): | ||||
| data = request.json | data = request.json | ||||
| @@ -30,15 +31,29 @@ def log(cbpi): | |||||
| return ('',401) | return ('',401) | ||||
| @cbpi._app.route('/logout', methods=['POST']) | |||||
| @cbpi.web.route('/logout', methods=['POST']) | |||||
| def logout(): | def logout(): | ||||
| flask_login.logout_user() | flask_login.logout_user() | ||||
| return 'Logged out' | return 'Logged out' | ||||
| @cbpi._login_manager.user_loader | |||||
| def user_loader(user): | |||||
| @cbpi._login_manager.request_loader | |||||
| def load_user_from_request(request): | |||||
| api_key = request.args.get('api_key') | |||||
| if cbpi.get_config_parameter("password_security", "NO") == "NO": | |||||
| user = User() | |||||
| user.id = "craftbeerpi" | |||||
| return user | |||||
| elif api_key == "123": | |||||
| user = User() | |||||
| user.id = "craftbeerpi" | |||||
| return user | |||||
| return None | |||||
| @cbpi._login_manager.user_loader | |||||
| def user_loader(user): | |||||
| if cbpi.get_config_parameter("password_security", "NO") == "YES": | if cbpi.get_config_parameter("password_security", "NO") == "YES": | ||||
| if user != "craftbeerpi": | if user != "craftbeerpi": | ||||
| @@ -53,4 +68,6 @@ def log(cbpi): | |||||
| @cbpi._login_manager.unauthorized_handler | @cbpi._login_manager.unauthorized_handler | ||||
| def unauthorized_handler(): | def unauthorized_handler(): | ||||
| return ('Please login',401) | return ('Please login',401) | ||||
| @@ -2,7 +2,7 @@ import datetime | |||||
| import os | import os | ||||
| from flask import Blueprint, request, send_from_directory, json | from flask import Blueprint, request, send_from_directory, json | ||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| class LogView(FlaskView): | class LogView(FlaskView): | ||||
| @@ -172,4 +172,4 @@ def init(cbpi): | |||||
| :param app: the flask app | :param app: the flask app | ||||
| :return: None | :return: None | ||||
| """ | """ | ||||
| LogView.register(cbpi._app, route_base='/api/logs') | |||||
| LogView.register(cbpi.web, route_base='/api/logs') | |||||
| @@ -1,6 +1,6 @@ | |||||
| import json | import json | ||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| class NotificationView(FlaskView): | class NotificationView(FlaskView): | ||||
| @@ -63,4 +63,4 @@ def init(cbpi): | |||||
| msg = {"id": len(cbpi.cache["messages"]), "type": "info", "headline": "Support CraftBeerPi with your donation", "message": "You will find the PayPay Donation button in the system menu" , "read": False} | msg = {"id": len(cbpi.cache["messages"]), "type": "info", "headline": "Support CraftBeerPi with your donation", "message": "You will find the PayPay Donation button in the system menu" , "read": False} | ||||
| cbpi.cache["messages"].append(msg) | cbpi.cache["messages"].append(msg) | ||||
| NotificationView.register(cbpi._app, route_base='/api/notification') | |||||
| NotificationView.register(cbpi.web, route_base='/api/notification') | |||||
| @@ -1,7 +1,7 @@ | |||||
| import sys | import sys | ||||
| from flask import request, send_from_directory, json | from flask import request, send_from_directory, json | ||||
| from importlib import import_module | from importlib import import_module | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from git import Repo | from git import Repo | ||||
| import os | import os | ||||
| import requests | import requests | ||||
| @@ -46,7 +46,7 @@ class PluginView(FlaskView): | |||||
| response = requests.get("https://raw.githubusercontent.com/Manuel83/craftbeerpi-plugins/master/plugins.yaml") | response = requests.get("https://raw.githubusercontent.com/Manuel83/craftbeerpi-plugins/master/plugins.yaml") | ||||
| self.api.cache["plugins"] = self.merge(yaml.load(response.text), self.api.cache["plugins"]) | self.api.cache["plugins"] = self.merge(yaml.load(response.text), self.api.cache["plugins"]) | ||||
| for key, value in cbpi.cache["plugins"].iteritems(): | for key, value in cbpi.cache["plugins"].iteritems(): | ||||
| print key | |||||
| value["installed"] = os.path.isdir("./plugins/%s/" % (key)) | value["installed"] = os.path.isdir("./plugins/%s/" % (key)) | ||||
| return json.dumps(cbpi.cache["plugins"]) | return json.dumps(cbpi.cache["plugins"]) | ||||
| @@ -136,4 +136,4 @@ class PluginView(FlaskView): | |||||
| def init(cbpi): | def init(cbpi): | ||||
| cbpi.cache["plugins"] = {} | cbpi.cache["plugins"] = {} | ||||
| PluginView.api = cbpi | PluginView.api = cbpi | ||||
| PluginView.register(cbpi._app, route_base='/api/plugin') | |||||
| PluginView.register(cbpi.web, route_base='/api/plugin') | |||||
| @@ -7,8 +7,8 @@ from flask import json, request, send_from_directory | |||||
| from flask_classy import route, FlaskView | from flask_classy import route, FlaskView | ||||
| from modules.core.db import DBModel | from modules.core.db import DBModel | ||||
| from modules.core.baseview import BaseView | |||||
| from modules.core.core import cbpi | |||||
| from modules.core.baseview import RestApi | |||||
| from modules import cbpi | |||||
| from modules.database.dbmodel import Step | from modules.database.dbmodel import Step | ||||
| from yaml import Loader, Dumper | from yaml import Loader, Dumper | ||||
| from yaml import load, dump | from yaml import load, dump | ||||
| @@ -59,7 +59,7 @@ class RecipeBook(FlaskView): | |||||
| description: Log file downloaded | description: Log file downloaded | ||||
| """ | """ | ||||
| file = "%s.json" % name | file = "%s.json" % name | ||||
| print file | |||||
| if not self.check_filename(file): | if not self.check_filename(file): | ||||
| return ('File Not Found111', 404) | return ('File Not Found111', 404) | ||||
| return send_from_directory('../../recipes', file, as_attachment=True, attachment_filename=file) | return send_from_directory('../../recipes', file, as_attachment=True, attachment_filename=file) | ||||
| @@ -143,4 +143,4 @@ class RecipeBook(FlaskView): | |||||
| @cbpi.addon.core.initializer(order=2000) | @cbpi.addon.core.initializer(order=2000) | ||||
| def init(cbpi): | def init(cbpi): | ||||
| RecipeBook.api = cbpi | RecipeBook.api = cbpi | ||||
| RecipeBook.register(cbpi._app, route_base='/api/recipebook') | |||||
| RecipeBook.register(cbpi.web, route_base='/api/recipebook') | |||||
| @@ -2,7 +2,7 @@ from flask import json, request | |||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from git import Repo, Git | from git import Repo, Git | ||||
| import sqlite3 | import sqlite3 | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from werkzeug.utils import secure_filename | from werkzeug.utils import secure_filename | ||||
| import pprint | import pprint | ||||
| import time | import time | ||||
| @@ -60,7 +60,7 @@ class BeerXMLImport(FlaskView): | |||||
| return ('', 204) | return ('', 204) | ||||
| return ('', 404) | return ('', 404) | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.api.logger.error(e) | |||||
| self.api.notify(headline="Upload Failed", message="Failed to upload Beer xml", type="danger") | self.api.notify(headline="Upload Failed", message="Failed to upload Beer xml", type="danger") | ||||
| return ('', 500) | return ('', 500) | ||||
| @@ -143,4 +143,4 @@ class BeerXMLImport(FlaskView): | |||||
| def init(cbpi): | def init(cbpi): | ||||
| BeerXMLImport.api = cbpi | BeerXMLImport.api = cbpi | ||||
| BeerXMLImport.register(cbpi._app, route_base='/api/beerxml') | |||||
| BeerXMLImport.register(cbpi.web, route_base='/api/beerxml') | |||||
| @@ -2,7 +2,7 @@ from flask import json, request | |||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from git import Repo, Git | from git import Repo, Git | ||||
| import sqlite3 | import sqlite3 | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from werkzeug.utils import secure_filename | from werkzeug.utils import secure_filename | ||||
| import pprint | import pprint | ||||
| import time | import time | ||||
| @@ -39,7 +39,7 @@ class KBH(FlaskView): | |||||
| result.append({"id": row[0], "name": row[1], "brewed": row[2]}) | result.append({"id": row[0], "name": row[1], "brewed": row[2]}) | ||||
| return json.dumps(result) | return json.dumps(result) | ||||
| except Exception as e: | except Exception as e: | ||||
| print e | |||||
| self.api.logger.error(e) | |||||
| self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger") | self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger") | ||||
| return ('', 500) | return ('', 500) | ||||
| finally: | finally: | ||||
| @@ -143,4 +143,4 @@ class KBH(FlaskView): | |||||
| def init(cbpi): | def init(cbpi): | ||||
| KBH.api = cbpi | KBH.api = cbpi | ||||
| KBH.register(cbpi._app, route_base='/api/kbh') | |||||
| KBH.register(cbpi.web, route_base='/api/kbh') | |||||
| @@ -2,7 +2,7 @@ from flask import json, request | |||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from git import Repo, Git | from git import Repo, Git | ||||
| import sqlite3 | import sqlite3 | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from werkzeug.utils import secure_filename | from werkzeug.utils import secure_filename | ||||
| import pprint | import pprint | ||||
| import time | import time | ||||
| @@ -59,4 +59,4 @@ class RESTImport(FlaskView): | |||||
| @cbpi.addon.core.initializer() | @cbpi.addon.core.initializer() | ||||
| def init(cbpi): | def init(cbpi): | ||||
| RESTImport.api = cbpi | RESTImport.api = cbpi | ||||
| RESTImport.register(cbpi._app, route_base='/api/recipe/import/v1') | |||||
| RESTImport.register(cbpi.web, route_base='/api/recipe/import/v1') | |||||
| @@ -1,12 +1,12 @@ | |||||
| import time | import time | ||||
| from flask_classy import route | from flask_classy import route | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| from modules.core.db import DBModel | from modules.core.db import DBModel | ||||
| from modules.core.baseview import BaseView | |||||
| from modules.core.baseview import RestApi | |||||
| from modules.database.dbmodel import Sensor | from modules.database.dbmodel import Sensor | ||||
| from flask import request | |||||
| class SensorView(BaseView): | |||||
| class SensorView(RestApi): | |||||
| model = Sensor | model = Sensor | ||||
| cache_key = "sensors" | cache_key = "sensors" | ||||
| @@ -34,7 +34,11 @@ class SensorView(BaseView): | |||||
| 200: | 200: | ||||
| description: Sensor Action called | description: Sensor Action called | ||||
| """ | """ | ||||
| cbpi.sensor.action(id, method) | |||||
| data = request.json | |||||
| if data: | |||||
| cbpi.sensor.action(id, method, **data) | |||||
| else: | |||||
| cbpi.sensor.action(id, method) | |||||
| return ('', 204) | return ('', 204) | ||||
| def _post_post_callback(self, m): | def _post_post_callback(self, m): | ||||
| @@ -51,17 +55,19 @@ class SensorView(BaseView): | |||||
| @cbpi.addon.core.initializer(order=1000) | @cbpi.addon.core.initializer(order=1000) | ||||
| def init(cbpi): | def init(cbpi): | ||||
| SensorView.register(cbpi._app, route_base='/api/sensor') | |||||
| SensorView.register(cbpi.web, route_base='/api/sensor') | |||||
| SensorView.init_cache() | SensorView.init_cache() | ||||
| #@cbpi.backgroundtask(key="read_passiv_sensor", interval=5) | |||||
| #@cbpi.addon.core.backgroundtask(key="read_passiv_sensor", interval=5) | |||||
| def read_passive_sensor(api): | def read_passive_sensor(api): | ||||
| """ | """ | ||||
| background process that reads all passive sensors in interval of 1 second | background process that reads all passive sensors in interval of 1 second | ||||
| :return: None | :return: None | ||||
| """ | """ | ||||
| for key, value in cbpi.cache.get("sensors").iteritems(): | |||||
| if value.mode == "P": | |||||
| value.instance.read() | |||||
| #for key, value in cbpi.cache.get("sensors").iteritems(): | |||||
| # if value.mode == "P": | |||||
| # value.instance.read() | |||||
| @@ -3,12 +3,12 @@ from flask import json, request | |||||
| from flask_classy import route | from flask_classy import route | ||||
| from modules.core.db import DBModel | from modules.core.db import DBModel | ||||
| from modules.core.baseview import BaseView | |||||
| from modules.core.core import cbpi | |||||
| from modules.core.baseview import RestApi | |||||
| from modules import cbpi | |||||
| from modules.database.dbmodel import Step | from modules.database.dbmodel import Step | ||||
| class StepView(BaseView): | |||||
| class StepView(RestApi): | |||||
| model = Step | model = Step | ||||
| def _pre_post_callback(self, data): | def _pre_post_callback(self, data): | ||||
| order = self.model.get_max_order() | order = self.model.get_max_order() | ||||
| @@ -207,24 +207,25 @@ def init_after_startup(): | |||||
| @cbpi.addon.core.initializer(order=2000) | @cbpi.addon.core.initializer(order=2000) | ||||
| def init(cbpi): | def init(cbpi): | ||||
| StepView.register(cbpi._app, route_base='/api/step') | |||||
| StepView.register(cbpi.web, route_base='/api/step') | |||||
| def get_all(): | def get_all(): | ||||
| with cbpi._app.app_context(): | |||||
| with cbpi.web.app_context(): | |||||
| return Step.get_all() | return Step.get_all() | ||||
| with cbpi._app.app_context(): | |||||
| with cbpi.web.app_context(): | |||||
| init_after_startup() | init_after_startup() | ||||
| cbpi.add_cache_callback("steps", get_all) | cbpi.add_cache_callback("steps", get_all) | ||||
| @cbpi.addon.core.backgroundjob(key="step_task", interval=0.1) | |||||
| @cbpi.addon.core.backgroundtask(key="step_task", interval=0.1) | |||||
| def execute_step(api): | def execute_step(api): | ||||
| ''' | ''' | ||||
| Background job which executes the step | Background job which executes the step | ||||
| :return: | :return: | ||||
| ''' | ''' | ||||
| with cbpi._app.app_context(): | |||||
| with cbpi.web.app_context(): | |||||
| step = cbpi.cache.get("active_step") | step = cbpi.cache.get("active_step") | ||||
| if step is not None: | if step is not None: | ||||
| step.execute() | step.execute() | ||||
| @@ -5,7 +5,7 @@ from flask import json, url_for, Response, request | |||||
| from flask_classy import FlaskView, route | from flask_classy import FlaskView, route | ||||
| from flask_login import login_required, current_user | from flask_login import login_required, current_user | ||||
| from git import Repo, Git | from git import Repo, Git | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| import pprint | import pprint | ||||
| import time | import time | ||||
| @@ -190,4 +190,4 @@ class SystemView(FlaskView): | |||||
| def init(cbpi): | def init(cbpi): | ||||
| SystemView.api = cbpi | SystemView.api = cbpi | ||||
| SystemView.register(cbpi._app, route_base='/api/system') | |||||
| SystemView.register(cbpi.web, route_base='/api/system') | |||||
| @@ -1,12 +1,12 @@ | |||||
| from flask import Blueprint,render_template | from flask import Blueprint,render_template | ||||
| from modules.core.core import cbpi | |||||
| from modules import cbpi | |||||
| react = Blueprint('ui', __name__, template_folder='templates', static_folder='static') | react = Blueprint('ui', __name__, template_folder='templates', static_folder='static') | ||||
| @cbpi.addon.core.initializer(order=10) | @cbpi.addon.core.initializer(order=10) | ||||
| def init(cbpi): | def init(cbpi): | ||||
| cbpi._app.register_blueprint(react, url_prefix='/ui') | |||||
| cbpi.web.register_blueprint(react, url_prefix='/ui') | |||||
| @react.route('/', methods=["GET"]) | @react.route('/', methods=["GET"]) | ||||
| @@ -22,7 +22,7 @@ def index(): | |||||
| @cbpi._app.errorhandler(404) | |||||
| @cbpi.web.errorhandler(404) | |||||
| def page_not_found(e): | def page_not_found(e): | ||||
| return render_template('404.html'), 404 | return render_template('404.html'), 404 | ||||
| @@ -10,11 +10,17 @@ | |||||
| <link rel="stylesheet" href="static/bootstrap.dark.css"> | <link rel="stylesheet" href="static/bootstrap.dark.css"> | ||||
| <style> | |||||
| html { | |||||
| background-image: url('static/bg.png'); | |||||
| } | |||||
| </style> | |||||
| <title>CraftBeerPi 3.0</title> | <title>CraftBeerPi 3.0</title> | ||||
| </head> | </head> | ||||
| <body> | <body> | ||||
| <div id="root" ></div> | <div id="root" ></div> | ||||
| HALLO | |||||
| <script src="static/bundle.js" type="text/javascript"></script> | <script src="static/bundle.js" type="text/javascript"></script> | ||||
| @@ -7,18 +7,13 @@ | |||||
| <link rel="stylesheet" href="static/bootstrap.min.css"> | <link rel="stylesheet" href="static/bootstrap.min.css"> | ||||
| <link rel="stylesheet" href="static/css/font-awesome.min.css"> | <link rel="stylesheet" href="static/css/font-awesome.min.css"> | ||||
| <link rel="stylesheet" href="static/bootstrap.dark.css"> | |||||
| <link href="https://fonts.googleapis.com/css?family=Dosis:200,500" rel="stylesheet"> | |||||
| <style> | |||||
| <link rel="stylesheet" href="static/theme.css"> | |||||
| <link href="https://fonts.googleapis.com/css?family=Dosis:200,500" rel="stylesheet"/> | |||||
| body, h1, h2, h3, h4, h5, h6 { | |||||
| font-family: 'Dosis', sans-serif; | |||||
| } | |||||
| </style> | |||||
| <title>CraftBeerPi 3.1</title> | |||||
| <title>CraftBeerPi 3.1</title> | |||||
| </head> | </head> | ||||
| <body> | <body> | ||||
| <div id="root" ></div> | <div id="root" ></div> | ||||
| @@ -1,4 +0,0 @@ | |||||
| import re | |||||
| recipe_name = "Manuel 8881881 18181 " | |||||
| print re.match("^[\sA-Za-z0-9_-]*$", recipe_name) | |||||
| @@ -1,10 +1,8 @@ | |||||
| #!/usr/bin/env python | #!/usr/bin/env python | ||||
| from modules.core.core import * | |||||
| cbpi = CraftBeerPI() | |||||
| addon = cbpi.addon | |||||
| from modules import cbpi | |||||
| from modules.core.db_migrate import * | from modules.core.db_migrate import * | ||||