mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-15 00:04:05 +02:00
fix: entity translations were dead, and both validators disabled themselves
Entity._name_internal returns _attr_name before it ever consults translation_key (homeassistant/helpers/entity.py:689). sensor.py and number.py set both, so every entity.sensor.* and entity.number.* string added to strings.json has been unreachable — the five sliders and five sensors rendered English regardless of the user's language, bolted onto an integration that is otherwise translated into 36. Dropping the three _attr_name assignments makes the keys live; display_name was then a dead constructor parameter and goes too. Two keys existed in strings.json but not translations/en.json (ambient_lux, lux_reduction) and ramp_half_width was in neither, so a bare deletion would have left three entities unnamed. Added them to both files. ambient_lux carries unit lx and is textbook SensorDeviceClass.ILLUMINANCE; it was inheriting the class-level _attr_device_class = None along with the four curve outputs that genuinely have no equivalent. Without it the sensor loses standard icon, unit handling and long-term-statistics grouping. Now a per-key lookup, so the outputs keep their honest None. The five number entities are behaviour knobs, not state — EntityCategory.CONFIG moves them off the primary device page. Both validate.yml and hassfest.yaml carried `schedule: cron "0 0 * * *"`, and GitHub auto-disables any workflow with a schedule after 60 days of repository inactivity. Both were taken out on 2026-09-08, 60 days after the last push. A disabled workflow also stops answering push and pull_request, so this repo now has no HACS or hassfest validation at all. Removing the cron is the durable fix; re-enabling in the UI just restarts the same clock. README claimed the tanh ramp has "a fixed 30-minute half-width" 60 lines above documenting the live 5-120 min slider that replaced it. 164 tests pass, ruff clean.
This commit is contained in:
parent
d5dc129c11
commit
6725f164aa
7 changed files with 58 additions and 31 deletions
6
.github/workflows/hassfest.yaml
vendored
6
.github/workflows/hassfest.yaml
vendored
|
|
@ -4,9 +4,11 @@ on:
|
|||
push:
|
||||
branches: [main, master]
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
# No schedule: GitHub auto-disables any workflow containing one after 60
|
||||
# days of repository inactivity, and a disabled workflow stops answering
|
||||
# push and pull_request too. Both of this repo's validators were taken
|
||||
# out that way on 2026-09-08.
|
||||
|
||||
jobs:
|
||||
validate_hassfest:
|
||||
|
|
|
|||
6
.github/workflows/validate.yml
vendored
6
.github/workflows/validate.yml
vendored
|
|
@ -4,9 +4,11 @@ on:
|
|||
push:
|
||||
branches: [main, master]
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
# No schedule: GitHub auto-disables any workflow containing one after 60
|
||||
# days of repository inactivity, and a disabled workflow stops answering
|
||||
# push and pull_request too. Both of this repo's validators were taken
|
||||
# out that way on 2026-09-08.
|
||||
|
||||
jobs:
|
||||
validate_hacs:
|
||||
|
|
|
|||
|
|
@ -67,8 +67,9 @@
|
|||
> (`sensor.sun2_dawn`, `sensor.sun2_astro_dawn`, etc.) work without code
|
||||
> changes — see "Recommended companions" below.
|
||||
> 3. **Synthetic tanh curve** — brightness and color temperature follow a
|
||||
> smooth tanh ramp anchored at the two sun events with a fixed 30-minute
|
||||
> half-width. No `brightness_mode` selector to fiddle with.
|
||||
> smooth tanh ramp anchored at the two sun events, with a half-width you can
|
||||
> tune live (5-120 min, default 30). No `brightness_mode` selector to fiddle
|
||||
> with.
|
||||
> 4. **Fewer features, on purpose** — sleep mode, take-over-control, manual
|
||||
> sun-time overrides, `only_once`, and `adapt_only_on_bare_turn_on` are
|
||||
> **removed**. Manual overrides are expected to live at the
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ from homeassistant.components.number import (
|
|||
NumberMode,
|
||||
RestoreNumber,
|
||||
)
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
|
||||
|
|
@ -56,7 +57,6 @@ async def async_setup_entry(
|
|||
field_key=row["field_key"],
|
||||
conf_key=row["conf_key"],
|
||||
default=row["default"],
|
||||
display_name=row["name"],
|
||||
native_min=row["native_min"],
|
||||
native_max=row["native_max"],
|
||||
step=row["step"],
|
||||
|
|
@ -75,6 +75,8 @@ class AdaptiveRangeNumber(RestoreNumber):
|
|||
_attr_has_entity_name = True
|
||||
_attr_mode = NumberMode.SLIDER
|
||||
_attr_should_poll = False
|
||||
# Behaviour knobs, not state — keep them off the primary device page.
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
|
@ -83,7 +85,6 @@ class AdaptiveRangeNumber(RestoreNumber):
|
|||
field_key: str,
|
||||
conf_key: str,
|
||||
default: float,
|
||||
display_name: str,
|
||||
native_min: float,
|
||||
native_max: float,
|
||||
step: float,
|
||||
|
|
@ -95,7 +96,7 @@ class AdaptiveRangeNumber(RestoreNumber):
|
|||
self._field_key = field_key
|
||||
self._conf_key = conf_key
|
||||
self._default = default
|
||||
self._attr_name = display_name
|
||||
# No _attr_name — see the note in sensor.py.
|
||||
self._attr_translation_key = field_key
|
||||
self._attr_unique_id = f"{entry.entry_id}_{field_key}"
|
||||
self._attr_native_min_value = native_min
|
||||
|
|
@ -197,13 +198,14 @@ class AdaptiveRampWidthNumber(RestoreNumber):
|
|||
_attr_has_entity_name = True
|
||||
_attr_mode = NumberMode.SLIDER
|
||||
_attr_should_poll = False
|
||||
# Behaviour knobs, not state — keep them off the primary device page.
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
|
||||
def __init__(self, *, entry: ConfigEntry) -> None:
|
||||
"""Initialise the ramp half-width entity from its const declaration."""
|
||||
self._entry = entry
|
||||
self._field_key: str = RAMP_WIDTH_ENTITY["field_key"]
|
||||
self._default: float = float(RAMP_WIDTH_ENTITY["default"])
|
||||
self._attr_name = RAMP_WIDTH_ENTITY["name"]
|
||||
self._attr_translation_key = self._field_key
|
||||
self._attr_unique_id = f"{entry.entry_id}_{self._field_key}"
|
||||
self._attr_native_min_value = RAMP_WIDTH_ENTITY["native_min"]
|
||||
|
|
|
|||
|
|
@ -18,7 +18,11 @@ from __future__ import annotations
|
|||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from homeassistant.components.sensor import SensorEntity, SensorStateClass
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
|
@ -49,7 +53,6 @@ async def async_setup_entry(
|
|||
hass=hass,
|
||||
entry=config_entry,
|
||||
output_key=row["key"],
|
||||
display_name=row["name"],
|
||||
unit=row["unit"],
|
||||
icon=row["icon"],
|
||||
)
|
||||
|
|
@ -59,13 +62,17 @@ async def async_setup_entry(
|
|||
async_add_entities(entities)
|
||||
|
||||
|
||||
# Only ambient_lux maps onto a standard HA device class. The rest are AL curve
|
||||
# outputs with no equivalent, and claiming one would break their unit handling.
|
||||
_SENSOR_DEVICE_CLASSES = {"ambient_lux": SensorDeviceClass.ILLUMINANCE}
|
||||
|
||||
|
||||
class AdaptiveOutputSensor(SensorEntity):
|
||||
"""One read-only output value from an AL profile's curve tick."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
_attr_should_poll = False
|
||||
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||
_attr_device_class = None # explicit — no fitting HA device class
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
|
@ -73,7 +80,6 @@ class AdaptiveOutputSensor(SensorEntity):
|
|||
hass: HomeAssistant,
|
||||
entry: ConfigEntry,
|
||||
output_key: str,
|
||||
display_name: str,
|
||||
unit: str,
|
||||
icon: str,
|
||||
) -> None:
|
||||
|
|
@ -81,8 +87,10 @@ class AdaptiveOutputSensor(SensorEntity):
|
|||
self._hass = hass
|
||||
self._entry = entry
|
||||
self._output_key = output_key
|
||||
self._attr_name = display_name
|
||||
# No _attr_name: Entity._name_internal returns it before it ever
|
||||
# consults translation_key, which would leave every translation dead.
|
||||
self._attr_translation_key = output_key
|
||||
self._attr_device_class = _SENSOR_DEVICE_CLASSES.get(output_key)
|
||||
self._attr_unique_id = f"{entry.entry_id}_{output_key}"
|
||||
self._attr_native_unit_of_measurement = unit
|
||||
self._attr_icon = icon
|
||||
|
|
|
|||
|
|
@ -258,20 +258,29 @@
|
|||
},
|
||||
"entity": {
|
||||
"number": {
|
||||
"min_brightness": {
|
||||
"name": "Brightness lower"
|
||||
},
|
||||
"max_brightness": {
|
||||
"name": "Brightness upper"
|
||||
},
|
||||
"max_color_temp": {
|
||||
"name": "Color temp upper"
|
||||
},
|
||||
"min_brightness": {
|
||||
"name": "Brightness lower"
|
||||
},
|
||||
"min_color_temp": {
|
||||
"name": "Color temp lower"
|
||||
},
|
||||
"max_color_temp": {
|
||||
"name": "Color temp upper"
|
||||
"ramp_half_width": {
|
||||
"name": "Ramp half-width"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"ambient_lux": {
|
||||
"name": "Ambient lux"
|
||||
},
|
||||
"lux_reduction": {
|
||||
"name": "Lux reduction"
|
||||
},
|
||||
"output_brightness": {
|
||||
"name": "Output brightness"
|
||||
},
|
||||
|
|
@ -280,12 +289,6 @@
|
|||
},
|
||||
"sun_elevation": {
|
||||
"name": "Sun elevation"
|
||||
},
|
||||
"ambient_lux": {
|
||||
"name": "Ambient lux"
|
||||
},
|
||||
"lux_reduction": {
|
||||
"name": "Lux reduction"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -246,20 +246,29 @@
|
|||
},
|
||||
"entity": {
|
||||
"number": {
|
||||
"min_brightness": {
|
||||
"name": "Brightness lower"
|
||||
},
|
||||
"max_brightness": {
|
||||
"name": "Brightness upper"
|
||||
},
|
||||
"max_color_temp": {
|
||||
"name": "Color temp upper"
|
||||
},
|
||||
"min_brightness": {
|
||||
"name": "Brightness lower"
|
||||
},
|
||||
"min_color_temp": {
|
||||
"name": "Color temp lower"
|
||||
},
|
||||
"max_color_temp": {
|
||||
"name": "Color temp upper"
|
||||
"ramp_half_width": {
|
||||
"name": "Ramp half-width"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"ambient_lux": {
|
||||
"name": "Ambient lux"
|
||||
},
|
||||
"lux_reduction": {
|
||||
"name": "Lux reduction"
|
||||
},
|
||||
"output_brightness": {
|
||||
"name": "Output brightness"
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue