SHARE
TWEET

Untitled

a guest Feb 13th, 2020 5 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import appdaemon.plugins.hass.hassapi as hass
  2. import math
  3. import time
  4. #
  5. # Maps HUE lights to the KNX bus
  6. #
  7. # Args:
  8. #
  9.  
  10. class Hue2Knx(hass.Hass):
  11.  
  12.     DIM_STEP_SIZE = 12.7
  13.     DIM_DELAY = 0.3
  14.     BRIGHTNESS_MAX = 254
  15.     BRIGHTNESS_MIN = 0
  16.  
  17.     HSV_STEP_SIZE = 12
  18.     HSV_DELAY = 0.3
  19.     HSV_MODE_HUE = 1
  20.     HSV_MODE_SATURATION = 2
  21.     HUE_MAX = 360
  22.     HUE_MIN = 0
  23.     SATURATION_MAX = 100
  24.     SATURATION_MIN = 0
  25.  
  26.     KNX_MODE_INCREASE = 9
  27.     KNX_MODE_DECREASE = 1
  28.     KNX_MODE_END = 0
  29.     KNX_MAX_VALUE = 255
  30.     KNX_MIN_VALUE = 0
  31.  
  32.  
  33.  
  34.     def initialize(self):
  35.         self._state = ""
  36.         self._brightness = 0
  37.         self._hue = False
  38.         self._saturation = False
  39.         self._isDimming = False
  40.         self._isChangingColor = False
  41.         self._dimHandle = False
  42.         self._hsvHandle = False
  43.  
  44.         # init states
  45.         states = self.get_state(self.args["entity"], attribute="all")["attributes"]
  46.         if ("brightness" in states):
  47.             self._brightness = states["brightness"]
  48.         if ("hs_color" in states):
  49.             self._hue = int(states["hs_color"][0])
  50.             self._saturation = int(states["hs_color"][1])
  51.  
  52.         # register listeners
  53.         self._stateListener = self.listen_state(self.light_changed, entity = self.args["entity"], attribue = "all")
  54.         self._eventListener = self.listen_event(self.event_triggered, "knx_event")
  55.  
  56.     def terminate(self):
  57.         self.clear_timer(self._dimHandle)
  58.         self.clear_timer(self._hsvHandle)
  59.         self.cancel_listen_state(self._stateListener)
  60.         self.cancel_listen_event(self._eventListener)
  61.  
  62.     # HASS EVENT
  63.     def light_changed(self, entity, attribute, old, new, kwargs):
  64.         states = self.get_state(self.args["entity"], attribute="all")["attributes"]
  65.         #self.log(states)
  66.         if (new != self._state):
  67.             self._state = new
  68.             state = 1 if new == "on" else 0
  69.             self.update_knx_value("stateAddress", state, 0, 1)
  70.             # KNX switches that can dimm need a brightness of 0 in the "off" state to correctly show the lights state
  71.             if (state == 0):
  72.                 states["brightness"] = self.BRIGHTNESS_MIN
  73.  
  74.         if ("brightnessAddress" in self.args and "brightness" in states):
  75.             brightness = int(states["brightness"])
  76.             if (self._brightness != brightness and self._isDimming == False):
  77.                 self._brightness = brightness
  78.                 self.update_knx_value("brightnessAddress", brightness, self.BRIGHTNESS_MIN, self.BRIGHTNESS_MAX)
  79.  
  80.         if ("hueStateAddress" in self.args and "hs_color" in states):
  81.             hue = int(states["hs_color"][0])
  82.             if (self._hue != hue and self._isChangingColor == False):
  83.                 self._hue = hue
  84.                 self.update_knx_value("hueStateAddress", hue, self.HUE_MIN, self.HUE_MAX)
  85.  
  86.         if ("saturationStateAddress" in self.args and "hs_color" in states):
  87.             saturation = int(states["hs_color"][1])
  88.             if (self._saturation != saturation and self._isChangingColor == False):
  89.                 self._saturation = saturation
  90.                 self.update_knx_value("saturationStateAddress", saturation, self.SATURATION_MIN, self.SATURATION_MAX)
  91.  
  92.     # KNX event
  93.     def event_triggered(self, event, payload, kwargs):
  94.         value = payload["data"]
  95.         address = payload["address"]
  96.         #self.log(["knx event", value, address])
  97.  
  98.         # handle button presses and toogle the light
  99.         if ("toggleAddress" in self.args and address == self.args["toggleAddress"]):
  100.             mode = "turn_on" if int(value) == 1 else "turn_off"
  101.             self.call_service("light/" + mode, entity_id=self.args["entity"])
  102.  
  103.         # handle dimming of the lights
  104.         elif ("dimmAddress" in self.args and address == self.args["dimmAddress"]):
  105.             value = int(value)
  106.             self.clear_timer(self._dimHandle)
  107.             self._isDimming = False
  108.             if (value != self.KNX_MODE_END):
  109.                 if (self._brightness == self.BRIGHTNESS_MAX and value == self.KNX_MODE_INCREASE):
  110.                     return
  111.                 elif (self._brightness == self.BRIGHTNESS_MIN and value == self.KNX_MODE_DECREASE):
  112.                     return
  113.  
  114.                 self._isDimming = True
  115.  
  116.                 direction = 1 if value == self.KNX_MODE_INCREASE else -1
  117.                 step = self.DIM_STEP_SIZE * direction
  118.                 self.dim_light({"step": step})
  119.  
  120.         # handle color cycle
  121.         elif ("hueAddress" in self.args and address == self.args["hueAddress"]):
  122.             value = int(value)
  123.             self.clear_timer(self._hsvHandle)
  124.             self._isChangingColor = False
  125.             if (value != self.KNX_MODE_END):
  126.                 if (self._hue == self.HUE_MAX and value == self.KNX_MODE_INCREASE):
  127.                     return
  128.                 elif (self._hue == self.HUE_MIN and value == self.KNX_MODE_DECREASE):
  129.                     return
  130.  
  131.                 self._isChangingColor = True
  132.  
  133.                 direction = 1 if value == self.KNX_MODE_INCREASE else -1
  134.                 step = self.HSV_STEP_SIZE * direction
  135.                 self.tune_color({"step": step, "mode": self.HSV_MODE_HUE})
  136.  
  137.         # handle saturation changes
  138.         elif ("saturationAddress" in self.args and address == self.args["saturationAddress"]):
  139.             value = int(value)
  140.             self.clear_timer(self._hsvHandle)
  141.             self._isChangingColor = False
  142.             if (value != self.KNX_MODE_END):
  143.                 if (self._saturation == self.SATURATION_MAX and value == self.KNX_MODE_INCREASE):
  144.                     return
  145.                 elif (self._saturation == self.SATURATION_MIN and value == self.KNX_MODE_DECREASE):
  146.                     return
  147.  
  148.                 self._isChangingColor = True
  149.  
  150.                 direction = 1 if value == self.KNX_MODE_INCREASE else -1
  151.                 step = self.HSV_STEP_SIZE * direction
  152.                 self.tune_color({"step": step, "mode": self.HSV_MODE_SATURATION})
  153.  
  154.     def dim_light(self, kwargs):
  155.         self.clear_timer(self._dimHandle);
  156.         lastCycle = time.time();
  157.         while (self._isDimming):
  158.             if (lastCycle + self.DIM_DELAY > time.time()):
  159.                 time.sleep(0.1);
  160.                 continue;
  161.  
  162.             brightness = min( max(self.BRIGHTNESS_MIN, self._brightness + kwargs["step"]), self.BRIGHTNESS_MAX)
  163.             if (brightness == self._brightness):
  164.                 return
  165.                
  166.             self._brightness = brightness;
  167.             #self.log(["dim light via KNX", self._brightness])
  168.             # update KNX right here, to get feedback there ASAP
  169.             self.update_knx_value("brightnessAddress", self._brightness, self.BRIGHTNESS_MIN, self.BRIGHTNESS_MAX)
  170.             self.set_light_properties({"brightness":self._brightness})
  171.             #self._dimHandle = self.run_in(self.dim_light, self.DIM_DELAY, **kwargs)
  172.  
  173.     def tune_color(self, kwargs):
  174.         self.clear_timer(self._hsvHandle);
  175.         lastCycle = time.time();
  176.         while (self._isChangingColor):
  177.             if (lastCycle + self.HSV_DELAY > time.time()):
  178.                 time.sleep(0.1);
  179.                 continue;
  180.  
  181.             lastCycle = time.time();
  182.        
  183.             if (self._saturation == False or self._hue == False):
  184.                 states = self.get_state(self.args["entity"], attribute="all")["attributes"]
  185.                 self._hue = int(states["hs_color"][0])
  186.                 self._saturation = int(states["hs_color"][1])
  187.  
  188.             if (kwargs["mode"] == self.HSV_MODE_HUE):
  189.                 hue = min( max(self.HUE_MIN, self._hue + kwargs["step"]), self.HUE_MAX)
  190.                 if (hue == self._hue):
  191.                     return
  192.                 self._hue = hue
  193.                 # update KNX right here, to get feedback there ASAP
  194.                 self.update_knx_value("hueStateAddress", self._hue, self.HUE_MIN, self.HUE_MAX)
  195.  
  196.             if (kwargs["mode"] == self.HSV_MODE_SATURATION):
  197.                 saturation = min( max(self.SATURATION_MIN, self._saturation + kwargs["step"]), self.SATURATION_MAX)
  198.                 if (saturation == self._saturation):
  199.                     return
  200.                 self._saturation = saturation
  201.                 # update KNX right here, to get feedback there ASAP
  202.                 self.update_knx_value("saturationStateAddress", self._saturation, self.SATURATION_MIN, self.SATURATION_MAX)
  203.  
  204.             #self.log(["set hsv via KNX", self._hue, self._saturation])
  205.             self.set_light_properties({"hs_color":[self._hue, self._saturation]})
  206.             #self._hsvHandle = self.run_in(self.tune_color, self.HSV_DELAY, **kwargs)
  207.  
  208.     def update_knx_value(self, groupAddress, value, min, max):
  209.         sanitizedValue = self.sanitize_knx_value(value, min, max)
  210.         #self.log(["update KNX status [addressType, value, sanitized value]", groupAddress, value, sanitizedValue])
  211.         self.call_service("knx/send", address=self.args[groupAddress], payload=[sanitizedValue])
  212.  
  213.     def sanitize_knx_value(self, value, minVal, maxVal):
  214.         sanitizedValue = max(minVal, value)
  215.         if (maxVal != self.KNX_MAX_VALUE):
  216.             if (value == maxVal):
  217.                 sanitizedValue = self.KNX_MAX_VALUE
  218.             elif (value == minVal):
  219.                 sanitizedValue = self.KNX_MIN_VALUE
  220.             else :
  221.                 sanitizedValue = min( math.ceil(self.KNX_MAX_VALUE / maxVal * sanitizedValue), self.KNX_MAX_VALUE )
  222.         #self.log(["sanitized knx value",value, sanitizedValue])
  223.         return sanitizedValue
  224.  
  225.     def set_light_properties(self, kwargs):
  226.         kwargs["entity_id"] = self.args["entity"]
  227.         self.call_service("light/turn_on", **kwargs)
  228.  
  229.     def clear_timer(self, handle):
  230.         if (handle):
  231.             self.cancel_timer(handle)
  232.             handle = False
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top