mirror of
https://github.com/Manuel83/craftbeerpi3
synced 2026-08-09 18:52:40 +02:00
-Ui Changes
-Brew Steps added -Clean AddOn Dialog
This commit is contained in:
@@ -8,3 +8,7 @@ craftbeerpi.db
|
|||||||
modules/plugins/*
|
modules/plugins/*
|
||||||
!modules/plugins/__init__.py
|
!modules/plugins/__init__.py
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.js
|
||||||
|
modules/ui/package.json
|
||||||
|
|
||||||
|
modules/ui/.babelrc
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ INSERT INTO config VALUES ('unit', 'C', 'select', 'Temperature Unit', '["C","F"]
|
|||||||
INSERT INTO config VALUES ('brewery_name', 'My Home Brewery', 'text', 'Your brewery name', NULL );
|
INSERT INTO config VALUES ('brewery_name', 'My Home Brewery', 'text', 'Your brewery name', NULL );
|
||||||
INSERT INTO config VALUES ('buzzer', 16, 'select', 'Buzzer GPIO', '[16,17,18,19,20]');
|
INSERT INTO config VALUES ('buzzer', 16, 'select', 'Buzzer GPIO', '[16,17,18,19,20]');
|
||||||
INSERT INTO config VALUES ('setup', 'YES', 'select', 'Show the Setup dialog', '["YES","NO"]');
|
INSERT INTO config VALUES ('setup', 'YES', 'select', 'Show the Setup dialog', '["YES","NO"]');
|
||||||
|
INSERT INTO config VALUES ('brew_name', '', 'text', 'Brew Name', NULL);
|
||||||
|
INSERT INTO config VALUES ('donation_notification', 'YES', 'select', 'Disable Donation Notification', '["YES","NO"]');
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE actor
|
CREATE TABLE actor
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
3.0.1
|
||||||
@@ -63,3 +63,6 @@ cbpi.run_background_processes()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app.logger.info("##########################################")
|
||||||
|
app.logger.info("### STARTUP COMPLETE")
|
||||||
|
app.logger.info("##########################################")
|
||||||
@@ -15,7 +15,9 @@ from modules.core.db import DBModel
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
logging.basicConfig(filename='./logs/app.log',level=logging.INFO)
|
FORMAT = '%(asctime)-15s - %(levelname)s - %(message)s'
|
||||||
|
|
||||||
|
logging.basicConfig(filename='./logs/app.log',level=logging.INFO, format=FORMAT)
|
||||||
app.config['SECRET_KEY'] = 'craftbeerpi'
|
app.config['SECRET_KEY'] = 'craftbeerpi'
|
||||||
app.config['UPLOAD_FOLDER'] = './upload'
|
app.config['UPLOAD_FOLDER'] = './upload'
|
||||||
|
|
||||||
@@ -45,7 +47,7 @@ class ComplexEncoder(json.JSONEncoder):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
app.json_encoder = ComplexEncoder
|
app.json_encoder = ComplexEncoder
|
||||||
socketio = SocketIO(app, json=json)
|
socketio = SocketIO(app, json=json, logging=False)
|
||||||
cbpi = CraftBeerPi(app, socketio)
|
cbpi = CraftBeerPi(app, socketio)
|
||||||
|
|
||||||
app.logger.info("##########################################")
|
app.logger.info("##########################################")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from modules.core.step import StepBase
|
|||||||
from modules import cbpi
|
from modules import cbpi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@cbpi.step
|
@cbpi.step
|
||||||
class MashStep(StepBase):
|
class MashStep(StepBase):
|
||||||
'''
|
'''
|
||||||
@@ -69,6 +70,10 @@ class MashInStep(StepBase):
|
|||||||
kettle = StepProperty.Kettle("Kettle")
|
kettle = StepProperty.Kettle("Kettle")
|
||||||
s = False
|
s = False
|
||||||
|
|
||||||
|
@cbpi.action("Change Power")
|
||||||
|
def change_power(self):
|
||||||
|
self.actor_power(1, 50)
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
'''
|
'''
|
||||||
Initialize Step. This method is called once at the beginning of the step
|
Initialize Step. This method is called once at the beginning of the step
|
||||||
@@ -93,3 +98,125 @@ class MashInStep(StepBase):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@cbpi.step
|
||||||
|
class ChilStep(StepBase):
|
||||||
|
|
||||||
|
timer = Property.Number("Timer in Minutes", configurable=True, default_value=0)
|
||||||
|
|
||||||
|
@cbpi.action("Stat Timer")
|
||||||
|
def start(self):
|
||||||
|
if self.is_timer_finished() is None:
|
||||||
|
self.start_timer(int(self.timer) * 60)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.stop_timer()
|
||||||
|
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
if self.is_timer_finished() is None:
|
||||||
|
self.start_timer(int(self.timer) * 60)
|
||||||
|
|
||||||
|
if self.is_timer_finished() == True:
|
||||||
|
self.next()
|
||||||
|
|
||||||
|
@cbpi.step
|
||||||
|
class PumpStep(StepBase):
|
||||||
|
|
||||||
|
pump = StepProperty.Actor("Pump")
|
||||||
|
timer = Property.Number("Timer in Minutes", configurable=True, default_value=0)
|
||||||
|
|
||||||
|
@cbpi.action("Stat Timer")
|
||||||
|
def start(self):
|
||||||
|
if self.is_timer_finished() is None:
|
||||||
|
self.start_timer(int(self.timer) * 60)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.stop_timer()
|
||||||
|
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
self.actor_off(int(self.pump))
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
self.actor_on(int(self.pump))
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
if self.is_timer_finished() is None:
|
||||||
|
self.start_timer(int(self.timer) * 60)
|
||||||
|
|
||||||
|
if self.is_timer_finished() == True:
|
||||||
|
self.next()
|
||||||
|
|
||||||
|
@cbpi.step
|
||||||
|
class BoilStep(StepBase):
|
||||||
|
'''
|
||||||
|
Just put the decorator @cbpi.step on top of a method
|
||||||
|
'''
|
||||||
|
# Properties
|
||||||
|
temp = Property.Number("Temperature", configurable=True, default_value=100)
|
||||||
|
kettle = StepProperty.Kettle("Kettle")
|
||||||
|
timer = Property.Number("Timer in Minutes", configurable=True, default_value=90)
|
||||||
|
hop_1 = Property.Number("Hop 1 Addition", configurable=True)
|
||||||
|
hop_1_added = Property.Number("",default_value=None)
|
||||||
|
|
||||||
|
hop_2 = Property.Number("Hop 2 Addition", configurable=True)
|
||||||
|
hop_2_added = Property.Number("", default_value=None)
|
||||||
|
hop_3 = Property.Number("Hop 3 Addition", configurable=True)
|
||||||
|
hop_3_added = Property.Number("", default_value=None)
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
'''
|
||||||
|
Initialize Step. This method is called once at the beginning of the step
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
# set target tep
|
||||||
|
self.set_target_temp(self.temp, self.kettle)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@cbpi.action("Start Timer Now")
|
||||||
|
def start(self):
|
||||||
|
'''
|
||||||
|
Custom Action which can be execute form the brewing dashboard.
|
||||||
|
All method with decorator @cbpi.action("YOUR CUSTOM NAME") will be available in the user interface
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
if self.is_timer_finished() is None:
|
||||||
|
self.start_timer(int(self.timer) * 60)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.stop_timer()
|
||||||
|
self.set_target_temp(self.temp, self.kettle)
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
self.set_target_temp(0, self.kettle)
|
||||||
|
|
||||||
|
|
||||||
|
def check_hop_timer(self, number, value):
|
||||||
|
|
||||||
|
if self.__getattribute__("hop_%s_added" % number) is not True and time.time() > (
|
||||||
|
self.timer_end - (int(self.timer) * 60 - int(value) * 60)):
|
||||||
|
self.__setattr__("hop_%s_added" % number, True)
|
||||||
|
self.notify("Hop Alert", "Please add Hop %s" % number, timeout=None)
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
'''
|
||||||
|
This method is execute in an interval
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
# Check if Target Temp is reached
|
||||||
|
if self.get_kettle_temp(self.kettle) >= int(self.temp):
|
||||||
|
# Check if Timer is Running
|
||||||
|
if self.is_timer_finished() is None:
|
||||||
|
self.start_timer(int(self.timer) * 60)
|
||||||
|
else:
|
||||||
|
self.check_hop_timer(1, self.hop_1)
|
||||||
|
self.check_hop_timer(2, self.hop_2)
|
||||||
|
self.check_hop_timer(3, self.hop_3)
|
||||||
|
# Check if timer finished and go to next step
|
||||||
|
if self.is_timer_finished() == True:
|
||||||
|
self.next()
|
||||||
@@ -10,21 +10,37 @@ from modules.core.props import Property
|
|||||||
|
|
||||||
@cbpi.sensor
|
@cbpi.sensor
|
||||||
class DummyTempSensor(SensorActive):
|
class DummyTempSensor(SensorActive):
|
||||||
|
|
||||||
temp = Property.Number("Temperature", configurable=True, default_value=5)
|
temp = Property.Number("Temperature", configurable=True, default_value=5)
|
||||||
|
|
||||||
def get_unit(self):
|
def get_unit(self):
|
||||||
|
'''
|
||||||
|
:return: Unit of the sensor as string. Should not be longer than 3 characters
|
||||||
|
'''
|
||||||
return "°C" if self.get_config_parameter("unit", "C") == "C" else "°F"
|
return "°C" if self.get_config_parameter("unit", "C") == "C" else "°F"
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
'''
|
||||||
|
Stop the sensor. Is called when the sensor config is updated or the sensor is deleted
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
|
'''
|
||||||
|
Active sensor has to handle his own loop
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
while self.is_running():
|
while self.is_running():
|
||||||
|
|
||||||
self.data_received(self.temp)
|
self.data_received(self.temp)
|
||||||
socketio.sleep(5)
|
socketio.sleep(5)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def init_global(cls):
|
||||||
|
'''
|
||||||
|
Called one at the startup for all sensors
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ class GPIOPWM(ActorBase):
|
|||||||
self.p.start(int(self.power))
|
self.p.start(int(self.power))
|
||||||
|
|
||||||
def set_power(self, power):
|
def set_power(self, power):
|
||||||
|
'''
|
||||||
|
Optional: Set the power of your actor
|
||||||
|
:param power: int value between 0 - 100
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
if power is not None:
|
if power is not None:
|
||||||
self.power = int(power)
|
self.power = int(power)
|
||||||
self.p.ChangeDutyCycle(self.power)
|
self.p.ChangeDutyCycle(self.power)
|
||||||
@@ -87,7 +92,13 @@ class RelayBoard(ActorBase):
|
|||||||
class Dummy(ActorBase):
|
class Dummy(ActorBase):
|
||||||
|
|
||||||
def on(self, power=100):
|
def on(self, power=100):
|
||||||
|
'''
|
||||||
|
Code to switch on the actor
|
||||||
|
:param power: int value between 0 - 100
|
||||||
|
:return:
|
||||||
|
'''
|
||||||
print "ON"
|
print "ON"
|
||||||
|
|
||||||
def off(self):
|
def off(self):
|
||||||
print "OFF"
|
print "OFF"
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,6 @@ class Buzzer(object):
|
|||||||
|
|
||||||
@cbpi.initalizer(order=0)
|
@cbpi.initalizer(order=0)
|
||||||
def init(cbpi):
|
def init(cbpi):
|
||||||
print "INIT BUZZER"
|
|
||||||
cbpi.app.logger.info("INIT BUZZER")
|
|
||||||
gpio = cbpi.get_config_parameter("buzzer", 16)
|
gpio = cbpi.get_config_parameter("buzzer", 16)
|
||||||
cbpi.buzzer = Buzzer(gpio)
|
cbpi.buzzer = Buzzer(gpio)
|
||||||
cbpi.beep()
|
cbpi.beep()
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ class ConfigView(BaseView):
|
|||||||
|
|
||||||
if self.api.cache.get(self.cache_key) is not None:
|
if self.api.cache.get(self.cache_key) is not None:
|
||||||
#self.pre_post_callback(self.api.cache.get(self.cache_key)[name])
|
#self.pre_post_callback(self.api.cache.get(self.cache_key)[name])
|
||||||
|
print self.api.cache.get(self.cache_key)[name]
|
||||||
self.api.cache.get(self.cache_key)[name].__dict__.update(**update_data)
|
self.api.cache.get(self.cache_key)[name].__dict__.update(**update_data)
|
||||||
m = self.model.update(**self.api.cache.get(self.cache_key)[name].__dict__)
|
m = self.model.update(**self.api.cache.get(self.cache_key)[name].__dict__)
|
||||||
self.post_put_callback(self.api.cache.get(self.cache_key)[name])
|
self.post_put_callback(self.api.cache.get(self.cache_key)[name])
|
||||||
@@ -51,7 +52,6 @@ class ConfigView(BaseView):
|
|||||||
cls.post_init_callback(value)
|
cls.post_init_callback(value)
|
||||||
cls.api.cache[cls.cache_key][value.name] = value
|
cls.api.cache[cls.cache_key][value.name] = value
|
||||||
|
|
||||||
|
|
||||||
@cbpi.initalizer(order=1)
|
@cbpi.initalizer(order=1)
|
||||||
def init(cbpi):
|
def init(cbpi):
|
||||||
print "INITIALIZE CONFIG MODULE"
|
print "INITIALIZE CONFIG MODULE"
|
||||||
|
|||||||
+17
-7
@@ -1,3 +1,4 @@
|
|||||||
|
import inspect
|
||||||
import pprint
|
import pprint
|
||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
@@ -28,6 +29,7 @@ class ActorAPI(object):
|
|||||||
self.app.logger.info("Init Actors")
|
self.app.logger.info("Init Actors")
|
||||||
t = self.cache.get("actor_types")
|
t = self.cache.get("actor_types")
|
||||||
for key, value in t.iteritems():
|
for key, value in t.iteritems():
|
||||||
|
value.get("class").api = self
|
||||||
value.get("class").init_global()
|
value.get("class").init_global()
|
||||||
|
|
||||||
for key in self.cache.get("actors"):
|
for key in self.cache.get("actors"):
|
||||||
@@ -73,12 +75,8 @@ class ActorAPI(object):
|
|||||||
|
|
||||||
if actor.state == 0:
|
if actor.state == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
actor.instance.off()
|
actor.instance.off()
|
||||||
actor.state = 0
|
actor.state = 0
|
||||||
|
|
||||||
|
|
||||||
self.emit("SWITCH_ACTOR", actor)
|
self.emit("SWITCH_ACTOR", actor)
|
||||||
|
|
||||||
class SensorAPI(object):
|
class SensorAPI(object):
|
||||||
@@ -231,7 +229,6 @@ class CraftBeerPi(ActorAPI, SensorAPI):
|
|||||||
self.emit("NOTIFY", msg)
|
self.emit("NOTIFY", msg)
|
||||||
|
|
||||||
def beep(self):
|
def beep(self):
|
||||||
|
|
||||||
if self.buzzer is not None:
|
if self.buzzer is not None:
|
||||||
self.buzzer.beep()
|
self.buzzer.beep()
|
||||||
|
|
||||||
@@ -286,6 +283,15 @@ class CraftBeerPi(ActorAPI, SensorAPI):
|
|||||||
def actor(self, cls):
|
def actor(self, cls):
|
||||||
return self.__parseProps("actor_types", cls)
|
return self.__parseProps("actor_types", cls)
|
||||||
|
|
||||||
|
def actor2(self, description="", power=True, **options):
|
||||||
|
|
||||||
|
def decorator(f):
|
||||||
|
print f()
|
||||||
|
print options
|
||||||
|
print description
|
||||||
|
return f
|
||||||
|
return decorator
|
||||||
|
|
||||||
def sensor(self, cls):
|
def sensor(self, cls):
|
||||||
return self.__parseProps("sensor_types", cls)
|
return self.__parseProps("sensor_types", cls)
|
||||||
|
|
||||||
@@ -320,9 +326,13 @@ class CraftBeerPi(ActorAPI, SensorAPI):
|
|||||||
for m in members:
|
for m in members:
|
||||||
if isinstance(tmpObj.__getattribute__(m), StepProperty.Number):
|
if isinstance(tmpObj.__getattribute__(m), StepProperty.Number):
|
||||||
t = tmpObj.__getattribute__(m)
|
t = tmpObj.__getattribute__(m)
|
||||||
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "number", "configurable": t.configurable})
|
print t.__dict__
|
||||||
|
#self.cache[key][name]["properties"].append(t.__dict__)
|
||||||
|
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "number", "configurable": t.configurable, "default_value": t.default_value})
|
||||||
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Text):
|
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Text):
|
||||||
t = tmpObj.__getattribute__(m)
|
t = tmpObj.__getattribute__(m)
|
||||||
|
print t.__dict__
|
||||||
|
#self.cache[key][name]["properties"].append(t.__dict__)
|
||||||
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "text", "configurable": t.configurable})
|
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "text", "configurable": t.configurable})
|
||||||
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Select):
|
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Select):
|
||||||
t = tmpObj.__getattribute__(m)
|
t = tmpObj.__getattribute__(m)
|
||||||
@@ -420,7 +430,7 @@ class CraftBeerPi(ActorAPI, SensorAPI):
|
|||||||
self.app.logger.info("Invoke Init")
|
self.app.logger.info("Invoke Init")
|
||||||
self.cache["init"] = sorted(self.cache["init"], key=lambda k: k['order'])
|
self.cache["init"] = sorted(self.cache["init"], key=lambda k: k['order'])
|
||||||
for i in self.cache.get("init"):
|
for i in self.cache.get("init"):
|
||||||
self.app.logger.info("-> %s " % i.get("function").__name__)
|
self.app.logger.info("INITIALIZER - METHOD %s PAHT %s: " % (i.get("function").__name__, str(inspect.getmodule(i.get("function")).__file__) ))
|
||||||
i.get("function")(self)
|
i.get("function")(self)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -42,13 +42,15 @@ class DBModel(object):
|
|||||||
def get_all(cls):
|
def get_all(cls):
|
||||||
cur = get_db().cursor()
|
cur = get_db().cursor()
|
||||||
if cls.__order_by__ is not None:
|
if cls.__order_by__ is not None:
|
||||||
cur.execute("SELECT * FROM %s ORDER BY '%s'" % (cls.__table_name__,cls.__order_by__))
|
|
||||||
|
cur.execute("SELECT * FROM %s ORDER BY %s.'%s'" % (cls.__table_name__,cls.__table_name__,cls.__order_by__))
|
||||||
else:
|
else:
|
||||||
cur.execute("SELECT * FROM %s" % cls.__table_name__)
|
cur.execute("SELECT * FROM %s" % cls.__table_name__)
|
||||||
|
|
||||||
if cls.__as_array__ is True:
|
if cls.__as_array__ is True:
|
||||||
result = []
|
result = []
|
||||||
for r in cur.fetchall():
|
for r in cur.fetchall():
|
||||||
|
|
||||||
result.append( cls(r))
|
result.append( cls(r))
|
||||||
else:
|
else:
|
||||||
result = {}
|
result = {}
|
||||||
@@ -104,7 +106,7 @@ class DBModel(object):
|
|||||||
else:
|
else:
|
||||||
data = data + (kwargs.get(f),)
|
data = data + (kwargs.get(f),)
|
||||||
|
|
||||||
print query, data
|
|
||||||
cur.execute(query, data)
|
cur.execute(query, data)
|
||||||
get_db().commit()
|
get_db().commit()
|
||||||
i = cur.lastrowid
|
i = cur.lastrowid
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ class Base(object):
|
|||||||
def get_config_parameter(self, key, default_value):
|
def get_config_parameter(self, key, default_value):
|
||||||
return self.api.get_config_parameter(key, default_value)
|
return self.api.get_config_parameter(key, default_value)
|
||||||
|
|
||||||
|
def sleep(self, seconds):
|
||||||
|
self.api.socketio.sleep(seconds)
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
print "INIT BASE"
|
print "INIT BASE"
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ class Property(object):
|
|||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
class Number(PropertyType):
|
class Number(PropertyType):
|
||||||
def __init__(self, label, configurable=False, default_value=0, unit=""):
|
def __init__(self, label, configurable=False, default_value=None, unit=""):
|
||||||
PropertyType.__init__(self)
|
PropertyType.__init__(self)
|
||||||
self.label = label
|
self.label = label
|
||||||
self.configurable = configurable
|
self.configurable = configurable
|
||||||
|
self.default_value = default_value
|
||||||
|
|
||||||
class Text(PropertyType):
|
class Text(PropertyType):
|
||||||
def __init__(self, label, configurable=False, default_value=""):
|
def __init__(self, label, configurable=False, default_value=""):
|
||||||
|
|||||||
@@ -44,9 +44,8 @@ def init(cbpi):
|
|||||||
:param app: the flask app
|
:param app: the flask app
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
print "INITIALIZE MESSAGE MODULE"
|
if cbpi.get_config_parameter("donation_notification", "YES") == "YES":
|
||||||
|
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.app, route_base='/api/notification')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import time
|
import time
|
||||||
from flask import json
|
from flask import json, request
|
||||||
from flask_classy import route
|
from flask_classy import route
|
||||||
|
|
||||||
from modules import DBModel, cbpi, get_db
|
from modules import DBModel, cbpi, get_db
|
||||||
@@ -21,9 +21,9 @@ class Step(DBModel):
|
|||||||
return r.get("order")
|
return r.get("order")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_by_state(cls, state):
|
def get_by_state(cls, state, order=True):
|
||||||
cur = get_db().cursor()
|
cur = get_db().cursor()
|
||||||
cur.execute("SELECT * FROM %s WHERE state = ?" % cls.__table_name__, state)
|
cur.execute("SELECT * FROM %s WHERE state = ? ORDER BY %s.'order'" % (cls.__table_name__,cls.__table_name__,), state)
|
||||||
r = cur.fetchone()
|
r = cur.fetchone()
|
||||||
if r is not None:
|
if r is not None:
|
||||||
return cls(r)
|
return cls(r)
|
||||||
@@ -54,6 +54,16 @@ class Step(DBModel):
|
|||||||
cur.execute("UPDATE %s SET stepstate = ? WHERE id =?" % cls.__table_name__, (json.dumps(state),id))
|
cur.execute("UPDATE %s SET stepstate = ? WHERE id =?" % cls.__table_name__, (json.dumps(state),id))
|
||||||
get_db().commit()
|
get_db().commit()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sort(cls, new_order):
|
||||||
|
cur = get_db().cursor()
|
||||||
|
|
||||||
|
for e in new_order:
|
||||||
|
|
||||||
|
cur.execute("UPDATE %s SET '%s' = ? WHERE id = ?" % (cls.__table_name__, "order"), (e[1], e[0]))
|
||||||
|
get_db().commit()
|
||||||
|
|
||||||
|
|
||||||
class StepView(BaseView):
|
class StepView(BaseView):
|
||||||
model = Step
|
model = Step
|
||||||
def pre_post_callback(self, data):
|
def pre_post_callback(self, data):
|
||||||
@@ -61,6 +71,14 @@ class StepView(BaseView):
|
|||||||
data["order"] = 1 if order is None else order + 1
|
data["order"] = 1 if order is None else order + 1
|
||||||
data["state"] = "I"
|
data["state"] = "I"
|
||||||
|
|
||||||
|
@route('/sort', methods=["POST"])
|
||||||
|
def sort_steps(self):
|
||||||
|
|
||||||
|
Step.sort(request.json)
|
||||||
|
|
||||||
|
cbpi.emit("UPDATE_ALL_STEPS", self.model.get_all())
|
||||||
|
return ('', 204)
|
||||||
|
|
||||||
@route('/', methods=["DELETE"])
|
@route('/', methods=["DELETE"])
|
||||||
def deleteAll(self):
|
def deleteAll(self):
|
||||||
self.model.delete_all()
|
self.model.delete_all()
|
||||||
@@ -185,8 +203,10 @@ def init_after_startup():
|
|||||||
if type_cfg is None:
|
if type_cfg is None:
|
||||||
# step type not found. cant restart step
|
# step type not found. cant restart step
|
||||||
return
|
return
|
||||||
|
|
||||||
|
print "STEP SATE......", step.stepstate
|
||||||
cfg = step.stepstate.copy()
|
cfg = step.stepstate.copy()
|
||||||
cfg.update(dict(api=cbpi, id=step.id, timer_end=None, managed_fields=get_manged_fields_as_array(type_cfg)))
|
cfg.update(dict(api=cbpi, id=step.id, managed_fields=get_manged_fields_as_array(type_cfg)))
|
||||||
instance = type_cfg.get("class")(**cfg)
|
instance = type_cfg.get("class")(**cfg)
|
||||||
instance.init()
|
instance.init()
|
||||||
cbpi.cache["active_step"] = instance
|
cbpi.cache["active_step"] = instance
|
||||||
@@ -214,9 +234,7 @@ def execute_step():
|
|||||||
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()
|
||||||
|
|
||||||
if step.is_dirty():
|
if step.is_dirty():
|
||||||
|
|
||||||
state = {}
|
state = {}
|
||||||
for field in step.managed_fields:
|
for field in step.managed_fields:
|
||||||
state[field] = step.__getattribute__(field)
|
state[field] = step.__getattribute__(field)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ def init(cbpi):
|
|||||||
cbpi.app.register_blueprint(react, url_prefix='/ui')
|
cbpi.app.register_blueprint(react, url_prefix='/ui')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@react.route('/')
|
@react.route('/')
|
||||||
def index():
|
def index():
|
||||||
return react.send_static_file("index.html")
|
return react.send_static_file("index.html")
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
.App {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
padding-right: 5px;
|
||||||
|
padding-left: 5px;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-fluid {
|
||||||
|
padding-right: 5px;
|
||||||
|
padding-left: 5px;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
+47
-48
File diff suppressed because one or more lines are too long
@@ -13,6 +13,8 @@
|
|||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
|
.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-height: 1px;
|
min-height: 1px;
|
||||||
|
|||||||
Reference in New Issue
Block a user