You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
7.4KB

  1. from proptypes import *
  2. class BaseAPI(object):
  3. def __init__(self, cbpi):
  4. self.cbpi = cbpi
  5. self.cbpi.cache[self.key] = {}
  6. def init(self):
  7. for name, value in self.cbpi.cache[self.key].iteritems():
  8. value["class"].init_global()
  9. def parseProps(self, key, cls, **options):
  10. name = cls.__name__
  11. tmpObj = cls()
  12. try:
  13. doc = tmpObj.__doc__.strip()
  14. except:
  15. doc = ""
  16. self.cbpi.cache.get(key)[name] = {"name": name, "class": cls, "description":doc, "properties": [], "actions": []}
  17. self.cbpi.cache.get(key)[name].update(options)
  18. members = [attr for attr in dir(tmpObj) if not callable(getattr(tmpObj, attr)) and not attr.startswith("__")]
  19. for m in members:
  20. t = tmpObj.__getattribute__(m)
  21. if isinstance(t, Property.Number):
  22. 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})
  23. elif isinstance(t, Property.Text):
  24. 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})
  25. elif isinstance(tmpObj.__getattribute__(m), Property.Select):
  26. self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "select", "configurable": True, "options": t.options, "description": t.description})
  27. elif isinstance(tmpObj.__getattribute__(m), Property.Actor):
  28. self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "actor", "configurable": True, "description": t.description})
  29. elif isinstance(tmpObj.__getattribute__(m), Property.Sensor):
  30. self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "sensor", "configurable": True, "description": t.description})
  31. elif isinstance(tmpObj.__getattribute__(m), Property.Kettle):
  32. self.cbpi.cache.get(key)[name]["properties"].append({"name": m, "label": t.label, "type": "kettle", "configurable": True, "description": t.description})
  33. for method_name, method in cls.__dict__.iteritems():
  34. if hasattr(method, "action"):
  35. label = method.__getattribute__("label")
  36. self.cbpi.cache.get(key)[name]["actions"].append({"method": method_name, "label": label})
  37. return cls
  38. class SensorAPI(BaseAPI):
  39. key = "sensor_types"
  40. def type(self, description="Step", **options):
  41. def decorator(f):
  42. BaseAPI.parseProps(self, self.key,f, description=description)
  43. return f
  44. return decorator
  45. def action(self, label):
  46. def real_decorator(func):
  47. func.action = True
  48. func.label = label
  49. return func
  50. return real_decorator
  51. class StepAPI(BaseAPI):
  52. key = "step_types"
  53. def init(self):
  54. pass
  55. def type(self, description="Step", **options):
  56. def decorator(f):
  57. BaseAPI.parseProps(self, self.key,f, description=description)
  58. return f
  59. return decorator
  60. def action(self, label):
  61. def real_decorator(func):
  62. func.action = True
  63. func.label = label
  64. return func
  65. return real_decorator
  66. class ActorAPI(BaseAPI):
  67. key = "actor_types"
  68. def type(self, description="", **options):
  69. def decorator(f):
  70. BaseAPI.parseProps(self, self.key, f, description=description)
  71. return f
  72. return decorator
  73. def action(self, label):
  74. def real_decorator(func):
  75. func.action = True
  76. func.label = label
  77. return func
  78. return real_decorator
  79. class KettleAPI(BaseAPI):
  80. key = "controller_types"
  81. def controller(self, description="", **options):
  82. def decorator(f):
  83. BaseAPI.parseProps(self, self.key,f,description=description)
  84. return f
  85. return decorator
  86. def action(self, label):
  87. def real_decorator(func):
  88. func.action = True
  89. func.label = label
  90. return func
  91. return real_decorator
  92. class FermenterAPI(BaseAPI):
  93. key = "fermentation_controller_types"
  94. def controller(self, description="Step", **options):
  95. def decorator(f):
  96. BaseAPI.parseProps(self, self.key,f,description=description)
  97. return f
  98. return decorator
  99. def action(self, label):
  100. def real_decorator(func):
  101. func.action = True
  102. func.label = label
  103. return func
  104. return real_decorator
  105. class CoreAPI(BaseAPI):
  106. key = "core"
  107. def __init__(self, cbpi):
  108. self.cbpi = cbpi
  109. self.cbpi.cache["actions"] = {}
  110. self.cbpi.cache["init"] = []
  111. self.cbpi.cache["js"] = {}
  112. self.cbpi.cache["background"] = []
  113. self.cbpi.cache["web_menu"] =[]
  114. def init(self):
  115. self.cbpi.cache["init"] = sorted(self.cbpi.cache["init"], key=lambda k: k['order'])
  116. for value in self.cbpi.cache.get("init"):
  117. value["function"](self.cbpi)
  118. def job(interval, method):
  119. while True:
  120. try:
  121. method(self.cbpi)
  122. except Exception as e:
  123. print e
  124. self.cbpi._socketio.sleep(interval)
  125. for value in self.cbpi.cache.get("background"):
  126. t = self.cbpi._socketio.start_background_task(target=job, interval=value.get("interval"), method=value.get("function"))
  127. def add_js(self, name, file):
  128. self.cbpi.cache["js"][name] = file
  129. def add_menu_link(self, name, path):
  130. self.cbpi.cache["web_menu"].append(dict(name=name, path=path))
  131. def initializer(self, order=0, **options):
  132. def decorator(f):
  133. self.cbpi.cache.get("init").append({"function": f, "order": order})
  134. return f
  135. return decorator
  136. def action(self, key, label, **options):
  137. def decorator(f):
  138. self.cbpi.cache.get("actions")[key] = {"label": label, "function": f}
  139. return f
  140. return decorator
  141. def backgroundjob(self, key, interval, **options):
  142. def decorator(f):
  143. self.cbpi.cache.get("background").append({"function": f, "key": key, "interval": interval})
  144. return f
  145. return decorator
  146. def listen(self, name, method=None, async=False):
  147. if method is not None:
  148. if self.cbpi.eventbus.get(name) is None:
  149. self.cbpi.eventbus[name] = []
  150. self.cbpi.eventbus[name].append({"function": method, "async": async})
  151. else:
  152. def real_decorator(function):
  153. if self.cbpi.eventbus.get(name) is None:
  154. self.cbpi.eventbus[name] = []
  155. self.cbpi.eventbus[name].append({"function": function, "async": async})
  156. def wrapper(*args, **kwargs):
  157. return function(*args, **kwargs)
  158. return wrapper
  159. return real_decorator
  160. class Buzzer(object):
  161. def beep():
  162. pass