mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 03:07:37 +00:00
Homekit: Use util functions for unit conversion (#13253)
* Updated to util/color for conversion * Updated temperature sensor to use util/temperature conversion
This commit is contained in:
parent
99f7e2bd97
commit
f6ae2d338d
@ -5,6 +5,7 @@ from homeassistant.components.light import (
|
||||
ATTR_RGB_COLOR, ATTR_BRIGHTNESS,
|
||||
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR)
|
||||
from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_ON, STATE_OFF
|
||||
from homeassistant.util.color import color_RGB_to_hsv, color_hsv_to_RGB
|
||||
|
||||
from . import TYPES
|
||||
from .accessories import HomeAccessory, add_preload_service
|
||||
@ -17,69 +18,6 @@ _LOGGER = logging.getLogger(__name__)
|
||||
RGB_COLOR = 'rgb_color'
|
||||
|
||||
|
||||
class Color:
|
||||
"""Class to handle color conversions."""
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
|
||||
def __init__(self, hue=None, saturation=None):
|
||||
"""Initialize a new Color object."""
|
||||
self.hue = hue # [0, 360]
|
||||
self.saturation = saturation # [0, 1]
|
||||
|
||||
def calc_hsv_to_rgb(self):
|
||||
"""Convert hsv_color value to rgb_color."""
|
||||
if not self.hue or not self.saturation:
|
||||
return [None] * 3
|
||||
|
||||
i = int(self.hue / 60)
|
||||
f = self.hue / 60 - i
|
||||
v = 1
|
||||
p = 1 - self.saturation
|
||||
q = 1 - self.saturation * f
|
||||
t = 1 - self.saturation * (1 - f)
|
||||
|
||||
rgb = []
|
||||
if i in [0, 6]:
|
||||
rgb = [v, t, p]
|
||||
elif i == 1:
|
||||
rgb = [q, v, p]
|
||||
elif i == 2:
|
||||
rgb = [p, v, t]
|
||||
elif i == 3:
|
||||
rgb = [p, q, v]
|
||||
elif i == 4:
|
||||
rgb = [t, p, v]
|
||||
elif i == 5:
|
||||
rgb = [v, p, q]
|
||||
|
||||
return [round(c * 255) for c in rgb]
|
||||
|
||||
@classmethod
|
||||
def calc_rgb_to_hsv(cls, rgb_color):
|
||||
"""Convert a give rgb_color back to a hsv_color."""
|
||||
rgb_color = [c / 255 for c in rgb_color]
|
||||
c_max = max(rgb_color)
|
||||
c_min = min(rgb_color)
|
||||
c_diff = c_max - c_min
|
||||
r, g, b = rgb_color
|
||||
|
||||
hue, saturation = 0, 0
|
||||
if c_max == r:
|
||||
hue = 60 * (0 + (g - b) / c_diff)
|
||||
elif c_max == g:
|
||||
hue = 60 * (2 + (b - r) / c_diff)
|
||||
elif c_max == b:
|
||||
hue = 60 * (4 + (r - g) / c_diff)
|
||||
|
||||
hue = round(hue + 360) if hue < 0 else round(hue)
|
||||
|
||||
if c_max != 0:
|
||||
saturation = round((c_max - c_min) / c_max * 100)
|
||||
|
||||
return (hue, saturation)
|
||||
|
||||
|
||||
@TYPES.register('Light')
|
||||
class Light(HomeAccessory):
|
||||
"""Generate a Light accessory for a light entity.
|
||||
@ -97,8 +35,6 @@ class Light(HomeAccessory):
|
||||
CHAR_HUE: False, CHAR_SATURATION: False,
|
||||
RGB_COLOR: False}
|
||||
|
||||
self.color = Color()
|
||||
|
||||
self.chars = []
|
||||
self._features = self._hass.states.get(self._entity_id) \
|
||||
.attributes.get(ATTR_SUPPORTED_FEATURES)
|
||||
@ -107,6 +43,8 @@ class Light(HomeAccessory):
|
||||
if self._features & SUPPORT_RGB_COLOR:
|
||||
self.chars.append(CHAR_HUE)
|
||||
self.chars.append(CHAR_SATURATION)
|
||||
self._hue = None
|
||||
self._saturation = None
|
||||
|
||||
serv_light = add_preload_service(self, SERV_LIGHTBULB, self.chars)
|
||||
self.char_on = serv_light.get_characteristic(CHAR_ON)
|
||||
@ -152,14 +90,14 @@ class Light(HomeAccessory):
|
||||
"""Set saturation if call came from HomeKit."""
|
||||
_LOGGER.debug('%s: Set saturation to %d', self._entity_id, value)
|
||||
self._flag[CHAR_SATURATION] = True
|
||||
self.color.saturation = value / 100
|
||||
self._saturation = value
|
||||
self.set_color()
|
||||
|
||||
def set_hue(self, value):
|
||||
"""Set hue if call came from HomeKit."""
|
||||
_LOGGER.debug('%s: Set hue to %d', self._entity_id, value)
|
||||
self._flag[CHAR_HUE] = True
|
||||
self.color.hue = value
|
||||
self._hue = value
|
||||
self.set_color()
|
||||
|
||||
def set_color(self):
|
||||
@ -167,7 +105,7 @@ class Light(HomeAccessory):
|
||||
# Handle RGB Color
|
||||
if self._features & SUPPORT_RGB_COLOR and self._flag[CHAR_HUE] and \
|
||||
self._flag[CHAR_SATURATION]:
|
||||
color = self.color.calc_hsv_to_rgb()
|
||||
color = color_hsv_to_RGB(self._hue, self._saturation, 100)
|
||||
_LOGGER.debug('%s: Set rgb_color to %s', self._entity_id, color)
|
||||
self._flag.update({
|
||||
CHAR_HUE: False, CHAR_SATURATION: False, RGB_COLOR: True})
|
||||
@ -199,10 +137,12 @@ class Light(HomeAccessory):
|
||||
# Handle RGB Color
|
||||
if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars:
|
||||
rgb_color = new_state.attributes.get(ATTR_RGB_COLOR)
|
||||
current_color = color_hsv_to_RGB(self._hue, self._saturation, 100)\
|
||||
if self._hue and self._saturation else [None] * 3
|
||||
if not self._flag[RGB_COLOR] and \
|
||||
isinstance(rgb_color, (list, tuple)) and \
|
||||
list(rgb_color) != self.color.calc_hsv_to_rgb():
|
||||
hue, saturation = Color.calc_rgb_to_hsv(rgb_color)
|
||||
tuple(rgb_color) != current_color:
|
||||
hue, saturation, _ = color_RGB_to_hsv(*rgb_color)
|
||||
self.char_hue.set_value(hue, should_callback=False)
|
||||
self.char_saturation.set_value(saturation,
|
||||
should_callback=False)
|
||||
|
@ -3,6 +3,7 @@ import logging
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT, TEMP_FAHRENHEIT, TEMP_CELSIUS)
|
||||
from homeassistant.util.temperature import fahrenheit_to_celsius
|
||||
|
||||
from . import TYPES
|
||||
from .accessories import (
|
||||
@ -26,7 +27,7 @@ def calc_temperature(state, unit=TEMP_CELSIUS):
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
return round((value - 32) / 1.8, 2) if unit == TEMP_FAHRENHEIT else value
|
||||
return fahrenheit_to_celsius(value) if unit == TEMP_FAHRENHEIT else value
|
||||
|
||||
|
||||
def calc_humidity(state):
|
||||
|
@ -2,7 +2,7 @@
|
||||
import unittest
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.components.homekit.type_lights import Light, Color
|
||||
from homeassistant.components.homekit.type_lights import Light
|
||||
from homeassistant.components.light import (
|
||||
DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_RGB_COLOR,
|
||||
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR)
|
||||
@ -14,34 +14,6 @@ from homeassistant.const import (
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
def test_calc_hsv_to_rgb():
|
||||
"""Test conversion hsv to rgb."""
|
||||
color = Color(43, 23 / 100)
|
||||
assert color.calc_hsv_to_rgb() == [255, 238, 196]
|
||||
|
||||
color.hue, color.saturation = (79, 12 / 100)
|
||||
assert color.calc_hsv_to_rgb() == [245, 255, 224]
|
||||
|
||||
color.hue, color.saturation = (177, 2 / 100)
|
||||
assert color.calc_hsv_to_rgb() == [250, 255, 255]
|
||||
|
||||
color.hue, color.saturation = (212, 26 / 100)
|
||||
assert color.calc_hsv_to_rgb() == [189, 220, 255]
|
||||
|
||||
color.hue, color.saturation = (271, 93 / 100)
|
||||
assert color.calc_hsv_to_rgb() == [140, 18, 255]
|
||||
|
||||
color.hue, color.saturation = (355, 100 / 100)
|
||||
assert color.calc_hsv_to_rgb() == [255, 0, 21]
|
||||
|
||||
|
||||
def test_calc_rgb_to_hsv():
|
||||
"""Test conversion rgb to hsv."""
|
||||
assert Color.calc_rgb_to_hsv([255, 0, 21]) == (355, 100)
|
||||
assert Color.calc_rgb_to_hsv([245, 255, 224]) == (79, 12)
|
||||
assert Color.calc_rgb_to_hsv([189, 220, 255]) == (212, 26)
|
||||
|
||||
|
||||
class TestHomekitLights(unittest.TestCase):
|
||||
"""Test class for all accessory types regarding lights."""
|
||||
|
||||
@ -137,15 +109,15 @@ class TestHomekitLights(unittest.TestCase):
|
||||
entity_id = 'light.demo'
|
||||
self.hass.states.set(entity_id, STATE_ON, {
|
||||
ATTR_SUPPORTED_FEATURES: SUPPORT_RGB_COLOR,
|
||||
ATTR_RGB_COLOR: (120, 20, 300)})
|
||||
ATTR_RGB_COLOR: (120, 20, 255)})
|
||||
acc = Light(self.hass, entity_id, 'Light', aid=2)
|
||||
self.assertEqual(acc.char_hue.value, 0)
|
||||
self.assertEqual(acc.char_saturation.value, 75)
|
||||
|
||||
acc.run()
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(acc.char_hue.value, 261)
|
||||
self.assertEqual(acc.char_saturation.value, 93)
|
||||
self.assertEqual(acc.char_hue.value, 265.532)
|
||||
self.assertEqual(acc.char_saturation.value, 92.157)
|
||||
|
||||
# Set from HomeKit
|
||||
acc.char_hue.set_value(145)
|
||||
@ -157,4 +129,4 @@ class TestHomekitLights(unittest.TestCase):
|
||||
self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
|
||||
self.assertEqual(
|
||||
self.events[0].data[ATTR_SERVICE_DATA], {
|
||||
ATTR_ENTITY_ID: entity_id, ATTR_RGB_COLOR: [64, 255, 143]})
|
||||
ATTR_ENTITY_ID: entity_id, ATTR_RGB_COLOR: (63, 255, 143)})
|
||||
|
@ -17,9 +17,7 @@ def test_calc_temperature():
|
||||
|
||||
assert calc_temperature('20') == 20
|
||||
assert calc_temperature('20.12', TEMP_CELSIUS) == 20.12
|
||||
|
||||
assert calc_temperature('75.2', TEMP_FAHRENHEIT) == 24
|
||||
assert calc_temperature('-20.6', TEMP_FAHRENHEIT) == -29.22
|
||||
|
||||
|
||||
def test_calc_humidity():
|
||||
|
Loading…
x
Reference in New Issue
Block a user