Advertisement
Guest User

Untitled

a guest
Feb 13th, 2020
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 9.79 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement