First Version

This commit is contained in:
Manuel83
2017-06-11 17:12:22 +02:00
parent b03966562c
commit 58e927b0bf
57 changed files with 8540 additions and 1 deletions
View File
+109
View File
@@ -0,0 +1,109 @@
from flask import request, json
from flask_classy import route, FlaskView
from modules import cbpi
class BaseView(FlaskView):
as_array = False
cache_key = None
api = cbpi
@route('/<int:id>')
def getOne(self, id):
if self.api.cache.get(self.cache_key) is not None:
return json.dumps(self.api.cache.get(self.cache_key).get(id))
else:
return json.dumps(self.model.get_one(id))
@route('/')
def getAll(self):
if self.api.cache.get(self.cache_key) is not None:
return json.dumps(self.api.cache.get(self.cache_key))
else:
return json.dumps(self.model.get_all())
def pre_post_callback(self, data):
pass
def post_post_callback(self, m):
pass
@route('/', methods=["POST"])
def post(self):
data = request.json
self.pre_post_callback(data)
m = self.model.insert(**data)
if self.api.cache.get(self.cache_key) is not None:
self.api.cache.get(self.cache_key)[m.id] = m
self.post_post_callback(m)
return json.dumps(m)
def pre_put_callback(self, m):
pass
def post_put_callback(self, m):
pass
@route('/<int:id>', methods=["PUT"])
def put(self, id):
data = request.json
data["id"] = id
try:
del data["instance"]
except:
pass
if self.api.cache.get(self.cache_key) is not None:
self.pre_put_callback(self.api.cache.get(self.cache_key)[id])
self.api.cache.get(self.cache_key)[id].__dict__.update(**data)
m = self.model.update(**self.api.cache.get(self.cache_key)[id].__dict__)
self.post_put_callback(self.api.cache.get(self.cache_key)[id])
return json.dumps(self.api.cache.get(self.cache_key)[id])
else:
m = self.model.update(**data)
self.post_put_callback(m)
return json.dumps(m)
def pre_delete_callback(self, m):
pass
def post_delete_callback(self, id):
pass
@route('/<int:id>', methods=["DELETE"])
def delete(self, id):
if self.api.cache.get(self.cache_key) is not None:
self.pre_delete_callback(self.api.cache.get(self.cache_key)[id])
del self.api.cache.get(self.cache_key)[id]
m = self.model.delete(id)
def post_delete_callback(self, id):
pass
return ('',204)
@classmethod
def post_init_callback(cls, obj):
pass
@classmethod
def init_cache(cls):
with cls.api.app.app_context():
if cls.model.__as_array__ is True:
cls.api.cache[cls.cache_key] = []
for value in cls.model.get_all():
cls.post_init_callback(value)
cls.api.cache[cls.cache_key].append(value)
else:
cls.api.cache[cls.cache_key] = {}
for key, value in cls.model.get_all().iteritems():
cls.post_init_callback(value)
cls.api.cache[cls.cache_key][key] = value
+134
View File
@@ -0,0 +1,134 @@
from modules import cbpi
class ActorController(object):
@cbpi.try_catch(None)
def actor_on(self, power=100, id=None):
if id is None:
id = self.heater
self.api.switch_actor_on(int(id), power=power)
@cbpi.try_catch(None)
def actor_off(self, id=None):
if id is None:
id = self.heater
self.api.switch_actor_off(int(id))
class SensorController(object):
@cbpi.try_catch(None)
def get_sensor_value(self, id=None):
if id is None:
id = self.sensor
return cbpi.get_sensor_value(id)
class ControllerBase(object):
__dirty = False
__running = False
@staticmethod
def init_global():
print "GLOBAL CONTROLLER INIT"
def notify(self, headline, message, type="success", timeout=5000):
self.api.notify(headline, message, type, timeout)
def is_running(self):
return self.__running
def init(self):
self.__running = True
def sleep(self, seconds):
self.api.socketio.sleep(seconds)
def stop(self):
self.__running = False
def __init__(self, *args, **kwds):
for a in kwds:
super(ControllerBase, self).__setattr__(a, kwds.get(a))
self.api = kwds.get("api")
self.heater = kwds.get("heater")
self.sensor = kwds.get("sensor")
def run(self):
pass
class KettleController(ControllerBase, ActorController, SensorController):
def __init__(self, *args, **kwds):
ControllerBase.__init__(self, *args, **kwds)
self.kettle_id = kwds.get("kettle_id")
@cbpi.try_catch(None)
def heater_on(self, power=100):
k = self.api.cache.get("kettle").get(self.kettle_id)
if k.heater is not None:
self.actor_on(power, int(k.heater))
@cbpi.try_catch(None)
def heater_off(self):
k = self.api.cache.get("kettle").get(self.kettle_id)
if k.heater is not None:
self.actor_off(int(k.heater))
@cbpi.try_catch(None)
def get_temp(self, id=None):
if id is None:
id = self.kettle_id
return self.get_sensor_value(int(self.api.cache.get("kettle").get(id).sensor))
@cbpi.try_catch(None)
def get_target_temp(self, id=None):
if id is None:
id = self.kettle_id
return self.api.cache.get("kettle").get(id).target_temp
class FermenterController(ControllerBase, ActorController, SensorController):
def __init__(self, *args, **kwds):
ControllerBase.__init__(self, *args, **kwds)
self.fermenter_id = kwds.get("fermenter_id")
self.cooler = kwds.get("cooler")
@cbpi.try_catch(None)
def get_target_temp(self, id=None):
if id is None:
id = self.fermenter_id
return self.api.cache.get("fermenter").get(id).target_temp
@cbpi.try_catch(None)
def heater_on(self, power=100):
f = self.api.cache.get("fermenter").get(self.fermenter_id)
if k.heater is not None:
self.actor_on(int(f.heater))
@cbpi.try_catch(None)
def heater_off(self):
f = self.api.cache.get("fermenter").get(self.fermenter_id)
if k.heater is not None:
self.actor_off(int(f.heater))
@cbpi.try_catch(None)
def get_temp(self, id=None):
if id is None:
id = self.fermenter_id
return self.get_sensor_value(int(self.api.cache.get("fermenter").get(id).sensor))
+452
View File
@@ -0,0 +1,452 @@
import pprint
import sqlite3
from flask import make_response, g
import datetime
from datetime import datetime
from flask.views import MethodView
from flask_classy import FlaskView, route
from flask_sqlalchemy import SQLAlchemy
from time import localtime, strftime
from functools import wraps, update_wrapper
from props import *
from hardware import *
import time
import uuid
class NotificationAPI(object):
pass
class ActorAPI(object):
def init_actors(self):
self.app.logger.info("Init Actors")
t = self.cache.get("actor_types")
for key, value in t.iteritems():
value.get("class").init_global()
for key in self.cache.get("actors"):
self.init_actor(key)
def init_actor(self, id):
try:
value = self.cache.get("actors").get(int(id))
cfg = value.config.copy()
cfg.update(dict(api=self, id=id, name=value.name))
cfg.update(dict(api=self, id=id, name=value.name))
clazz = self.cache.get("actor_types").get(value.type).get("class")
value.instance = clazz(**cfg)
value.instance.init()
value.state = 0
value.power = 100
except Exception as e:
self.notify("Actor Error", "Failed to setup actor %s. Please check the configuraiton" % value.name,
type="danger", timeout=None)
self.app.logger.error("Initializing of Actor %s failed" % id)
def switch_actor_on(self, id, power=None):
actor = self.cache.get("actors").get(id)
if actor.state == 1:
return
actor.instance.on(power=power)
actor.state = 1
if power is not None:
actor.power = power
self.emit("SWITCH_ACTOR", actor)
def actor_power(self, id, power=100):
actor = self.cache.get("actors").get(id)
actor.instance.set_power(power=power)
actor.power = power
self.emit("SWITCH_ACTOR", actor)
def switch_actor_off(self, id):
actor = self.cache.get("actors").get(id)
if actor.state == 0:
return
actor.instance.off()
actor.state = 0
self.emit("SWITCH_ACTOR", actor)
class SensorAPI(object):
def init_sensors(self):
'''
Initialize all sensors
:return:
'''
self.app.logger.info("Init Sensors")
t = self.cache.get("sensor_types")
for key, value in t.iteritems():
value.get("class").init_global()
for key in self.cache.get("sensors"):
self.init_sensor(key)
def stop_sensor(self, id):
try:
self.cache.get("sensors").get(id).instance.stop()
except Exception as e:
self.app.logger.info("Stop Sensor Error")
pass
def init_sensor(self, id):
'''
initialize sensor by id
:param id:
:return:
'''
def start_active_sensor(instance):
'''
start active sensors as background job
:param instance:
:return:
'''
instance.execute()
try:
if id in self.cache.get("sensor_instances"):
self.cache.get("sensor_instances").get(id).stop()
value = self.cache.get("sensors").get(id)
cfg = value.config.copy()
cfg.update(dict(api=self, id=id, name=value.name))
clazz = self.cache.get("sensor_types").get(value.type).get("class")
value.instance = clazz(**cfg)
value.instance.init()
if isinstance(value.instance, SensorPassive):
# Passive Sensors
value.mode = "P"
else:
# Active Sensors
value.mode = "A"
t = self.socketio.start_background_task(target=start_active_sensor, instance=value.instance)
except Exception as e:
self.notify("Sensor Error", "Failed to setup Sensor %s. Please check the configuraiton" % value.name, type="danger", timeout=None)
self.app.logger.error("Initializing of Sensor %s failed" % id)
def receive_sensor_value(self, id, value):
self.emit("SENSOR_UPDATE", self.cache.get("sensors")[id])
self.save_to_file(id, value)
def save_to_file(self, id, value, prefix="sensor"):
filename = "./logs/%s_%s.log" % (prefix, str(id))
formatted_time = strftime("%Y-%m-%d %H:%M:%S", localtime())
msg = str(formatted_time) + "," +str(value) + "\n"
with open(filename, "a") as file:
file.write(msg)
def log_action(self, text):
filename = "./logs/action.log"
formatted_time = strftime("%Y-%m-%d %H:%M:%S", localtime())
with open(filename, "a") as file:
file.write("%s,%s\n" % (formatted_time, text))
def shutdown_sensor(self, id):
self.cache.get("sensors")[id].stop()
def get_sensor_value(self, id):
try:
id = int(id)
return int(self.cache.get("sensors")[id].instance.last_value)
except Exception as e:
return None
class CacheAPI(object):
def get_sensor(self, id):
try:
return self.cache["sensors"][id]
except:
return None
def get_actor(self, id):
try:
return self.cache["actors"][id]
except:
return None
class CraftBeerPi(ActorAPI, SensorAPI):
cache = {
"init": {},
"config": {},
"actor_types": {},
"sensor_types": {},
"sensors": {},
"sensor_instances": {},
"init": [],
"background":[],
"step_types": {},
"controller_types": {},
"messages": [],
"plugins": {},
"fermentation_controller_types": {},
"fermenter_task": {}
}
buzzer = None
eventbus = {}
# constructor
def __init__(self, app, socketio):
self.app = app
self.socketio = socketio
def emit(self, key, data):
self.socketio.emit(key, data, namespace='/brew')
def notify(self, headline, message, type="success", timeout=5000):
self.beep()
msg = {"id": str(uuid.uuid1()), "type": type, "headline": headline, "message": message, "timeout": timeout}
if timeout is None:
self.cache["messages"].append(msg)
self.emit("NOTIFY", msg)
def beep(self):
if self.buzzer is not None:
self.buzzer.beep()
def add_cache_callback(self, key, method):
method.callback = True
self.cache[key] = method
def get_config_parameter(self, key, default):
cfg = self.cache.get("config").get(key)
if cfg is None:
return default
else:
return cfg.value
def clear_cache(self, key, is_array=False):
if is_array:
self.cache[key] = []
else:
self.cache[key] = {}
# helper method for parsing props
def __parseProps(self, key, cls):
name = cls.__name__
self.cache[key][name] = {"name": name, "class": cls, "properties": []}
tmpObj = cls()
members = [attr for attr in dir(tmpObj) if not callable(getattr(tmpObj, attr)) and not attr.startswith("__")]
for m in members:
if isinstance(tmpObj.__getattribute__(m), Property.Number):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append(
{"name": m, "label": t.label, "type": "number", "configurable": t.configurable})
elif isinstance(tmpObj.__getattribute__(m), Property.Text):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append(
{"name": m, "label": t.label, "type": "text", "configurable": t.configurable})
elif isinstance(tmpObj.__getattribute__(m), Property.Select):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append(
{"name": m, "label": t.label, "type": "select", "configurable": True, "options": t.options})
return cls
def actor(self, cls):
return self.__parseProps("actor_types", cls)
def sensor(self, cls):
return self.__parseProps("sensor_types", cls)
def controller(self, cls):
return self.__parseProps("controller_types", cls)
def fermentation_controller(self, cls):
return self.__parseProps("fermentation_controller_types", cls)
def get_controller(self, name):
return self.cache["controller_types"].get(name)
def get_fermentation_controller(self, name):
return self.cache["fermentation_controller_types"].get(name)
# Step action
def action(self,label):
def real_decorator(func):
func.action = True
func.label = label
return func
return real_decorator
# step decorator
def step(self, cls):
key = "step_types"
name = cls.__name__
self.cache[key][name] = {"name": name, "class": cls, "properties": [], "actions": []}
tmpObj = cls()
members = [attr for attr in dir(tmpObj) if not callable(getattr(tmpObj, attr)) and not attr.startswith("__")]
for m in members:
if isinstance(tmpObj.__getattribute__(m), StepProperty.Number):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "number", "configurable": t.configurable})
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Text):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "text", "configurable": t.configurable})
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Select):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "select", "options": t.options})
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Actor):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "actor", "configurable": t.configurable})
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Sensor):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "sensor", "configurable": t.configurable})
elif isinstance(tmpObj.__getattribute__(m), StepProperty.Kettle):
t = tmpObj.__getattribute__(m)
self.cache[key][name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": t.configurable})
for name, method in cls.__dict__.iteritems():
if hasattr(method, "action"):
label = method.__getattribute__("label")
self.cache[key][cls.__name__]["actions"].append({"method": name, "label": label})
return cls
# Event Bus
def event(self, name, async=False):
def real_decorator(function):
if self.eventbus.get(name) is None:
self.eventbus[name] = []
self.eventbus[name].append({"function": function, "async": async})
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
return real_decorator
def emit_message(self, message):
self.emit_event(name="MESSAGE", message=message)
def emit_event(self, name, **kwargs):
for i in self.eventbus.get(name, []):
if i["async"] is False:
i["function"](**kwargs)
else:
t = self.socketio.start_background_task(target=i["function"], **kwargs)
# initializer decorator
def initalizer(self, order=0):
def real_decorator(function):
self.cache["init"].append({"function": function, "order": order})
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
return real_decorator
def try_catch(self, errorResult="ERROR"):
def real_decorator(function):
def wrapper(*args, **kwargs):
try:
return function(*args, **kwargs)
except:
self.app.logger.error("Exception in function %s. Return default %s" % (function.__name__, errorResult))
return errorResult
return wrapper
return real_decorator
def nocache(self, view):
@wraps(view)
def no_cache(*args, **kwargs):
response = make_response(view(*args, **kwargs))
response.headers['Last-Modified'] = datetime.now()
response.headers[
'Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '-1'
return response
return update_wrapper(no_cache, view)
def init_kettle(self, id):
try:
value = self.cache.get("kettle").get(id)
value["state"] = False
except:
self.notify("Kettle Setup Faild", "Please check %s configuration" % value.name, type="danger", timeout=None)
self.app.logger.error("Initializing of Kettle %s failed" % id)
def run_init(self):
'''
call all initialziers after startup
:return:
'''
self.app.logger.info("Invoke Init")
self.cache["init"] = sorted(self.cache["init"], key=lambda k: k['order'])
for i in self.cache.get("init"):
self.app.logger.info("-> %s " % i.get("function").__name__)
i.get("function")(self)
def backgroundtask(self, key, interval, config_parameter=None):
'''
Background Task Decorator
:param key:
:param interval:
:param config_parameter:
:return:
'''
def real_decorator(function):
self.cache["background"].append({"function": function, "key": key, "interval": interval, "config_parameter": config_parameter})
def wrapper(*args, **kwargs):
return function(*args, **kwargs)
return wrapper
return real_decorator
def run_background_processes(self):
'''
call all background task after startup
:return:
'''
self.app.logger.info("Start Background")
def job(interval, method):
while True:
try:
method()
except Exception as e:
self.app.logger.error("Exception" + method.__name__ + ": " + str(e))
self.socketio.sleep(interval)
for value in self.cache.get("background"):
t = self.socketio.start_background_task(target=job, interval=value.get("interval"), method=value.get("function"))
+115
View File
@@ -0,0 +1,115 @@
import sqlite3
from flask import json, g
def get_db():
db = getattr(g, '_database', None)
if db is None:
def dict_factory(cursor, row):
d = {}
for idx, col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
db = g._database = sqlite3.connect('craftbeerpi.db')
db.row_factory = dict_factory
return db
class DBModel(object):
__priamry_key__ = "id"
__as_array__ = False
__order_by__ = None
__json_fields__ = []
def __init__(self, args):
self.__setattr__(self.__priamry_key__, args.get(self.__priamry_key__))
for f in self.__fields__:
if f in self.__json_fields__:
if args.get(f) is not None:
if isinstance(args.get(f) , dict) or isinstance(args.get(f) , list) :
self.__setattr__(f, args.get(f))
else:
self.__setattr__(f, json.loads(args.get(f)))
else:
self.__setattr__(f, None)
else:
self.__setattr__(f, args.get(f))
@classmethod
def get_all(cls):
cur = get_db().cursor()
if cls.__order_by__ is not None:
cur.execute("SELECT * FROM %s ORDER BY '%s'" % (cls.__table_name__,cls.__order_by__))
else:
cur.execute("SELECT * FROM %s" % cls.__table_name__)
if cls.__as_array__ is True:
result = []
for r in cur.fetchall():
result.append( cls(r))
else:
result = {}
for r in cur.fetchall():
result[r.get(cls.__priamry_key__)] = cls(r)
return result
@classmethod
def get_one(cls, id):
cur = get_db().cursor()
cur.execute("SELECT * FROM %s WHERE %s = ?" % (cls.__table_name__, cls.__priamry_key__), (id,))
r = cur.fetchone()
if r is not None:
return cls(r)
else:
return None
@classmethod
def delete(cls, id):
cur = get_db().cursor()
cur.execute("DELETE FROM %s WHERE %s = ? " % (cls.__table_name__, cls.__priamry_key__), (id,))
get_db().commit()
@classmethod
def insert(cls, **kwargs):
cur = get_db().cursor()
query = 'INSERT INTO %s (%s) VALUES (%s)' % (
cls.__table_name__,
', '.join("'%s'" % str(x) for x in cls.__fields__),
', '.join(['?'] * len(cls.__fields__)))
data = ()
for f in cls.__fields__:
if f in cls.__json_fields__:
data = data + (json.dumps(kwargs.get(f)),)
else:
data = data + (kwargs.get(f),)
cur.execute(query, data)
get_db().commit()
i = cur.lastrowid
kwargs["id"] = i
return cls(kwargs)
@classmethod
def update(cls, **kwargs):
cur = get_db().cursor()
query = 'UPDATE %s SET %s WHERE %s = ?' % (
cls.__table_name__,
', '.join("'%s' = ?" % str(x) for x in cls.__fields__),cls.__priamry_key__)
data = ()
for f in cls.__fields__:
if f in cls.__json_fields__:
data = data + (json.dumps(kwargs.get(f)),)
else:
data = data + (kwargs.get(f),)
data = data + (kwargs.get(cls.__priamry_key__),)
cur.execute(query, data)
get_db().commit()
return cls(kwargs)
+104
View File
@@ -0,0 +1,104 @@
# -*- coding: utf-8 -*-
class Base(object):
__dirty = False
@classmethod
def init_global(cls):
print "GLOBAL ACTOR INIT"
def get_config_parameter(self, key, default_value):
return self.api.get_config_parameter(key, default_value)
def init(self):
print "INIT BASE"
def stop(self):
print "STOP HARDWARE"
def update(self, **kwds):
pass
def __init__(self, *args, **kwds):
for a in kwds:
super(Base, self).__setattr__(a, kwds.get(a))
self.api = kwds.get("api")
self.id = kwds.get("id")
self.value = None
self.__dirty = False
def __setattr__(self, name, value):
if name != "_Base__dirty":
self.__dirty = True
super(Base, self).__setattr__(name, value)
else:
super(Base, self).__setattr__(name, value)
class SensorBase(Base):
last_value = 0
def init(self):
print "INIT Base SENSOR"
def stop(self):
print "STOP SENSOR"
def data_received(self, data):
self.last_value = data
self.api.receive_sensor_value(self.id, data)
def get_unit(self):
if self.get_config_parameter("unit", "C") == "C":
return "°C"
else:
return "°F"
def get_value(self):
return {"value": self.last_value, "unit": self.get_unit()}
class SensorActive(SensorBase):
__running = False
def is_running(self):
return self.__running
def init(self):
self.__running = True
print "INIT ACTIVE SENSOR"
def stop(self):
self.__running = False
def execute(self):
pass
class SensorPassive(SensorBase):
def init(self):
print "INIT PASSIV SENSOR"
pass
def read(self):
return 0
class ActorBase(Base):
def state(self):
return 1
def set_power(self, power):
print "SET POWER TO %s" % power
def on(self, power=0):
print "ON"
def off(self):
print "OFF"
+38
View File
@@ -0,0 +1,38 @@
class PropertyType(object):
pass
class Property(object):
class Select(PropertyType):
def __init__(self, label, options):
PropertyType.__init__(self)
self.label = label
self.options = options
class Number(PropertyType):
def __init__(self, label, configurable=False, default_value=0, unit=""):
PropertyType.__init__(self)
self.label = label
self.configurable = configurable
class Text(PropertyType):
def __init__(self, label, configurable=False, default_value=""):
PropertyType.__init__(self)
self.label = label
self.configurable = configurable
class StepProperty(Property):
class Actor(PropertyType):
def __init__(self, label):
PropertyType.__init__(self)
self.label = label
self.configurable = True
class Sensor(PropertyType):
def __init__(self, label):
PropertyType.__init__(self)
self.label = label
self.configurable = True
class Kettle(PropertyType):
def __init__(self, label):
PropertyType.__init__(self)
self.label = label
self.configurable = True
+132
View File
@@ -0,0 +1,132 @@
from modules import cbpi
from modules.core.props import StepProperty, Property
import time
class NotificationAPI(object):
def notify(self, headline, message, type="success", timeout=5000):
self.api.notify(headline, message, type, timeout)
class ActorAPI(NotificationAPI):
@cbpi.try_catch(None)
def actor_on(self, id, power=100):
self.api.switch_actor_on(int(id), power=power)
@cbpi.try_catch(None)
def actor_off(self, id):
self.api.switch_actor_off(int(id))
class SensorAPI(NotificationAPI):
@cbpi.try_catch(None)
def get_sensor_value(self, id):
return cbpi.get_sensor_value(id)
class KettleAPI(NotificationAPI):
@cbpi.try_catch(None)
def get_kettle_temp(self, id=None):
id = int(id)
if id is None:
id = self.kettle_id
return cbpi.get_sensor_value(int(self.api.cache.get("kettle").get(id).sensor))
@cbpi.try_catch(None)
def get_target_temp(self, id=None):
id = int(id)
if id is None:
id = self.kettle_id
return self.api.cache.get("kettle").get(id).target_temp
def set_target_temp(self, temp, id=None):
temp = int(temp)
try:
if id is None:
self.api.emit_event("SET_TARGET_TEMP", id=self.kettle_id, temp=temp)
else:
self.api.emit_event("SET_TARGET_TEMP", id=id, temp=temp)
except Exception as e:
self.notify("Faild to set Target Temp", "", type="warning")
class Timer(object):
timer_end = Property.Number("TIMER_END", configurable=False)
def start_timer(self, timer):
if self.timer_end is not None:
return
self.timer_end = int(time.time()) + timer
def stop_timer(self):
if self.timer_end is not None:
self.timer_end = None
def is_timer_running(self):
if self.timer_end is not None:
return True
else:
return False
def is_timer_finished(self):
if self.timer_end is None:
return None
if self.timer_end <= int(time.time()):
return True
else:
return False
class StepBase(Timer, ActorAPI, SensorAPI, KettleAPI):
__dirty = False
managed_fields = []
n = False
def next(self):
self.n = True
def init(self):
print "INIT STEP"
def finish(self):
print "FINSIH STEP"
def reset(self):
print "REST STEP"
def execute(self):
print "-------------"
print "Step Info"
print "Kettle ID: %s" % self.kettle_id
print "ID: %s" % self.id
def __init__(self, *args, **kwds):
for a in kwds:
super(StepBase, self).__setattr__(a, kwds.get(a))
self.api = kwds.get("api")
self.id = kwds.get("id")
self.name = kwds.get("name")
self.kettle_id = kwds.get("kettleid")
self.value = None
self.__dirty = False
def is_dirty(self):
return self.__dirty
def reset_dirty(self):
self.__dirty = False
def __setattr__(self, name, value):
if name != "_StepBase__dirty" and name in self.managed_fields:
self.__dirty = True
super(StepBase, self).__setattr__(name, value)
else:
super(StepBase, self).__setattr__(name, value)