Home Assistant Unofficial Reference 2024.12.1
light.py
Go to the documentation of this file.
1 """Support for X10 dimmer over Mochad."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from pymochad import controller, device
9 from pymochad.exceptions import MochadException
10 import voluptuous as vol
11 
13  ATTR_BRIGHTNESS,
14  PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
15  ColorMode,
16  LightEntity,
17 )
18 from homeassistant.const import CONF_ADDRESS, CONF_DEVICES, CONF_NAME, CONF_PLATFORM
19 from homeassistant.core import HomeAssistant
20 from homeassistant.helpers import config_validation as cv
21 from homeassistant.helpers.entity_platform import AddEntitiesCallback
22 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
23 
24 from . import CONF_COMM_TYPE, DOMAIN, REQ_LOCK, MochadCtrl
25 
26 _LOGGER = logging.getLogger(__name__)
27 CONF_BRIGHTNESS_LEVELS = "brightness_levels"
28 
29 PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
30  {
31  vol.Required(CONF_PLATFORM): DOMAIN,
32  CONF_DEVICES: [
33  {
34  vol.Optional(CONF_NAME): cv.string,
35  vol.Required(CONF_ADDRESS): cv.x10_address,
36  vol.Optional(CONF_COMM_TYPE): cv.string,
37  vol.Optional(CONF_BRIGHTNESS_LEVELS, default=32): vol.All(
38  vol.Coerce(int), vol.In([32, 64, 256])
39  ),
40  }
41  ],
42  }
43 )
44 
45 
47  hass: HomeAssistant,
48  config: ConfigType,
49  add_entities: AddEntitiesCallback,
50  discovery_info: DiscoveryInfoType | None = None,
51 ) -> None:
52  """Set up X10 dimmers over a mochad controller."""
53  mochad_controller: MochadCtrl = hass.data[DOMAIN]
54  devs: list[dict[str, Any]] = config[CONF_DEVICES]
55  add_entities([MochadLight(hass, mochad_controller.ctrl, dev) for dev in devs])
56 
57 
59  """Representation of a X10 dimmer over Mochad."""
60 
61  _attr_assumed_state = True # X10 devices are normally 1-way
62  _attr_color_mode = ColorMode.BRIGHTNESS
63  _attr_supported_color_modes = {ColorMode.BRIGHTNESS}
64 
65  def __init__(
66  self, hass: HomeAssistant, ctrl: controller.PyMochad, dev: dict[str, Any]
67  ) -> None:
68  """Initialize a Mochad Light Device."""
69 
70  self._controller_controller = ctrl
71  self._address: str = dev[CONF_ADDRESS]
72  self._attr_name: str = dev.get(CONF_NAME, f"x10_light_dev_{self._address}")
73  self._comm_type: str = dev.get(CONF_COMM_TYPE, "pl")
74  self.lightlight = device.Device(ctrl, self._address, comm_type=self._comm_type)
75  self._attr_brightness_attr_brightness = 0
76  self._attr_is_on_attr_is_on = self._get_device_status_get_device_status()
77  self._brightness_levels_brightness_levels: int = dev[CONF_BRIGHTNESS_LEVELS] - 1
78 
79  def _get_device_status(self) -> bool:
80  """Get the status of the light from mochad."""
81  with REQ_LOCK:
82  status = self.lightlight.get_status().rstrip()
83  return status == "on"
84 
85  def _calculate_brightness_value(self, value: int) -> int:
86  return int(value * (float(self._brightness_levels_brightness_levels) / 255.0))
87 
88  def _adjust_brightness(self, brightness: int) -> None:
89  assert self.brightnessbrightnessbrightness is not None
90  if self.brightnessbrightnessbrightness > brightness:
91  bdelta = self.brightnessbrightnessbrightness - brightness
92  mochad_brightness = self._calculate_brightness_value_calculate_brightness_value(bdelta)
93  self.lightlight.send_cmd(f"dim {mochad_brightness}")
94  self._controller_controller.read_data()
95  elif self.brightnessbrightnessbrightness < brightness:
96  bdelta = brightness - self.brightnessbrightnessbrightness
97  mochad_brightness = self._calculate_brightness_value_calculate_brightness_value(bdelta)
98  self.lightlight.send_cmd(f"bright {mochad_brightness}")
99  self._controller_controller.read_data()
100 
101  def turn_on(self, **kwargs: Any) -> None:
102  """Send the command to turn the light on."""
103  _LOGGER.debug("Reconnect %s:%s", self._controller_controller.server, self._controller_controller.port)
104  brightness: int = kwargs.get(ATTR_BRIGHTNESS, 255)
105  with REQ_LOCK:
106  try:
107  # Recycle socket on new command to recover mochad connection
108  self._controller_controller.reconnect()
109  if self._brightness_levels_brightness_levels > 32:
110  out_brightness = self._calculate_brightness_value_calculate_brightness_value(brightness)
111  self.lightlight.send_cmd(f"xdim {out_brightness}")
112  self._controller_controller.read_data()
113  else:
114  self.lightlight.send_cmd("on")
115  self._controller_controller.read_data()
116  # There is no persistence for X10 modules so a fresh on command
117  # will be full brightness
118  if self.brightnessbrightnessbrightness == 0:
119  self._attr_brightness_attr_brightness = 255
120  self._adjust_brightness_adjust_brightness(brightness)
121  self._attr_brightness_attr_brightness = brightness
122  self._attr_is_on_attr_is_on = True
123  except (MochadException, OSError) as exc:
124  _LOGGER.error("Error with mochad communication: %s", exc)
125 
126  def turn_off(self, **kwargs: Any) -> None:
127  """Send the command to turn the light on."""
128  _LOGGER.debug("Reconnect %s:%s", self._controller_controller.server, self._controller_controller.port)
129  with REQ_LOCK:
130  try:
131  # Recycle socket on new command to recover mochad connection
132  self._controller_controller.reconnect()
133  self.lightlight.send_cmd("off")
134  self._controller_controller.read_data()
135  # There is no persistence for X10 modules so we need to prepare
136  # to track a fresh on command will full brightness
137  if self._brightness_levels_brightness_levels == 31:
138  self._attr_brightness_attr_brightness = 0
139  self._attr_is_on_attr_is_on = False
140  except (MochadException, OSError) as exc:
141  _LOGGER.error("Error with mochad communication: %s", exc)
int _calculate_brightness_value(self, int value)
Definition: light.py:85
None _adjust_brightness(self, int brightness)
Definition: light.py:88
None __init__(self, HomeAssistant hass, controller.PyMochad ctrl, dict[str, Any] dev)
Definition: light.py:67
None add_entities(AsusWrtRouter router, AddEntitiesCallback async_add_entities, set[str] tracked)
def get_status(hass, host, port)
Definition: panel.py:387
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: light.py:51