async def test_empty_full_responses(aresponses): """Test failure handling of full data request WLED device state.""" aresponses.add( "example.com", "/json/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text="{}", ), ) aresponses.add( "example.com", "/json/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text=('{"state": {"on": true},' '"effects": [], "palettes": [],' '"info": {"ver": "0.10.0"}}'), ), ) async with aiohttp.ClientSession() as session: wled = WLED("example.com", session=session) await wled.update()
async def test_si_request_probing_based(aresponses): """Test for supporting SI requests based on probing.""" aresponses.add( "example.com", "/json/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text=('{"state": {"on": true},' '"effects": [], "palettes": [],' '"info": {"ver": "INVALID VERSION NUMBER"}}'), ), ) aresponses.add( "example.com", "/json/si", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text='{"yes": true}', ), ) async with aiohttp.ClientSession() as session: wled = WLED("example.com", session=session) await wled.update() assert wled._supports_si_request
async def test_state_on_si_request(aresponses): """Test request of current WLED device state.""" aresponses.add( "example.com", "/json/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text=('{"state": {"on": true},' '"effects": [], "palettes": [],' '"info": {"ver": "0.10.0"}}'), ), ) aresponses.add( "example.com", "/json/si", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text='{"state": {"on": false},"info": {"ver": "1.0"}}', ), ) async with aiohttp.ClientSession() as session: wled = WLED("example.com", session=session) device = await wled.update() assert device.state.on device = await wled.update() assert not device.state.on
async def test_state_on(event_loop, aresponses): """Test request of current WLED device state.""" aresponses.add( "example.com", "/json/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text='{"state": {"on": true}}', ), ) aresponses.add( "example.com", "/json/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text='{"state": {"on": false}}', ), ) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", session=session, loop=event_loop) device = await wled.update() assert device.state.on device = await wled.update() assert not device.state.on
async def led_off(): async with WLED(config.LED_IP_ADDRESS) as led: device = await led.update() print(device.info.version) # Turn strip off if device.state.on: await led.master(on=False)
async def led_off(): async with WLED(config.LED_IP_ADDRESS) as led: device = await led.update() # Turn strip off if currently on if device.state.on: print("LEDs turned off") await led.master(on=False)
async def test_post_request(event_loop, aresponses): """Test POST requests are handled correctly.""" aresponses.add("example.com", "/", "POST", aresponses.Response(status=200, text="OK")) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", session=session, loop=event_loop) response = await wled._request("/", method="POST") assert response == "OK"
async def test_text_request(event_loop, aresponses): """Test non JSON response is handled correctly.""" aresponses.add("example.com", "/", "GET", aresponses.Response(status=200, text="OK")) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", session=session, loop=event_loop) response = await wled._request("/") assert response == "OK"
async def flash(preset: Preset, length: Optional[int] = 0): async with WLED(LIGHT_IP) as led: await led.preset(preset.index) if length: await asyncio.sleep(length) else: await asyncio.sleep(preset.seconds) await led.preset(Preset.DEFAULT.index)
async def main(): """Show example on controlling your WLED device.""" async with WLED("wled-frenck.local") as led: device = await led.update() print(device.info.version) # Turn strip on, full brightness await led.light(on=True, brightness=255)
async def led_on(): async with WLED(config.LED_IP_ADDRESS) as led: device = await led.update() if not device.state.on: prev_brightness = device.state.brightness # Turn strip on, with previous brightness print("LEDs turned on") await led.master(on=True, brightness=prev_brightness)
async def main(): """Show example on controlling your WLED device.""" async with WLED("10.76.5.152") as led: device = await led.update() print(device.info.version) await led.master(on=False) await asyncio.sleep(5) await led.master(on=True)
async def test_http_error400(event_loop, aresponses): """Test HTTP 404 response handling.""" aresponses.add("example.com", "/", "GET", aresponses.Response(text="OMG PUPPIES!", status=404)) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", session=session, loop=event_loop) with pytest.raises(WLEDError): assert await wled._request("/")
async def test_request_base_path(aresponses): """Test WLED running on different base path.""" aresponses.add( "example.com", "/admin/status", "GET", aresponses.Response(text="OMG PUPPIES!", status=200), ) async with aiohttp.ClientSession() as session: wled = WLED("example.com", base_path="/admin", session=session) response = await wled._request("status") assert response == "OMG PUPPIES!"
async def test_request_user_agent(aresponses): """Test WLED client sending correct user agent headers.""" # Handle to run asserts on request in async def response_handler(request): assert request.headers["User-Agent"] == f"PythonWLED/{__version__}" return aresponses.Response(text="TEDDYBEAR", status=200) aresponses.add("example.com", "/", "GET", response_handler) async with aiohttp.ClientSession() as session: wled = WLED("example.com", base_path="/", session=session) await wled._request("/")
async def test_request_port(event_loop, aresponses): """Test WLED running on non-standard port.""" aresponses.add( "example.com:3333", "/", "GET", aresponses.Response(text="OMG PUPPIES!", status=200), ) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", port=3333, session=session, loop=event_loop) response = await wled._request("/") assert response == "OMG PUPPIES!"
async def _handle_config_flow(self, user_input: Optional[ConfigType] = None, prepare: bool = False) -> Dict[str, Any]: """Config flow handler for WLED.""" # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 source = self.context.get("source") # Request user input, unless we are preparing discovery flow if user_input is None and not prepare: if source == SOURCE_ZEROCONF: return self._show_confirm_dialog() return self._show_setup_form() if source == SOURCE_ZEROCONF: # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 user_input[CONF_HOST] = self.context.get(CONF_HOST) errors = {} session = async_get_clientsession(self.hass) wled = WLED(user_input[CONF_HOST], loop=self.hass.loop, session=session) try: device = await wled.update() except WLEDConnectionError: if source == SOURCE_ZEROCONF: return self.async_abort(reason="connection_error") errors["base"] = "connection_error" return self._show_setup_form(errors) # Check if already configured mac_address = device.info.mac_address for entry in self._async_current_entries(): if entry.data[CONF_MAC] == mac_address: # This mac address is already configured return self.async_abort(reason="already_configured") title = user_input[CONF_HOST] if source == SOURCE_ZEROCONF: # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 title = self.context.get(CONF_NAME) if prepare: return await self.async_step_zeroconf_confirm() return self.async_create_entry(title=title, data={ CONF_HOST: user_input[CONF_HOST], CONF_MAC: mac_address })
async def _handle_config_flow(self, user_input: dict[str, Any] | None = None, prepare: bool = False) -> FlowResult: """Config flow handler for WLED.""" source = self.context.get("source") # Request user input, unless we are preparing discovery flow if user_input is None and not prepare: if source == SOURCE_ZEROCONF: return self._show_confirm_dialog() return self._show_setup_form() # if prepare is True, user_input can not be None. assert user_input is not None if source == SOURCE_ZEROCONF: user_input[CONF_HOST] = self.context.get(CONF_HOST) user_input[CONF_MAC] = self.context.get(CONF_MAC) if user_input.get(CONF_MAC) is None or not prepare: session = async_get_clientsession(self.hass) wled = WLED(user_input[CONF_HOST], session=session) try: device = await wled.update() except WLEDConnectionError: if source == SOURCE_ZEROCONF: return self.async_abort(reason="cannot_connect") return self._show_setup_form({"base": "cannot_connect"}) user_input[CONF_MAC] = device.info.mac_address # Check if already configured await self.async_set_unique_id(user_input[CONF_MAC]) self._abort_if_unique_id_configured( updates={CONF_HOST: user_input[CONF_HOST]}) title = user_input[CONF_HOST] if source == SOURCE_ZEROCONF: title = self.context.get(CONF_NAME) if prepare: return await self.async_step_zeroconf_confirm() return self.async_create_entry( title=title, data={ CONF_HOST: user_input[CONF_HOST], CONF_MAC: user_input[CONF_MAC] }, )
async def _handle_config_flow(self, user_input: Optional[ConfigType] = None, prepare: bool = False) -> Dict[str, Any]: """Config flow handler for WLED.""" # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 source = self.context.get("source") # Request user input, unless we are preparing discovery flow if user_input is None and not prepare: if source == SOURCE_ZEROCONF: return self._show_confirm_dialog() return self._show_setup_form() if source == SOURCE_ZEROCONF: # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 user_input[CONF_HOST] = self.context.get(CONF_HOST) user_input[CONF_MAC] = self.context.get(CONF_MAC) if user_input.get(CONF_MAC) is None or not prepare: session = async_get_clientsession(self.hass) wled = WLED(user_input[CONF_HOST], session=session) try: device = await wled.update() except WLEDConnectionError: if source == SOURCE_ZEROCONF: return self.async_abort(reason="cannot_connect") return self._show_setup_form({"base": "cannot_connect"}) user_input[CONF_MAC] = device.info.mac_address # Check if already configured await self.async_set_unique_id(user_input[CONF_MAC]) self._abort_if_unique_id_configured( updates={CONF_HOST: user_input[CONF_HOST]}) title = user_input[CONF_HOST] if source == SOURCE_ZEROCONF: # pylint: disable=no-member # https://github.com/PyCQA/pylint/issues/3167 title = self.context.get(CONF_NAME) if prepare: return await self.async_step_zeroconf_confirm() return self.async_create_entry( title=title, data={ CONF_HOST: user_input[CONF_HOST], CONF_MAC: user_input[CONF_MAC] }, )
def __init__( self, hass: HomeAssistant, *, host: str, ): """Initialize global WLED data updater.""" self.wled = WLED(host, session=async_get_clientsession(hass)) super().__init__( hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL, )
def __init__( self, opp: OpenPeerPower, *, host: str, ) -> None: """Initialize global WLED data updater.""" self.wled = WLED(host, session=async_get_clientsession(opp)) super().__init__( opp, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL, )
async def test_internal_eventloop(aresponses): """Test JSON response is handled correctly.""" aresponses.add( "example.com", "/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text='{"status": "ok"}', ), ) async with WLED("example.com") as wled: response = await wled._request("/") assert response["status"] == "ok"
async def test_json_request(event_loop, aresponses): """Test JSON response is handled correctly.""" aresponses.add( "example.com", "/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text='{"status": "ok"}', ), ) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", session=session, loop=event_loop) response = await wled._request("/") assert response["status"] == "ok"
async def test_http_error500(event_loop, aresponses): """Test HTTP 500 response handling.""" aresponses.add( "example.com", "/", "GET", aresponses.Response( body=b'{"status":"nok"}', status=500, headers={"Content-Type": "application/json"}, ), ) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", session=session, loop=event_loop) with pytest.raises(WLEDError): assert await wled._request("/")
async def test_timeout(event_loop, aresponses): """Test request timeout from WLED.""" # Faking a timeout by sleeping async def response_handler(_): await asyncio.sleep(2) return aresponses.Response(body="Goodmorning!") aresponses.add("example.com", "/", "GET", response_handler) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED("example.com", session=session, loop=event_loop, request_timeout=1) with pytest.raises(WLEDConnectionError): assert await wled._request("/")
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up WLED from a config entry.""" # Create WLED instance for this entry session = async_get_clientsession(hass) wled = WLED(entry.data[CONF_HOST], session=session) # Ensure we can connect and talk to it try: await wled.update() except WLEDConnectionError as exception: raise ConfigEntryNotReady from exception hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = {DATA_WLED_CLIENT: wled} # For backwards compat, set unique ID if entry.unique_id is None: hass.config_entries.async_update_entry( entry, unique_id=wled.device.info.mac_address ) # Set up all platforms for this device/entry. for component in WLED_COMPONENTS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component) ) async def interval_update(now: dt_util.dt.datetime = None) -> None: """Poll WLED device function, dispatches event after update.""" try: await wled.update() except WLEDError: _LOGGER.debug("An error occurred while updating WLED", exc_info=True) # Even if the update failed, we still send out the event. # To allow entities to make themselves unavailable. async_dispatcher_send(hass, DATA_WLED_UPDATED, entry.entry_id) # Schedule update interval hass.data[DOMAIN][entry.entry_id][DATA_WLED_TIMER] = async_track_time_interval( hass, interval_update, SCAN_INTERVAL ) return True
def __init__( self, hass: HomeAssistant, *, entry: ConfigEntry, ) -> None: """Initialize global WLED data updater.""" self.keep_master_light = entry.options.get( CONF_KEEP_MASTER_LIGHT, DEFAULT_KEEP_MASTER_LIGHT ) self.wled = WLED(entry.data[CONF_HOST], session=async_get_clientsession(hass)) self.unsub: Callable | None = None super().__init__( hass, LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL, )
async def test_request_custom_user_agent(event_loop, aresponses): """Test WLED client sending correct user agent headers.""" # Handle to run asserts on request in async def response_handler(request): assert request.headers["User-Agent"] == "LoremIpsum/1.0" return aresponses.Response(text="TEDDYBEAR", status=200) aresponses.add("example.com", "/", "GET", response_handler) async with aiohttp.ClientSession(loop=event_loop) as session: wled = WLED( "example.com", base_path="/", session=session, loop=event_loop, user_agent="LoremIpsum/1.0", ) await wled._request("/")
async def test_backoff(aresponses): """Test requests are handled with retries.""" async def response_handler(_): await asyncio.sleep(0.2) return aresponses.Response(body="Goodmorning!") aresponses.add( "example.com", "/", "GET", response_handler, repeat=2, ) aresponses.add("example.com", "/", "GET", aresponses.Response(status=200, text="OK")) async with aiohttp.ClientSession() as session: wled = WLED("example.com", session=session, request_timeout=0.1) response = await wled._request("/") assert response == "OK"
async def test_authenticated_request(aresponses): """Test JSON response is handled correctly.""" aresponses.add( "example.com", "/", "GET", aresponses.Response( status=200, headers={"Content-Type": "application/json"}, text='{"status": "ok"}', ), ) async with aiohttp.ClientSession() as session: wled = WLED( "example.com", username="******", password="******", session=session, ) response = await wled._request("/") assert response["status"] == "ok"