-
-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add LED brightness control (#404)
* feat: add LED brightness control * formatting * linting * update test * formatting again
- Loading branch information
Showing
8 changed files
with
260 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
"""Support for OpenEVSE controls using the light platform.""" | ||
|
||
from __future__ import annotations | ||
|
||
import logging | ||
from typing import Any | ||
|
||
from homeassistant.components.light import ( | ||
ATTR_BRIGHTNESS, | ||
ColorMode, | ||
LightEntity, | ||
) | ||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
from homeassistant.helpers.update_coordinator import CoordinatorEntity | ||
|
||
from .const import CONF_NAME, COORDINATOR, DOMAIN, LIGHT_TYPES, MANAGER | ||
from .entity import OpenEVSELightEntityDescription | ||
|
||
from . import ( | ||
OpenEVSEManager, | ||
OpenEVSEUpdateCoordinator, | ||
) | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
DEFAULT_ON = 125 | ||
DEFAULT_OFF = 0 | ||
|
||
|
||
async def async_setup_entry( | ||
hass: HomeAssistant, | ||
config_entry: ConfigEntry, | ||
async_add_entities: AddEntitiesCallback, | ||
) -> None: | ||
"""Set up OpenEVSE Number entity from Config Entry.""" | ||
coordinator = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR] | ||
manager = hass.data[DOMAIN][config_entry.entry_id][MANAGER] | ||
|
||
entities: list[LightEntity] = [] | ||
|
||
for light in LIGHT_TYPES: # pylint: disable=consider-using-dict-items | ||
entities.append( | ||
OpenEVSELight(config_entry, coordinator, LIGHT_TYPES[light], manager) | ||
) | ||
async_add_entities(entities) | ||
|
||
|
||
class OpenEVSELight(CoordinatorEntity, LightEntity): | ||
"""Implementation of an OpenEVSE light.""" | ||
|
||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS} | ||
_attr_color_mode = ColorMode.BRIGHTNESS | ||
|
||
def __init__( | ||
self, | ||
config: ConfigEntry, | ||
coordinator: OpenEVSEUpdateCoordinator, | ||
light_description: OpenEVSELightEntityDescription, | ||
manager: OpenEVSEManager, | ||
) -> None: | ||
"""Initialize the sensor.""" | ||
super().__init__(coordinator) | ||
self._config = config | ||
self.entity_description = light_description | ||
self._name = light_description.name | ||
self._type = light_description.key | ||
self._unique_id = config.entry_id | ||
self._command = light_description.command | ||
self._data = coordinator.data | ||
self.coordinator = coordinator | ||
self.manager = manager | ||
|
||
self._attr_name = f"{self._config.data[CONF_NAME]} {self._name}" | ||
self._attr_unique_id = f"{self._name}_{self._unique_id}" | ||
self._attr_brightness = coordinator.data[self._type] | ||
|
||
@property | ||
def device_info(self) -> dict: | ||
"""Return a port description for device registry.""" | ||
info = { | ||
"manufacturer": "OpenEVSE", | ||
"name": self._config.data[CONF_NAME], | ||
"connections": {(DOMAIN, self._unique_id)}, | ||
} | ||
|
||
return info | ||
|
||
@property | ||
def brightness(self) -> int | None: | ||
"""Return the brightness of this light between 0..255.""" | ||
self._attr_brightness = self.coordinator.data[self._type] | ||
return self._attr_brightness | ||
|
||
@property | ||
def is_on(self) -> bool: | ||
"""Return true if light is on.""" | ||
return bool(self._attr_brightness != 0) | ||
|
||
async def async_turn_on(self, **kwargs: Any) -> None: | ||
"""Instruct the light to turn on.""" | ||
brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness) | ||
|
||
if ATTR_BRIGHTNESS in kwargs: | ||
await self.manager.set_led_brightness(brightness) | ||
return | ||
await self.manager.set_led_brightness(DEFAULT_ON) | ||
|
||
async def async_turn_off(self, **kwargs: Any) -> None: | ||
"""Instruct the light to turn off.""" | ||
await self.manager.set_led_brightness(DEFAULT_OFF) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
"""Provide tests for OpenEVSE light platform.""" | ||
|
||
from datetime import timedelta | ||
from unittest.mock import patch | ||
|
||
import pytest | ||
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN | ||
from homeassistant.components.light import DOMAIN as LIGHT_DOMAIN, ATTR_BRIGHTNESS | ||
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN | ||
from homeassistant.components.select import DOMAIN as SELECT_DOMAIN | ||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN | ||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN | ||
from homeassistant.helpers import entity_registry as er | ||
from homeassistant.util import dt as dt_util | ||
from pytest_homeassistant_custom_component.common import MockConfigEntry | ||
|
||
from custom_components.openevse.const import DOMAIN | ||
|
||
from .const import CONFIG_DATA | ||
from .conftest import TEST_URL_CONFIG | ||
|
||
pytestmark = pytest.mark.asyncio | ||
|
||
CHARGER_NAME = "openevse" | ||
|
||
|
||
async def test_light( | ||
hass, | ||
test_charger, | ||
mock_ws_start, | ||
mock_aioclient, | ||
): | ||
"""Test setup_entry.""" | ||
entry = MockConfigEntry( | ||
domain=DOMAIN, | ||
title=CHARGER_NAME, | ||
data=CONFIG_DATA, | ||
) | ||
|
||
entry.add_to_hass(hass) | ||
assert await hass.config_entries.async_setup(entry.entry_id) | ||
await hass.async_block_till_done() | ||
|
||
assert len(hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN)) == 4 | ||
assert len(hass.states.async_entity_ids(SENSOR_DOMAIN)) == 21 | ||
assert len(hass.states.async_entity_ids(SWITCH_DOMAIN)) == 4 | ||
assert len(hass.states.async_entity_ids(SELECT_DOMAIN)) == 2 | ||
assert len(hass.states.async_entity_ids(NUMBER_DOMAIN)) == 1 | ||
assert len(hass.states.async_entity_ids(LIGHT_DOMAIN)) == 1 | ||
entries = hass.config_entries.async_entries(DOMAIN) | ||
assert len(entries) == 1 | ||
|
||
assert DOMAIN in hass.config.components | ||
|
||
entity_id = "light.openevse_led_brightness" | ||
state = hass.states.get(entity_id) | ||
assert state | ||
assert state.state == "on" | ||
assert state.attributes[ATTR_BRIGHTNESS] == 128 | ||
|
||
mock_aioclient.post( | ||
TEST_URL_CONFIG, | ||
status=200, | ||
body='{"msg": "Ok"}', | ||
repeat=True, | ||
) | ||
|
||
await hass.services.async_call( | ||
LIGHT_DOMAIN, | ||
"turn_off", | ||
{"entity_id": entity_id}, | ||
blocking=True, | ||
) | ||
|
||
mock_aioclient.assert_any_call( | ||
TEST_URL_CONFIG, method="POST", data={ATTR_BRIGHTNESS: 0} | ||
) | ||
|
||
await hass.services.async_call( | ||
LIGHT_DOMAIN, | ||
"turn_on", | ||
{"entity_id": entity_id}, | ||
blocking=True, | ||
) | ||
|
||
mock_aioclient.assert_any_call( | ||
TEST_URL_CONFIG, method="POST", data={ATTR_BRIGHTNESS: 128} | ||
) | ||
|
||
await hass.services.async_call( | ||
LIGHT_DOMAIN, | ||
"turn_on", | ||
{"entity_id": entity_id, "brightness": 26}, | ||
blocking=True, | ||
) | ||
|
||
mock_aioclient.assert_any_call( | ||
TEST_URL_CONFIG, method="POST", data={ATTR_BRIGHTNESS: 26} | ||
) |