- 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 | |||
| from flask import request | |||
| from flask_classy import FlaskView, route | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| class ActionView(FlaskView): | |||
| @@ -15,9 +17,10 @@ class ActionView(FlaskView): | |||
| 200: | |||
| 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) | |||
| @cbpi.addon.core.initializer() | |||
| @@ -28,4 +31,4 @@ def init(cbpi): | |||
| :return: None | |||
| """ | |||
| 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 | |||
| from flask import request | |||
| from flask_classy import route | |||
| from flask_login import login_required | |||
| 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 | |||
| class ActorView(BaseView): | |||
| class ActorView(RestApi): | |||
| model = Actor | |||
| cache_key = "actors" | |||
| @@ -121,7 +123,7 @@ class ActorView(BaseView): | |||
| def toggleTimeJob(self, id, t): | |||
| self.api.cache.get("actors").get(int(id)).timer = int(time.time()) + int(t) | |||
| self.toggle(int(id)) | |||
| self.api._socketio.sleep(t) | |||
| self.api.sleep(t) | |||
| self.api.cache.get("actors").get(int(id)).timer = None | |||
| self.toggle(int(id)) | |||
| @@ -179,13 +181,18 @@ class ActorView(BaseView): | |||
| 200: | |||
| 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) | |||
| @cbpi.addon.core.initializer(order=1000) | |||
| def init(cbpi): | |||
| ActorView.register(cbpi._app, route_base='/api/actor') | |||
| ActorView.register(cbpi.web, route_base='/api/actor') | |||
| ActorView.init_cache() | |||
| #cbpi.init_actors() | |||
| @@ -1,15 +1,37 @@ | |||
| from modules.core.baseapi import Buzzer | |||
| 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") | |||
| 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): | |||
| ''' | |||
| @@ -17,11 +39,10 @@ class Dummy(Actor): | |||
| :param power: int value between 0 - 100 | |||
| :return: | |||
| ''' | |||
| print "ON" | |||
| print "ID %s ON" % self.id | |||
| def off(self): | |||
| print "OFF" | |||
| print "ID %s OFF" % self.id | |||
| @cbpi.addon.kettle.controller() | |||
| @@ -29,7 +50,7 @@ class MyController(KettleController): | |||
| def run(self): | |||
| while self.is_running(): | |||
| print "HALLO" | |||
| self.sleep(1) | |||
| @@ -49,6 +70,7 @@ def init(cbpi): | |||
| class MyBuzzer(Buzzer): | |||
| def beep(self): | |||
| print "BEEEEEP" | |||
| pass | |||
| cbpi.buzzer = MyBuzzer() | |||
| @@ -3,11 +3,12 @@ import os | |||
| 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 | |||
| import random | |||
| @cbpi.addon.sensor.type("Dummy Sensor") | |||
| class Dummy(Sensor): | |||
| @@ -21,10 +22,15 @@ class Dummy(Sensor): | |||
| else: | |||
| 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): | |||
| while True: | |||
| @@ -34,14 +40,28 @@ class Dummy(Sensor): | |||
| pass | |||
| 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.core import cbpi | |||
| from modules import cbpi | |||
| from modules.core.proptypes import Property | |||
| import time | |||
| @@ -18,7 +18,7 @@ class Dummy(Step): | |||
| time = Property.Text(label="Text", configurable=True, description="WOHOOO") | |||
| def execute(self): | |||
| #print self.text | |||
| pass | |||
| def reset(self): | |||
| @@ -36,8 +36,8 @@ class MashStep(Step): | |||
| Just put the decorator @cbpi.step on top of a method | |||
| ''' | |||
| # 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") | |||
| def init(self): | |||
| @@ -79,6 +79,7 @@ class MashStep(Step): | |||
| # Check if timer finished and go to next step | |||
| if self.is_timer_finished() == True: | |||
| self.api.beep() | |||
| self.notify("Mash Step Completed!", "Starting the next step", timeout=None) | |||
| self.next() | |||
| @@ -243,3 +244,5 @@ class BoilStep(Step): | |||
| if self.is_timer_finished() == True: | |||
| self.notify("Boil Step Completed!", "Starting the next step", timeout=None) | |||
| self.next() | |||
| @@ -2,7 +2,7 @@ import time | |||
| from thread import start_new_thread | |||
| from modules.core.baseapi import Buzzer | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| try: | |||
| import RPi.GPIO as GPIO | |||
| @@ -16,19 +16,19 @@ class GPIOBuzzer(Buzzer): | |||
| def __init__(self, gpio): | |||
| 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) | |||
| GPIO.setmode(GPIO.BCM) | |||
| GPIO.setup(self.gpio, GPIO.OUT) | |||
| self.state = True | |||
| cbpi._app.logger.info("BUZZER SETUP OK") | |||
| cbpi.web.logger.info("BUZZER SETUP OK") | |||
| 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 | |||
| def beep(self): | |||
| if self.state is False: | |||
| cbpi._app.logger.error("BUZZER not working") | |||
| cbpi.web.logger.error("BUZZER not working") | |||
| return | |||
| def play(sound): | |||
| @@ -2,13 +2,13 @@ import time | |||
| from flask import json, request | |||
| from flask_classy import route | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| from modules.core.db import DBModel | |||
| from modules.core.baseview import BaseView | |||
| from modules.core.baseview import RestApi | |||
| from modules.database.dbmodel import Config | |||
| class ConfigView(BaseView): | |||
| class ConfigView(RestApi): | |||
| model = Config | |||
| cache_key = "config" | |||
| @@ -77,7 +77,7 @@ class ConfigView(BaseView): | |||
| @classmethod | |||
| def init_cache(cls): | |||
| with cls.api._app.app_context(): | |||
| with cls.api.web.app_context(): | |||
| cls.api.cache[cls.cache_key] = {} | |||
| for key, value in cls.model.get_all().iteritems(): | |||
| cls.post_init_callback(value) | |||
| @@ -85,5 +85,5 @@ class ConfigView(BaseView): | |||
| @cbpi.addon.core.initializer(order=0) | |||
| def init(cbpi): | |||
| ConfigView.register(cbpi._app, route_base='/api/config') | |||
| ConfigView.register(cbpi.web, route_base='/api/config') | |||
| ConfigView.init_cache() | |||
| @@ -22,6 +22,9 @@ class BaseAPI(object): | |||
| except: | |||
| 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].update(options) | |||
| 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) | |||
| 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): | |||
| 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}) | |||
| 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}) | |||
| 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}) | |||
| 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}) | |||
| for method_name, method in cls.__dict__.iteritems(): | |||
| if hasattr(method, "action"): | |||
| 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 | |||
| @@ -59,9 +78,11 @@ class SensorAPI(BaseAPI): | |||
| return f | |||
| return decorator | |||
| def action(self, label): | |||
| def action(self, label, parameters=None): | |||
| def real_decorator(func): | |||
| func.action = True | |||
| func.parameters = parameters | |||
| func.label = label | |||
| return func | |||
| return real_decorator | |||
| @@ -80,10 +101,11 @@ class StepAPI(BaseAPI): | |||
| return f | |||
| return decorator | |||
| def action(self, label): | |||
| def action(self, label, parameters=None): | |||
| def real_decorator(func): | |||
| func.action = True | |||
| func.label = label | |||
| func.parameters = parameters | |||
| return func | |||
| return real_decorator | |||
| @@ -100,10 +122,11 @@ class ActorAPI(BaseAPI): | |||
| return f | |||
| return decorator | |||
| def action(self, label): | |||
| def action(self, label, parameters=None): | |||
| def real_decorator(func): | |||
| func.action = True | |||
| func.label = label | |||
| func.parameters = parameters | |||
| return func | |||
| return real_decorator | |||
| @@ -119,10 +142,11 @@ class KettleAPI(BaseAPI): | |||
| return f | |||
| return decorator | |||
| def action(self, label): | |||
| def action(self, label, parameters=None): | |||
| def real_decorator(func): | |||
| func.action = True | |||
| func.label = label | |||
| func.parameters = parameters | |||
| return func | |||
| return real_decorator | |||
| @@ -136,10 +160,11 @@ class FermenterAPI(BaseAPI): | |||
| return f | |||
| return decorator | |||
| def action(self, label): | |||
| def action(self, label, parameters=None): | |||
| def real_decorator(func): | |||
| func.action = True | |||
| func.label = label | |||
| func.parameters = parameters | |||
| return func | |||
| return real_decorator | |||
| @@ -156,7 +181,6 @@ class CoreAPI(BaseAPI): | |||
| self.cbpi.cache["web_menu"] =[] | |||
| def init(self): | |||
| self.cbpi.cache["init"] = sorted(self.cbpi.cache["init"], key=lambda k: k['order']) | |||
| for value in self.cbpi.cache.get("init"): | |||
| @@ -168,12 +192,17 @@ class CoreAPI(BaseAPI): | |||
| try: | |||
| method(self.cbpi) | |||
| 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"): | |||
| 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): | |||
| self.cbpi.cache["js"][name] = file | |||
| @@ -187,15 +216,7 @@ class CoreAPI(BaseAPI): | |||
| return f | |||
| 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): | |||
| self.cbpi.cache.get("background").append({"function": f, "key": key, "interval": interval}) | |||
| return f | |||
| @@ -220,5 +241,20 @@ class CoreAPI(BaseAPI): | |||
| 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.__dirty = False | |||
| class Action(Base): | |||
| def execute(self): | |||
| pass | |||
| class Actor(Base): | |||
| @classmethod | |||
| def init_global(cls): | |||
| pass | |||
| def init(self): | |||
| @@ -68,9 +72,6 @@ class Sensor(Base): | |||
| print "EXECUTE" | |||
| pass | |||
| class ControllerBase(object): | |||
| __dirty = False | |||
| __running = False | |||
| @@ -271,7 +272,6 @@ class Step(Base, Timer): | |||
| def set_target_temp(self, temp, id=None): | |||
| temp = float(temp) | |||
| try: | |||
| if id is None: | |||
| 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") | |||
| def get_kettle_temp(self, id=None): | |||
| id = int(id) | |||
| if id is None: | |||
| @@ -294,6 +293,8 @@ class Step(Base, Timer): | |||
| def reset_dirty(self): | |||
| self.__dirty = False | |||
| def notify(self, headline, messsage, timeout=None): | |||
| self.api.notify(headline, messsage, timeout) | |||
| def __setattr__(self, name, value): | |||
| 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_login import login_required | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| class BaseView(FlaskView): | |||
| class RestApi(FlaskView): | |||
| as_array = False | |||
| cache_key = None | |||
| @@ -39,7 +39,7 @@ class BaseView(FlaskView): | |||
| def post(self): | |||
| 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) | |||
| m = self.model.insert(**data) | |||
| if self.api.cache.get(self.cache_key) is not None: | |||
| @@ -101,7 +101,7 @@ class BaseView(FlaskView): | |||
| @classmethod | |||
| def init_cache(cls): | |||
| with cls.api._app.app_context(): | |||
| with cls.api.web.app_context(): | |||
| if cls.model.__as_array__ is True: | |||
| cls.api.cache[cls.cache_key] = [] | |||
| @@ -22,7 +22,6 @@ from modules.database.dbmodel import Kettle | |||
| class ComplexEncoder(json.JSONEncoder): | |||
| def default(self, obj): | |||
| try: | |||
| if isinstance(obj, DBModel): | |||
| return obj.__dict__ | |||
| elif isinstance(obj, Actor): | |||
| @@ -33,31 +32,11 @@ class ComplexEncoder(json.JSONEncoder): | |||
| return obj() | |||
| else: | |||
| return None | |||
| return None | |||
| except TypeError as e: | |||
| pass | |||
| 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): | |||
| key = "actor_types" | |||
| @@ -82,8 +61,7 @@ class ActorCore(object): | |||
| actor.power = 100 | |||
| self.cbpi.emit("INIT_ACTOR", id=id) | |||
| except Exception as e: | |||
| print e | |||
| self.cbpi._app.logger.error(e) | |||
| self.cbpi.web.logger.error(e) | |||
| def stop_one(self, id): | |||
| self.cbpi.cache["actors"][id]["instance"].stop() | |||
| @@ -99,7 +77,7 @@ class ActorCore(object): | |||
| self.cbpi.emit("SWITCH_ACTOR_ON", id=id, power=power) | |||
| return True | |||
| except Exception as e: | |||
| print e | |||
| self.cbpi.logger.error(e) | |||
| return False | |||
| def off(self, id): | |||
| @@ -111,7 +89,7 @@ class ActorCore(object): | |||
| self.cbpi.emit("SWITCH_ACTOR_OFF", id=id) | |||
| return True | |||
| except Exception as e: | |||
| print e | |||
| self.cbpi.logger.error(e) | |||
| return False | |||
| def toggle(self, id): | |||
| @@ -129,11 +107,11 @@ class ActorCore(object): | |||
| self.cbpi.emit("SWITCH_ACTOR_POWER_CHANGE", id=id, power=power) | |||
| return True | |||
| except Exception as e: | |||
| print e | |||
| self.cbpi.logger.error(e) | |||
| 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): | |||
| @@ -182,7 +160,7 @@ class SensorCore(object): | |||
| except Exception as e: | |||
| print "ERROR" | |||
| self.cbpi._app.logger.error(e) | |||
| self.cbpi.web.logger.error(e) | |||
| def stop_one(self, id): | |||
| @@ -206,12 +184,12 @@ 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)() | |||
| def action(self, id, method, **data): | |||
| self.cbpi.cache.get("sensors").get(id).instance.__getattribute__(method)(**data) | |||
| class BrewingCore(object): | |||
| def __init__(self, cbpi): | |||
| self.cbpi = cbpi | |||
| self.cbpi.cache["step_types"] = {} | |||
| @@ -240,7 +218,7 @@ class BrewingCore(object): | |||
| # 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)) | |||
| 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.init() | |||
| kettle.instance = instance | |||
| @@ -250,13 +228,13 @@ class BrewingCore(object): | |||
| 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.ws_emit("UPDATE_KETTLE", self.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.ws_emit("UPDATE_KETTLE", self.cbpi.cache.get("kettle").get(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) | |||
| 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): | |||
| cache = {} | |||
| eventbus = {} | |||
| 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["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.actor = ActorCore(self) | |||
| self.sensor = SensorCore(self) | |||
| self.brewing = BrewingCore(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(): | |||
| return redirect('ui') | |||
| @@ -303,11 +303,11 @@ class CraftBeerPI(object): | |||
| self.actor.init() | |||
| self.beep() | |||
| try: | |||
| port = int(cbpi.get_config_parameter('port', '5000')) | |||
| port = int(self.get_config_parameter('port', '5000')) | |||
| except ValueError: | |||
| 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): | |||
| self.buzzer.beep() | |||
| @@ -315,6 +315,10 @@ class CraftBeerPI(object): | |||
| def sleep(self, 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): | |||
| msg = {"id": str(uuid.uuid1()), "type": type, "headline": headline, "message": message, "timeout": timeout} | |||
| self.ws_emit("NOTIFY", msg) | |||
| @@ -324,10 +328,10 @@ class CraftBeerPI(object): | |||
| def __init_db(self, ): | |||
| with self._app.app_context(): | |||
| with self.web.app_context(): | |||
| db = self.get_db() | |||
| 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.commit() | |||
| except Exception as e: | |||
| @@ -373,7 +377,7 @@ class CraftBeerPI(object): | |||
| def set_config_parameter(self, name, value): | |||
| from modules.config import Config | |||
| with self._app.app_context(): | |||
| with self.web.app_context(): | |||
| update_data = {"name": name, "value": value} | |||
| self.cache.get("config")[name].__dict__.update(**update_data) | |||
| c = Config.update(**update_data) | |||
| @@ -381,7 +385,6 @@ class CraftBeerPI(object): | |||
| def emit(self, key, **kwargs): | |||
| if self.eventbus.get(key) is not None: | |||
| for value in self.eventbus[key]: | |||
| 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) | |||
| cbpi = CraftBeerPI() | |||
| addon = cbpi.addon | |||
| @@ -1,11 +1,11 @@ | |||
| import sqlite3 | |||
| import os | |||
| from modules.core.core import cbpi | |||
| from modules 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"]) | |||
| cbpi.web.logger.info("SKIP DB FILE: %s" % data["file"]) | |||
| return | |||
| try: | |||
| 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"])) | |||
| conn.commit() | |||
| except sqlite3.OperationalError as err: | |||
| print err | |||
| except sqlite3.OperationalError as e: | |||
| cbpi.logger.error(e) | |||
| @cbpi.addon.core.initializer(order=-9999) | |||
| def init(cbpi): | |||
| with cbpi._app.app_context(): | |||
| with cbpi.web.app_context(): | |||
| conn = get_db() | |||
| cur = conn.cursor() | |||
| current_version = None | |||
| @@ -16,6 +16,7 @@ class Property(object): | |||
| self.configurable = configurable | |||
| self.default_value = default_value | |||
| self.description = description | |||
| self.unit = unit | |||
| class Text(PropertyType): | |||
| def __init__(self, label, configurable=False, required=False, default_value="", description=""): | |||
| @@ -44,5 +45,6 @@ class Property(object): | |||
| def __init__(self, label, description=""): | |||
| PropertyType.__init__(self) | |||
| self.label = label | |||
| self.unit = "" | |||
| self.configurable = True | |||
| self.description = description | |||
| @@ -1,11 +1,11 @@ | |||
| from flask import Blueprint | |||
| from modules.core.core import cbpi, addon | |||
| from modules import cbpi | |||
| from flask_swagger import swagger | |||
| from flask import json | |||
| from flask import Blueprint | |||
| @addon.core.initializer(order=22) | |||
| @cbpi.addon.core.initializer(order=22) | |||
| def web(cbpi): | |||
| 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._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 modules.core.core import cbpi, addon | |||
| from modules import cbpi | |||
| from flask_swagger import swagger | |||
| from flask import json | |||
| from flask import Blueprint | |||
| @addon.core.initializer(order=22) | |||
| @cbpi.addon.core.initializer(order=22) | |||
| def web(cbpi): | |||
| 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._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 import json | |||
| from flask import Blueprint | |||
| @addon.core.initializer(order=22) | |||
| @cbpi.addon.core.initializer(order=22) | |||
| def hello(cbpi): | |||
| s = Blueprint('react', __name__, template_folder='templates', static_folder='static') | |||
| @@ -14,10 +14,10 @@ def hello(cbpi): | |||
| @s.route('/swagger.json', methods=["GET"]) | |||
| def spec(): | |||
| swag = swagger(cbpi._app) | |||
| swag = swagger(cbpi.web) | |||
| swag['info']['version'] = "3.0" | |||
| swag['info']['title'] = "CraftBeerPi" | |||
| return json.dumps(swag) | |||
| 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_classy import route | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| 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 | |||
| class FermenterView(BaseView): | |||
| class FermenterView(RestApi): | |||
| model = Fermenter | |||
| cache_key = "fermenter" | |||
| @@ -212,10 +212,9 @@ class FermenterView(BaseView): | |||
| cbpi.ws_emit("UPDATE_FERMENTER", cbpi.cache.get(self.cache_key)[id]) | |||
| def check_step(self): | |||
| print "CHECK STEP" | |||
| print cbpi.cache["fermenter_task"] | |||
| for key, value in cbpi.cache["fermenter_task"].iteritems(): | |||
| print value | |||
| try: | |||
| fermenter = self.get_fermenter(key) | |||
| current_temp = current_temp = cbpi.sensor.get_value(int(fermenter.sensor)) | |||
| @@ -236,11 +235,11 @@ class FermenterView(BaseView): | |||
| else: | |||
| pass | |||
| except Exception as e: | |||
| print e | |||
| self.api.looger.error(e) | |||
| 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): | |||
| """ | |||
| background process that reads all passive sensors in interval of 1 second | |||
| @@ -253,9 +252,9 @@ def read_target_temps(cbpi): | |||
| 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): | |||
| with cbpi._app.app_context(): | |||
| with cbpi.web.app_context(): | |||
| instance.check_step() | |||
| @@ -268,5 +267,5 @@ def init_active_steps(): | |||
| def init(cbpi): | |||
| cbpi.cache["fermenter_task"] = {} | |||
| FermenterView.register(cbpi._app, route_base='/api/fermenter') | |||
| FermenterView.register(cbpi.web, route_base='/api/fermenter') | |||
| FermenterView.init_cache() | |||
| @@ -1,11 +1,11 @@ | |||
| from flask import request | |||
| 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.database.dbmodel import Kettle | |||
| class KettleView(BaseView): | |||
| class KettleView(RestApi): | |||
| model = Kettle | |||
| cache_key = "kettle" | |||
| @@ -228,7 +228,7 @@ def set_target_temp(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): | |||
| """ | |||
| 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() | |||
| def init(cbpi): | |||
| KettleView.api = cbpi | |||
| KettleView.register(cbpi._app, route_base='/api/kettle') | |||
| KettleView.register(cbpi.web, route_base='/api/kettle') | |||
| KettleView.init_cache() | |||
| @@ -1,18 +1,19 @@ | |||
| import flask_login | |||
| from flask import request | |||
| from modules.core.core import cbpi, addon | |||
| from modules import cbpi | |||
| class User(flask_login.UserMixin): | |||
| pass | |||
| @addon.core.initializer(order=0) | |||
| @cbpi.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=['POST']) | |||
| cbpi._login_manager.init_app(cbpi.web) | |||
| @cbpi.web.route('/login', methods=['POST']) | |||
| def login(): | |||
| data = request.json | |||
| @@ -30,15 +31,29 @@ def log(cbpi): | |||
| return ('',401) | |||
| @cbpi._app.route('/logout', methods=['POST']) | |||
| @cbpi.web.route('/logout', methods=['POST']) | |||
| def logout(): | |||
| flask_login.logout_user() | |||
| 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 user != "craftbeerpi": | |||
| @@ -53,4 +68,6 @@ def log(cbpi): | |||
| @cbpi._login_manager.unauthorized_handler | |||
| def unauthorized_handler(): | |||
| return ('Please login',401) | |||
| @@ -2,7 +2,7 @@ import datetime | |||
| import os | |||
| from flask import Blueprint, request, send_from_directory, json | |||
| from flask_classy import FlaskView, route | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| class LogView(FlaskView): | |||
| @@ -172,4 +172,4 @@ def init(cbpi): | |||
| :param app: the flask app | |||
| :return: None | |||
| """ | |||
| LogView.register(cbpi._app, route_base='/api/logs') | |||
| LogView.register(cbpi.web, route_base='/api/logs') | |||
| @@ -1,6 +1,6 @@ | |||
| import json | |||
| from flask_classy import FlaskView, route | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| 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} | |||
| 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 | |||
| from flask import request, send_from_directory, json | |||
| from importlib import import_module | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| from git import Repo | |||
| import os | |||
| import requests | |||
| @@ -46,7 +46,7 @@ class PluginView(FlaskView): | |||
| 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"]) | |||
| for key, value in cbpi.cache["plugins"].iteritems(): | |||
| print key | |||
| value["installed"] = os.path.isdir("./plugins/%s/" % (key)) | |||
| return json.dumps(cbpi.cache["plugins"]) | |||
| @@ -136,4 +136,4 @@ class PluginView(FlaskView): | |||
| def init(cbpi): | |||
| cbpi.cache["plugins"] = {} | |||
| 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 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 yaml import Loader, Dumper | |||
| from yaml import load, dump | |||
| @@ -59,7 +59,7 @@ class RecipeBook(FlaskView): | |||
| description: Log file downloaded | |||
| """ | |||
| file = "%s.json" % name | |||
| print file | |||
| if not self.check_filename(file): | |||
| return ('File Not Found111', 404) | |||
| 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) | |||
| def init(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 git import Repo, Git | |||
| import sqlite3 | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| from werkzeug.utils import secure_filename | |||
| import pprint | |||
| import time | |||
| @@ -60,7 +60,7 @@ class BeerXMLImport(FlaskView): | |||
| return ('', 204) | |||
| return ('', 404) | |||
| 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") | |||
| return ('', 500) | |||
| @@ -143,4 +143,4 @@ class BeerXMLImport(FlaskView): | |||
| def init(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 git import Repo, Git | |||
| import sqlite3 | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| from werkzeug.utils import secure_filename | |||
| import pprint | |||
| import time | |||
| @@ -39,7 +39,7 @@ class KBH(FlaskView): | |||
| result.append({"id": row[0], "name": row[1], "brewed": row[2]}) | |||
| return json.dumps(result) | |||
| except Exception as e: | |||
| print e | |||
| self.api.logger.error(e) | |||
| self.api.notify(headline="Failed to load KHB database", message="ERROR", type="danger") | |||
| return ('', 500) | |||
| finally: | |||
| @@ -143,4 +143,4 @@ class KBH(FlaskView): | |||
| def init(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 git import Repo, Git | |||
| import sqlite3 | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| from werkzeug.utils import secure_filename | |||
| import pprint | |||
| import time | |||
| @@ -59,4 +59,4 @@ class RESTImport(FlaskView): | |||
| @cbpi.addon.core.initializer() | |||
| def init(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 | |||
| from flask_classy import route | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| 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 flask import request | |||
| class SensorView(BaseView): | |||
| class SensorView(RestApi): | |||
| model = Sensor | |||
| cache_key = "sensors" | |||
| @@ -34,7 +34,11 @@ class SensorView(BaseView): | |||
| 200: | |||
| 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) | |||
| def _post_post_callback(self, m): | |||
| @@ -51,17 +55,19 @@ class SensorView(BaseView): | |||
| @cbpi.addon.core.initializer(order=1000) | |||
| def init(cbpi): | |||
| SensorView.register(cbpi._app, route_base='/api/sensor') | |||
| SensorView.register(cbpi.web, route_base='/api/sensor') | |||
| 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): | |||
| """ | |||
| background process that reads all passive sensors in interval of 1 second | |||
| :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 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 | |||
| class StepView(BaseView): | |||
| class StepView(RestApi): | |||
| model = Step | |||
| def _pre_post_callback(self, data): | |||
| order = self.model.get_max_order() | |||
| @@ -207,24 +207,25 @@ def init_after_startup(): | |||
| @cbpi.addon.core.initializer(order=2000) | |||
| def init(cbpi): | |||
| StepView.register(cbpi._app, route_base='/api/step') | |||
| StepView.register(cbpi.web, route_base='/api/step') | |||
| def get_all(): | |||
| with cbpi._app.app_context(): | |||
| with cbpi.web.app_context(): | |||
| return Step.get_all() | |||
| with cbpi._app.app_context(): | |||
| with cbpi.web.app_context(): | |||
| init_after_startup() | |||
| 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): | |||
| ''' | |||
| Background job which executes the step | |||
| :return: | |||
| ''' | |||
| with cbpi._app.app_context(): | |||
| with cbpi.web.app_context(): | |||
| step = cbpi.cache.get("active_step") | |||
| if step is not None: | |||
| step.execute() | |||
| @@ -5,7 +5,7 @@ from flask import json, url_for, Response, request | |||
| from flask_classy import FlaskView, route | |||
| from flask_login import login_required, current_user | |||
| from git import Repo, Git | |||
| from modules.core.core import cbpi | |||
| from modules import cbpi | |||
| import pprint | |||
| import time | |||
| @@ -190,4 +190,4 @@ class SystemView(FlaskView): | |||
| def init(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 modules.core.core import cbpi | |||
| from modules import cbpi | |||
| react = Blueprint('ui', __name__, template_folder='templates', static_folder='static') | |||
| @cbpi.addon.core.initializer(order=10) | |||
| def init(cbpi): | |||
| cbpi._app.register_blueprint(react, url_prefix='/ui') | |||
| cbpi.web.register_blueprint(react, url_prefix='/ui') | |||
| @react.route('/', methods=["GET"]) | |||
| @@ -22,7 +22,7 @@ def index(): | |||
| @cbpi._app.errorhandler(404) | |||
| @cbpi.web.errorhandler(404) | |||
| def page_not_found(e): | |||
| return render_template('404.html'), 404 | |||
| @@ -10,11 +10,17 @@ | |||
| <link rel="stylesheet" href="static/bootstrap.dark.css"> | |||
| <style> | |||
| html { | |||
| background-image: url('static/bg.png'); | |||
| } | |||
| </style> | |||
| <title>CraftBeerPi 3.0</title> | |||
| </head> | |||
| <body> | |||
| <div id="root" ></div> | |||
| HALLO | |||
| <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/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> | |||
| <body> | |||
| <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 | |||
| from modules.core.core import * | |||
| cbpi = CraftBeerPI() | |||
| addon = cbpi.addon | |||
| from modules import cbpi | |||
| from modules.core.db_migrate import * | |||