Skip to content

Commit

Permalink
Update to Hass 2024.1 API format
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexxIT committed Jan 16, 2024
1 parent 1650ac9 commit 321a61d
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 131 deletions.
9 changes: 4 additions & 5 deletions custom_components/gyverlamp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

DOMAIN = 'gyverlamp'
DOMAIN = "gyverlamp"


async def async_setup(hass, hass_config):
Expand All @@ -13,14 +13,13 @@ async def async_setup(hass, hass_config):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
# migrate data (after first setup) to options
if entry.data:
hass.config_entries.async_update_entry(entry, data={},
options=entry.data)
hass.config_entries.async_update_entry(entry, data={}, options=entry.data)

# add options handler
entry.add_update_listener(async_update_options)

# forward to light setup
coro = hass.config_entries.async_forward_entry_setup(entry, 'light')
coro = hass.config_entries.async_forward_entry_setup(entry, "light")
hass.async_create_task(coro)

return True
Expand All @@ -32,4 +31,4 @@ async def async_update_options(hass: HomeAssistant, entry: ConfigEntry):


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
return await hass.config_entries.async_forward_entry_unload(entry, 'light')
return await hass.config_entries.async_forward_entry_unload(entry, "light")
32 changes: 18 additions & 14 deletions custom_components/gyverlamp/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


def parse_effects(data: str) -> list:
return re.split(r'\s*,\s*', data.strip())
return re.split(r"\s*,\s*", data.strip())


class ConfigFlowHandler(ConfigFlow, domain=DOMAIN):
Expand All @@ -23,13 +23,15 @@ async def async_step_user(self, user_input=None):
user_input[CONF_EFFECTS] = parse_effects(user_input[CONF_EFFECTS])
return self.async_create_entry(title=host, data=user_input)

effects = ','.join(EFFECTS)
effects = ",".join(EFFECTS)
return self.async_show_form(
step_id='user',
data_schema=vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_EFFECTS, default=effects): cv.string
})
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_EFFECTS, default=effects): cv.string,
}
),
)

@staticmethod
Expand All @@ -44,15 +46,17 @@ def __init__(self, config_entry: ConfigEntry):

async def async_step_init(self, user_input=None):
host = self.config_entry.options[CONF_HOST]
effects = ','.join(self.config_entry.options[CONF_EFFECTS])
effects = ",".join(self.config_entry.options[CONF_EFFECTS])
return self.async_show_form(
step_id='user',
data_schema=vol.Schema({
vol.Required(CONF_HOST, default=host): cv.string,
vol.Optional(CONF_EFFECTS, default=effects): cv.string
})
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_HOST, default=host): cv.string,
vol.Optional(CONF_EFFECTS, default=effects): cv.string,
}
),
)

async def async_step_user(self, user_input: dict = None):
user_input[CONF_EFFECTS] = parse_effects(user_input[CONF_EFFECTS])
return self.async_create_entry(title='', data=user_input)
return self.async_create_entry(title="", data=user_input)
200 changes: 88 additions & 112 deletions custom_components/gyverlamp/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,60 @@

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
from homeassistant.components.light import PLATFORM_SCHEMA, LightEntity, \
SUPPORT_BRIGHTNESS, SUPPORT_EFFECT, SUPPORT_COLOR, ATTR_BRIGHTNESS, \
ATTR_EFFECT, ATTR_HS_COLOR
from homeassistant.components.light import (
ColorMode,
LightEntity,
LightEntityFeature,
PLATFORM_SCHEMA,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo

from . import DOMAIN

_LOGGER = logging.getLogger(__name__)

CONF_EFFECTS = 'effects'

EFFECTS = ["Конфетти", "Огонь", "Радуга вертикальная", "Радуга горизонтальная",
"Смена цвета", "Безумие", "Облака", "Лава", "Плазма", "Радуга",
"Павлин", "Зебра", "Лес", "Океан", "Цвет", "Снег", "Матрица",
"Светлячки"]

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_EFFECTS): cv.ensure_list
})
CONF_EFFECTS = "effects"

EFFECTS = [
"Конфетти",
"Огонь",
"Радуга вертикальная",
"Радуга горизонтальная",
"Смена цвета",
"Безумие",
"Облака",
"Лава",
"Плазма",
"Радуга",
"Павлин",
"Зебра",
"Лес",
"Океан",
"Цвет",
"Снег",
"Матрица",
"Светлячки",
]

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_EFFECTS): cv.ensure_list,
}
)


def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities([GyverLamp(config)], True)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry,
async_add_entities):
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities
):
entity = GyverLamp(entry.options, entry.entry_id)
async_add_entities([entity], True)

Expand All @@ -46,108 +69,57 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):


class GyverLamp(LightEntity):
_available = False
_brightness = None
_effect = None
_effects = None
_host = None
_hs_color = None
_is_on = None

def __init__(self, config: dict, unique_id=None):
self._name = config.get(CONF_NAME, "Gyver Lamp")
self._unique_id = unique_id
self._attr_effect_list = config.get(CONF_EFFECTS, EFFECTS)
self._attr_name = config.get(CONF_NAME, "Gyver Lamp")
self._attr_should_poll = True
self._attr_supported_color_modes = {ColorMode.HS}
self._attr_supported_features = LightEntityFeature.EFFECT
self._attr_unique_id = unique_id

self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, unique_id)},
manufacturer="@AlexGyver",
model="GyverLamp",
)

self.update_config(config)
self.host = config[CONF_HOST]

self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.settimeout(5)

@property
def should_poll(self):
return True

@property
def unique_id(self):
return self._unique_id

@property
def name(self):
return self._name

@property
def brightness(self):
return self._brightness

@property
def hs_color(self):
return self._hs_color

@property
def effect_list(self):
return self._effects

@property
def effect(self):
return self._effect

@property
def supported_features(self):
return SUPPORT_BRIGHTNESS | SUPPORT_EFFECT | SUPPORT_COLOR

@property
def is_on(self):
return self._is_on

@property
def available(self):
return self._available

@property
def device_info(self):
"""
https://developers.home-assistant.io/docs/device_registry_index/
"""
return {
'identifiers': {(DOMAIN, self._unique_id)},
'manufacturer': "@AlexGyver",
'model': "GyverLamp"
}

@property
def address(self) -> tuple:
return self._host, 8888
return self.host, 8888

def debug(self, message):
_LOGGER.debug(f"{self._host} | {message}")

def update_config(self, config: dict):
self._effects = config.get(CONF_EFFECTS, EFFECTS)
self._host = config[CONF_HOST]

if self.hass:
self._async_write_ha_state()

def turn_on(self, **kwargs):
_LOGGER.debug(f"{self.host} | {message}")

def turn_on(
self,
brightness: int = None,
effect: str = None,
hs_color: tuple = None,
**kwargs,
):
payload = []
if ATTR_BRIGHTNESS in kwargs:
payload.append('BRI%d' % kwargs[ATTR_BRIGHTNESS])
if brightness:
payload.append("BRI%d" % brightness)

if ATTR_EFFECT in kwargs:
effect = kwargs[ATTR_EFFECT]
if effect:
try:
payload.append('EFF%d' % self._effects.index(effect))
payload.append("EFF%d" % self._attr_effect_list.index(effect))
except ValueError:
payload.append(effect)

if ATTR_HS_COLOR in kwargs:
scale = round(kwargs[ATTR_HS_COLOR][0] / 360.0 * 100.0)
payload.append('SCA%d' % scale)
speed = kwargs[ATTR_HS_COLOR][1] / 100.0 * 255.0
payload.append('SPD%d' % speed)
if hs_color:
scale = round(hs_color[0] / 360.0 * 100.0)
payload.append("SCA%d" % scale)
speed = hs_color[1] / 100.0 * 255.0
payload.append("SPD%d" % speed)

if not self.is_on:
payload.append('P_ON')
if not self._attr_is_on:
payload.append("P_ON")

self.debug(f"SEND {payload}")

Expand All @@ -157,24 +129,28 @@ def turn_on(self, **kwargs):
self.debug(f"RESP {resp}")

def turn_off(self, **kwargs):
self.sock.sendto(b'P_OFF', self.address)
self.sock.sendto(b"P_OFF", self.address)
resp = self.sock.recv(1024)
self.debug(f"RESP {resp}")

def update(self):
try:
self.sock.sendto(b'GET', self.address)
data = self.sock.recv(1024).decode().split(' ')
self.sock.sendto(b"GET", self.address)
data = self.sock.recv(1024).decode().split(" ")
self.debug(f"UPDATE {data}")
# bri eff spd sca pow
i = int(data[1])
self._effect = self._effects[i] if i < len(self._effects) else None
self._brightness = int(data[2])
self._hs_color = (float(data[4]) / 100.0 * 360.0,
float(data[3]) / 255.0 * 100.0)
self._is_on = data[5] == '1'
self._available = True
self._attr_effect = (
self._attr_effect_list[i] if i < len(self._attr_effect_list) else None
)
self._attr_brightness = int(data[2])
self._attr_hs_color = (
float(data[4]) / 100.0 * 360.0,
float(data[3]) / 255.0 * 100.0,
)
self._attr_is_on = data[5] == "1"
self._attr_available = True

except Exception as e:
self.debug(f"Can't update: {e}")
self._available = False
self._attr_available = False

0 comments on commit 321a61d

Please sign in to comment.