This commit is contained in:
2026-01-30 23:31:00 -06:00
commit a39095b3de
2665 changed files with 263970 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
"""The Govee integration."""
import asyncio
import logging
from govee_api_laggat import Govee
import voluptuous as vol
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_API_KEY
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
from .const import DOMAIN
from .learning_storage import GoveeLearningStorage
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
# supported platforms
PLATFORMS = ["light"]
def setup(hass, config):
"""This setup does nothing, we use the async setup."""
hass.states.set("govee.state", "setup called")
return True
async def async_setup(hass: HomeAssistant, config: dict):
"""Set up the Govee component."""
hass.states.async_set("govee.state", "async_setup called")
hass.data[DOMAIN] = {}
return True
def is_online(online: bool):
"""Log online/offline change."""
msg = "API is offline."
if online:
msg = "API is back online."
_LOGGER.warning(msg)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Set up Govee from a config entry."""
# get vars from ConfigFlow/OptionsFlow
config = entry.data
options = entry.options
api_key = options.get(CONF_API_KEY, config.get(CONF_API_KEY, ""))
# Setup connection with devices/cloud
hub = await Govee.create(
api_key, learning_storage=GoveeLearningStorage(hass.config.config_dir)
)
# keep reference for disposing
hass.data[DOMAIN] = {}
hass.data[DOMAIN]["hub"] = hub
# inform when api is offline/online
hub.events.online += is_online
# Verify that passed in configuration works
_, err = await hub.get_devices()
if err:
_LOGGER.warning("Could not connect to Govee API: %s", err)
await hub.rate_limit_delay()
await async_unload_entry(hass, entry)
raise PlatformNotReady()
for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, component)
)
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[
_unload_component_entry(hass, entry, component)
for component in PLATFORMS
]
)
)
if unload_ok:
hub = hass.data[DOMAIN].pop("hub")
await hub.close()
return unload_ok
def _unload_component_entry(
hass: HomeAssistant, entry: ConfigEntry, component: str
) -> bool:
"""Unload an entry for a specific component."""
success = False
try:
success = hass.config_entries.async_forward_entry_unload(entry, component)
except ValueError:
# probably ValueError: Config entry was never loaded!
return success
except Exception as ex:
_LOGGER.warning(
"Continuing on exception when unloading %s component's entry: %s",
component,
ex,
)
return success

View File

@@ -0,0 +1,210 @@
"""Config flow for Govee integration."""
import logging
from govee_api_laggat import Govee, GoveeNoLearningStorage, GoveeError
from homeassistant import config_entries, core, exceptions
import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_API_KEY, CONF_DELAY
from homeassistant.core import callback
import voluptuous as vol
from .const import (
CONF_DISABLE_ATTRIBUTE_UPDATES,
CONF_OFFLINE_IS_OFF,
CONF_USE_ASSUMED_STATE,
DOMAIN,
)
_LOGGER = logging.getLogger(__name__)
async def validate_api_key(hass: core.HomeAssistant, user_input):
"""Validate the user input allows us to connect.
Return info that you want to store in the config entry.
"""
api_key = user_input[CONF_API_KEY]
async with Govee(api_key, learning_storage=GoveeNoLearningStorage()) as hub:
_, error = await hub.get_devices()
if error:
raise CannotConnect(error)
# Return info that you want to store in the config entry.
return user_input
async def validate_disabled_attribute_updates(hass: core.HomeAssistant, user_input):
"""Validate format of the ignore_device_attributes parameter string
Return info that you want to store in the config entry.
"""
disable_str = user_input[CONF_DISABLE_ATTRIBUTE_UPDATES]
if disable_str:
# we have something to check, connect without API key
async with Govee("", learning_storage=GoveeNoLearningStorage()) as hub:
# this will throw an GoveeError if something fails
hub.ignore_device_attributes(disable_str)
# Return info that you want to store in the config entry.
return user_input
@config_entries.HANDLERS.register(DOMAIN)
class GoveeFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Govee."""
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
async def async_step_user(self, user_input=None):
"""Handle the initial step."""
errors = {}
if user_input is not None:
try:
user_input = await validate_api_key(self.hass, user_input)
except CannotConnect as conn_ex:
_LOGGER.exception("Cannot connect: %s", conn_ex)
errors[CONF_API_KEY] = "cannot_connect"
except GoveeError as govee_ex:
_LOGGER.exception("Govee library error: %s", govee_ex)
errors["base"] = "govee_ex"
except Exception as ex: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception: %s", ex)
errors["base"] = "unknown"
if not errors:
return self.async_create_entry(title=DOMAIN, data=user_input)
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Optional(CONF_DELAY, default=10): cv.positive_int,
}
),
errors=errors,
)
@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow."""
return GoveeOptionsFlowHandler(config_entry)
class GoveeOptionsFlowHandler(config_entries.OptionsFlow):
"""Handle options."""
VERSION = 1
def __init__(self, config_entry):
"""Initialize options flow."""
self.config_entry = config_entry
self.options = dict(config_entry.options)
async def async_step_init(self, user_input=None):
"""Manage the options."""
return await self.async_step_user()
async def async_step_user(self, user_input=None):
"""Manage the options."""
# get the current value for API key for comparison and default value
old_api_key = self.config_entry.options.get(
CONF_API_KEY, self.config_entry.data.get(CONF_API_KEY, "")
)
errors = {}
if user_input is not None:
# check if API Key changed and is valid
try:
api_key = user_input[CONF_API_KEY]
if old_api_key != api_key:
user_input = await validate_api_key(self.hass, user_input)
except CannotConnect as conn_ex:
_LOGGER.exception("Cannot connect: %s", conn_ex)
errors[CONF_API_KEY] = "cannot_connect"
except GoveeError as govee_ex:
_LOGGER.exception("Govee library error: %s", govee_ex)
errors["base"] = "govee_ex"
except Exception as ex: # pylint: disable=broad-except
_LOGGER.exception("Unexpected exception: %s", ex)
errors["base"] = "unknown"
# check validate_disabled_attribute_updates
try:
user_input = await validate_disabled_attribute_updates(
self.hass, user_input
)
# apply settings to the running instance
if DOMAIN in self.hass.data and "hub" in self.hass.data[DOMAIN]:
hub = self.hass.data[DOMAIN]["hub"]
if hub:
disable_str = user_input[CONF_DISABLE_ATTRIBUTE_UPDATES]
hub.ignore_device_attributes(disable_str)
except GoveeError as govee_ex:
_LOGGER.exception(
"Wrong input format for validate_disabled_attribute_updates: %s",
govee_ex,
)
errors[
CONF_DISABLE_ATTRIBUTE_UPDATES
] = "disabled_attribute_updates_wrong"
if not errors:
# update options flow values
self.options.update(user_input)
return await self._update_options()
# for later - extend with options you don't want in config but option flow
# return await self.async_step_options_2()
options_schema = vol.Schema(
{
# to config flow
vol.Required(
CONF_API_KEY,
default=old_api_key,
): cv.string,
vol.Optional(
CONF_DELAY,
default=self.config_entry.options.get(
CONF_DELAY, self.config_entry.data.get(CONF_DELAY, 10)
),
): cv.positive_int,
# to options flow
vol.Required(
CONF_USE_ASSUMED_STATE,
default=self.config_entry.options.get(CONF_USE_ASSUMED_STATE, True),
): cv.boolean,
vol.Required(
CONF_OFFLINE_IS_OFF,
default=self.config_entry.options.get(CONF_OFFLINE_IS_OFF, False),
): cv.boolean,
# TODO: validator doesn't work, change to list?
vol.Optional(
CONF_DISABLE_ATTRIBUTE_UPDATES,
default=self.config_entry.options.get(
CONF_DISABLE_ATTRIBUTE_UPDATES, ""
),
): cv.string,
},
)
return self.async_show_form(
step_id="user",
data_schema=options_schema,
errors=errors,
)
async def _update_options(self):
"""Update config entry options."""
return self.async_create_entry(title=DOMAIN, data=self.options)
class CannotConnect(exceptions.HomeAssistantError):
"""Error to indicate we cannot connect."""

View File

@@ -0,0 +1,10 @@
"""Constants for the Govee LED strips integration."""
DOMAIN = "govee"
CONF_DISABLE_ATTRIBUTE_UPDATES = "disable_attribute_updates"
CONF_OFFLINE_IS_OFF = "offline_is_off"
CONF_USE_ASSUMED_STATE = "use_assumed_state"
COLOR_TEMP_KELVIN_MIN = 2000
COLOR_TEMP_KELVIN_MAX = 9000

View File

@@ -0,0 +1 @@
/workspaces/hacs-govee/custom_components/govee

View File

@@ -0,0 +1,66 @@
"""The Govee learned storage yaml file manager."""
from dataclasses import asdict
import logging
import dacite
from govee_api_laggat import GoveeAbstractLearningStorage, GoveeLearnedInfo
import yaml
from homeassistant.util.yaml import load_yaml, save_yaml
_LOGGER = logging.getLogger(__name__)
LEARNING_STORAGE_YAML = "/govee_learning.yaml"
class GoveeLearningStorage(GoveeAbstractLearningStorage):
"""The govee_api_laggat library uses this to store learned information about lights."""
def __init__(self, config_dir, *args, **kwargs):
"""Get the config directory."""
super().__init__(*args, **kwargs)
self._config_dir = config_dir
async def read(self):
"""Restore from yaml file."""
learned_info = {}
try:
learned_dict = load_yaml(self._config_dir + LEARNING_STORAGE_YAML)
learned_info = {
device: dacite.from_dict(
data_class=GoveeLearnedInfo, data=learned_dict[device]
)
for device in learned_dict
}
_LOGGER.info(
"Loaded learning information from %s.",
self._config_dir + LEARNING_STORAGE_YAML,
)
except FileNotFoundError:
_LOGGER.warning(
"There is no %s file containing learned information about your devices. "
+ "This is normal for first start of Govee integration.",
self._config_dir + LEARNING_STORAGE_YAML,
)
except (
dacite.DaciteError,
TypeError,
UnicodeDecodeError,
yaml.YAMLError,
) as ex:
_LOGGER.warning(
"The %s file containing learned information about your devices is invalid: %s. "
+ "Learning starts from scratch.",
self._config_dir + LEARNING_STORAGE_YAML,
ex,
)
return learned_info
async def write(self, learned_info):
"""Save to yaml file."""
leaned_dict = {device: asdict(learned_info[device]) for device in learned_info}
save_yaml(self._config_dir + LEARNING_STORAGE_YAML, leaned_dict)
_LOGGER.info(
"Stored learning information to %s.",
self._config_dir + LEARNING_STORAGE_YAML,
)

View File

@@ -0,0 +1,325 @@
"""Govee platform."""
from datetime import timedelta, datetime
import logging
from govee_api_laggat import Govee, GoveeDevice, GoveeError
from govee_api_laggat.govee_dtos import GoveeSource
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_COLOR_TEMP,
ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS,
SUPPORT_COLOR,
SUPPORT_COLOR_TEMP,
LightEntity,
)
from homeassistant.const import CONF_DELAY
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util import color
from .const import (
DOMAIN,
CONF_OFFLINE_IS_OFF,
CONF_USE_ASSUMED_STATE,
COLOR_TEMP_KELVIN_MIN,
COLOR_TEMP_KELVIN_MAX,
)
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass, entry, async_add_entities):
"""Set up the Govee Light platform."""
_LOGGER.debug("Setting up Govee lights")
config = entry.data
options = entry.options
hub = hass.data[DOMAIN]["hub"]
# refresh
update_interval = timedelta(
seconds=options.get(CONF_DELAY, config.get(CONF_DELAY, 10))
)
coordinator = GoveeDataUpdateCoordinator(
hass, _LOGGER, update_interval=update_interval, config_entry=entry
)
# Fetch initial data so we have data when entities subscribe
hub.events.new_device += lambda device: add_entity(
async_add_entities, hub, entry, coordinator, device
)
await coordinator.async_refresh()
# Add devices
for device in hub.devices:
add_entity(async_add_entities, hub, entry, coordinator, device)
# async_add_entities(
# [
# GoveeLightEntity(hub, entry.title, coordinator, device)
# for device in hub.devices
# ],
# update_before_add=False,
# )
def add_entity(async_add_entities, hub, entry, coordinator, device):
async_add_entities(
[GoveeLightEntity(hub, entry.title, coordinator, device)],
update_before_add=False,
)
class GoveeDataUpdateCoordinator(DataUpdateCoordinator):
"""Device state update handler."""
def __init__(self, hass, logger, update_interval=None, *, config_entry):
"""Initialize global data updater."""
self._config_entry = config_entry
super().__init__(
hass,
logger,
name=DOMAIN,
update_interval=update_interval,
update_method=self._async_update,
)
@property
def use_assumed_state(self):
"""Use assumed states."""
return self._config_entry.options.get(CONF_USE_ASSUMED_STATE, True)
@property
def config_offline_is_off(self):
"""Interpret offline led's as off (global config)."""
return self._config_entry.options.get(CONF_OFFLINE_IS_OFF, False)
async def _async_update(self):
"""Fetch data."""
self.logger.debug("_async_update")
if "govee" not in self.hass.data:
raise UpdateFailed("Govee instance not available")
try:
hub = self.hass.data[DOMAIN]["hub"]
if not hub.online:
# when offline, check connection, this will set hub.online
await hub.check_connection()
if hub.online:
# set global options to library
if self.config_offline_is_off:
hub.config_offline_is_off = True
else:
hub.config_offline_is_off = None # allow override in learning info
# govee will change this to a single request in 2021
device_states = await hub.get_states()
for device in device_states:
if device.error:
self.logger.warning(
"update failed for %s: %s", device.device, device.error
)
return device_states
except GoveeError as ex:
raise UpdateFailed(f"Exception on getting states: {ex}") from ex
class GoveeLightEntity(LightEntity):
"""Representation of a stateful light entity."""
def __init__(
self,
hub: Govee,
title: str,
coordinator: GoveeDataUpdateCoordinator,
device: GoveeDevice,
):
"""Init a Govee light strip."""
self._hub = hub
self._title = title
self._coordinator = coordinator
self._device = device
@property
def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry."""
return True
async def async_added_to_hass(self):
"""Connect to dispatcher listening for entity data notifications."""
self._coordinator.async_add_listener(self.async_write_ha_state)
@property
def _state(self):
"""Lights internal state."""
return self._device # self._hub.state(self._device)
@property
def supported_features(self):
"""Flag supported features."""
support_flags = 0
if self._device.support_brightness:
support_flags |= SUPPORT_BRIGHTNESS
if self._device.support_color:
support_flags |= SUPPORT_COLOR
if self._device.support_color_tem:
support_flags |= SUPPORT_COLOR_TEMP
return support_flags
async def async_turn_on(self, **kwargs):
"""Turn device on."""
_LOGGER.debug(
"async_turn_on for Govee light %s, kwargs: %s", self._device.device, kwargs
)
err = None
just_turn_on = True
if ATTR_HS_COLOR in kwargs:
hs_color = kwargs.pop(ATTR_HS_COLOR)
just_turn_on = False
col = color.color_hs_to_RGB(hs_color[0], hs_color[1])
_, err = await self._hub.set_color(self._device, col)
if ATTR_BRIGHTNESS in kwargs:
brightness = kwargs.pop(ATTR_BRIGHTNESS)
just_turn_on = False
bright_set = brightness - 1
_, err = await self._hub.set_brightness(self._device, bright_set)
if ATTR_COLOR_TEMP in kwargs:
color_temp = kwargs.pop(ATTR_COLOR_TEMP)
just_turn_on = False
color_temp_kelvin = color.color_temperature_mired_to_kelvin(color_temp)
if color_temp_kelvin > COLOR_TEMP_KELVIN_MAX:
color_temp_kelvin = COLOR_TEMP_KELVIN_MAX
elif color_temp_kelvin < COLOR_TEMP_KELVIN_MIN:
color_temp_kelvin = COLOR_TEMP_KELVIN_MIN
_, err = await self._hub.set_color_temp(self._device, color_temp_kelvin)
# if there is no known specific command - turn on
if just_turn_on:
_, err = await self._hub.turn_on(self._device)
# debug log unknown commands
if kwargs:
_LOGGER.debug(
"async_turn_on doesnt know how to handle kwargs: %s", repr(kwargs)
)
# warn on any error
if err:
_LOGGER.warning(
"async_turn_on failed with '%s' for %s, kwargs: %s",
err,
self._device.device,
kwargs,
)
async def async_turn_off(self, **kwargs):
"""Turn device off."""
_LOGGER.debug("async_turn_off for Govee light %s", self._device.device)
await self._hub.turn_off(self._device)
@property
def unique_id(self):
"""Return the unique ID."""
return f"govee_{self._title}_{self._device.device}"
@property
def device_id(self):
"""Return the ID."""
return self.unique_id
@property
def name(self):
"""Return the name."""
return self._device.device_name
@property
def device_info(self):
"""Return the device info."""
return {
"identifiers": {(DOMAIN, self.device_id)},
"name": self.name,
"manufacturer": "Govee",
"model": self._device.model,
"via_device": (DOMAIN, "Govee API (cloud)"),
}
@property
def is_on(self):
"""Return true if device is on."""
return self._device.power_state
@property
def assumed_state(self):
"""
Return true if the state is assumed.
This can be disabled in options.
"""
return (
self._coordinator.use_assumed_state
and self._device.source == GoveeSource.HISTORY
)
@property
def available(self):
"""Return if light is available."""
return self._device.online
@property
def hs_color(self):
"""Return the hs color value."""
return color.color_RGB_to_hs(
self._device.color[0],
self._device.color[1],
self._device.color[2],
)
@property
def rgb_color(self):
"""Return the rgb color value."""
return [
self._device.color[0],
self._device.color[1],
self._device.color[2],
]
@property
def brightness(self):
"""Return the brightness value."""
# govee is reporting 0 to 254 - home assistant uses 1 to 255
return self._device.brightness + 1
@property
def color_temp(self):
"""Return the color_temp of the light."""
if not self._device.color_temp:
return None
return color.color_temperature_kelvin_to_mired(self._device.color_temp)
@property
def min_mireds(self):
"""Return the coldest color_temp that this light supports."""
return color.color_temperature_kelvin_to_mired(COLOR_TEMP_KELVIN_MAX)
@property
def max_mireds(self):
"""Return the warmest color_temp that this light supports."""
return color.color_temperature_kelvin_to_mired(COLOR_TEMP_KELVIN_MIN)
@property
def extra_state_attributes(self):
"""Return the device state attributes."""
return {
# rate limiting information on Govee API
"rate_limit_total": self._hub.rate_limit_total,
"rate_limit_remaining": self._hub.rate_limit_remaining,
"rate_limit_reset_seconds": round(self._hub.rate_limit_reset_seconds, 2),
"rate_limit_reset": datetime.fromtimestamp(
self._hub.rate_limit_reset
).isoformat(),
"rate_limit_on": self._hub.rate_limit_on,
# general information
"manufacturer": "Govee",
"model": self._device.model,
}

View File

@@ -0,0 +1,15 @@
{
"domain": "govee",
"name": "Govee",
"codeowners": ["@LaggAt"],
"config_flow": true,
"dependencies": [],
"documentation": "https://github.com/LaggAt/hacs-govee/blob/master/README.md",
"homekit": {},
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/LaggAt/hacs-govee/issues",
"requirements": ["govee-api-laggat==0.2.2", "dacite==1.8.0"],
"ssdp": [],
"version": "2023.11.1",
"zeroconf": []
}

View File

@@ -0,0 +1,42 @@
{
"title": "Govee",
"config": {
"abort": {
"already_configured": "Already configured. Only a single configuration possible."
},
"error": {
"cannot_connect": "Cannot connect. Is the API-Key correct and the internet connection working?",
"unknown": "Unknown Error."
},
"step": {
"user": {
"data": {
"api_key": "API Key",
"delay": "Poll Interval"
},
"title": "",
"description": "Get your API Key from the Govee Home App. For Details see https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
},
"options": {
"error": {
"cannot_connect": "Cannot connect. Is the API-Key correct and the internet connection working?",
"unknown": "Unknown Error.",
"disabled_attribute_updates_wrong": "Wrong format, see README above."
},
"step": {
"user": {
"data": {
"api_key": "API Key (requires restart)",
"delay": "Poll Interval (requires restart)",
"use_assumed_state": "Use 'assumed state' (two buttons). Default: True",
"offline_is_off": "When a led is offline, show it as off (default doesn't change state). Default: False",
"disable_attribute_updates": "DISABLE state updates. Space to disable. Read the README above!"
},
"title": "Options",
"description": "Configure the Govee integration. For Details see https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
}
}

View File

@@ -0,0 +1,41 @@
{
"title": "Govee",
"config": {
"abort": {
"already_configured": "Bereits eingerichtet. Es ist nur eine Konfiguration möglich."
},
"error": {
"cannot_connect": "Keine Verbindung möglich. Ist der API-Key richtig und die Internet Verbindung in Ordnung?",
"unknown": "Unbekannter Fehler."
},
"step": {
"user": {
"data": {
"api_key": "API Key",
"delay": "Abfrage-Intervall"
},
"description": "Den API Key bekommen Sie in der Govee Home App. Details dazu hier: https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
},
"options": {
"error": {
"cannot_connect": "Keine Verbindung möglich. Ist der API-Key richtig und die Internet Verbindung in Ordnung?",
"unknown": "Unbekannter Fehler.",
"disabled_attribute_updates_wrong": "Format ist inkorrekt, bitte README lesen."
},
"step": {
"user": {
"data": {
"api_key": "API Key (benötigt Neustart)",
"delay": "Abfrage-Intervall (benötigt Neustart)",
"use_assumed_state": "Verwende 'angenommenen Zustand' (zwei Buttons). Standard: True",
"offline_is_off": "Wenn eine LED offline ist, zeige sie als Aus (Standard ändert den Status nicht). Standard: False",
"disable_attribute_updates": "Status updates verhindern. Leertaste zum ausschalten. Bitte das README oben dazu lesen."
},
"title": "Einstellungen",
"description": "Einstellen der Govee Integration. Details dazu hier: https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
}
}

View File

@@ -0,0 +1,41 @@
{
"title": "Govee",
"config": {
"abort": {
"already_configured": "Already configured. Only a single configuration possible."
},
"error": {
"cannot_connect": "Cannot connect. Is the API-Key correct and the internet connection working?",
"unknown": "Unknown Error."
},
"step": {
"user": {
"data": {
"api_key": "API Key",
"delay": "Poll Interval"
},
"description": "Get your API Key from the Govee Home App. For Details see https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
},
"options": {
"error": {
"cannot_connect": "Cannot connect. Is the API-Key correct and the internet connection working?",
"unknown": "Unknown Error.",
"disabled_attribute_updates_wrong": "Wrong format, see README above."
},
"step": {
"user": {
"data": {
"api_key": "API Key (requires restart)",
"delay": "Poll Interval (requires restart)",
"use_assumed_state": "Use 'assumed state' (two buttons). Default: True",
"offline_is_off": "When a led is offline, show it as off (default doesn't change state). Default: False",
"disable_attribute_updates": "DISABLE state updates. Space to disable. Read the README above!"
},
"title": "Options",
"description": "Configure the Govee integration. For Details see https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
}
}

View File

@@ -0,0 +1,41 @@
{
"title": "Govee",
"config": {
"abort": {
"already_configured": "Déjà configuré. Une seule configuration possible."
},
"error": {
"cannot_connect": "Impossible de se connecter. La clé d'API est-elle correcte et la connexion Internet fonctionne-t-elle?",
"unknown": "Erreure inconnue."
},
"step": {
"user": {
"data": {
"api_key": "clé d'API",
"delay": "Intervalle d'interrogation"
},
"description": "Obtenez votre clé API à partir de l'application Govee Home. Pour plus de détails, visitez https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
},
"options": {
"error": {
"cannot_connect": "Impossible de se connecter. La clé d'API est-elle correcte et la connexion Internet fonctionne-t-elle?",
"unknown": "Erreure inconnue.",
"disabled_attribute_updates_wrong": "Format incorrect, voir le 'lisez-moi' ci-dessus."
},
"step": {
"user": {
"data": {
"api_key": "Clé d'API (nécessite un redémarrage)",
"delay": "Intervalle d'interrogation (nécessite un redémarrage)",
"use_assumed_state": "Utiliser 'état supposé' (deux boutons). Par défaut : Vrai",
"offline_is_off": "Lorsqu'une DEL est hors ligne, affichez-la comme éteinte (la valeur par défaut ne change pas d'état). Par défaut : Faux",
"disable_attribute_updates": "DÉSACTIVER les mises à jour d'état. Espace pour désactiver. Lisez le 'lisez-moi' ci-dessus !"
},
"title": "Options",
"description": "Configurez l'intégration Govee. Pour plus de détails, visitez https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
}
}

View File

@@ -0,0 +1,41 @@
{
"title": "Govee",
"config": {
"abort": {
"already_configured": "Já configurado. Apenas uma única configuração é possível."
},
"error": {
"cannot_connect": "Não pode conectar. A API-Key está correta e a conexão com a Internet está funcionando?",
"unknown": "Erro desconhecido."
},
"step": {
"user": {
"data": {
"api_key": "Chave de API",
"delay": "Intervalo de escaneamento"
},
"description": "Obtenha sua chave de API do aplicativo Govee Home. Para detalhes consulte https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
},
"options": {
"error": {
"cannot_connect": "Não pode conectar. A API-Key está correta e a conexão com a Internet está funcionando?",
"unknown": "Erro desconhecido.",
"disabled_attribute_updates_wrong": "Formato errado, veja README acima."
},
"step": {
"user": {
"data": {
"api_key": "Chave de API (requer reinicialização)",
"delay": "Intervalo de escaneamento (requer reinicialização)",
"use_assumed_state": "Use 'estado presumido' (dois botões). Padrão: true",
"offline_is_off": "Quando um led estiver offline, mostre-o como desligado (o padrão não muda de estado). Padrão: False",
"disable_attribute_updates": "DESATIVAR atualizações de estado. Espaço para desativar. Leia o README acima!"
},
"title": "Opções",
"description": "Configure a integração do Govee. Para detalhes consulte https://github.com/LaggAt/hacs-govee/blob/master/README.md"
}
}
}
}