Home Assistant Unofficial Reference 2024.12.1
switch.py
Go to the documentation of this file.
1 """Support for an exposed aREST RESTful API of a device."""
2 
3 from __future__ import annotations
4 
5 from http import HTTPStatus
6 import logging
7 from typing import Any
8 
9 import requests
10 import voluptuous as vol
11 
13  PLATFORM_SCHEMA as SWITCH_PLATFORM_SCHEMA,
14  SwitchEntity,
15 )
16 from homeassistant.const import CONF_NAME, CONF_RESOURCE
17 from homeassistant.core import HomeAssistant
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
21 
22 _LOGGER = logging.getLogger(__name__)
23 
24 CONF_FUNCTIONS = "functions"
25 CONF_PINS = "pins"
26 CONF_INVERT = "invert"
27 
28 DEFAULT_NAME = "aREST switch"
29 
30 PIN_FUNCTION_SCHEMA = vol.Schema(
31  {
32  vol.Optional(CONF_NAME): cv.string,
33  vol.Optional(CONF_INVERT, default=False): cv.boolean,
34  }
35 )
36 
37 PLATFORM_SCHEMA = SWITCH_PLATFORM_SCHEMA.extend(
38  {
39  vol.Required(CONF_RESOURCE): cv.url,
40  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
41  vol.Optional(CONF_PINS, default={}): vol.Schema(
42  {cv.string: PIN_FUNCTION_SCHEMA}
43  ),
44  vol.Optional(CONF_FUNCTIONS, default={}): vol.Schema(
45  {cv.string: PIN_FUNCTION_SCHEMA}
46  ),
47  }
48 )
49 
50 
52  hass: HomeAssistant,
53  config: ConfigType,
54  add_entities: AddEntitiesCallback,
55  discovery_info: DiscoveryInfoType | None = None,
56 ) -> None:
57  """Set up the aREST switches."""
58  resource = config[CONF_RESOURCE]
59 
60  try:
61  response = requests.get(resource, timeout=10)
62  except requests.exceptions.MissingSchema:
63  _LOGGER.error(
64  "Missing resource or schema in configuration. Add http:// to your URL"
65  )
66  return
67  except requests.exceptions.ConnectionError:
68  _LOGGER.error("No route to device at %s", resource)
69  return
70 
71  dev: list[SwitchEntity] = []
72  pins = config[CONF_PINS]
73  for pinnum, pin in pins.items():
74  dev.append(
76  resource,
77  config.get(CONF_NAME, response.json()[CONF_NAME]),
78  pin.get(CONF_NAME),
79  pinnum,
80  pin[CONF_INVERT],
81  )
82  )
83 
84  functions = config[CONF_FUNCTIONS]
85  for funcname, func in functions.items():
86  dev.append(
88  resource,
89  config.get(CONF_NAME, response.json()[CONF_NAME]),
90  func.get(CONF_NAME),
91  funcname,
92  )
93  )
94 
95  add_entities(dev)
96 
97 
99  """Representation of an aREST switch."""
100 
101  def __init__(self, resource, location, name):
102  """Initialize the switch."""
103  self._resource_resource = resource
104  self._attr_name_attr_name = f"{location.title()} {name.title()}"
105  self._attr_available_attr_available = True
106  self._attr_is_on_attr_is_on = False
107 
108 
110  """Representation of an aREST switch."""
111 
112  def __init__(self, resource, location, name, func):
113  """Initialize the switch."""
114  super().__init__(resource, location, name)
115  self._func_func = func
116 
117  request = requests.get(f"{self._resource}/{self._func}", timeout=10)
118 
119  if request.status_code != HTTPStatus.OK:
120  _LOGGER.error("Can't find function")
121  return
122 
123  try:
124  request.json()["return_value"]
125  except KeyError:
126  _LOGGER.error("No return_value received")
127  except ValueError:
128  _LOGGER.error("Response invalid")
129 
130  def turn_on(self, **kwargs: Any) -> None:
131  """Turn the device on."""
132  request = requests.get(
133  f"{self._resource}/{self._func}", timeout=10, params={"params": "1"}
134  )
135 
136  if request.status_code == HTTPStatus.OK:
137  self._attr_is_on_attr_is_on_attr_is_on = True
138  else:
139  _LOGGER.error("Can't turn on function %s at %s", self._func_func, self._resource_resource)
140 
141  def turn_off(self, **kwargs: Any) -> None:
142  """Turn the device off."""
143  request = requests.get(
144  f"{self._resource}/{self._func}", timeout=10, params={"params": "0"}
145  )
146 
147  if request.status_code == HTTPStatus.OK:
148  self._attr_is_on_attr_is_on_attr_is_on = False
149  else:
150  _LOGGER.error(
151  "Can't turn off function %s at %s", self._func_func, self._resource_resource
152  )
153 
154  def update(self) -> None:
155  """Get the latest data from aREST API and update the state."""
156  try:
157  request = requests.get(f"{self._resource}/{self._func}", timeout=10)
158  self._attr_is_on_attr_is_on_attr_is_on = request.json()["return_value"] != 0
159  self._attr_available_attr_available_attr_available = True
160  except requests.exceptions.ConnectionError:
161  _LOGGER.warning("No route to device %s", self._resource_resource)
162  self._attr_available_attr_available_attr_available = False
163 
164 
166  """Representation of an aREST switch. Based on digital I/O."""
167 
168  def __init__(self, resource, location, name, pin, invert) -> None:
169  """Initialize the switch."""
170  super().__init__(resource, location, name)
171  self._pin_pin = pin
172  self.invertinvert = invert
173 
174  self.__set_pin_output__set_pin_output()
175 
176  def turn_on(self, **kwargs: Any) -> None:
177  """Turn the device on."""
178  turn_on_payload = int(not self.invertinvert)
179  request = requests.get(
180  f"{self._resource}/digital/{self._pin}/{turn_on_payload}", timeout=10
181  )
182  if request.status_code == HTTPStatus.OK:
183  self._attr_is_on_attr_is_on_attr_is_on = True
184  else:
185  _LOGGER.error("Can't turn on pin %s at %s", self._pin_pin, self._resource_resource)
186 
187  def turn_off(self, **kwargs: Any) -> None:
188  """Turn the device off."""
189  turn_off_payload = int(self.invertinvert)
190  request = requests.get(
191  f"{self._resource}/digital/{self._pin}/{turn_off_payload}", timeout=10
192  )
193  if request.status_code == HTTPStatus.OK:
194  self._attr_is_on_attr_is_on_attr_is_on = False
195  else:
196  _LOGGER.error("Can't turn off pin %s at %s", self._pin_pin, self._resource_resource)
197 
198  def update(self) -> None:
199  """Get the latest data from aREST API and update the state."""
200  try:
201  request = requests.get(f"{self._resource}/digital/{self._pin}", timeout=10)
202  status_value = int(self.invertinvert)
203  self._attr_is_on_attr_is_on_attr_is_on = request.json()["return_value"] != status_value
204  if self._attr_available_attr_available_attr_available is False:
205  self._attr_available_attr_available_attr_available = True
206  self.__set_pin_output__set_pin_output()
207  except requests.exceptions.ConnectionError:
208  _LOGGER.warning("No route to device %s", self._resource_resource)
209  self._attr_available_attr_available_attr_available = False
210 
211  def __set_pin_output(self) -> None:
212  request = requests.get(f"{self._resource}/mode/{self._pin}/o", timeout=10)
213  if request.status_code != HTTPStatus.OK:
214  _LOGGER.error("Can't set mode")
215  self._attr_available_attr_available_attr_available = False
def __init__(self, resource, location, name)
Definition: switch.py:101
def __init__(self, resource, location, name, func)
Definition: switch.py:112
None __init__(self, resource, location, name, pin, invert)
Definition: switch.py:168
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: switch.py:56
None add_entities(AsusWrtRouter router, AddEntitiesCallback async_add_entities, set[str] tracked)