mirror of
https://github.com/basnijholt/adaptive-lighting.git
synced 2026-09-15 08:14:04 +02:00
Delete upstream docs apparatus; rewrite README for the fork
The CDiT fork is single-household and was carrying an entire upstream docs/ mkdocs site documenting features the fork has removed (sleep mode, take-over-control, brightness_mode selector, YAML config). The README mostly auto-generated from those pages via markdown-code-runner. What's gone: - docs/ — all 11 pages + assets + run_markdown_code_runner.py - .github/workflows/docs.yml — zensical+shinylive GitHub Pages build - .github/workflows/markdown-code-runner.yml — auto-edit of README from docs/ - .github/update-services.py / update-strings.py — would clobber the hand-edited services.yaml / strings.json - scripts/update-generated-content — orchestrator for the above - custom_components/adaptive_lighting/_docs_helpers.py + docs_gen.py — only used by the deleted markdown-code-runner - zensical.toml — docs-site config - "docs" dependency group in pyproject.toml (markdown-code-runner, shinylive, zensical, etc.) + lock regenerated What's new: - README.md rewritten to describe the fork's actual surface — 3 switches, 4 number entities, 3 sensor entities per profile, 2 services (apply + change_switch_settings), entry-only setup, UI tuning, sun source. Preserves the existing "What's new in 2.1" / "2.2" block quotes. - webapp/README.md annotated to flag the Shiny simulator models the upstream curve (with brightness_mode, sleep mode, etc.) and does not reflect the fork. - CLAUDE.md command table no longer references update-generated-content. Sensor.py + test_sensor_platform.py: incidental black reformat from the lint pass (multi-arg function calls split per line). Tests still pass (123/123). Lint clean. Sensors implementation unchanged.
This commit is contained in:
parent
1b21228b30
commit
bba0ef31d8
31 changed files with 165 additions and 2999 deletions
27
.github/update-services.py
vendored
27
.github/update-services.py
vendored
|
|
@ -1,27 +0,0 @@
|
|||
"""Creates a services.yaml file with the latest docs."""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
sys.path.append(str(Path(__file__).parent.parent))
|
||||
|
||||
from custom_components.adaptive_lighting import const
|
||||
|
||||
services_filename = Path("custom_components") / "adaptive_lighting" / "services.yaml"
|
||||
with open(services_filename) as f: # noqa: PTH123
|
||||
services = yaml.safe_load(f)
|
||||
|
||||
for service_name, dct in services.items():
|
||||
_docs = {"set_manual_control": const.DOCS_MANUAL_CONTROL, "apply": const.DOCS_APPLY}
|
||||
alternative_docs = _docs.get(service_name, const.DOCS)
|
||||
for field_name, field in dct["fields"].items():
|
||||
description = alternative_docs.get(field_name, const.DOCS[field_name])
|
||||
field["description"] = description
|
||||
|
||||
comment = "# This file is auto-generated by .github/update-services.py."
|
||||
|
||||
with services_filename.open("w") as f:
|
||||
f.write(comment + "\n")
|
||||
yaml.dump(services, f, sort_keys=False, width=1000, allow_unicode=True)
|
||||
70
.github/update-strings.py
vendored
70
.github/update-strings.py
vendored
|
|
@ -1,70 +0,0 @@
|
|||
"""Update strings.json and en.json from const.py."""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import yaml
|
||||
|
||||
sys.path.append(str(Path(__file__).parent.parent))
|
||||
|
||||
from custom_components.adaptive_lighting import const
|
||||
|
||||
folder = Path("custom_components") / "adaptive_lighting"
|
||||
strings_fname = folder / "strings.json"
|
||||
en_fname = folder / "translations" / "en.json"
|
||||
with strings_fname.open() as f:
|
||||
strings = json.load(f)
|
||||
|
||||
# Set "options"
|
||||
data = {}
|
||||
data_description = {}
|
||||
for k, _, typ in const.VALIDATION_TUPLES:
|
||||
desc = const.DOCS[k]
|
||||
if len(desc) > 40 and typ not in (bool, cv.entity_ids):
|
||||
data[k] = k
|
||||
data_description[k] = desc
|
||||
else:
|
||||
data[k] = f"{k}: {desc}"
|
||||
strings["options"]["step"]["init"]["data"] = data
|
||||
strings["options"]["step"]["init"]["data_description"] = data_description
|
||||
|
||||
# Set "services"
|
||||
services_filename = Path("custom_components") / "adaptive_lighting" / "services.yaml"
|
||||
with open(services_filename) as f: # noqa: PTH123
|
||||
services = yaml.safe_load(f)
|
||||
services_json = {}
|
||||
for service_name, dct in services.items():
|
||||
services_json[service_name] = {
|
||||
"name": service_name,
|
||||
"description": dct["description"],
|
||||
"fields": {},
|
||||
}
|
||||
for field_name, field in dct["fields"].items():
|
||||
services_json[service_name]["fields"][field_name] = {
|
||||
"description": field["description"],
|
||||
"name": field_name,
|
||||
}
|
||||
strings["services"] = services_json
|
||||
|
||||
# Write changes to strings.json
|
||||
with strings_fname.open("w") as f:
|
||||
json.dump(strings, f, indent=2, ensure_ascii=False)
|
||||
f.write("\n")
|
||||
|
||||
# Sync changes from strings.json to en.json
|
||||
with en_fname.open() as f:
|
||||
en = json.load(f)
|
||||
|
||||
en["config"]["step"]["user"] = strings["config"]["step"]["user"]
|
||||
en["options"]["step"]["init"]["data"] = data
|
||||
en["options"]["step"]["init"]["data_description"] = data_description
|
||||
en["options"]["step"]["init"]["description"] = strings["options"]["step"]["init"][
|
||||
"description"
|
||||
]
|
||||
en["services"] = services_json
|
||||
|
||||
with en_fname.open("w") as f:
|
||||
json.dump(en, f, indent=2, ensure_ascii=False)
|
||||
f.write("\n")
|
||||
64
.github/workflows/docs.yml
vendored
64
.github/workflows/docs.yml
vendored
|
|
@ -1,64 +0,0 @@
|
|||
name: Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: "pages"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.14.2'
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v8.1.0
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --group docs
|
||||
|
||||
- name: Build documentation
|
||||
run: uv run zensical build
|
||||
|
||||
- name: Build webapp (simulator)
|
||||
run: uv run shinylive export webapp webapp-site
|
||||
|
||||
- name: Integrate webapp into docs
|
||||
run: |
|
||||
# Copy webapp into docs site at /simulator/
|
||||
mkdir -p site/simulator
|
||||
cp -r webapp-site/* site/simulator/
|
||||
echo "Webapp integrated at site/simulator/"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v5
|
||||
with:
|
||||
path: ./site
|
||||
|
||||
deploy:
|
||||
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v5
|
||||
48
.github/workflows/markdown-code-runner.yml
vendored
48
.github/workflows/markdown-code-runner.yml
vendored
|
|
@ -1,48 +0,0 @@
|
|||
name: markdown-code-runner
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
markdown-code-runner:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }}
|
||||
ref: ${{ github.head_ref || github.ref }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14.2"
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v8.1.0
|
||||
|
||||
- name: Update generated content
|
||||
run: ./scripts/update-generated-content
|
||||
|
||||
- name: Check for changes
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain)" ]; then
|
||||
if [ "${{ github.event_name }}" == "pull_request" ]; then
|
||||
echo "::error::Auto-generated files are not up to date. Please run './scripts/update-generated-content' locally and push the changes."
|
||||
exit 1
|
||||
else
|
||||
echo "Changes detected, committing and pushing..."
|
||||
git add -u .
|
||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --local user.name "github-actions[bot]"
|
||||
git commit -m "Update auto-generated content"
|
||||
git pull --rebase
|
||||
git push
|
||||
fi
|
||||
else
|
||||
echo "No changes detected."
|
||||
fi
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -68,9 +68,6 @@ instance/
|
|||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ Python tooling is `uv` (not `pip` or `poetry`). All commands assume an activated
|
|||
| Run a single test | `uv run pytest tests/test_config_flow.py::test_options_flow_init` |
|
||||
| Lint everything (pre-commit) | `./scripts/lint` |
|
||||
| Run HA locally with the custom component loaded | `./scripts/develop` (boots HA on `localhost:8123` from `./config/`) |
|
||||
| Update generated docs/content in README | `./scripts/update-generated-content` |
|
||||
| Refresh test matrix | `./scripts/update-test-matrix.py` |
|
||||
|
||||
Ruff config lives in `.ruff.toml`. Pre-commit hooks in `.pre-commit-config.yaml`. Both enforce on push via `./scripts/lint`.
|
||||
|
|
|
|||
792
README.md
792
README.md
|
|
@ -125,697 +125,191 @@
|
|||
> - entity: sensor.dining_mvp_output_color_temp
|
||||
> - entity: sensor.dining_mvp_sun_elevation
|
||||
> ```
|
||||
>
|
||||
> The rest of this README is from upstream and may describe features that no
|
||||
> longer exist in this fork. See `CHANGELOG.md` for the canonical list of
|
||||
> CDiT-specific changes.
|
||||
|
||||
---
|
||||
|
||||
# 🌞 Adaptive Lighting: Enhance Your Home's Atmosphere with Smart, Sun-Synchronized Lighting 🌙
|
||||
# 🌞 Adaptive Lighting (CDiT fork)
|
||||
|
||||
<img src="https://raw.githubusercontent.com/home-assistant/brands/master/custom_integrations/adaptive_lighting/icon@2x.png" alt="logo" width="256px" height="256px" />
|
||||
A Home Assistant custom component that adapts light brightness and color
|
||||
temperature to a sun-driven tanh curve. Each profile owns a set of lights
|
||||
and exposes three switches, four live-tunable sliders, and three graphable
|
||||
sensors per profile.
|
||||
|
||||
[Adaptive Lighting](https://github.com/basnijholt/adaptive-lighting) is a custom component for [Home Assistant](https://www.home-assistant.io/) that intelligently adjusts the brightness and color of your lights 💡 based on the sun's position, while still allowing for manual control.
|
||||
## Install
|
||||
|
||||
Download and install directly through [HACS (Home Assistant Community Store)](https://hacs.xyz/):
|
||||
Via HACS as a custom repository (this fork is not in the HACS default index):
|
||||
|
||||
[](https://my.home-assistant.io/redirect/hacs_repository/?owner=basnijholt&repository=adaptive-lighting&category=integration)
|
||||
1. HACS → Integrations → ⋮ → Custom repositories.
|
||||
2. Add `https://github.com/CaseyRo/adaptive-lighting` as an **Integration**.
|
||||
3. Install **Adaptive Lighting (CDiT)**.
|
||||
4. Restart Home Assistant.
|
||||
|
||||
By automatically adapting the settings of your lights throughout the day, Adaptive Lighting helps maintain your natural circadian rhythm 😴, which can lead to improved sleep, mood, and overall well-being. Experience cooler color temperatures at noon, gradually transitioning to warmer colors at sunset and sunrise.
|
||||
Or manually copy `custom_components/adaptive_lighting/` into your HA
|
||||
config's `custom_components/` directory and restart.
|
||||
|
||||
In addition to its regular mode, Adaptive Lighting also offers a "sleep mode" 🌜 which sets your lights to minimal brightness and a very warm color, perfect for winding down at night.
|
||||
## Setup
|
||||
|
||||
> 🌈 Visualize Adaptive Lighting's settings with the [_🌞 Adaptive Lighting Simulator WebApp 🌛_](https://basnijholt.github.io/adaptive-lighting)
|
||||
UI-only — there is no YAML schema in this fork. Existing
|
||||
`adaptive_lighting:` blocks in `configuration.yaml` are ignored.
|
||||
|
||||
https://github.com/basnijholt/adaptive-lighting/assets/6897215/68908f7d-fbf1-4991-98ce-3f2af6df996f
|
||||
1. Settings → Devices & Services → **Add Integration** → **Adaptive Lighting**.
|
||||
2. Name the profile (e.g., `Kitchen`).
|
||||
3. Click ⚙️ Configure on the new entry to open the sectioned options dialog
|
||||
and pick lights, sun-time entities, and curve bounds.
|
||||
|
||||
[[ToC](#books-table-of-contents)]
|
||||
A profile can be **edited** any time via the same ⚙️ Configure menu — saving
|
||||
reloads the integration via `OptionsFlowWithReload` (no restart needed).
|
||||
|
||||
<!-- SECTION:features:START -->
|
||||
## :bulb: Features
|
||||
## What each profile creates
|
||||
|
||||
When initially turning on a light that is controlled by Adaptive Lighting, the `light.turn_on` service call is intercepted, and the light's brightness and color are automatically adjusted based on the sun's position.
|
||||
After that, the light's brightness and color are automatically adjusted at a regular interval.
|
||||
For a profile named `Kitchen`:
|
||||
|
||||
Adaptive Lighting provides four switches (using "living_room" as an example component name):
|
||||
### Switches (3)
|
||||
|
||||
- `switch.adaptive_lighting_living_room`: Turn Adaptive Lighting on or off and view current light settings through its attributes.
|
||||
- `switch.adaptive_lighting_sleep_mode_living_room`: Activate "sleep mode" 😴 and set custom sleep_brightness and sleep_color_temp.
|
||||
- `switch.adaptive_lighting_adapt_brightness_living_room`: Enable or disable brightness adaptation 🔆 for supported lights.
|
||||
- `switch.adaptive_lighting_adapt_color_living_room`: Enable or disable color adaptation 🌈 for supported lights.
|
||||
<!-- SECTION:features:END -->
|
||||
| Entity | Role |
|
||||
|---|---|
|
||||
| `switch.kitchen` | Master on/off — when off, no adaptation runs |
|
||||
| `switch.kitchen_brightness` | Toggle brightness adaptation only |
|
||||
| `switch.kitchen_color` | Toggle color-temperature adaptation only |
|
||||
|
||||
<!-- SECTION:manual-control:START -->
|
||||
### :control_knobs: Regain Manual Control
|
||||
### Number entities (4) — live-tunable sliders
|
||||
|
||||
Adaptive Lighting is designed to automatically detect when you or another source (e.g., automation) manually changes light settings 🕹️.
|
||||
When this occurs, the affected light is marked as "manually controlled," and Adaptive Lighting will not make further adjustments until the light is turned off and back on or reset using the `adaptive_lighting.set_manual_control` service call.
|
||||
This feature is available when `take_over_control` is enabled.
|
||||
| Entity | Range | Step | Persist |
|
||||
|---|---|---|---|
|
||||
| `number.kitchen_min_brightness` | 1–100 % | 1 | RestoreNumber |
|
||||
| `number.kitchen_max_brightness` | 1–100 % | 1 | RestoreNumber |
|
||||
| `number.kitchen_min_color_temp` | 1000–10000 K | 100 | RestoreNumber |
|
||||
| `number.kitchen_max_color_temp` | 1000–10000 K | 100 | RestoreNumber |
|
||||
|
||||
Additionally, enabling `detect_non_ha_changes` allows Adaptive Lighting to detect all state changes, including those made outside of Home Assistant, by comparing the light's state to its previously used settings.
|
||||
The `adaptive_lighting.manual_control` event is fired when a light is marked as "manually controlled," allowing for integration with automations 🤖.
|
||||
Slider position is the runtime truth — the curve reads from the entity on
|
||||
every tick. No integration reload on slider change. Values survive HA
|
||||
restarts. The options dialog re-seeds these values from the entities on
|
||||
open and overwrites them on save (explicit gesture wins).
|
||||
|
||||
> ⚠️ **_Caution: Some lights might falsely indicate an 'on' state, which could result in lights turning on unexpectedly. Disable `detect_non_ha_changes` if you encounter such issues._**
|
||||
<!-- SECTION:manual-control:END -->
|
||||
### Sensor entities (3) — graphable outputs
|
||||
|
||||
## :books: Table of Contents
|
||||
| Entity | Unit | Source |
|
||||
|---|---|---|
|
||||
| `sensor.kitchen_output_brightness` | % | `self._settings["brightness_pct"]` |
|
||||
| `sensor.kitchen_output_color_temp` | K | `self._settings["color_temp_kelvin"]` |
|
||||
| `sensor.kitchen_sun_elevation` | ° | `sun.sun.attributes.elevation` |
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
All three are `state_class: measurement` so HA's recorder graphs them as
|
||||
continuous numeric series. Drop them into `apexcharts-card`,
|
||||
`mini-graph-card`, or the built-in History panel.
|
||||
|
||||
- [:gear: Configuration](#gear-configuration)
|
||||
- [:memo: Options](#memo-options)
|
||||
- [:hammer_and_wrench: Services](#hammer_and_wrench-services)
|
||||
- [`adaptive_lighting.apply`](#adaptive_lightingapply)
|
||||
- [`adaptive_lighting.set_manual_control`](#adaptive_lightingset_manual_control)
|
||||
- [`adaptive_lighting.change_switch_settings`](#adaptive_lightingchange_switch_settings)
|
||||
- [:robot: Automation examples](#robot-automation-examples)
|
||||
- [Additional Information](#additional-information)
|
||||
- [:sos: Troubleshooting](#sos-troubleshooting)
|
||||
- [:exclamation: Common Problems & Solutions](#exclamation-common-problems--solutions)
|
||||
- [:bulb: Lights Not Responding or Turning On by Themselves](#bulb-lights-not-responding-or-turning-on-by-themselves)
|
||||
- [:signal_strength: WiFi Networks](#signal_strength-wifi-networks)
|
||||
- [:spider_web: Zigbee, Z-Wave, and Other Mesh Networks](#spider_web-zigbee-z-wave-and-other-mesh-networks)
|
||||
- [:rainbow: Light Colors Not Matching](#rainbow-light-colors-not-matching)
|
||||
- [:bulb: Bulb-Specific Issues](#bulb-bulb-specific-issues)
|
||||
- [:bar_chart: Graphs!](#bar_chart-graphs)
|
||||
- [:sunny: Sun Position](#sunny-sun-position)
|
||||
- [:thermometer: Color Temperature](#thermometer-color-temperature)
|
||||
- [:high_brightness: Brightness](#high_brightness-brightness)
|
||||
- [While using `transition_until_sleep: true`](#while-using-transition_until_sleep-true)
|
||||
- [Custom brightness ramps using `brightness_mode` with `"linear"` and `"tanh"`](#custom-brightness-ramps-using-brightness_mode-with-linear-and-tanh)
|
||||
- [:eyes: See also](#eyes-see-also)
|
||||
- [:busts_in_silhouette: Contributors](#busts_in_silhouette-contributors)
|
||||
- [Translating Adaptive Lighting](#translating-adaptive-lighting)
|
||||
The master switch also exposes the curve's internal values as attributes
|
||||
(`brightness_pct`, `color_temp_kelvin`, synthetic `sun_position` in
|
||||
[-1, +1], etc.) — those are unchanged from prior versions for diagnostic
|
||||
use.
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
## Tuning live
|
||||
|
||||
## :gear: Configuration
|
||||
Three ways to change what the curve does — pick the right gesture for the
|
||||
right scope:
|
||||
|
||||
Adaptive Lighting supports configuration through both YAML and the frontend (**Settings** -> **Devices and Services** -> **Adaptive Lighting**, **Adaptive Lighting** -> **Options**), with identical option names in both methods.
|
||||
| Gesture | Scope | Persistence |
|
||||
|---|---|---|
|
||||
| Drag a number slider on a dashboard | Live, this profile, these bounds | RestoreNumber (survives restart) |
|
||||
| Open the options dialog and save | All profile settings | `entry.options` (canonical) |
|
||||
| Toggle the master / adapt switches | On/off for this profile | RestoreEntity (survives restart) |
|
||||
|
||||
## Services
|
||||
|
||||
This fork exposes two services. The upstream
|
||||
`adaptive_lighting.set_manual_control` service is **removed** (take-over-control
|
||||
was dropped — see Differences from upstream).
|
||||
|
||||
### `adaptive_lighting.apply`
|
||||
|
||||
Apply this profile's current curve values to its lights immediately. Useful
|
||||
in automations that turn on a scene and want AL to take over.
|
||||
|
||||
```yaml
|
||||
# Example configuration.yaml entry
|
||||
adaptive_lighting:
|
||||
service: adaptive_lighting.apply
|
||||
data:
|
||||
entity_id: switch.kitchen
|
||||
lights:
|
||||
- light.living_room_lights
|
||||
- light.kitchen_ceiling
|
||||
turn_on_lights: true # also flip the lights on if currently off
|
||||
transition: 2
|
||||
```
|
||||
Note: If you plan to strictly use the UI, the `adaptive_lighting:` entry must still be added to the YAML.
|
||||
|
||||
Transform your home's atmosphere with Adaptive Lighting 🏠, and experience the benefits of intelligent, sun-synchronized lighting today!
|
||||
### `adaptive_lighting.change_switch_settings`
|
||||
|
||||
### :memo: Options
|
||||
|
||||
All of the configuration options are listed below, along with their default values.
|
||||
The YAML and frontend configuration methods support all of the options listed below.
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting._docs_helpers import generate_config_markdown_table -->
|
||||
<!-- print(generate_config_markdown_table()) -->
|
||||
<!-- CODE:END -->
|
||||
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
| Variable name | Description | Default | Type |
|
||||
|:-------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------|:----------------------------------------|
|
||||
| `lights` | List of light entity_ids to be controlled (may be empty). 🌟 | `[]` | list of `entity_id`s |
|
||||
| `interval` | Frequency to adapt the lights, in seconds. 🔄 | `90` | `int > 0` |
|
||||
| `transition` | Duration of transition when lights change, in seconds. 🕑 | `45` | `float` 0-6553 |
|
||||
| `initial_transition` | Duration of the first transition when lights turn from `off` to `on` in seconds. ⏲️ | `1` | `float` 0-6553 |
|
||||
| `min_brightness` | Minimum brightness percentage. 💡 | `1` | `int` 1-100 |
|
||||
| `max_brightness` | Maximum brightness percentage. 💡 | `100` | `int` 1-100 |
|
||||
| `min_color_temp` | Warmest color temperature in Kelvin. 🔥 | `2000` | `int` 1000-10000 |
|
||||
| `max_color_temp` | Coldest color temperature in Kelvin. ❄️ | `5500` | `int` 1000-10000 |
|
||||
| `prefer_rgb_color` | Whether to prefer RGB color adjustment over light color temperature when possible. 🌈 | `False` | `bool` |
|
||||
| `sleep_brightness` | Brightness percentage of lights in sleep mode. 😴 | `1` | `int` 1-100 |
|
||||
| `sleep_rgb_or_color_temp` | Use either `"rgb_color"` or `"color_temp"` in sleep mode. 🌙 | `color_temp` | one of `['color_temp', 'rgb_color']` |
|
||||
| `sleep_color_temp` | Color temperature in sleep mode (used when `sleep_rgb_or_color_temp` is `color_temp`) in Kelvin. 😴 | `1000` | `int` 1000-10000 |
|
||||
| `sleep_rgb_color` | RGB color in sleep mode (used when `sleep_rgb_or_color_temp` is "rgb_color"). 🌈 | `[255, 56, 0]` | RGB color |
|
||||
| `sleep_transition` | Duration of transition when "sleep mode" is toggled in seconds. 😴 | `1` | `float` 0-6553 |
|
||||
| `transition_until_sleep` | When enabled, Adaptive Lighting will treat sleep settings as the minimum, transitioning to these values after sunset. 🌙 | `False` | `bool` |
|
||||
| `sunrise_time` | Set a fixed time (HH:MM:SS) for sunrise. 🌅 | `None` | `str` |
|
||||
| `min_sunrise_time` | Set the earliest virtual sunrise time (HH:MM:SS), allowing for later sunrises. 🌅 | `None` | `str` |
|
||||
| `max_sunrise_time` | Set the latest virtual sunrise time (HH:MM:SS), allowing for earlier sunrises. 🌅 | `None` | `str` |
|
||||
| `sunrise_offset` | Adjust sunrise time with a positive or negative offset in seconds. ⏰ | `0` | `int` |
|
||||
| `sunset_time` | Set a fixed time (HH:MM:SS) for sunset. 🌇 | `None` | `str` |
|
||||
| `min_sunset_time` | Set the earliest virtual sunset time (HH:MM:SS), allowing for later sunsets. 🌇 | `None` | `str` |
|
||||
| `max_sunset_time` | Set the latest virtual sunset time (HH:MM:SS), allowing for earlier sunsets. 🌇 | `None` | `str` |
|
||||
| `sunset_offset` | Adjust sunset time with a positive or negative offset in seconds. ⏰ | `0` | `int` |
|
||||
| `brightness_mode` | Brightness mode to use. Possible values are `default`, `linear`, and `tanh` (uses `brightness_mode_time_dark` and `brightness_mode_time_light`). 📈 | `default` | one of `['default', 'linear', 'tanh']` |
|
||||
| `brightness_mode_time_dark` | (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness before/after sunrise/sunset. 📈📉 | `900` | `int` |
|
||||
| `brightness_mode_time_light` | (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness after/before sunrise/sunset. 📈📉. | `3600` | `int` |
|
||||
| `take_over_control` | Pause adaptation of individual lights and hand over (manual) control to other sources that issue `light.turn_on` calls for lights that are on. 🔒 | `True` | `bool` |
|
||||
| `take_over_control_mode` | The adaptation pausing mode when other sources change brightness and/or color of lights. `pause_all` always pauses both brightness and color adaptation. `pause_changed` pauses the adaptation of only the changed attributes and continues adapting unchanged attributes, e.g., continues color adaptation when only brightness was changed. | `pause_all` | one of `['pause_all', 'pause_changed']` |
|
||||
| `detect_non_ha_changes` | Detects and halts adaptations for non-`light.turn_on` state changes. Needs `take_over_control` enabled. 🕵️ Caution: ⚠️ Some lights might falsely indicate an 'on' state, which could result in lights turning on unexpectedly. Note that this calls `homeassistant.update_entity` every `interval`! Disable this feature if you encounter such issues. | `False` | `bool` |
|
||||
| `autoreset_control_seconds` | Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️ | `0` | `int` 0-31536000 |
|
||||
| `only_once` | Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). 🔄 | `False` | `bool` |
|
||||
| `adapt_only_on_bare_turn_on` | When turning lights on initially. If set to `true`, AL adapts only if `light.turn_on` is invoked without specifying color or brightness. ❌🌈 This e.g., prevents adaptation when activating a scene and marks the light as manually controlled. If `false`, AL adapts regardless of the presence of color or brightness in the initial `service_data`. Needs `take_over_control` enabled. 🕵️ | `False` | `bool` |
|
||||
| `separate_turn_on_commands` | Use separate `light.turn_on` calls for color and brightness, needed for some light types. 🔀 | `False` | `bool` |
|
||||
| `send_split_delay` | Delay (ms) between `separate_turn_on_commands` for lights that don't support simultaneous brightness and color setting. ⏲️ | `0` | `int` 0-10000 |
|
||||
| `adapt_delay` | Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️ | `0` | `float > 0` |
|
||||
| `skip_redundant_commands` | Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. 📉Disable if physical light states get out of sync with HA's recorded state. | `False` | `bool` |
|
||||
| `intercept` | Intercept and adapt `light.turn_on` calls to enabling instantaneous color and brightness adaptation. 🏎️ Disable for lights that do not support `light.turn_on` with color and brightness. | `True` | `bool` |
|
||||
| `multi_light_intercept` | Intercept and adapt `light.turn_on` calls that target multiple lights. ➗⚠️ This might result in splitting up a single `light.turn_on` call into multiple calls, e.g., when lights are in different switches. Requires `intercept` to be enabled. | `True` | `bool` |
|
||||
| `include_config_in_attributes` | Show all options as attributes on the switch in Home Assistant when set to `true`. 📝 | `False` | `bool` |
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
<!-- SECTION:config-example-full:START -->
|
||||
Full example:
|
||||
Change one or more of this profile's settings at runtime. The change
|
||||
persists until the next options-flow save or HA restart.
|
||||
|
||||
```yaml
|
||||
# Example configuration.yaml entry
|
||||
adaptive_lighting:
|
||||
- name: "default"
|
||||
lights: []
|
||||
prefer_rgb_color: false
|
||||
transition: 45
|
||||
initial_transition: 1
|
||||
interval: 90
|
||||
min_brightness: 1
|
||||
max_brightness: 100
|
||||
min_color_temp: 2000
|
||||
max_color_temp: 5500
|
||||
sleep_brightness: 1
|
||||
sleep_color_temp: 1000
|
||||
sunrise_time: "08:00:00" # override the sunrise time
|
||||
sunrise_offset:
|
||||
sunset_time:
|
||||
sunset_offset: 1800 # in seconds or '00:30:00'
|
||||
take_over_control: true
|
||||
detect_non_ha_changes: false
|
||||
only_once: false
|
||||
|
||||
```
|
||||
<!-- SECTION:config-example-full:END -->
|
||||
|
||||
### :hammer_and_wrench: Services
|
||||
|
||||
#### `adaptive_lighting.apply`
|
||||
|
||||
`adaptive_lighting.apply` applies Adaptive Lighting settings to lights on demand.
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting._docs_helpers import generate_apply_markdown_table -->
|
||||
<!-- print(generate_apply_markdown_table()) -->
|
||||
<!-- CODE:END -->
|
||||
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
| Service data attribute | Description | Required | Type |
|
||||
|:-------------------------|:--------------------------------------------------------------------------------------|:-----------|:---------------------|
|
||||
| `entity_id` | The `entity_id` of the switch with the settings to apply. 📝 | ✅ | list of `entity_id`s |
|
||||
| `lights` | A light (or list of lights) to apply the settings to. 💡 | ❌ | list of `entity_id`s |
|
||||
| `transition` | Duration of transition when lights change, in seconds. 🕑 | ❌ | `float` 0-6553 |
|
||||
| `adapt_brightness` | Whether to adapt the brightness of the light. 🌞 | ❌ | bool |
|
||||
| `adapt_color` | Whether to adapt the color on supporting lights. 🌈 | ❌ | bool |
|
||||
| `prefer_rgb_color` | Whether to prefer RGB color adjustment over light color temperature when possible. 🌈 | ❌ | bool |
|
||||
| `turn_on_lights` | Whether to turn on lights that are currently off. 🔆 | ❌ | bool |
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
#### `adaptive_lighting.set_manual_control`
|
||||
|
||||
`adaptive_lighting.set_manual_control` can mark (or unmark) whether a light is "manually controlled", meaning that when a light has `manual_control`, the light is not adapted.
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting._docs_helpers import generate_set_manual_control_markdown_table -->
|
||||
<!-- print(generate_set_manual_control_markdown_table()) -->
|
||||
<!-- CODE:END -->
|
||||
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
| Service data attribute | Description | Required | Type |
|
||||
|:-------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------|:-----------------------------------------|
|
||||
| `entity_id` | The `entity_id` of the switch in which to (un)mark the light as being `manually controlled`. 📝 | ✅ | list of `entity_id`s |
|
||||
| `lights` | entity_id(s) of lights, if not specified, all lights in the switch are selected. 💡 | ❌ | list of `entity_id`s |
|
||||
| `manual_control` | Whether to add ("true") or remove ("false") all adapted attributes of the light from the "manual_control" list, or the name of an attribute for selective addition. 🔒 | ❌ | bool or one of `['brightness', 'color']` |
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
<!-- SECTION:change-switch-settings:START -->
|
||||
#### `adaptive_lighting.change_switch_settings`
|
||||
|
||||
`adaptive_lighting.change_switch_settings` (new in 1.7.0) Change any of the above configuration options of Adaptive Lighting (such as `sunrise_time` or `prefer_rgb_color`) with a service call directly from your script/automation.
|
||||
|
||||
> [!WARNING]
|
||||
> These settings will **not** be written to your config and will be reset on restart of Home Assistant! You can see the current settings in the `switch.adaptive_lighting_XXX` attributes if `include_config_in_attributes` is enabled.
|
||||
|
||||
| Service data attribute | Required | Description |
|
||||
| --------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `use_defaults` | ❌ | (default: `current` for current settings) Choose from `factory`, `configuration`, or `current` to reset variables not being set with this service call. `current` leaves them as they are, `configuration` resets to initial startup values, `factory` resets to default values listed in the documentation. |
|
||||
| **all other keys** (except the ones in the table below ⚠️) | ❌ | See the table below for disallowed keys. |
|
||||
|
||||
The following keys are disallowed:
|
||||
|
||||
| **DISALLOWED** service data | Description |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `entity_id` | You cannot change the switch's `entity_id`, as it has already been registered. |
|
||||
| `lights` | You may call `adaptive_lighting.apply` with your lights or create a new config instead. |
|
||||
| `name` | You can rename your switch's display name in Home Assistant's UI. |
|
||||
| `interval` | The interval is used only once when the config loads. A config change and restart are required. |
|
||||
<!-- SECTION:change-switch-settings:END -->
|
||||
|
||||
<!-- SECTION:automation-examples:START -->
|
||||
## :robot: Automation examples
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Reset the <code>manual_control</code> status of a light after an hour.</summary>
|
||||
|
||||
```yaml
|
||||
- alias: "Adaptive lighting: reset manual_control after 1 hour"
|
||||
mode: parallel
|
||||
trigger:
|
||||
platform: event
|
||||
event_type: adaptive_lighting.manual_control
|
||||
variables:
|
||||
light: "{{ trigger.event.data.entity_id }}"
|
||||
switch: "{{ trigger.event.data.switch }}"
|
||||
action:
|
||||
- delay: "01:00:00"
|
||||
- condition: template
|
||||
value_template: "{{ light in state_attr(switch, 'manual_control') }}"
|
||||
- service: adaptive_lighting.set_manual_control
|
||||
data:
|
||||
entity_id: "{{ switch }}"
|
||||
lights: "{{ light }}"
|
||||
manual_control: false
|
||||
service: adaptive_lighting.change_switch_settings
|
||||
data:
|
||||
entity_id: switch.kitchen
|
||||
use_defaults: current # | factory | configuration
|
||||
min_brightness: 20 # any subset of options-flow fields
|
||||
max_color_temp: 4500
|
||||
```
|
||||
|
||||
</details>
|
||||
The full per-service argument list lives in `services.yaml` and is
|
||||
rendered into the HA Developer Tools → Services UI.
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Toggle multiple Adaptive Lighting switches to "sleep mode" using an <code>input_boolean.sleep_mode</code>.</summary>
|
||||
## Sun source
|
||||
|
||||
```yaml
|
||||
- alias: "Adaptive lighting: toggle 'sleep mode'"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_boolean.sleep_mode
|
||||
- platform: homeassistant
|
||||
event: start # in case the states aren't properly restored
|
||||
variables:
|
||||
sleep_mode: "{{ states('input_boolean.sleep_mode') }}"
|
||||
action:
|
||||
service: "switch.turn_{{ sleep_mode }}"
|
||||
entity_id:
|
||||
- switch.adaptive_lighting_sleep_mode_living_room
|
||||
- switch.adaptive_lighting_sleep_mode_bedroom
|
||||
The curve is anchored at two `device_class: timestamp` sensors —
|
||||
`sunrise_entity` and `sunset_entity` — configured in the options dialog.
|
||||
|
||||
**Defaults**: HA's built-in `sensor.sun_next_rising` and
|
||||
`sensor.sun_next_setting`. These are always present.
|
||||
|
||||
**Recommended**: install [Sun2](https://github.com/pnbruckner/ha-sun2) and
|
||||
point at `sensor.sun2_dawn` (civil twilight) or `sensor.sun2_astro_dawn`
|
||||
(astronomical twilight) for a smoother fade from deep night to dawn. The
|
||||
integration reads `hass.states.get(<entity_id>).state` and parses the
|
||||
timestamp; any sensor with `device_class: timestamp` works.
|
||||
|
||||
The new `sensor.<profile>_sun_elevation` reads from HA's built-in `sun.sun`
|
||||
entity's `elevation` attribute — independent of which timestamp source you
|
||||
picked for the curve.
|
||||
|
||||
## Development
|
||||
|
||||
This is a CDiT-internal fork; PRs from outside are not the workflow. If
|
||||
you want to dig in:
|
||||
|
||||
| Task | Command |
|
||||
|---|---|
|
||||
| Boot a dev HA with the component loaded | `./scripts/develop` |
|
||||
| Run the test suite | `uv run pytest` |
|
||||
| Run a specific test | `uv run pytest tests/test_sensor_platform.py` |
|
||||
| Lint | `./scripts/lint` |
|
||||
| Validate active OpenSpec changes | `openspec validate <change-name> --strict` |
|
||||
|
||||
Architecture, conventions, OpenSpec workflow, and the upstream-sync recipe
|
||||
are documented in [`CLAUDE.md`](CLAUDE.md). The `openspec/` tree holds the
|
||||
proposal/design/spec/tasks artifacts for every non-trivial change; archived
|
||||
changes under `openspec/changes/archive/` are the historical record.
|
||||
|
||||
## Sync with upstream
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git merge upstream/main # or rebase, depending on local policy
|
||||
# resolve conflicts under custom_components/adaptive_lighting/
|
||||
```
|
||||
|
||||
Set your sunrise and sunset time based on your alarm. The below script sets sunset_time exactly 12 hours after the custom sunrise time.
|
||||
Remote setup:
|
||||
|
||||
```yaml
|
||||
iphone_carly_wakeup:
|
||||
alias: iPhone Carly Wakeup
|
||||
sequence:
|
||||
- condition: state
|
||||
entity_id: input_boolean.carly_iphone_wakeup
|
||||
state: "off"
|
||||
- service: input_datetime.set_datetime
|
||||
target:
|
||||
entity_id: input_datetime.carly_iphone_wakeup
|
||||
data:
|
||||
time: '{{ now().strftime("%H:%M:%S") }}'
|
||||
- service: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.carly_iphone_wakeup
|
||||
- repeat:
|
||||
count: >
|
||||
{{ (states.switch
|
||||
| map(attribute="entity_id")
|
||||
| select(">","switch.adaptive_lighting_al_")
|
||||
| select("<", "switch.adaptive_lighting_al_z")
|
||||
| join(",")
|
||||
).split(",") | length }}
|
||||
sequence:
|
||||
- service: adaptive_lighting.change_switch_settings
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_al_den_ceilingfan_lights
|
||||
sunrise_time: '{{ now().strftime("%H:%M:%S") }}'
|
||||
sunset_time: >
|
||||
{{ (as_timestamp(now()) + 12*60*60) | timestamp_custom("%H:%M:%S") }}
|
||||
- service: script.turn_on
|
||||
target:
|
||||
entity_id: script.run_wakeup_routine
|
||||
- service: input_boolean.turn_off
|
||||
target:
|
||||
entity_id:
|
||||
- input_boolean.carly_iphone_winddown
|
||||
- input_boolean.carly_iphone_bedtime
|
||||
- service: input_datetime.set_datetime
|
||||
target:
|
||||
entity_id: input_datetime.wakeup_time
|
||||
data:
|
||||
time: '{{ now().strftime("%H:%M:%S") }}'
|
||||
- service: script.adaptive_lighting_disable_sleep_mode
|
||||
mode: queued
|
||||
icon: mdi:weather-sunset
|
||||
max: 10
|
||||
```
|
||||
origin git@github.com:CaseyRo/adaptive-lighting.git (this fork, read-write)
|
||||
upstream https://github.com/basnijholt/adaptive-lighting.git (read-only)
|
||||
```
|
||||
|
||||
</details>
|
||||
<!-- SECTION:automation-examples:END -->
|
||||
## Credits
|
||||
|
||||
## Additional Information
|
||||
This fork is a thin opinion on top of
|
||||
[@basnijholt](https://github.com/basnijholt)'s work and the 130+ upstream
|
||||
contributors. The curve math, the `light.turn_on` interception, the HACS
|
||||
plumbing — that's *their* work. If you've never starred the upstream repo,
|
||||
do it now: [github.com/basnijholt/adaptive-lighting](https://github.com/basnijholt/adaptive-lighting).
|
||||
|
||||
For more details on adding the integration and setting options, refer to the [documentation of the PR](https://deploy-preview-14877--home-assistant-docs.netlify.app/integrations/adaptive_lighting/) and [this video tutorial on Reddit](https://www.reddit.com/r/homeassistant/comments/jabhso/ha_has_it_before_apple_has_even_finished_it_i/).
|
||||
|
||||
Adaptive Lighting was initially inspired by @claytonjn's [hass-circadian\_lighting](https://github.com/claytonjn/hass-circadian_lighting), but has since been entirely rewritten and expanded with new features.
|
||||
|
||||
## :sos: Troubleshooting
|
||||
|
||||
<!-- SECTION:troubleshooting-intro:START -->
|
||||
Encountering issues? Enable debug logging in your `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
logger:
|
||||
default: warning
|
||||
logs:
|
||||
custom_components.adaptive_lighting: debug
|
||||
```
|
||||
|
||||
After the issue occurs, create a new issue report with the log (`/config/home-assistant.log`).
|
||||
<!-- SECTION:troubleshooting-intro:END -->
|
||||
|
||||
<!-- SECTION:common-problems:START -->
|
||||
### :exclamation: Common Problems & Solutions
|
||||
|
||||
#### :bulb: Lights Not Responding or Turning On by Themselves
|
||||
|
||||
Adaptive Lighting sends more commands to lights than a typical human user would. If your light control network is unhealthy, you may experience:
|
||||
|
||||
- Laggy manual commands (e.g., turning lights on or off).
|
||||
- Unresponsive lights.
|
||||
- Home Assistant reporting incorrect light states, causing Adaptive Lighting to inadvertently turn lights back on.
|
||||
|
||||
Most issues that appear to be caused by Adaptive Lighting are actually due to unrelated problems.
|
||||
Addressing these issues will significantly improve your Home Assistant experience.
|
||||
|
||||
In case lights are suddenly turning on by themselves, this is most likely due to the light incorrectly reporting an "on" state to Home Assistant, leading to an undesired Adaptive Lighting action.
|
||||
To prevent adapting in cases *where the state of the light is suddenly "on" and only adapt if there is an associated `light.turn_on` service call*, set `detect_non_ha_changes: false`.
|
||||
|
||||
#### :signal_strength: WiFi Networks
|
||||
|
||||
Ensure your light bulbs have a strong WiFi connection. If the signal strength is less than -70dBm, the connection may be weak and prone to dropping messages.
|
||||
|
||||
#### :spider_web: Zigbee, Z-Wave, and Other Mesh Networks
|
||||
|
||||
Mesh networks typically require powered devices to act as routers, relaying messages back to the central coordinator (the radio connected to Home Assistant).
|
||||
Most modern lights function as routers, very early models may not.
|
||||
If devices become unresponsive or fail to respond to commands, Adaptive Lighting can exacerbate the issue.
|
||||
Use network maps (available in ZHA, zigbee2mqtt, deCONZ, and ZWaveJS UI) to evaluate your network health.
|
||||
Smart plugs can be an affordable way to add more routers to your network.
|
||||
|
||||
For most Zigbee networks, **using groups is essential for optimal performance**.
|
||||
For example, if you want to use Adaptive Lighting in a hallway with six bulbs, adding each bulb individually to the Adaptive Lighting configuration could overwhelm the network with commands.
|
||||
Instead, create a group in your Zigbee software (not a regular Home Assistant group) and add that single group to the Adaptive Lighting configuration.
|
||||
This sends a single broadcast command to adjust all bulbs, improving response times and keeping the bulbs in sync.
|
||||
|
||||
As a rule of thumb, if you always control lights together (e.g., bulbs in a ceiling fixture), they should be in a Zigbee group.
|
||||
Expose only the group (not individual bulbs) in Home Assistant Dashboards and external systems like Google Home or Apple HomeKit.
|
||||
|
||||
> :warning: **If you control lights individually, `manual_control` cannot behave correctly! If you need to control lights individually as well, use a [Home Assistant Light Group](https://www.home-assistant.io/integrations/group/).**
|
||||
|
||||
#### :rainbow: Light Colors Not Matching
|
||||
|
||||
Bulbs from different manufacturers or models may have varying color temperature specifications. For instance, if you have two Adaptive Lighting configurations—one with only Philips Hue White Ambiance bulbs and another with a mix of Philips Hue White Ambiance and Sengled bulbs—the Philips Hue bulbs may appear to have different color temperatures despite having identical settings.
|
||||
|
||||
To resolve this:
|
||||
|
||||
1. Include only bulbs of the same make and model in a single Adaptive Lighting configuration.
|
||||
2. Rearrange bulbs so that different color temperatures are not visible simultaneously.
|
||||
|
||||
#### :bulb: Bulb-Specific Issues
|
||||
|
||||
These lights are known to exhibit disadvantageous behaviour due to firmware bugs, insufficient functionality, or hardware limitations:
|
||||
|
||||
- [Sengled Z01-A19NAE26](https://www.zigbee2mqtt.io/devices/Z01-A19NAE26.html#sengled-z01-a19nae26)
|
||||
- Unexpected turn-ons: If Adaptive Lighting sends a long transition time (like the default 45 seconds), and the bulb is turned off during that time, it may turn back on after approximately 10 seconds to continue the transition command. Since the bulb is turning itself on, there will be no obvious trigger in Home Assistant or other logs indicating the cause of the light turning on. To fix this, set a much shorter `transition` time, such as 1 second.
|
||||
- Heat sensitivity: Additionally, these bulbs may perform poorly in enclosed "dome" style ceiling lights, particularly when hot. While most LEDs (even non-smart ones) state in the fine print that they do not support working in enclosed fixtures, in practice, more expensive bulbs like Philips Hue generally perform better. To resolve this issue, move the problematic bulbs to open-air fixtures.
|
||||
- Ikea Tradfri bulbs/drivers (and related Ikea smart light products)
|
||||
- Unsupported simultaneous transition of brightness and color: When receiving such a command, they switch the brightness instantly and only transition the color. To get smooth transitions of both brightness and color, enable `separate_turn_on_commands`.
|
||||
- Unresponsiveness during color transitions: No other commands are processed during an ongoing color transition, e.g., turn-off commands are ignored and lights stay on despite being reported as off to Home Assistant. The default config with long transitions thus results in long periods of unresponsiveness. To work around this, disable transitions by setting `transition` to `0`, and increase the adaptation frequency by setting `interval` to a short time, e.g., `15` seconds, to retain the impression of smooth continuous adaptations. Keeping the `initial_transition` is recommended for a smooth fade-in (lights are usually not turned off momentarily after being turned on, in which case a short period of unresponsiveness is tolerable).
|
||||
<!-- SECTION:common-problems:END -->
|
||||
|
||||
<!-- SECTION:graphs:START -->
|
||||
## :bar_chart: Graphs!
|
||||
These graphs were generated using the values calculated by the Adaptive Lighting sensor/switch(es).
|
||||
|
||||
### :sunny: Sun Position
|
||||

|
||||
|
||||
### :thermometer: Color Temperature
|
||||

|
||||
|
||||
### :high_brightness: Brightness
|
||||

|
||||
|
||||
### While using `transition_until_sleep: true`
|
||||

|
||||
<!-- SECTION:graphs:END -->
|
||||
|
||||
<!-- SECTION:brightness-modes:START -->
|
||||
### Custom brightness ramps using `brightness_mode` with `"linear"` and `"tanh"`
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Enhance your control over brightness transitions during sunrise and sunset with <code>brightness_mode</code> (click here to learn more 🧠).</summary>
|
||||
|
||||
With Adaptive Lighting, you can set a `brightness_mode` to specify how the brightness changes during sunrise and sunset. The `brightness_mode` can be set to `"default"` ([as illustrated in other graphs above](#high_brightness-brightness)), `"linear"`, or `"tanh"`. If you choose to deviate from the `"default"` mode, you can adjust `brightness_mode_time_dark` and `brightness_mode_time_light` to further customize the lighting transitions.
|
||||
|
||||
When `brightness_mode` is set to `"linear"`:
|
||||
|
||||
- During **_sunset_**, the brightness begins to gradually decrease from `max_brightness` starting at `time=sunset_time - brightness_mode_time_light`, until it reaches `min_brightness` at `time=sunset_time + brightness_mode_time_dark`.
|
||||
- During **_sunrise_**, the brightness begins to gradually increase from `min_brightness` starting at `time=sunrise_time - brightness_mode_time_dark`, until it reaches `max_brightness` at `time=sunrise_time + brightness_mode_time_light`.
|
||||
|
||||
When `brightness_mode` is set to `"tanh"`, it uses the smooth transition of a [hyperbolic tangent function](https://mathworld.wolfram.com/HyperbolicTangent.html):
|
||||
|
||||
- During **_sunset_**, the brightness starts to decrease from 95% of `max_brightness` starting at `time=sunset_time - brightness_mode_time_light`, until it reaches 5% of `min_brightness` at `time=sunset_time + brightness_mode_time_dark`.
|
||||
- During **_sunrise_**, the brightness starts to increase from 5% of `min_brightness` starting at `time=sunrise_time - brightness_mode_time_dark`, until it reaches 95% of `max_brightness` at `time=sunrise_time + brightness_mode_time_light`.
|
||||
</details>
|
||||
|
||||
Notice the values of `brightness_mode_time_light` and `brightness_mode_time_dark` in the text box.
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
> Check out the interactive webapp on https://basnijholt.github.io/adaptive-lighting/ to play with the parameters and see how the brightness changes!
|
||||
<!-- SECTION:brightness-modes:END -->
|
||||
|
||||
<!-- SECTION:see-also:START -->
|
||||
## :eyes: See also
|
||||
|
||||
- [*Sleep better with Adaptive Lighting in Home Assistant*](https://wartner.io/sleep-better-with-adaptive-lightning-in-home-assistant/) by Florian Wartner on 2023-02-23 (blog post 📜)
|
||||
- [*Automatic smart light brightness and color based on the sun*](https://www.youtube.com/watch?v=Rg3zI1Oyk3c) by Home Automation Guy on 2022-08-31 (YouTube video 📺)
|
||||
- [*Adaptive Lighting Blew My Mind in Home Assistant - How to set it up*](https://www.youtube.com/watch?v=c1cnccmgl3k) by Smart Home Junkie on 2022-06-26 (YouTube video 📺)
|
||||
<!-- SECTION:see-also:END -->
|
||||
|
||||
## :busts_in_silhouette: Contributors
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.nijho.lt/"><img src="https://avatars.githubusercontent.com/u/6897215?v=4?s=100" width="100px;" alt="Bas Nijholt"/><br /><sub><b>Bas Nijholt</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=basnijholt" title="Code">💻</a> <a href="#maintenance-basnijholt" title="Maintenance">🚧</a> <a href="https://github.com/basnijholt/adaptive-lighting/issues?q=author%3Abasnijholt" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wrt54g"><img src="https://avatars.githubusercontent.com/u/85389871?v=4?s=100" width="100px;" alt="Sven Serlier"/><br /><sub><b>Sven Serlier</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=wrt54g" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/willpuckett"><img src="https://avatars.githubusercontent.com/u/12959477?v=4?s=100" width="100px;" alt="Will Puckett"/><br /><sub><b>Will Puckett</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=willpuckett" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/vapescherov"><img src="https://avatars.githubusercontent.com/u/9620482?v=4?s=100" width="100px;" alt="vapescherov"/><br /><sub><b>vapescherov</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=vapescherov" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/travisp"><img src="https://avatars.githubusercontent.com/u/165698?v=4?s=100" width="100px;" alt="Travis Pew"/><br /><sub><b>Travis Pew</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=travisp" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sindrebroch"><img src="https://avatars.githubusercontent.com/u/10772085?v=4?s=100" width="100px;" alt="Sindre Broch"/><br /><sub><b>Sindre Broch</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=sindrebroch" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Shulyaka"><img src="https://avatars.githubusercontent.com/u/2741408?v=4?s=100" width="100px;" alt="Denis Shulyaka"/><br /><sub><b>Denis Shulyaka</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Shulyaka" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/RubenKelevra"><img src="https://avatars.githubusercontent.com/u/614929?v=4?s=100" width="100px;" alt="@RubenKelevra"/><br /><sub><b>@RubenKelevra</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=RubenKelevra" title="Documentation">📖</a> <a href="https://github.com/basnijholt/adaptive-lighting/commits?author=RubenKelevra" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Repsionu"><img src="https://avatars.githubusercontent.com/u/46962963?v=4?s=100" width="100px;" alt="Jüri Rebane"/><br /><sub><b>Jüri Rebane</b></sub></a><br /><a href="#translation-Repsionu" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/quantumlemur"><img src="https://avatars.githubusercontent.com/u/229782?v=4?s=100" width="100px;" alt="quantumlemur"/><br /><sub><b>quantumlemur</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=quantumlemur" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Oekn5w"><img src="https://avatars.githubusercontent.com/u/38046255?v=4?s=100" width="100px;" alt="Michael Kirsch"/><br /><sub><b>Michael Kirsch</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Oekn5w" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://nicholai.dev/"><img src="https://avatars.githubusercontent.com/u/7280931?v=4?s=100" width="100px;" alt="Nicholai Nissen"/><br /><sub><b>Nicholai Nissen</b></sub></a><br /><a href="#translation-Nicholaiii" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/myhrmans"><img src="https://avatars.githubusercontent.com/u/14261388?v=4?s=100" width="100px;" alt="Martin Myhrman"/><br /><sub><b>Martin Myhrman</b></sub></a><br /><a href="#translation-myhrmans" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/mpeterson"><img src="https://avatars.githubusercontent.com/u/11870?v=4?s=100" width="100px;" alt="Michel Peterson"/><br /><sub><b>Michel Peterson</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=mpeterson" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MangoScango"><img src="https://avatars.githubusercontent.com/u/7623678?v=4?s=100" width="100px;" alt="MangoScango"/><br /><sub><b>MangoScango</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=MangoScango" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Lynilia"><img src="https://avatars.githubusercontent.com/u/89228568?v=4?s=100" width="100px;" alt="Lynilia"/><br /><sub><b>Lynilia</b></sub></a><br /><a href="#translation-Lynilia" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/LukaszP2"><img src="https://avatars.githubusercontent.com/u/44735995?v=4?s=100" width="100px;" alt="LukaszP2"/><br /><sub><b>LukaszP2</b></sub></a><br /><a href="#translation-LukaszP2" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jowgn"><img src="https://avatars.githubusercontent.com/u/24966042?v=4?s=100" width="100px;" alt="Joscha Wagner"/><br /><sub><b>Joscha Wagner</b></sub></a><br /><a href="#translation-jowgn" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/josecarlosfernandez"><img src="https://avatars.githubusercontent.com/u/624242?v=4?s=100" width="100px;" alt="skdzzz"/><br /><sub><b>skdzzz</b></sub></a><br /><a href="#translation-josecarlosfernandez" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/itssimon"><img src="https://avatars.githubusercontent.com/u/1176585?v=4?s=100" width="100px;" alt="Simon Gurcke"/><br /><sub><b>Simon Gurcke</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=itssimon" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://hypfer.de/"><img src="https://avatars.githubusercontent.com/u/974410?v=4?s=100" width="100px;" alt="Sören Beye"/><br /><sub><b>Sören Beye</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Hypfer" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://medium.com/@hudsonbrendon"><img src="https://avatars.githubusercontent.com/u/5201888?v=4?s=100" width="100px;" alt="Hudson Brendon"/><br /><sub><b>Hudson Brendon</b></sub></a><br /><a href="#translation-hudsonbrendon" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gvssr"><img src="https://avatars.githubusercontent.com/u/61377476?v=4?s=100" width="100px;" alt="Gabriel Visser"/><br /><sub><b>Gabriel Visser</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=gvssr" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/glebsterx"><img src="https://avatars.githubusercontent.com/u/8779304?v=4?s=100" width="100px;" alt="Gleb"/><br /><sub><b>Gleb</b></sub></a><br /><a href="#translation-glebsterx" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ghost"><img src="https://avatars.githubusercontent.com/u/10137?v=4?s=100" width="100px;" alt="Deleted user"/><br /><sub><b>Deleted user</b></sub></a><br /><a href="#translation-ghost" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://omg.dje.li/"><img src="https://avatars.githubusercontent.com/u/103232?v=4?s=100" width="100px;" alt="Avi Miller"/><br /><sub><b>Avi Miller</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Djelibeybi" title="Documentation">📖</a> <a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Djelibeybi" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/denysdovhan"><img src="https://avatars.githubusercontent.com/u/3459374?v=4?s=100" width="100px;" alt="Denys Dovhan"/><br /><sub><b>Denys Dovhan</b></sub></a><br /><a href="#translation-denysdovhan" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://davidstenbeck.com/"><img src="https://avatars.githubusercontent.com/u/3330933?v=4?s=100" width="100px;" alt="David Stenbeck"/><br /><sub><b>David Stenbeck</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Davst" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/danaues"><img src="https://avatars.githubusercontent.com/u/24459240?v=4?s=100" width="100px;" alt="Kevin Addeman"/><br /><sub><b>Kevin Addeman</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=danaues" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/covid10"><img src="https://avatars.githubusercontent.com/u/71146231?v=4?s=100" width="100px;" alt="covid10"/><br /><sub><b>covid10</b></sub></a><br /><a href="#translation-covid10" title="Translation">🌍</a> <a href="https://github.com/basnijholt/adaptive-lighting/commits?author=covid10" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chishm"><img src="https://avatars.githubusercontent.com/u/18148723?v=4?s=100" width="100px;" alt="Michael Chisholm"/><br /><sub><b>Michael Chisholm</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=chishm" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/blueshiftlabs"><img src="https://avatars.githubusercontent.com/u/1445520?v=4?s=100" width="100px;" alt="Justin Paupore"/><br /><sub><b>Justin Paupore</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=blueshiftlabs" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bedaes"><img src="https://avatars.githubusercontent.com/u/8410205?v=4?s=100" width="100px;" alt="bedaes"/><br /><sub><b>bedaes</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=bedaes" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/awashingmachine"><img src="https://avatars.githubusercontent.com/u/79043726?v=4?s=100" width="100px;" alt="awashingmachine"/><br /><sub><b>awashingmachine</b></sub></a><br /><a href="#translation-awashingmachine" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/claytonjn"><img src="https://avatars.githubusercontent.com/u/3850252?v=4?s=100" width="100px;" alt="Clayton Nummer"/><br /><sub><b>Clayton Nummer</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=claytonjn" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/robert-crandall"><img src="https://avatars.githubusercontent.com/u/86014438?v=4?s=100" width="100px;" alt="Robert Crandall"/><br /><sub><b>Robert Crandall</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=robert-crandall" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://mattforster.ca/"><img src="https://avatars.githubusercontent.com/u/3375444?v=4?s=100" width="100px;" alt="Matt Forster"/><br /><sub><b>Matt Forster</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=matt-forster" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.dfki.de/en/web/about-us/employee/person/maho10"><img src="https://avatars.githubusercontent.com/u/64665067?v=4?s=100" width="100px;" alt="Mark Niemeyer"/><br /><sub><b>Mark Niemeyer</b></sub></a><br /><a href="#translation-Mark-Niemeyer" title="Translation">🌍</a> <a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Mark-Niemeyer" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/elliottplack/"><img src="https://avatars.githubusercontent.com/u/1827881?v=4?s=100" width="100px;" alt="Elliott Plack"/><br /><sub><b>Elliott Plack</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=talllguy" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ngommers"><img src="https://avatars.githubusercontent.com/u/82467671?v=4?s=100" width="100px;" alt="ngommers"/><br /><sub><b>ngommers</b></sub></a><br /><a href="#translation-ngommers" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/deviantintegral"><img src="https://avatars.githubusercontent.com/u/255023?v=4?s=100" width="100px;" alt="Andrew Berry"/><br /><sub><b>Andrew Berry</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=deviantintegral" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brebtatv"><img src="https://avatars.githubusercontent.com/u/10747062?v=4?s=100" width="100px;" alt="Tomáš Valigura"/><br /><sub><b>Tomáš Valigura</b></sub></a><br /><a href="#translation-brebtatv" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/th3w1zard1"><img src="https://avatars.githubusercontent.com/u/2219836?v=4?s=100" width="100px;" alt="Benjamin Auquite"/><br /><sub><b>Benjamin Auquite</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=th3w1zard1" title="Code">💻</a> <a href="https://github.com/basnijholt/adaptive-lighting/issues?q=author%3Ath3w1zard1" title="Bug reports">🐛</a> <a href="#maintenance-th3w1zard1" title="Maintenance">🚧</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/skycarl"><img src="https://avatars.githubusercontent.com/u/43375685?v=4?s=100" width="100px;" alt="Skyler Carlson"/><br /><sub><b>Skyler Carlson</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=skycarl" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/firstof9"><img src="https://avatars.githubusercontent.com/u/1105672?v=4?s=100" width="100px;" alt="Chris"/><br /><sub><b>Chris</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=firstof9" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/raman325"><img src="https://avatars.githubusercontent.com/u/7243222?v=4?s=100" width="100px;" alt="Raman Gupta"/><br /><sub><b>Raman Gupta</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=raman325" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/igiannakas"><img src="https://avatars.githubusercontent.com/u/59056762?v=4?s=100" width="100px;" alt="igiannakas"/><br /><sub><b>igiannakas</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=igiannakas" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://protyposis.net"><img src="https://avatars.githubusercontent.com/u/189372?v=4?s=100" width="100px;" alt="Mario Guggenberger"/><br /><sub><b>Mario Guggenberger</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=protyposis" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://ktibow.github.io/"><img src="https://avatars.githubusercontent.com/u/10727862?v=4?s=100" width="100px;" alt="Kendell R"/><br /><sub><b>Kendell R</b></sub></a><br /><a href="#design-KTibow" title="Design">🎨</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lukerix"><img src="https://avatars.githubusercontent.com/u/93864731?v=4?s=100" width="100px;" alt="lukerix"/><br /><sub><b>lukerix</b></sub></a><br /><a href="#translation-lukerix" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mexx62"><img src="https://avatars.githubusercontent.com/u/8066485?v=4?s=100" width="100px;" alt="Maxime Bailleul"/><br /><sub><b>Maxime Bailleul</b></sub></a><br /><a href="#translation-Mexx62" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://michelbalzer.de"><img src="https://avatars.githubusercontent.com/u/1337412?v=4?s=100" width="100px;" alt="Michel Balzer"/><br /><sub><b>Michel Balzer</b></sub></a><br /><a href="#translation-michelbalzer" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/enrico1036"><img src="https://avatars.githubusercontent.com/u/9280405?v=4?s=100" width="100px;" alt="Enrico Gambini"/><br /><sub><b>Enrico Gambini</b></sub></a><br /><a href="#translation-enrico1036" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MirCore"><img src="https://avatars.githubusercontent.com/u/9919366?v=4?s=100" width="100px;" alt="MirCore"/><br /><sub><b>MirCore</b></sub></a><br /><a href="#translation-MirCore" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://kilfer.es/"><img src="https://avatars.githubusercontent.com/u/290854?v=4?s=100" width="100px;" alt="Fernando Belaza"/><br /><sub><b>Fernando Belaza</b></sub></a><br /><a href="#translation-KilFer" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wilcomir"><img src="https://avatars.githubusercontent.com/u/795981?v=4?s=100" width="100px;" alt="Vladimir Cravero"/><br /><sub><b>Vladimir Cravero</b></sub></a><br /><a href="#translation-wilcomir" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.latavernedutroll.fr"><img src="https://avatars.githubusercontent.com/u/255774?v=4?s=100" width="100px;" alt="Julien Quiévreux"/><br /><sub><b>Julien Quiévreux</b></sub></a><br /><a href="#translation-letroll" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lightrabbit"><img src="https://avatars.githubusercontent.com/u/1521765?v=4?s=100" width="100px;" alt="lightrabbit"/><br /><sub><b>lightrabbit</b></sub></a><br /><a href="#translation-lightrabbit" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Arie6414"><img src="https://avatars.githubusercontent.com/u/129661911?v=4?s=100" width="100px;" alt="Arie6414"/><br /><sub><b>Arie6414</b></sub></a><br /><a href="#translation-Arie6414" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/luixcaetano"><img src="https://avatars.githubusercontent.com/u/4554163?v=4?s=100" width="100px;" alt="luixcaetano"/><br /><sub><b>luixcaetano</b></sub></a><br /><a href="#translation-luixcaetano" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fmarcu"><img src="https://avatars.githubusercontent.com/u/81946691?v=4?s=100" width="100px;" alt="fmarcu"/><br /><sub><b>fmarcu</b></sub></a><br /><a href="#translation-fmarcu" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/michaelkmoch"><img src="https://avatars.githubusercontent.com/u/107689026?v=4?s=100" width="100px;" alt="michaelkmoch"/><br /><sub><b>michaelkmoch</b></sub></a><br /><a href="#translation-michaelkmoch" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/fbloemhof"><img src="https://avatars.githubusercontent.com/u/8753211?v=4?s=100" width="100px;" alt="Fred"/><br /><sub><b>Fred</b></sub></a><br /><a href="#translation-fbloemhof" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Z-weapon"><img src="https://avatars.githubusercontent.com/u/13939632?v=4?s=100" width="100px;" alt="Z-weapon"/><br /><sub><b>Z-weapon</b></sub></a><br /><a href="#translation-Z-weapon" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kylebjordahl"><img src="https://avatars.githubusercontent.com/u/3489222?v=4?s=100" width="100px;" alt="Kyle Bjordahl"/><br /><sub><b>Kyle Bjordahl</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=kylebjordahl" title="Code">💻</a> <a href="https://github.com/basnijholt/adaptive-lighting/issues?q=author%3Akylebjordahl" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/olekbruks"><img src="https://avatars.githubusercontent.com/u/8738016?v=4?s=100" width="100px;" alt="Olek Bruks"/><br /><sub><b>Olek Bruks</b></sub></a><br /><a href="#translation-olekbruks" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://gabrielebaldassarre.com"><img src="https://avatars.githubusercontent.com/u/1724406?v=4?s=100" width="100px;" alt="Gabriele Baldassarre"/><br /><sub><b>Gabriele Baldassarre</b></sub></a><br /><a href="#translation-theclue" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pbaart"><img src="https://avatars.githubusercontent.com/u/2856849?v=4?s=100" width="100px;" alt="Pepijn Baart"/><br /><sub><b>Pepijn Baart</b></sub></a><br /><a href="#translation-pbaart" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://ovoi.io"><img src="https://avatars.githubusercontent.com/u/3490616?v=4?s=100" width="100px;" alt="Artem Pastukhov"/><br /><sub><b>Artem Pastukhov</b></sub></a><br /><a href="#translation-pastukhov" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://stefany.eu"><img src="https://avatars.githubusercontent.com/u/57348587?v=4?s=100" width="100px;" alt="Martin Štefany"/><br /><sub><b>Martin Štefany</b></sub></a><br /><a href="#translation-mstefany" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/quenthal"><img src="https://avatars.githubusercontent.com/u/17827203?v=4?s=100" width="100px;" alt="quenthal"/><br /><sub><b>quenthal</b></sub></a><br /><a href="#translation-quenthal" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Luki72"><img src="https://avatars.githubusercontent.com/u/22493116?v=4?s=100" width="100px;" alt="Luki72"/><br /><sub><b>Luki72</b></sub></a><br /><a href="#translation-Luki72" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pantan-cymk"><img src="https://avatars.githubusercontent.com/u/87476229?v=4?s=100" width="100px;" alt="pantan-cymk"/><br /><sub><b>pantan-cymk</b></sub></a><br /><a href="#translation-pantan-cymk" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/yousaf465"><img src="https://avatars.githubusercontent.com/u/83491212?v=4?s=100" width="100px;" alt="yousaf465"/><br /><sub><b>yousaf465</b></sub></a><br /><a href="#translation-yousaf465" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/baylanger"><img src="https://avatars.githubusercontent.com/u/5240348?v=4?s=100" width="100px;" alt="Pierre Belanger"/><br /><sub><b>Pierre Belanger</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=baylanger" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://www.jan-sigurd.com"><img src="https://avatars.githubusercontent.com/u/8410766?v=4?s=100" width="100px;" alt="Jan-Sigurd Sørensen"/><br /><sub><b>Jan-Sigurd Sørensen</b></sub></a><br /><a href="#translation-jansigu" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/EF01"><img src="https://avatars.githubusercontent.com/u/20759250?v=4?s=100" width="100px;" alt="EF01"/><br /><sub><b>EF01</b></sub></a><br /><a href="#translation-EF01" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MrSnakeSPb"><img src="https://avatars.githubusercontent.com/u/68160409?v=4?s=100" width="100px;" alt="Mr Snake"/><br /><sub><b>Mr Snake</b></sub></a><br /><a href="#translation-MrSnakeSPb" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hungrymachine1"><img src="https://avatars.githubusercontent.com/u/73683742?v=4?s=100" width="100px;" alt="hungrymachine1"/><br /><sub><b>hungrymachine1</b></sub></a><br /><a href="#translation-hungrymachine1" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/4D4M-Github"><img src="https://avatars.githubusercontent.com/u/123521171?v=4?s=100" width="100px;" alt="4D4M-Github"/><br /><sub><b>4D4M-Github</b></sub></a><br /><a href="#translation-4D4M-Github" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sayaivan"><img src="https://avatars.githubusercontent.com/u/49090860?v=4?s=100" width="100px;" alt="Ivan"/><br /><sub><b>Ivan</b></sub></a><br /><a href="#translation-sayaivan" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.floca.be"><img src="https://avatars.githubusercontent.com/u/13313104?v=4?s=100" width="100px;" alt="Florent Cardoen"/><br /><sub><b>Florent Cardoen</b></sub></a><br /><a href="#translation-Fllorent0D" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/moemeli"><img src="https://avatars.githubusercontent.com/u/73445184?v=4?s=100" width="100px;" alt="moemeli"/><br /><sub><b>moemeli</b></sub></a><br /><a href="#translation-moemeli" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/saya6k"><img src="https://avatars.githubusercontent.com/u/63517312?v=4?s=100" width="100px;" alt="saya6k"/><br /><sub><b>saya6k</b></sub></a><br /><a href="#translation-saya6k" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/droans"><img src="https://avatars.githubusercontent.com/u/49721649?v=4?s=100" width="100px;" alt="droans"/><br /><sub><b>droans</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=droans" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://blogs.gnome.org/jonathankang/"><img src="https://avatars.githubusercontent.com/u/5607743?v=4?s=100" width="100px;" alt="Jonathan Kang"/><br /><sub><b>Jonathan Kang</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=JonathanKang" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/scuricvladimir"><img src="https://avatars.githubusercontent.com/u/46634162?v=4?s=100" width="100px;" alt="scuricvladimir"/><br /><sub><b>scuricvladimir</b></sub></a><br /><a href="#translation-scuricvladimir" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Welsyntoffie"><img src="https://avatars.githubusercontent.com/u/47089904?v=4?s=100" width="100px;" alt="Pieter"/><br /><sub><b>Pieter</b></sub></a><br /><a href="#translation-Welsyntoffie" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/san80068259"><img src="https://avatars.githubusercontent.com/u/68324107?v=4?s=100" width="100px;" alt="san80068259"/><br /><sub><b>san80068259</b></sub></a><br /><a href="#translation-san80068259" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/erdnaxela02"><img src="https://avatars.githubusercontent.com/u/21007415?v=4?s=100" width="100px;" alt="Frosh"/><br /><sub><b>Frosh</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=erdnaxela02" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/rafaeltmiranda/"><img src="https://avatars.githubusercontent.com/u/47206949?v=4?s=100" width="100px;" alt="Rafael Miranda"/><br /><sub><b>Rafael Miranda</b></sub></a><br /><a href="#translation-rafaeltmiranda" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rVlad93"><img src="https://avatars.githubusercontent.com/u/60452666?v=4?s=100" width="100px;" alt="rVlad93"/><br /><sub><b>rVlad93</b></sub></a><br /><a href="#translation-rVlad93" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://blog.ebbinghaus.me/"><img src="https://avatars.githubusercontent.com/u/2965273?v=4?s=100" width="100px;" alt="Björn Ebbinghaus"/><br /><sub><b>Björn Ebbinghaus</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=MrEbbinghaus" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Marck"><img src="https://avatars.githubusercontent.com/u/18088281?v=4?s=100" width="100px;" alt="Marck"/><br /><sub><b>Marck</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Marck" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://carmodsheaven.com"><img src="https://avatars.githubusercontent.com/u/11273726?v=4?s=100" width="100px;" alt="Lucho Gizdov"/><br /><sub><b>Lucho Gizdov</b></sub></a><br /><a href="#translation-lachezar-gizdov" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/MizterB"><img src="https://avatars.githubusercontent.com/u/5458030?v=4?s=100" width="100px;" alt="MizterB"/><br /><sub><b>MizterB</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=MizterB" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/brietman"><img src="https://avatars.githubusercontent.com/u/17436537?v=4?s=100" width="100px;" alt="brietman"/><br /><sub><b>brietman</b></sub></a><br /><a href="#translation-brietman" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TamilNeram"><img src="https://avatars.githubusercontent.com/u/67970539?v=4?s=100" width="100px;" alt="தமிழ் நேரம்"/><br /><sub><b>தமிழ் நேரம்</b></sub></a><br /><a href="#translation-TamilNeram" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Thunderstrike116"><img src="https://avatars.githubusercontent.com/u/23220766?v=4?s=100" width="100px;" alt="Thunderstrike116"/><br /><sub><b>Thunderstrike116</b></sub></a><br /><a href="#translation-Thunderstrike116" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/immeteor2"><img src="https://avatars.githubusercontent.com/u/125735487?v=4?s=100" width="100px;" alt="immeteor2"/><br /><sub><b>immeteor2</b></sub></a><br /><a href="#translation-immeteor2" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pbassut"><img src="https://avatars.githubusercontent.com/u/1500037?v=4?s=100" width="100px;" alt="Patrick Bassut"/><br /><sub><b>Patrick Bassut</b></sub></a><br /><a href="#translation-pbassut" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Ricky-Tigg"><img src="https://avatars.githubusercontent.com/u/26058215?v=4?s=100" width="100px;" alt="Ricky Tigg"/><br /><sub><b>Ricky Tigg</b></sub></a><br /><a href="#translation-Ricky-Tigg" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/marazmarci"><img src="https://avatars.githubusercontent.com/u/1349654?v=4?s=100" width="100px;" alt="Márton Maráz"/><br /><sub><b>Márton Maráz</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=marazmarci" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Sara492"><img src="https://avatars.githubusercontent.com/u/63058202?v=4?s=100" width="100px;" alt="Sara492"/><br /><sub><b>Sara492</b></sub></a><br /><a href="#translation-Sara492" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/enpaga"><img src="https://avatars.githubusercontent.com/u/180730931?v=4?s=100" width="100px;" alt="enpaga"/><br /><sub><b>enpaga</b></sub></a><br /><a href="#translation-enpaga" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/xuars"><img src="https://avatars.githubusercontent.com/u/197080354?v=4?s=100" width="100px;" alt="xuars"/><br /><sub><b>xuars</b></sub></a><br /><a href="#translation-xuars" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/tinutac"><img src="https://avatars.githubusercontent.com/u/2151553?v=4?s=100" width="100px;" alt="tinutac"/><br /><sub><b>tinutac</b></sub></a><br /><a href="#translation-tinutac" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/defaultpage"><img src="https://avatars.githubusercontent.com/u/22825202?v=4?s=100" width="100px;" alt="Default User"/><br /><sub><b>Default User</b></sub></a><br /><a href="#translation-defaultpage" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/amelenty"><img src="https://avatars.githubusercontent.com/u/29466876?v=4?s=100" width="100px;" alt="amelenty"/><br /><sub><b>amelenty</b></sub></a><br /><a href="#translation-amelenty" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://ua.linkedin.com/in/rostyslav-dudka"><img src="https://avatars.githubusercontent.com/u/15959384?v=4?s=100" width="100px;" alt="Rostyslav Dudka"/><br /><sub><b>Rostyslav Dudka</b></sub></a><br /><a href="#translation-yeaxi" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/helderfmf"><img src="https://avatars.githubusercontent.com/u/5622687?v=4?s=100" width="100px;" alt="Helder Ferreira"/><br /><sub><b>Helder Ferreira</b></sub></a><br /><a href="#translation-helderfmf" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://mrpiotr.dev"><img src="https://avatars.githubusercontent.com/u/11849621?v=4?s=100" width="100px;" alt="Piotr Laszczkowski"/><br /><sub><b>Piotr Laszczkowski</b></sub></a><br /><a href="#translation-mrpiotr-dev" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://rezaalmanda.github.io"><img src="https://avatars.githubusercontent.com/u/22217419?v=4?s=100" width="100px;" alt="Reza"/><br /><sub><b>Reza</b></sub></a><br /><a href="#translation-rezaalmanda" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bittin"><img src="https://avatars.githubusercontent.com/u/43197?v=4?s=100" width="100px;" alt="Luna Jernberg"/><br /><sub><b>Luna Jernberg</b></sub></a><br /><a href="#translation-bittin" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://jeffalwilson.com"><img src="https://avatars.githubusercontent.com/u/1368827?v=4?s=100" width="100px;" alt="Jeff Wilson"/><br /><sub><b>Jeff Wilson</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=jawilson" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/TermeHansen"><img src="https://avatars.githubusercontent.com/u/6922018?v=4?s=100" width="100px;" alt="Rasmus Lundsgaard"/><br /><sub><b>Rasmus Lundsgaard</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=TermeHansen" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Tommatheussen"><img src="https://avatars.githubusercontent.com/u/13683094?v=4?s=100" width="100px;" alt="Tom Matheussen"/><br /><sub><b>Tom Matheussen</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=Tommatheussen" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ams2990"><img src="https://avatars.githubusercontent.com/u/488907?v=4?s=100" width="100px;" alt="ams2990"/><br /><sub><b>ams2990</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=ams2990" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/DataGhost"><img src="https://avatars.githubusercontent.com/u/3911340?v=4?s=100" width="100px;" alt="DataGhost"/><br /><sub><b>DataGhost</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=DataGhost" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://iamfurkan.com"><img src="https://avatars.githubusercontent.com/u/23127261?v=4?s=100" width="100px;" alt="Furkan Kaya"/><br /><sub><b>Furkan Kaya</b></sub></a><br /><a href="#translation-Wijt" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Rafael4A"><img src="https://avatars.githubusercontent.com/u/32150173?v=4?s=100" width="100px;" alt="Rafael do Amaral Porciuncula"/><br /><sub><b>Rafael do Amaral Porciuncula</b></sub></a><br /><a href="#translation-Rafael4A" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/hhjuhl"><img src="https://avatars.githubusercontent.com/u/84127693?v=4?s=100" width="100px;" alt="hhjuhl"/><br /><sub><b>hhjuhl</b></sub></a><br /><a href="#translation-hhjuhl" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Athishbalu"><img src="https://avatars.githubusercontent.com/u/177029556?v=4?s=100" width="100px;" alt="B.Athish"/><br /><sub><b>B.Athish</b></sub></a><br /><a href="#translation-Athishbalu" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/maksim2005UKR"><img src="https://avatars.githubusercontent.com/u/233082001?v=4?s=100" width="100px;" alt="Горпиніч Максим Олександрович"/><br /><sub><b>Горпиніч Максим Олександрович</b></sub></a><br /><a href="#translation-maksim2005UKR" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://plageoj.me"><img src="https://avatars.githubusercontent.com/u/10688301?v=4?s=100" width="100px;" alt="Masayuki Sugahara"/><br /><sub><b>Masayuki Sugahara</b></sub></a><br /><a href="#translation-plageoj" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/therealmate"><img src="https://avatars.githubusercontent.com/u/61843503?v=4?s=100" width="100px;" alt="therealmate"/><br /><sub><b>therealmate</b></sub></a><br /><a href="#translation-therealmate" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/dobby5"><img src="https://avatars.githubusercontent.com/u/1346316?v=4?s=100" width="100px;" alt="Dobby"/><br /><sub><b>Dobby</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=dobby5" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lenucksi"><img src="https://avatars.githubusercontent.com/u/2451899?v=4?s=100" width="100px;" alt="lenucksi"/><br /><sub><b>lenucksi</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=lenucksi" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://gitlab.com/edgimar"><img src="https://avatars.githubusercontent.com/u/393850?v=4?s=100" width="100px;" alt="edgimar"/><br /><sub><b>edgimar</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=edgimar" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/andrei-lazarov"><img src="https://avatars.githubusercontent.com/u/51081857?v=4?s=100" width="100px;" alt="Andrei LAZAROV"/><br /><sub><b>Andrei LAZAROV</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=andrei-lazarov" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ademuri"><img src="https://avatars.githubusercontent.com/u/3051618?v=4?s=100" width="100px;" alt="Adam DeMuri"/><br /><sub><b>Adam DeMuri</b></sub></a><br /><a href="https://github.com/basnijholt/adaptive-lighting/commits?author=ademuri" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/NatanDosAnjos"><img src="https://avatars.githubusercontent.com/u/45629905?v=4?s=100" width="100px;" alt="Natanael"/><br /><sub><b>Natanael</b></sub></a><br /><a href="#translation-NatanDosAnjos" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Yllelder"><img src="https://avatars.githubusercontent.com/u/6941502?v=4?s=100" width="100px;" alt="Yllelder Bamir"/><br /><sub><b>Yllelder Bamir</b></sub></a><br /><a href="#translation-Yllelder" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Esspel"><img src="https://avatars.githubusercontent.com/u/47383506?v=4?s=100" width="100px;" alt="Esspel"/><br /><sub><b>Esspel</b></sub></a><br /><a href="#translation-Esspel" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td align="center" size="13px" colspan="7">
|
||||
<img src="https://raw.githubusercontent.com/all-contributors/all-contributors-cli/1b8533af435da9854653492b1327a23a4dbd0a10/assets/logo-small.svg">
|
||||
<a href="https://all-contributors.js.org/docs/en/bot/usage">Add your contributions</a>
|
||||
</img>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
## Translating Adaptive Lighting
|
||||
|
||||
Help to translate Adaptive Lighting into your language on [Hosted Weblate](https://hosted.weblate.org/engage/adaptive-lighting/)!
|
||||
|
||||
Translating can be done from your webbrowser, no programming knowledge
|
||||
is needed!
|
||||
|
||||
<a href="https://hosted.weblate.org/engage/adaptive-lighting/">
|
||||
<img src="https://hosted.weblate.org/widget/adaptive-lighting/multi-auto.svg" alt="Translation status" />
|
||||
</a>
|
||||
See [`CHANGELOG.md`](CHANGELOG.md) for the canonical list of CDiT-fork
|
||||
changes since forking from upstream.
|
||||
|
|
|
|||
|
|
@ -1,122 +0,0 @@
|
|||
from typing import Any
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import pandas as pd
|
||||
import voluptuous as vol
|
||||
from homeassistant.helpers import selector
|
||||
|
||||
from .const import (
|
||||
DOCS,
|
||||
DOCS_APPLY,
|
||||
VALIDATION_TUPLES,
|
||||
apply_service_schema,
|
||||
)
|
||||
|
||||
# Stubs for upstream docs sections that no longer exist in the CDiT fork.
|
||||
# The docs generator script reads these by name; provide empty placeholders
|
||||
# so the script does not crash. The section in the rendered README will be
|
||||
# empty and can be deleted from the template separately.
|
||||
DOCS_MANUAL_CONTROL: dict[str, str] = {}
|
||||
SET_MANUAL_CONTROL_SCHEMA = None
|
||||
|
||||
|
||||
def _format_voluptuous_instance(instance: vol.All) -> str:
|
||||
coerce_type = None
|
||||
min_val = None
|
||||
max_val = None
|
||||
|
||||
for validator in instance.validators:
|
||||
if isinstance(validator, vol.Coerce):
|
||||
coerce_type = validator.type.__name__
|
||||
elif isinstance(validator, vol.Clamp | vol.Range):
|
||||
min_val = validator.min
|
||||
max_val = validator.max
|
||||
|
||||
if min_val is not None and max_val is not None:
|
||||
return f"`{coerce_type}` {min_val}-{max_val}"
|
||||
if min_val is not None:
|
||||
return f"`{coerce_type} > {min_val}`"
|
||||
if max_val is not None:
|
||||
return f"`{coerce_type} < {max_val}`"
|
||||
return f"`{coerce_type}`"
|
||||
|
||||
|
||||
def _type_to_str(type_: Any) -> str: # noqa: PLR0911
|
||||
"""Convert a (voluptuous) type to a string."""
|
||||
if type_ == cv.entity_ids:
|
||||
return "list of `entity_id`s"
|
||||
if type_ in (bool, int, float, str):
|
||||
return f"`{type_.__name__}`"
|
||||
if type_ == cv.boolean:
|
||||
return "bool"
|
||||
if isinstance(type_, vol.All):
|
||||
return _format_voluptuous_instance(type_)
|
||||
if isinstance(type_, vol.Any):
|
||||
return " or ".join(_type_to_str(t) for t in type_.validators)
|
||||
if isinstance(type_, vol.In):
|
||||
return f"one of `{type_.container}`"
|
||||
if isinstance(type_, selector.SelectSelector):
|
||||
return f"one of `{type_.config['options']}`"
|
||||
if isinstance(type_, selector.ColorRGBSelector):
|
||||
return "RGB color"
|
||||
msg = f"Unknown type: {type_}"
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
def generate_config_markdown_table() -> str:
|
||||
rows: list[dict[str, str]] = []
|
||||
for k, default, type_ in VALIDATION_TUPLES:
|
||||
description = DOCS[k]
|
||||
row = {
|
||||
"Variable name": f"`{k}`",
|
||||
"Description": description,
|
||||
"Default": f"`{default}`",
|
||||
"Type": _type_to_str(type_),
|
||||
}
|
||||
rows.append(row)
|
||||
|
||||
df = pd.DataFrame(rows)
|
||||
return df.to_markdown(index=False)
|
||||
|
||||
|
||||
def _schema_to_dict(schema: vol.Schema) -> dict[str, tuple[Any, Any]]:
|
||||
result: dict[str, tuple[Any, Any]] = {}
|
||||
for key, value in schema.schema.items():
|
||||
if isinstance(key, vol.Optional):
|
||||
default_value = key.default
|
||||
result[key.schema] = (default_value, value)
|
||||
return result
|
||||
|
||||
|
||||
def _generate_service_markdown_table(
|
||||
schema: dict[str, tuple[Any, Any]] | vol.Schema,
|
||||
alternative_docs: dict[str, str] | None = None,
|
||||
) -> str:
|
||||
schema_dict = _schema_to_dict(schema) if isinstance(schema, vol.Schema) else schema
|
||||
rows: list[dict[str, str]] = []
|
||||
for k, (default, type_) in schema_dict.items():
|
||||
if alternative_docs is not None and k in alternative_docs:
|
||||
description = alternative_docs[k]
|
||||
else:
|
||||
description = DOCS[k]
|
||||
row = {
|
||||
"Service data attribute": f"`{k}`",
|
||||
"Description": description,
|
||||
"Required": "✅" if default == vol.UNDEFINED else "❌",
|
||||
"Type": _type_to_str(type_),
|
||||
}
|
||||
rows.append(row)
|
||||
|
||||
df = pd.DataFrame(rows)
|
||||
return df.to_markdown(index=False)
|
||||
|
||||
|
||||
def generate_apply_markdown_table() -> str:
|
||||
return _generate_service_markdown_table(apply_service_schema(), DOCS_APPLY)
|
||||
|
||||
|
||||
def generate_set_manual_control_markdown_table() -> str:
|
||||
return _generate_service_markdown_table(
|
||||
SET_MANUAL_CONTROL_SCHEMA,
|
||||
DOCS_MANUAL_CONTROL,
|
||||
)
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
"""Documentation generation utilities for Adaptive Lighting.
|
||||
|
||||
Provides functions to transform content for the documentation site.
|
||||
Used by markdown-code-runner to generate documentation pages from README content.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def _transform_readme_links(content: str) -> str:
|
||||
"""Transform README internal links to docs site links."""
|
||||
# Map README anchors to doc pages
|
||||
link_map = {
|
||||
"#gear-configuration": "configuration.md",
|
||||
"#memo-options": "configuration.md#all-options",
|
||||
"#hammer_and_wrench-services": "services.md",
|
||||
"#adaptive_lightingapply": "services.md#adaptive_lightingapply",
|
||||
"#adaptive_lightingset_manual_control": "services.md#adaptive_lightingset_manual_control",
|
||||
"#adaptive_lightingchange_switch_settings": "services.md#adaptive_lightingchange_switch_settings",
|
||||
"#robot-automation-examples": "automation-examples.md",
|
||||
"#sos-troubleshooting": "troubleshooting.md",
|
||||
"#exclamation-common-problems--solutions": "troubleshooting.md#common-problems-solutions",
|
||||
"#bar_chart-graphs": "advanced/brightness-modes.md#graphs",
|
||||
"#bulb-features": "index.md#features",
|
||||
"#control_knobs-regain-manual-control": "advanced/manual-control.md",
|
||||
"#eyes-see-also": "see-also.md",
|
||||
}
|
||||
|
||||
for old_link, new_link in link_map.items():
|
||||
content = content.replace(f"]({old_link})", f"]({new_link})")
|
||||
|
||||
# Remove ToC link pattern [[ToC](#...)]
|
||||
return re.sub(r"\[\[ToC\]\([^)]+\)\]", "", content)
|
||||
|
|
@ -112,9 +112,7 @@ class AdaptiveOutputSensor(SensorEntity):
|
|||
def _handle_outputs_updated(self) -> None:
|
||||
"""Read this sensor's value from the cache and write state."""
|
||||
outputs = (
|
||||
self._hass.data.get(DOMAIN, {})
|
||||
.get(self._entry.entry_id, {})
|
||||
.get("outputs")
|
||||
self._hass.data.get(DOMAIN, {}).get(self._entry.entry_id, {}).get("outputs")
|
||||
)
|
||||
if not outputs:
|
||||
# Early signal (e.g., setup race) — leave state as unknown.
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
adaptive-lighting.nijho.lt
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
---
|
||||
icon: lucide/trending-up
|
||||
---
|
||||
|
||||
# Brightness Modes
|
||||
|
||||
Enhance your control over brightness transitions during sunrise and sunset with the `brightness_mode` option.
|
||||
|
||||
## Available Modes
|
||||
|
||||
Adaptive Lighting supports three brightness modes:
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| `default` | Standard behavior based on sun position |
|
||||
| `linear` | Linear ramp between min/max brightness |
|
||||
| `tanh` | Smooth S-curve using hyperbolic tangent |
|
||||
|
||||
## Detailed Explanation
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- print(include_section("../../README.md", "brightness-modes", strip_heading=True)) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
<details markdown="1">
|
||||
<summary>Enhance your control over brightness transitions during sunrise and sunset with <code>brightness_mode</code> (click here to learn more 🧠).</summary>
|
||||
|
||||
With Adaptive Lighting, you can set a `brightness_mode` to specify how the brightness changes during sunrise and sunset. The `brightness_mode` can be set to `"default"` ([as illustrated in other graphs above](#high_brightness-brightness)), `"linear"`, or `"tanh"`. If you choose to deviate from the `"default"` mode, you can adjust `brightness_mode_time_dark` and `brightness_mode_time_light` to further customize the lighting transitions.
|
||||
|
||||
When `brightness_mode` is set to `"linear"`:
|
||||
|
||||
- During **_sunset_**, the brightness begins to gradually decrease from `max_brightness` starting at `time=sunset_time - brightness_mode_time_light`, until it reaches `min_brightness` at `time=sunset_time + brightness_mode_time_dark`.
|
||||
- During **_sunrise_**, the brightness begins to gradually increase from `min_brightness` starting at `time=sunrise_time - brightness_mode_time_dark`, until it reaches `max_brightness` at `time=sunrise_time + brightness_mode_time_light`.
|
||||
|
||||
When `brightness_mode` is set to `"tanh"`, it uses the smooth transition of a [hyperbolic tangent function](https://mathworld.wolfram.com/HyperbolicTangent.html):
|
||||
|
||||
- During **_sunset_**, the brightness starts to decrease from 95% of `max_brightness` starting at `time=sunset_time - brightness_mode_time_light`, until it reaches 5% of `min_brightness` at `time=sunset_time + brightness_mode_time_dark`.
|
||||
- During **_sunrise_**, the brightness starts to increase from 5% of `min_brightness` starting at `time=sunrise_time - brightness_mode_time_dark`, until it reaches 95% of `max_brightness` at `time=sunrise_time + brightness_mode_time_light`.
|
||||
</details>
|
||||
|
||||
Notice the values of `brightness_mode_time_light` and `brightness_mode_time_dark` in the text box.
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
> Check out the interactive webapp on https://basnijholt.github.io/adaptive-lighting/ to play with the parameters and see how the brightness changes!
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Configuration Parameters
|
||||
|
||||
When using `linear` or `tanh` modes, you can fine-tune the transition with these parameters:
|
||||
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `brightness_mode_time_dark` | 900 (15 min) | Duration to ramp brightness before/after sunrise/sunset |
|
||||
| `brightness_mode_time_light` | 3600 (1 hour) | Duration to ramp brightness after/before sunrise/sunset |
|
||||
|
||||
## Example Configurations
|
||||
|
||||
### Quick Transition (Linear)
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Quick transitions"
|
||||
lights:
|
||||
- light.living_room
|
||||
brightness_mode: linear
|
||||
brightness_mode_time_dark: 600 # 10 minutes
|
||||
brightness_mode_time_light: 1800 # 30 minutes
|
||||
```
|
||||
|
||||
### Smooth Transition (Tanh)
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Smooth transitions"
|
||||
lights:
|
||||
- light.bedroom
|
||||
brightness_mode: tanh
|
||||
brightness_mode_time_dark: 1200 # 20 minutes
|
||||
brightness_mode_time_light: 3600 # 1 hour
|
||||
```
|
||||
|
||||
## Graphs
|
||||
|
||||
These graphs show how brightness changes throughout the day based on calculated values:
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- print(include_section("../../README.md", "graphs", strip_heading=True)) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
These graphs were generated using the values calculated by the Adaptive Lighting sensor/switch(es).
|
||||
|
||||
### :sunny: Sun Position
|
||||

|
||||
|
||||
### :thermometer: Color Temperature
|
||||

|
||||
|
||||
### :high_brightness: Brightness
|
||||

|
||||
|
||||
### While using `transition_until_sleep: true`
|
||||

|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Interactive Simulator
|
||||
|
||||
The best way to understand brightness modes is to experiment with the interactive simulator:
|
||||
|
||||
<div style="text-align: center; margin: 2rem 0;">
|
||||
<a href="../simulator/" class="simulator-link">
|
||||
Try the Simulator
|
||||
</a>
|
||||
</div>
|
||||
|
||||
Adjust the `brightness_mode`, `brightness_mode_time_dark`, and `brightness_mode_time_light` parameters to see how they affect the brightness curve in real-time.
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
---
|
||||
icon: lucide/hand
|
||||
---
|
||||
|
||||
# Manual Control
|
||||
|
||||
Adaptive Lighting is designed to work seamlessly with manual adjustments, detecting when you or another source changes light settings and pausing adaptation accordingly.
|
||||
|
||||
## How It Works
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- print(include_section("../../README.md", "manual-control", strip_heading=True)) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
Adaptive Lighting is designed to automatically detect when you or another source (e.g., automation) manually changes light settings 🕹️.
|
||||
When this occurs, the affected light is marked as "manually controlled," and Adaptive Lighting will not make further adjustments until the light is turned off and back on or reset using the `adaptive_lighting.set_manual_control` service call.
|
||||
This feature is available when `take_over_control` is enabled.
|
||||
|
||||
Additionally, enabling `detect_non_ha_changes` allows Adaptive Lighting to detect all state changes, including those made outside of Home Assistant, by comparing the light's state to its previously used settings.
|
||||
The `adaptive_lighting.manual_control` event is fired when a light is marked as "manually controlled," allowing for integration with automations 🤖.
|
||||
|
||||
> ⚠️ **_Caution: Some lights might falsely indicate an 'on' state, which could result in lights turning on unexpectedly. Disable `detect_non_ha_changes` if you encounter such issues._**
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### take_over_control
|
||||
|
||||
When enabled (default: `true`), Adaptive Lighting detects `light.turn_on` service calls that specify brightness or color values. If such a call is detected for a light that's already on, that light is marked as "manually controlled".
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "With manual control detection"
|
||||
lights:
|
||||
- light.living_room
|
||||
take_over_control: true # default
|
||||
```
|
||||
|
||||
### take_over_control_mode
|
||||
|
||||
Controls how adaptation pauses when manual changes are detected:
|
||||
|
||||
| Mode | Behavior |
|
||||
|------|----------|
|
||||
| `pause_all` | Pause both brightness and color adaptation (default) |
|
||||
| `pause_changed` | Only pause adaptation of the changed attribute |
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Selective pause"
|
||||
lights:
|
||||
- light.living_room
|
||||
take_over_control: true
|
||||
take_over_control_mode: pause_changed # Only pause changed attributes
|
||||
```
|
||||
|
||||
### detect_non_ha_changes
|
||||
|
||||
When enabled, Adaptive Lighting detects state changes made outside of Home Assistant by comparing the light's current state to its previously applied settings.
|
||||
|
||||
> [!WARNING]
|
||||
> **Use with caution.** Some lights may falsely report an "on" state, which could result in lights turning on unexpectedly. Disable this option if you encounter such issues.
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Detect external changes"
|
||||
lights:
|
||||
- light.living_room
|
||||
take_over_control: true
|
||||
detect_non_ha_changes: true
|
||||
```
|
||||
|
||||
### autoreset_control_seconds
|
||||
|
||||
Automatically resets the manual control flag after a specified number of seconds. Set to `0` to disable (default).
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Auto-reset after 2 hours"
|
||||
lights:
|
||||
- light.living_room
|
||||
take_over_control: true
|
||||
autoreset_control_seconds: 7200 # 2 hours
|
||||
```
|
||||
|
||||
### adapt_only_on_bare_turn_on
|
||||
|
||||
When enabled, Adaptive Lighting only adapts lights when `light.turn_on` is called without specifying brightness or color. This is useful when you want scenes to work without interference.
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Respect scenes"
|
||||
lights:
|
||||
- light.living_room
|
||||
take_over_control: true
|
||||
adapt_only_on_bare_turn_on: true
|
||||
```
|
||||
|
||||
## Checking Manual Control Status
|
||||
|
||||
You can see which lights are marked as manually controlled by checking the switch attributes:
|
||||
|
||||
1. Go to **Developer Tools** → **States**
|
||||
2. Find your Adaptive Lighting switch (e.g., `switch.adaptive_lighting_living_room`)
|
||||
3. Look at the `manual_control` attribute - it lists all manually controlled lights
|
||||
|
||||
## Resetting Manual Control
|
||||
|
||||
### Via Service Call
|
||||
|
||||
```yaml
|
||||
service: adaptive_lighting.set_manual_control
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_living_room
|
||||
lights:
|
||||
- light.floor_lamp
|
||||
manual_control: false # Resume adaptation
|
||||
```
|
||||
|
||||
### By Turning Light Off and On
|
||||
|
||||
Simply turning a light off and then back on will reset its manual control status.
|
||||
|
||||
### Via Automation
|
||||
|
||||
See [Automation Examples](../automation-examples.md) for automation recipes that automatically reset manual control.
|
||||
|
||||
## Events
|
||||
|
||||
When a light is marked as manually controlled, Adaptive Lighting fires an event:
|
||||
|
||||
**Event type:** `adaptive_lighting.manual_control`
|
||||
|
||||
**Event data:**
|
||||
```yaml
|
||||
entity_id: light.living_room
|
||||
switch: switch.adaptive_lighting_living_room
|
||||
```
|
||||
|
||||
You can use this event to trigger automations:
|
||||
|
||||
```yaml
|
||||
automation:
|
||||
- alias: "Notify on manual control"
|
||||
trigger:
|
||||
platform: event
|
||||
event_type: adaptive_lighting.manual_control
|
||||
action:
|
||||
- service: notify.mobile_app
|
||||
data:
|
||||
message: "{{ trigger.event.data.entity_id }} was manually adjusted"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Zigbee groups** when controlling multiple bulbs together - this ensures consistent manual control detection
|
||||
2. **Set reasonable autoreset times** if you want lights to eventually resume adaptation
|
||||
3. **Use `pause_changed` mode** if you only adjust brightness or color individually
|
||||
4. **Disable `detect_non_ha_changes`** if you experience unexpected light turn-ons
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
---
|
||||
icon: lucide/moon
|
||||
---
|
||||
|
||||
# Sleep Mode
|
||||
|
||||
Sleep mode is a special operating mode that sets your lights to minimal brightness and very warm color, perfect for winding down at night without disrupting your circadian rhythm.
|
||||
|
||||
## Activating Sleep Mode
|
||||
|
||||
Each Adaptive Lighting configuration creates a sleep mode switch:
|
||||
|
||||
```
|
||||
switch.adaptive_lighting_sleep_mode_<name>
|
||||
```
|
||||
|
||||
Turn it on to activate sleep mode:
|
||||
|
||||
```yaml
|
||||
service: switch.turn_on
|
||||
target:
|
||||
entity_id: switch.adaptive_lighting_sleep_mode_living_room
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
Sleep mode is configured through the main Adaptive Lighting configuration. See the [Configuration](../configuration.md) page for the full options table. The sleep-related options are:
|
||||
|
||||
| Option | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| `sleep_brightness` | 1 | Brightness percentage in sleep mode |
|
||||
| `sleep_rgb_or_color_temp` | `color_temp` | Use `rgb_color` or `color_temp` in sleep mode |
|
||||
| `sleep_color_temp` | 1000 | Color temperature in Kelvin for sleep mode |
|
||||
| `sleep_rgb_color` | `[255, 56, 0]` | RGB color for sleep mode |
|
||||
| `sleep_transition` | 1 | Transition duration in seconds |
|
||||
| `transition_until_sleep` | false | Gradually transition to sleep settings after sunset |
|
||||
|
||||
## Automation Examples
|
||||
|
||||
See [Automation Examples](../automation-examples.md) for sleep mode automation recipes, including:
|
||||
|
||||
- Toggle sleep mode using an `input_boolean`
|
||||
- Set sunrise/sunset based on alarm time
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -1,46 +0,0 @@
|
|||
/* Adaptive Lighting Documentation Custom Styles */
|
||||
|
||||
/* Hero section on index page */
|
||||
.md-content__inner > h1:first-child {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Logo in header - make it slightly larger */
|
||||
.md-header__button.md-logo img {
|
||||
height: 1.8rem;
|
||||
}
|
||||
|
||||
/* Simulator link button styling */
|
||||
.simulator-link {
|
||||
display: inline-block;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background: linear-gradient(135deg, var(--md-primary-fg-color), var(--md-accent-fg-color));
|
||||
color: white !important;
|
||||
text-decoration: none;
|
||||
border-radius: 2rem;
|
||||
font-weight: 600;
|
||||
font-size: 1.1rem;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.simulator-link:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Code block improvements */
|
||||
.highlight code {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* Table improvements */
|
||||
.md-typeset table:not([class]) {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.md-typeset table:not([class]) th {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
---
|
||||
icon: lucide/bot
|
||||
---
|
||||
|
||||
# Automation Examples
|
||||
|
||||
Real-world automation examples showing how to integrate Adaptive Lighting with your Home Assistant setup.
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting.docs_gen import _transform_readme_links -->
|
||||
<!-- print(_transform_readme_links(include_section("../README.md", "automation-examples", strip_heading=True))) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
<details markdown="1">
|
||||
<summary>Reset the <code>manual_control</code> status of a light after an hour.</summary>
|
||||
|
||||
```yaml
|
||||
- alias: "Adaptive lighting: reset manual_control after 1 hour"
|
||||
mode: parallel
|
||||
trigger:
|
||||
platform: event
|
||||
event_type: adaptive_lighting.manual_control
|
||||
variables:
|
||||
light: "{{ trigger.event.data.entity_id }}"
|
||||
switch: "{{ trigger.event.data.switch }}"
|
||||
action:
|
||||
- delay: "01:00:00"
|
||||
- condition: template
|
||||
value_template: "{{ light in state_attr(switch, 'manual_control') }}"
|
||||
- service: adaptive_lighting.set_manual_control
|
||||
data:
|
||||
entity_id: "{{ switch }}"
|
||||
lights: "{{ light }}"
|
||||
manual_control: false
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details markdown="1">
|
||||
<summary>Toggle multiple Adaptive Lighting switches to "sleep mode" using an <code>input_boolean.sleep_mode</code>.</summary>
|
||||
|
||||
```yaml
|
||||
- alias: "Adaptive lighting: toggle 'sleep mode'"
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: input_boolean.sleep_mode
|
||||
- platform: homeassistant
|
||||
event: start # in case the states aren't properly restored
|
||||
variables:
|
||||
sleep_mode: "{{ states('input_boolean.sleep_mode') }}"
|
||||
action:
|
||||
service: "switch.turn_{{ sleep_mode }}"
|
||||
entity_id:
|
||||
- switch.adaptive_lighting_sleep_mode_living_room
|
||||
- switch.adaptive_lighting_sleep_mode_bedroom
|
||||
```
|
||||
|
||||
Set your sunrise and sunset time based on your alarm. The below script sets sunset_time exactly 12 hours after the custom sunrise time.
|
||||
|
||||
```yaml
|
||||
iphone_carly_wakeup:
|
||||
alias: iPhone Carly Wakeup
|
||||
sequence:
|
||||
- condition: state
|
||||
entity_id: input_boolean.carly_iphone_wakeup
|
||||
state: "off"
|
||||
- service: input_datetime.set_datetime
|
||||
target:
|
||||
entity_id: input_datetime.carly_iphone_wakeup
|
||||
data:
|
||||
time: '{{ now().strftime("%H:%M:%S") }}'
|
||||
- service: input_boolean.turn_on
|
||||
target:
|
||||
entity_id: input_boolean.carly_iphone_wakeup
|
||||
- repeat:
|
||||
count: >
|
||||
{{ (states.switch
|
||||
| map(attribute="entity_id")
|
||||
| select(">","switch.adaptive_lighting_al_")
|
||||
| select("<", "switch.adaptive_lighting_al_z")
|
||||
| join(",")
|
||||
).split(",") | length }}
|
||||
sequence:
|
||||
- service: adaptive_lighting.change_switch_settings
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_al_den_ceilingfan_lights
|
||||
sunrise_time: '{{ now().strftime("%H:%M:%S") }}'
|
||||
sunset_time: >
|
||||
{{ (as_timestamp(now()) + 12*60*60) | timestamp_custom("%H:%M:%S") }}
|
||||
- service: script.turn_on
|
||||
target:
|
||||
entity_id: script.run_wakeup_routine
|
||||
- service: input_boolean.turn_off
|
||||
target:
|
||||
entity_id:
|
||||
- input_boolean.carly_iphone_winddown
|
||||
- input_boolean.carly_iphone_bedtime
|
||||
- service: input_datetime.set_datetime
|
||||
target:
|
||||
entity_id: input_datetime.wakeup_time
|
||||
data:
|
||||
time: '{{ now().strftime("%H:%M:%S") }}'
|
||||
- service: script.adaptive_lighting_disable_sleep_mode
|
||||
mode: queued
|
||||
icon: mdi:weather-sunset
|
||||
max: 10
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
> [!TIP]
|
||||
> **Have a useful automation?** Share your automation examples by [opening an issue](https://github.com/basnijholt/adaptive-lighting/issues) or submitting a pull request to the README.
|
||||
|
|
@ -1,150 +0,0 @@
|
|||
---
|
||||
icon: lucide/settings
|
||||
---
|
||||
|
||||
# Configuration
|
||||
|
||||
Adaptive Lighting supports configuration through both YAML and the Home Assistant UI, with identical option names in both methods.
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
The minimal configuration requires only adding the integration to your `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
```
|
||||
|
||||
You can then configure everything through the UI at **Settings** → **Devices & Services** → **Adaptive Lighting** → **Configure**.
|
||||
|
||||
## YAML Configuration
|
||||
|
||||
For YAML configuration, you can specify lights and options directly:
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Living Room"
|
||||
lights:
|
||||
- light.living_room_ceiling
|
||||
- light.living_room_lamp
|
||||
```
|
||||
|
||||
## All Options
|
||||
|
||||
All configuration options are listed below with their default values. These options work identically in both YAML and the UI.
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting._docs_helpers import generate_config_markdown_table -->
|
||||
<!-- print(generate_config_markdown_table()) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
| Variable name | Description | Default | Type |
|
||||
|:-------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------|:----------------------------------------|
|
||||
| `lights` | List of light entity_ids to be controlled (may be empty). 🌟 | `[]` | list of `entity_id`s |
|
||||
| `interval` | Frequency to adapt the lights, in seconds. 🔄 | `90` | `int > 0` |
|
||||
| `transition` | Duration of transition when lights change, in seconds. 🕑 | `45` | `float` 0-6553 |
|
||||
| `initial_transition` | Duration of the first transition when lights turn from `off` to `on` in seconds. ⏲️ | `1` | `float` 0-6553 |
|
||||
| `min_brightness` | Minimum brightness percentage. 💡 | `1` | `int` 1-100 |
|
||||
| `max_brightness` | Maximum brightness percentage. 💡 | `100` | `int` 1-100 |
|
||||
| `min_color_temp` | Warmest color temperature in Kelvin. 🔥 | `2000` | `int` 1000-10000 |
|
||||
| `max_color_temp` | Coldest color temperature in Kelvin. ❄️ | `5500` | `int` 1000-10000 |
|
||||
| `prefer_rgb_color` | Whether to prefer RGB color adjustment over light color temperature when possible. 🌈 | `False` | `bool` |
|
||||
| `sleep_brightness` | Brightness percentage of lights in sleep mode. 😴 | `1` | `int` 1-100 |
|
||||
| `sleep_rgb_or_color_temp` | Use either `"rgb_color"` or `"color_temp"` in sleep mode. 🌙 | `color_temp` | one of `['color_temp', 'rgb_color']` |
|
||||
| `sleep_color_temp` | Color temperature in sleep mode (used when `sleep_rgb_or_color_temp` is `color_temp`) in Kelvin. 😴 | `1000` | `int` 1000-10000 |
|
||||
| `sleep_rgb_color` | RGB color in sleep mode (used when `sleep_rgb_or_color_temp` is "rgb_color"). 🌈 | `[255, 56, 0]` | RGB color |
|
||||
| `sleep_transition` | Duration of transition when "sleep mode" is toggled in seconds. 😴 | `1` | `float` 0-6553 |
|
||||
| `transition_until_sleep` | When enabled, Adaptive Lighting will treat sleep settings as the minimum, transitioning to these values after sunset. 🌙 | `False` | `bool` |
|
||||
| `sunrise_time` | Set a fixed time (HH:MM:SS) for sunrise. 🌅 | `None` | `str` |
|
||||
| `min_sunrise_time` | Set the earliest virtual sunrise time (HH:MM:SS), allowing for later sunrises. 🌅 | `None` | `str` |
|
||||
| `max_sunrise_time` | Set the latest virtual sunrise time (HH:MM:SS), allowing for earlier sunrises. 🌅 | `None` | `str` |
|
||||
| `sunrise_offset` | Adjust sunrise time with a positive or negative offset in seconds. ⏰ | `0` | `int` |
|
||||
| `sunset_time` | Set a fixed time (HH:MM:SS) for sunset. 🌇 | `None` | `str` |
|
||||
| `min_sunset_time` | Set the earliest virtual sunset time (HH:MM:SS), allowing for later sunsets. 🌇 | `None` | `str` |
|
||||
| `max_sunset_time` | Set the latest virtual sunset time (HH:MM:SS), allowing for earlier sunsets. 🌇 | `None` | `str` |
|
||||
| `sunset_offset` | Adjust sunset time with a positive or negative offset in seconds. ⏰ | `0` | `int` |
|
||||
| `brightness_mode` | Brightness mode to use. Possible values are `default`, `linear`, and `tanh` (uses `brightness_mode_time_dark` and `brightness_mode_time_light`). 📈 | `default` | one of `['default', 'linear', 'tanh']` |
|
||||
| `brightness_mode_time_dark` | (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness before/after sunrise/sunset. 📈📉 | `900` | `int` |
|
||||
| `brightness_mode_time_light` | (Ignored if `brightness_mode='default'`) The duration in seconds to ramp up/down the brightness after/before sunrise/sunset. 📈📉. | `3600` | `int` |
|
||||
| `take_over_control` | Pause adaptation of individual lights and hand over (manual) control to other sources that issue `light.turn_on` calls for lights that are on. 🔒 | `True` | `bool` |
|
||||
| `take_over_control_mode` | The adaptation pausing mode when other sources change brightness and/or color of lights. `pause_all` always pauses both brightness and color adaptation. `pause_changed` pauses the adaptation of only the changed attributes and continues adapting unchanged attributes, e.g., continues color adaptation when only brightness was changed. | `pause_all` | one of `['pause_all', 'pause_changed']` |
|
||||
| `detect_non_ha_changes` | Detects and halts adaptations for non-`light.turn_on` state changes. Needs `take_over_control` enabled. 🕵️ Caution: ⚠️ Some lights might falsely indicate an 'on' state, which could result in lights turning on unexpectedly. Note that this calls `homeassistant.update_entity` every `interval`! Disable this feature if you encounter such issues. | `False` | `bool` |
|
||||
| `autoreset_control_seconds` | Automatically reset the manual control after a number of seconds. Set to 0 to disable. ⏲️ | `0` | `int` 0-31536000 |
|
||||
| `only_once` | Adapt lights only when they are turned on (`true`) or keep adapting them (`false`). 🔄 | `False` | `bool` |
|
||||
| `adapt_only_on_bare_turn_on` | When turning lights on initially. If set to `true`, AL adapts only if `light.turn_on` is invoked without specifying color or brightness. ❌🌈 This e.g., prevents adaptation when activating a scene and marks the light as manually controlled. If `false`, AL adapts regardless of the presence of color or brightness in the initial `service_data`. Needs `take_over_control` enabled. 🕵️ | `False` | `bool` |
|
||||
| `separate_turn_on_commands` | Use separate `light.turn_on` calls for color and brightness, needed for some light types. 🔀 | `False` | `bool` |
|
||||
| `send_split_delay` | Delay (ms) between `separate_turn_on_commands` for lights that don't support simultaneous brightness and color setting. ⏲️ | `0` | `int` 0-10000 |
|
||||
| `adapt_delay` | Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️ | `0` | `float > 0` |
|
||||
| `skip_redundant_commands` | Skip sending adaptation commands whose target state already equals the light's known state. Minimizes network traffic and improves the adaptation responsivity in some situations. 📉Disable if physical light states get out of sync with HA's recorded state. | `False` | `bool` |
|
||||
| `intercept` | Intercept and adapt `light.turn_on` calls to enabling instantaneous color and brightness adaptation. 🏎️ Disable for lights that do not support `light.turn_on` with color and brightness. | `True` | `bool` |
|
||||
| `multi_light_intercept` | Intercept and adapt `light.turn_on` calls that target multiple lights. ➗⚠️ This might result in splitting up a single `light.turn_on` call into multiple calls, e.g., when lights are in different switches. Requires `intercept` to be enabled. | `True` | `bool` |
|
||||
| `include_config_in_attributes` | Show all options as attributes on the switch in Home Assistant when set to `true`. 📝 | `False` | `bool` |
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Full Configuration Example
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting.docs_gen import _transform_readme_links -->
|
||||
<!-- print(_transform_readme_links(include_section("../README.md", "config-example-full"))) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
Full example:
|
||||
|
||||
```yaml
|
||||
# Example configuration.yaml entry
|
||||
adaptive_lighting:
|
||||
- name: "default"
|
||||
lights: []
|
||||
prefer_rgb_color: false
|
||||
transition: 45
|
||||
initial_transition: 1
|
||||
interval: 90
|
||||
min_brightness: 1
|
||||
max_brightness: 100
|
||||
min_color_temp: 2000
|
||||
max_color_temp: 5500
|
||||
sleep_brightness: 1
|
||||
sleep_color_temp: 1000
|
||||
sunrise_time: "08:00:00" # override the sunrise time
|
||||
sunrise_offset:
|
||||
sunset_time:
|
||||
sunset_offset: 1800 # in seconds or '00:30:00'
|
||||
take_over_control: true
|
||||
detect_non_ha_changes: false
|
||||
only_once: false
|
||||
|
||||
```
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Multiple Configurations
|
||||
|
||||
You can create multiple Adaptive Lighting configurations for different areas or use cases:
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Daytime Spaces"
|
||||
lights:
|
||||
- light.living_room
|
||||
- light.kitchen
|
||||
- light.office
|
||||
min_brightness: 30
|
||||
max_brightness: 100
|
||||
|
||||
- name: "Bedroom"
|
||||
lights:
|
||||
- light.bedroom_ceiling
|
||||
- light.bedroom_lamp
|
||||
min_brightness: 5
|
||||
max_brightness: 80
|
||||
sleep_brightness: 1
|
||||
sleep_color_temp: 1000
|
||||
```
|
||||
|
||||
## Related Topics
|
||||
|
||||
- [Brightness Modes](advanced/brightness-modes.md) - Detailed explanation of brightness calculation modes
|
||||
- [Sleep Mode](advanced/sleep-mode.md) - Sleep mode configuration
|
||||
- [Manual Control](advanced/manual-control.md) - How manual control detection works
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
---
|
||||
icon: lucide/rocket
|
||||
---
|
||||
|
||||
# Getting Started
|
||||
|
||||
This guide will help you install and configure Adaptive Lighting for the first time.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Home Assistant](https://www.home-assistant.io/) 2024.12.0 or newer
|
||||
- [HACS](https://hacs.xyz/) (Home Assistant Community Store) installed
|
||||
|
||||
## Installation
|
||||
|
||||
### Via HACS (Recommended)
|
||||
|
||||
1. Open HACS in your Home Assistant instance
|
||||
2. Click on **Integrations**
|
||||
3. Click the **+ Explore & Download Repositories** button
|
||||
4. Search for "Adaptive Lighting"
|
||||
5. Click **Download**
|
||||
6. Restart Home Assistant
|
||||
|
||||
Or use this button to open HACS directly:
|
||||
|
||||
[](https://my.home-assistant.io/redirect/hacs_repository/?owner=basnijholt&repository=adaptive-lighting&category=integration)
|
||||
|
||||
### Manual Installation
|
||||
|
||||
1. Download the latest release from [GitHub](https://github.com/basnijholt/adaptive-lighting/releases)
|
||||
2. Extract the `adaptive_lighting` folder to your `config/custom_components/` directory
|
||||
3. Restart Home Assistant
|
||||
|
||||
## Configuration
|
||||
|
||||
### Step 1: Add to configuration.yaml
|
||||
|
||||
Add the following to your `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> This entry is required even if you plan to configure everything through the UI.
|
||||
|
||||
### Step 2: Restart Home Assistant
|
||||
|
||||
Restart Home Assistant for the changes to take effect.
|
||||
|
||||
### Step 3: Add the Integration
|
||||
|
||||
1. Go to **Settings** → **Devices & Services**
|
||||
2. Click **+ Add Integration**
|
||||
3. Search for "Adaptive Lighting"
|
||||
4. Follow the setup wizard to select your lights
|
||||
|
||||
### Step 4: Configure Your Lights
|
||||
|
||||
You can configure Adaptive Lighting in two ways:
|
||||
|
||||
=== "Via UI"
|
||||
|
||||
1. Go to **Settings** → **Devices & Services**
|
||||
2. Find Adaptive Lighting and click **Configure**
|
||||
3. Adjust settings as needed
|
||||
|
||||
=== "Via YAML"
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Living Room"
|
||||
lights:
|
||||
- light.living_room_ceiling
|
||||
- light.living_room_lamp
|
||||
min_brightness: 20
|
||||
max_brightness: 100
|
||||
min_color_temp: 2200
|
||||
max_color_temp: 5500
|
||||
```
|
||||
|
||||
## Basic Configuration Example
|
||||
|
||||
Here's a simple configuration to get you started:
|
||||
|
||||
```yaml
|
||||
adaptive_lighting:
|
||||
- name: "Main Lights"
|
||||
lights:
|
||||
- light.living_room
|
||||
- light.bedroom
|
||||
- light.kitchen
|
||||
transition: 30
|
||||
min_brightness: 10
|
||||
max_brightness: 100
|
||||
min_color_temp: 2000
|
||||
max_color_temp: 5500
|
||||
```
|
||||
|
||||
## Verifying Installation
|
||||
|
||||
After configuration, you should see new switches in Home Assistant:
|
||||
|
||||
- `switch.adaptive_lighting_main_lights`
|
||||
- `switch.adaptive_lighting_sleep_mode_main_lights`
|
||||
- `switch.adaptive_lighting_adapt_brightness_main_lights`
|
||||
- `switch.adaptive_lighting_adapt_color_main_lights`
|
||||
|
||||
Turn on `switch.adaptive_lighting_main_lights` to start adapting your lights!
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configuration Reference](configuration.md) - Explore all available options
|
||||
- [Services](services.md) - Learn about service calls for automations
|
||||
- [Automation Examples](automation-examples.md) - See real-world automation recipes
|
||||
- [Troubleshooting](troubleshooting.md) - Common issues and solutions
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
---
|
||||
icon: lucide/sun
|
||||
---
|
||||
|
||||
# Adaptive Lighting
|
||||
|
||||
**Enhance Your Home's Atmosphere with Smart, Sun-Synchronized Lighting**
|
||||
|
||||
<div style="text-align: center; margin: 2rem 0;">
|
||||
<img src="assets/logo.png" alt="Adaptive Lighting Logo" width="200" />
|
||||
</div>
|
||||
|
||||
[Adaptive Lighting](https://github.com/basnijholt/adaptive-lighting) is a custom component for [Home Assistant](https://www.home-assistant.io/) that intelligently adjusts the brightness and color of your lights based on the sun's position, while still allowing for manual control.
|
||||
|
||||
<div style="text-align: center; margin: 2rem 0;">
|
||||
<a href="https://my.home-assistant.io/redirect/hacs_repository/?owner=basnijholt&repository=adaptive-lighting&category=integration" class="md-button md-button--primary">
|
||||
Install via HACS
|
||||
</a>
|
||||
<a href="simulator/" class="md-button">
|
||||
Try the Simulator
|
||||
</a>
|
||||
</div>
|
||||
|
||||
By automatically adapting the settings of your lights throughout the day, Adaptive Lighting helps maintain your natural circadian rhythm, which can lead to improved sleep, mood, and overall well-being. Experience cooler color temperatures at noon, gradually transitioning to warmer colors at sunset and sunrise.
|
||||
|
||||
## Features
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting.docs_gen import _transform_readme_links -->
|
||||
<!-- print(_transform_readme_links(include_section("../README.md", "features", strip_heading=True))) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
When initially turning on a light that is controlled by Adaptive Lighting, the `light.turn_on` service call is intercepted, and the light's brightness and color are automatically adjusted based on the sun's position.
|
||||
After that, the light's brightness and color are automatically adjusted at a regular interval.
|
||||
|
||||
Adaptive Lighting provides four switches (using "living_room" as an example component name):
|
||||
|
||||
- `switch.adaptive_lighting_living_room`: Turn Adaptive Lighting on or off and view current light settings through its attributes.
|
||||
- `switch.adaptive_lighting_sleep_mode_living_room`: Activate "sleep mode" 😴 and set custom sleep_brightness and sleep_color_temp.
|
||||
- `switch.adaptive_lighting_adapt_brightness_living_room`: Enable or disable brightness adaptation 🔆 for supported lights.
|
||||
- `switch.adaptive_lighting_adapt_color_living_room`: Enable or disable color adaptation 🌈 for supported lights.
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Install via HACS**: Search for "Adaptive Lighting" in the [Home Assistant Community Store](https://hacs.xyz/)
|
||||
2. **Add to configuration**: Add `adaptive_lighting:` to your `configuration.yaml`
|
||||
3. **Configure**: Go to **Settings** → **Devices & Services** → **Add Integration** → **Adaptive Lighting**
|
||||
4. **Select your lights**: Choose which lights to control and enjoy automatic adaptation!
|
||||
|
||||
```yaml
|
||||
# Minimal configuration.yaml entry
|
||||
adaptive_lighting:
|
||||
lights:
|
||||
- light.living_room
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> **Using the UI exclusively?** Even if you plan to configure everything through the UI, the `adaptive_lighting:` entry must still be present in your `configuration.yaml`.
|
||||
|
||||
[Get Started →](getting-started.md){ .md-button .md-button--primary }
|
||||
[View All Options →](configuration.md){ .md-button }
|
||||
|
||||
## How It Works
|
||||
|
||||
Adaptive Lighting provides four switches for each configuration (using "living_room" as an example):
|
||||
|
||||
| Switch | Purpose |
|
||||
|--------|---------|
|
||||
| `switch.adaptive_lighting_living_room` | Main on/off control |
|
||||
| `switch.adaptive_lighting_sleep_mode_living_room` | Activate sleep mode |
|
||||
| `switch.adaptive_lighting_adapt_brightness_living_room` | Enable/disable brightness adaptation |
|
||||
| `switch.adaptive_lighting_adapt_color_living_room` | Enable/disable color adaptation |
|
||||
|
||||
## Interactive Simulator
|
||||
|
||||
Visualize how Adaptive Lighting will work with your settings using the interactive simulator:
|
||||
|
||||
<div style="text-align: center; margin: 2rem 0;">
|
||||
<a href="simulator/" class="simulator-link">
|
||||
Try the Interactive Simulator
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<!-- Privacy-friendly analytics by Plausible -->
|
||||
<script async src="https://plausible.nijho.lt/js/pa-yNpTS2silFzWxGYjHM_Bk.js"></script>
|
||||
<script>
|
||||
window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
|
||||
plausible.init()
|
||||
</script>
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# ruff: noqa: T201, S603, S607
|
||||
"""Update all markdown files that use markdown-code-runner for auto-generation.
|
||||
|
||||
Run from repo root: uv run python docs/run_markdown_code_runner.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def find_markdown_files_with_code_blocks(docs_dir: Path) -> list[Path]:
|
||||
"""Find all markdown files containing markdown-code-runner markers."""
|
||||
files_with_code = []
|
||||
for md_file in docs_dir.rglob("*.md"):
|
||||
content = md_file.read_text()
|
||||
if "<!-- CODE:START -->" in content:
|
||||
files_with_code.append(md_file)
|
||||
return sorted(files_with_code)
|
||||
|
||||
|
||||
def run_markdown_code_runner(files: list[Path], repo_root: Path) -> bool:
|
||||
"""Run markdown-code-runner on all files. Returns True if all succeeded."""
|
||||
if not files:
|
||||
print("No files with CODE:START markers found.")
|
||||
return True
|
||||
|
||||
print(f"Found {len(files)} file(s) with auto-generated content:")
|
||||
for f in files:
|
||||
print(f" - {f.relative_to(repo_root)}")
|
||||
print()
|
||||
|
||||
all_success = True
|
||||
for file in files:
|
||||
rel_path = file.relative_to(repo_root)
|
||||
print(f"Updating {rel_path}...", end=" ", flush=True)
|
||||
result = subprocess.run(
|
||||
["markdown-code-runner", str(file)],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
print("✓")
|
||||
else:
|
||||
print("✗")
|
||||
print(f" Error: {result.stderr}")
|
||||
all_success = False
|
||||
|
||||
return all_success
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Main entry point."""
|
||||
repo_root = Path(__file__).parent.parent
|
||||
|
||||
# Process docs/ files and README.md
|
||||
files = find_markdown_files_with_code_blocks(repo_root / "docs")
|
||||
readme = repo_root / "README.md"
|
||||
if readme.exists() and "<!-- CODE:START -->" in readme.read_text():
|
||||
files.append(readme)
|
||||
|
||||
success = run_markdown_code_runner(files, repo_root)
|
||||
return 0 if success else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
---
|
||||
icon: lucide/external-link
|
||||
---
|
||||
|
||||
# See Also
|
||||
|
||||
Resources, tutorials, and related projects for Adaptive Lighting.
|
||||
|
||||
## Tutorials & Articles
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting.docs_gen import _transform_readme_links -->
|
||||
<!-- print(_transform_readme_links(include_section("../README.md", "see-also", strip_heading=True))) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
- [*Sleep better with Adaptive Lighting in Home Assistant*](https://wartner.io/sleep-better-with-adaptive-lightning-in-home-assistant/) by Florian Wartner on 2023-02-23 (blog post 📜)
|
||||
- [*Automatic smart light brightness and color based on the sun*](https://www.youtube.com/watch?v=Rg3zI1Oyk3c) by Home Automation Guy on 2022-08-31 (YouTube video 📺)
|
||||
- [*Adaptive Lighting Blew My Mind in Home Assistant - How to set it up*](https://www.youtube.com/watch?v=c1cnccmgl3k) by Smart Home Junkie on 2022-06-26 (YouTube video 📺)
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Interactive Tools
|
||||
|
||||
### Adaptive Lighting Simulator
|
||||
|
||||
Visualize how different settings affect your lighting throughout the day:
|
||||
|
||||
<div style="text-align: center; margin: 2rem 0;">
|
||||
<a href="../simulator/" class="simulator-link">
|
||||
Open the Simulator
|
||||
</a>
|
||||
</div>
|
||||
|
||||
The simulator lets you:
|
||||
|
||||
- Adjust all configuration parameters in real-time
|
||||
- See how brightness and color temperature change throughout the day
|
||||
- Visualize the effects of different `brightness_mode` settings
|
||||
- Test sleep mode transitions
|
||||
|
||||
## Related Projects
|
||||
|
||||
### Circadian Lighting
|
||||
|
||||
Adaptive Lighting was initially inspired by [hass-circadian_lighting](https://github.com/claytonjn/hass-circadian_lighting) by @claytonjn, but has since been entirely rewritten and expanded with many new features.
|
||||
|
||||
## Official Documentation
|
||||
|
||||
- [Home Assistant Documentation (PR Preview)](https://deploy-preview-14877--home-assistant-docs.netlify.app/integrations/adaptive_lighting/)
|
||||
- [Home Assistant Community Store (HACS)](https://hacs.xyz/)
|
||||
|
||||
## Community
|
||||
|
||||
- [Home Assistant Community Forums](https://community.home-assistant.io/)
|
||||
- [Home Assistant Discord](https://discord.gg/home-assistant)
|
||||
- [Reddit r/homeassistant](https://www.reddit.com/r/homeassistant/)
|
||||
|
||||
## Contributing
|
||||
|
||||
Interested in contributing to Adaptive Lighting?
|
||||
|
||||
- [GitHub Repository](https://github.com/basnijholt/adaptive-lighting)
|
||||
- [Issue Tracker](https://github.com/basnijholt/adaptive-lighting/issues)
|
||||
- [Translation via Weblate](https://hosted.weblate.org/engage/adaptive-lighting/)
|
||||
|
||||
### Translation
|
||||
|
||||
Help translate Adaptive Lighting into your language on [Hosted Weblate](https://hosted.weblate.org/engage/adaptive-lighting/). No programming knowledge required!
|
||||
|
||||
<a href="https://hosted.weblate.org/engage/adaptive-lighting/">
|
||||
<img src="https://hosted.weblate.org/widget/adaptive-lighting/multi-auto.svg" alt="Translation status" />
|
||||
</a>
|
||||
201
docs/services.md
201
docs/services.md
|
|
@ -1,201 +0,0 @@
|
|||
---
|
||||
icon: lucide/zap
|
||||
---
|
||||
|
||||
# Services
|
||||
|
||||
Adaptive Lighting provides three services for programmatic control, allowing you to integrate with automations and scripts.
|
||||
|
||||
## adaptive_lighting.apply
|
||||
|
||||
Applies the current Adaptive Lighting settings to lights on demand. Useful for forcing an immediate update or applying settings to lights that aren't in the regular adaptation cycle.
|
||||
|
||||
### Parameters
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting._docs_helpers import generate_apply_markdown_table -->
|
||||
<!-- print(generate_apply_markdown_table()) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
| Service data attribute | Description | Required | Type |
|
||||
|:-------------------------|:--------------------------------------------------------------------------------------|:-----------|:---------------------|
|
||||
| `entity_id` | The `entity_id` of the switch with the settings to apply. 📝 | ✅ | list of `entity_id`s |
|
||||
| `lights` | A light (or list of lights) to apply the settings to. 💡 | ❌ | list of `entity_id`s |
|
||||
| `transition` | Duration of transition when lights change, in seconds. 🕑 | ❌ | `float` 0-6553 |
|
||||
| `adapt_brightness` | Whether to adapt the brightness of the light. 🌞 | ❌ | bool |
|
||||
| `adapt_color` | Whether to adapt the color on supporting lights. 🌈 | ❌ | bool |
|
||||
| `prefer_rgb_color` | Whether to prefer RGB color adjustment over light color temperature when possible. 🌈 | ❌ | bool |
|
||||
| `turn_on_lights` | Whether to turn on lights that are currently off. 🔆 | ❌ | bool |
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
### Example Usage
|
||||
|
||||
```yaml
|
||||
# Apply current settings to specific lights
|
||||
service: adaptive_lighting.apply
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_living_room
|
||||
lights:
|
||||
- light.floor_lamp
|
||||
- light.desk_lamp
|
||||
turn_on_lights: false
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Force apply with custom transition
|
||||
service: adaptive_lighting.apply
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_bedroom
|
||||
transition: 5
|
||||
adapt_brightness: true
|
||||
adapt_color: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## adaptive_lighting.set_manual_control
|
||||
|
||||
Marks or unmarks a light as "manually controlled". When a light is marked as manually controlled, Adaptive Lighting will not adjust it until the manual control flag is cleared.
|
||||
|
||||
### Parameters
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting._docs_helpers import generate_set_manual_control_markdown_table -->
|
||||
<!-- print(generate_set_manual_control_markdown_table()) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
| Service data attribute | Description | Required | Type |
|
||||
|:-------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------|:-----------------------------------------|
|
||||
| `entity_id` | The `entity_id` of the switch in which to (un)mark the light as being `manually controlled`. 📝 | ✅ | list of `entity_id`s |
|
||||
| `lights` | entity_id(s) of lights, if not specified, all lights in the switch are selected. 💡 | ❌ | list of `entity_id`s |
|
||||
| `manual_control` | Whether to add ("true") or remove ("false") all adapted attributes of the light from the "manual_control" list, or the name of an attribute for selective addition. 🔒 | ❌ | bool or one of `['brightness', 'color']` |
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
### Example Usage
|
||||
|
||||
```yaml
|
||||
# Remove manual control from a light (resume adaptation)
|
||||
service: adaptive_lighting.set_manual_control
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_living_room
|
||||
lights:
|
||||
- light.floor_lamp
|
||||
manual_control: false
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Mark a light as manually controlled (pause adaptation)
|
||||
service: adaptive_lighting.set_manual_control
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_living_room
|
||||
lights:
|
||||
- light.floor_lamp
|
||||
manual_control: true
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Only pause brightness adaptation, continue color adaptation
|
||||
service: adaptive_lighting.set_manual_control
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_living_room
|
||||
lights:
|
||||
- light.floor_lamp
|
||||
manual_control: brightness
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## adaptive_lighting.change_switch_settings
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting.docs_gen import _transform_readme_links -->
|
||||
<!-- print(_transform_readme_links(include_section("../README.md", "change-switch-settings", strip_heading=True))) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
`adaptive_lighting.change_switch_settings` (new in 1.7.0) Change any of the above configuration options of Adaptive Lighting (such as `sunrise_time` or `prefer_rgb_color`) with a service call directly from your script/automation.
|
||||
|
||||
> [!WARNING]
|
||||
> These settings will **not** be written to your config and will be reset on restart of Home Assistant! You can see the current settings in the `switch.adaptive_lighting_XXX` attributes if `include_config_in_attributes` is enabled.
|
||||
|
||||
| Service data attribute | Required | Description |
|
||||
| --------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `use_defaults` | ❌ | (default: `current` for current settings) Choose from `factory`, `configuration`, or `current` to reset variables not being set with this service call. `current` leaves them as they are, `configuration` resets to initial startup values, `factory` resets to default values listed in the documentation. |
|
||||
| **all other keys** (except the ones in the table below ⚠️) | ❌ | See the table below for disallowed keys. |
|
||||
|
||||
The following keys are disallowed:
|
||||
|
||||
| **DISALLOWED** service data | Description |
|
||||
| --------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `entity_id` | You cannot change the switch's `entity_id`, as it has already been registered. |
|
||||
| `lights` | You may call `adaptive_lighting.apply` with your lights or create a new config instead. |
|
||||
| `name` | You can rename your switch's display name in Home Assistant's UI. |
|
||||
| `interval` | The interval is used only once when the config loads. A config change and restart are required. |
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
### Example Usage
|
||||
|
||||
```yaml
|
||||
# Temporarily change color temperature range
|
||||
service: adaptive_lighting.change_switch_settings
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_living_room
|
||||
min_color_temp: 2500
|
||||
max_color_temp: 4000
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Override sunrise time for the day
|
||||
service: adaptive_lighting.change_switch_settings
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_bedroom
|
||||
sunrise_time: "07:00:00"
|
||||
use_defaults: current
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Reset to configuration defaults
|
||||
service: adaptive_lighting.change_switch_settings
|
||||
data:
|
||||
entity_id: switch.adaptive_lighting_living_room
|
||||
use_defaults: configuration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Events
|
||||
|
||||
Adaptive Lighting also fires events that you can use in automations.
|
||||
|
||||
### adaptive_lighting.manual_control
|
||||
|
||||
Fired when a light is marked as "manually controlled" due to a detected manual change.
|
||||
|
||||
**Event Data:**
|
||||
|
||||
| Attribute | Description |
|
||||
|-----------|-------------|
|
||||
| `entity_id` | The light that was marked as manually controlled |
|
||||
| `switch` | The Adaptive Lighting switch entity |
|
||||
|
||||
### Example Automation
|
||||
|
||||
```yaml
|
||||
automation:
|
||||
- alias: "Log manual control events"
|
||||
trigger:
|
||||
platform: event
|
||||
event_type: adaptive_lighting.manual_control
|
||||
action:
|
||||
- service: notify.mobile_app
|
||||
data:
|
||||
title: "Adaptive Lighting"
|
||||
message: "{{ trigger.event.data.entity_id }} was manually controlled"
|
||||
```
|
||||
|
||||
See [Automation Examples](automation-examples.md) for more use cases.
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
---
|
||||
icon: lucide/life-buoy
|
||||
---
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
This guide covers common issues and their solutions when using Adaptive Lighting.
|
||||
|
||||
## Enable Debug Logging
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting.docs_gen import _transform_readme_links -->
|
||||
<!-- print(_transform_readme_links(include_section("../README.md", "troubleshooting-intro", strip_heading=True))) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
Encountering issues? Enable debug logging in your `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
logger:
|
||||
default: warning
|
||||
logs:
|
||||
custom_components.adaptive_lighting: debug
|
||||
```
|
||||
|
||||
After the issue occurs, create a new issue report with the log (`/config/home-assistant.log`).
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Common Problems & Solutions
|
||||
|
||||
<!-- CODE:START -->
|
||||
<!-- from adaptive_lighting.docs_gen import _transform_readme_links -->
|
||||
<!-- print(_transform_readme_links(include_section("../README.md", "common-problems", strip_heading=True))) -->
|
||||
<!-- CODE:END -->
|
||||
<!-- OUTPUT:START -->
|
||||
<!-- ⚠️ This content is auto-generated by `markdown-code-runner`. -->
|
||||
#### :bulb: Lights Not Responding or Turning On by Themselves
|
||||
|
||||
Adaptive Lighting sends more commands to lights than a typical human user would. If your light control network is unhealthy, you may experience:
|
||||
|
||||
- Laggy manual commands (e.g., turning lights on or off).
|
||||
- Unresponsive lights.
|
||||
- Home Assistant reporting incorrect light states, causing Adaptive Lighting to inadvertently turn lights back on.
|
||||
|
||||
Most issues that appear to be caused by Adaptive Lighting are actually due to unrelated problems.
|
||||
Addressing these issues will significantly improve your Home Assistant experience.
|
||||
|
||||
In case lights are suddenly turning on by themselves, this is most likely due to the light incorrectly reporting an "on" state to Home Assistant, leading to an undesired Adaptive Lighting action.
|
||||
To prevent adapting in cases *where the state of the light is suddenly "on" and only adapt if there is an associated `light.turn_on` service call*, set `detect_non_ha_changes: false`.
|
||||
|
||||
#### :signal_strength: WiFi Networks
|
||||
|
||||
Ensure your light bulbs have a strong WiFi connection. If the signal strength is less than -70dBm, the connection may be weak and prone to dropping messages.
|
||||
|
||||
#### :spider_web: Zigbee, Z-Wave, and Other Mesh Networks
|
||||
|
||||
Mesh networks typically require powered devices to act as routers, relaying messages back to the central coordinator (the radio connected to Home Assistant).
|
||||
Most modern lights function as routers, very early models may not.
|
||||
If devices become unresponsive or fail to respond to commands, Adaptive Lighting can exacerbate the issue.
|
||||
Use network maps (available in ZHA, zigbee2mqtt, deCONZ, and ZWaveJS UI) to evaluate your network health.
|
||||
Smart plugs can be an affordable way to add more routers to your network.
|
||||
|
||||
For most Zigbee networks, **using groups is essential for optimal performance**.
|
||||
For example, if you want to use Adaptive Lighting in a hallway with six bulbs, adding each bulb individually to the Adaptive Lighting configuration could overwhelm the network with commands.
|
||||
Instead, create a group in your Zigbee software (not a regular Home Assistant group) and add that single group to the Adaptive Lighting configuration.
|
||||
This sends a single broadcast command to adjust all bulbs, improving response times and keeping the bulbs in sync.
|
||||
|
||||
As a rule of thumb, if you always control lights together (e.g., bulbs in a ceiling fixture), they should be in a Zigbee group.
|
||||
Expose only the group (not individual bulbs) in Home Assistant Dashboards and external systems like Google Home or Apple HomeKit.
|
||||
|
||||
> :warning: **If you control lights individually, `manual_control` cannot behave correctly! If you need to control lights individually as well, use a [Home Assistant Light Group](https://www.home-assistant.io/integrations/group/).**
|
||||
|
||||
#### :rainbow: Light Colors Not Matching
|
||||
|
||||
Bulbs from different manufacturers or models may have varying color temperature specifications. For instance, if you have two Adaptive Lighting configurations—one with only Philips Hue White Ambiance bulbs and another with a mix of Philips Hue White Ambiance and Sengled bulbs—the Philips Hue bulbs may appear to have different color temperatures despite having identical settings.
|
||||
|
||||
To resolve this:
|
||||
|
||||
1. Include only bulbs of the same make and model in a single Adaptive Lighting configuration.
|
||||
2. Rearrange bulbs so that different color temperatures are not visible simultaneously.
|
||||
|
||||
#### :bulb: Bulb-Specific Issues
|
||||
|
||||
These lights are known to exhibit disadvantageous behaviour due to firmware bugs, insufficient functionality, or hardware limitations:
|
||||
|
||||
- [Sengled Z01-A19NAE26](https://www.zigbee2mqtt.io/devices/Z01-A19NAE26.html#sengled-z01-a19nae26)
|
||||
- Unexpected turn-ons: If Adaptive Lighting sends a long transition time (like the default 45 seconds), and the bulb is turned off during that time, it may turn back on after approximately 10 seconds to continue the transition command. Since the bulb is turning itself on, there will be no obvious trigger in Home Assistant or other logs indicating the cause of the light turning on. To fix this, set a much shorter `transition` time, such as 1 second.
|
||||
- Heat sensitivity: Additionally, these bulbs may perform poorly in enclosed "dome" style ceiling lights, particularly when hot. While most LEDs (even non-smart ones) state in the fine print that they do not support working in enclosed fixtures, in practice, more expensive bulbs like Philips Hue generally perform better. To resolve this issue, move the problematic bulbs to open-air fixtures.
|
||||
- Ikea Tradfri bulbs/drivers (and related Ikea smart light products)
|
||||
- Unsupported simultaneous transition of brightness and color: When receiving such a command, they switch the brightness instantly and only transition the color. To get smooth transitions of both brightness and color, enable `separate_turn_on_commands`.
|
||||
- Unresponsiveness during color transitions: No other commands are processed during an ongoing color transition, e.g., turn-off commands are ignored and lights stay on despite being reported as off to Home Assistant. The default config with long transitions thus results in long periods of unresponsiveness. To work around this, disable transitions by setting `transition` to `0`, and increase the adaptation frequency by setting `interval` to a short time, e.g., `15` seconds, to retain the impression of smooth continuous adaptations. Keeping the `initial_transition` is recommended for a smooth fade-in (lights are usually not turned off momentarily after being turned on, in which case a short period of unresponsiveness is tolerable).
|
||||
|
||||
<!-- OUTPUT:END -->
|
||||
|
||||
## Getting Help
|
||||
|
||||
If you're still having issues:
|
||||
|
||||
1. Enable debug logging and capture the relevant logs
|
||||
2. Open an issue on [GitHub](https://github.com/basnijholt/adaptive-lighting/issues)
|
||||
3. Include:
|
||||
- Your configuration (redact sensitive info)
|
||||
- Debug logs
|
||||
- Home Assistant version
|
||||
- Description of expected vs actual behavior
|
||||
|
|
@ -11,18 +11,6 @@ license = "Apache-2.0"
|
|||
requires-python = ">=3.12"
|
||||
|
||||
[dependency-groups]
|
||||
docs = [
|
||||
"astral",
|
||||
"homeassistant",
|
||||
"markdown-code-runner>=2.7.0",
|
||||
"markdown-gfm-admonition",
|
||||
"pandas",
|
||||
"shinylive",
|
||||
"tabulate",
|
||||
"ulid-transform",
|
||||
"voluptuous",
|
||||
"zensical",
|
||||
]
|
||||
dev = [
|
||||
"mypy",
|
||||
"pre-commit",
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -ex
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
uv sync --group docs
|
||||
uv pip install -e .
|
||||
uv run python docs/run_markdown_code_runner.py
|
||||
uv run python .github/update-services.py
|
||||
uv run python .github/update-strings.py
|
||||
|
|
@ -49,7 +49,9 @@ def _unique_id(entry, key: str) -> str:
|
|||
|
||||
def _resolve_entity_id(hass, entry, key: str) -> str | None:
|
||||
return er.async_get(hass).async_get_entity_id(
|
||||
"sensor", DOMAIN, _unique_id(entry, key),
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
_unique_id(entry, key),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -63,7 +65,9 @@ async def test_three_sensor_entities_registered(hass) -> None:
|
|||
registry = er.async_get(hass)
|
||||
for key in SENSOR_KEYS:
|
||||
eid = registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, _unique_id(entry, key),
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
_unique_id(entry, key),
|
||||
)
|
||||
assert eid is not None, f"Missing sensor entity for {key}"
|
||||
assert eid.startswith("sensor.")
|
||||
|
|
@ -331,9 +335,9 @@ async def test_friendly_names_compose_correctly(hass) -> None:
|
|||
if fname in names.values():
|
||||
continue
|
||||
# Any other entity's friendly name must not match a sensor's.
|
||||
assert fname not in all_friendly, (
|
||||
f"Collision: {fname} appears on both sensor and another entity"
|
||||
)
|
||||
assert (
|
||||
fname not in all_friendly
|
||||
), f"Collision: {fname} appears on both sensor and another entity"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -370,11 +374,13 @@ async def test_unload_detaches_dispatcher(hass) -> None:
|
|||
# dispatcher subscription leaked.
|
||||
ent_reg = er.async_get(hass)
|
||||
eid = ent_reg.async_get_entity_id(
|
||||
"sensor", DOMAIN, _unique_id(entry, "output_brightness"),
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
_unique_id(entry, "output_brightness"),
|
||||
)
|
||||
if eid is not None:
|
||||
state = hass.states.get(eid)
|
||||
if state is not None:
|
||||
assert state.state != "99", (
|
||||
"Dispatcher subscription leaked: sensor updated after unload"
|
||||
)
|
||||
assert (
|
||||
state.state != "99"
|
||||
), "Dispatcher subscription leaked: sensor updated after unload"
|
||||
|
|
|
|||
539
uv.lock
generated
539
uv.lock
generated
|
|
@ -82,23 +82,6 @@ dev = [
|
|||
{ name = "pre-commit" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
docs = [
|
||||
{ name = "astral" },
|
||||
{ name = "homeassistant", version = "2024.12.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
|
||||
{ name = "homeassistant", version = "2025.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' and python_full_version < '3.13.2'" },
|
||||
{ name = "homeassistant", version = "2026.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13.2'" },
|
||||
{ name = "markdown-code-runner" },
|
||||
{ name = "markdown-gfm-admonition" },
|
||||
{ name = "pandas" },
|
||||
{ name = "shinylive" },
|
||||
{ name = "tabulate" },
|
||||
{ name = "ulid-transform", version = "1.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
|
||||
{ name = "ulid-transform", version = "1.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' and python_full_version < '3.13.2'" },
|
||||
{ name = "ulid-transform", version = "1.5.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13.2'" },
|
||||
{ name = "voluptuous", version = "0.15.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13.2'" },
|
||||
{ name = "voluptuous", version = "0.16.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13.2'" },
|
||||
{ name = "zensical" },
|
||||
]
|
||||
test = [
|
||||
{ name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
|
||||
{ name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' and python_full_version < '3.13.2'" },
|
||||
|
|
@ -119,18 +102,6 @@ dev = [
|
|||
{ name = "pre-commit" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
docs = [
|
||||
{ name = "astral" },
|
||||
{ name = "homeassistant" },
|
||||
{ name = "markdown-code-runner", specifier = ">=2.7.0" },
|
||||
{ name = "markdown-gfm-admonition" },
|
||||
{ name = "pandas" },
|
||||
{ name = "shinylive" },
|
||||
{ name = "tabulate" },
|
||||
{ name = "ulid-transform" },
|
||||
{ name = "voluptuous" },
|
||||
{ name = "zensical" },
|
||||
]
|
||||
test = [
|
||||
{ name = "pytest", specifier = ">=8" },
|
||||
{ name = "pytest-asyncio", specifier = ">=0.23" },
|
||||
|
|
@ -684,24 +655,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "appdirs"
|
||||
version = "1.4.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/d8/05696357e0311f5b5c316d7b95f46c669dd9c15aaeecbb48c7d0aeb88c40/appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", size = 13470, upload-time = "2020-05-11T07:59:51.037Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128", size = 9566, upload-time = "2020-05-11T07:59:49.499Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.11.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/b9/4db2509eabd14b4a8c71d1b24c8d5734c52b8560a7b1e1a8b56c8d25568b/asgiref-3.11.0.tar.gz", hash = "sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4", size = 37969, upload-time = "2025-11-19T15:32:20.106Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/91/be/317c2c55b8bbec407257d45f5c8d1b6867abc76d12043f2d3d58c538a4ea/asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d", size = 24096, upload-time = "2025-11-19T15:32:19.004Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "astral"
|
||||
version = "2.2"
|
||||
|
|
@ -1271,15 +1224,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chevron"
|
||||
version = "0.14.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/15/1f/ca74b65b19798895d63a6e92874162f44233467c9e7c1ed8afd19016ebe9/chevron-0.14.0.tar.gz", hash = "sha256:87613aafdf6d77b6a90ff073165a61ae5086e21ad49057aa0e53681601800ebf", size = 11440, upload-time = "2021-01-02T22:47:59.233Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/52/93/342cc62a70ab727e093ed98e02a725d85b746345f05d2b5e5034649f4ec8/chevron-0.14.0-py3-none-any.whl", hash = "sha256:fbf996a709f8da2e745ef763f482ce2d311aa817d287593a5b990d6d6e4f0443", size = 11595, upload-time = "2021-01-02T22:47:57.847Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciso8601"
|
||||
version = "2.3.1"
|
||||
|
|
@ -1359,7 +1303,7 @@ name = "click"
|
|||
version = "8.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "colorama", marker = "python_full_version >= '3.13.2' and sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" }
|
||||
wheels = [
|
||||
|
|
@ -1708,15 +1652,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/89/94/b7ff6279e642b014cd4aef4d914b9fca3917c2c9c35df49db062023cbdfc/dbus_fast-3.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1d7cc1315586e4c50875c9a2d56b9ad2e056ec75e2f27c43cd80392f72d0f6e3", size = 1623709, upload-time = "2025-11-17T03:49:59.571Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deepmerge"
|
||||
version = "2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/3a/b0ba594708f1ad0bc735884b3ad854d3ca3bdc1d741e56e40bbda6263499/deepmerge-2.0.tar.gz", hash = "sha256:5c3d86081fbebd04dd5de03626a0607b809a98fb6ccba5770b62466fe940ff20", size = 19890, upload-time = "2024-08-30T05:31:50.308Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/82/e5d2c1c67d19841e9edc74954c827444ae826978499bde3dfc1d007c8c11/deepmerge-2.0-py3-none-any.whl", hash = "sha256:6de9ce507115cff0bed95ff0ce9ecc31088ef50cbdf09bc90a09349a318b3d00", size = 13475, upload-time = "2024-08-30T05:31:48.659Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.4.0"
|
||||
|
|
@ -2078,15 +2013,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/01/c9/97cc5aae1648dcb851958a3ddf73ccd7dbe5650d95203ecb4d7720b4cdbf/fsspec-2026.1.0-py3-none-any.whl", hash = "sha256:cb76aa913c2285a3b49bdd5fc55b1d7c708d7208126b60f2eb8194fe1b4cbdcc", size = 201838, upload-time = "2026-01-09T15:21:34.041Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "future"
|
||||
version = "1.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a7/b2/4140c69c6a66432916b26158687e821ba631a4c9273c474343badf84d3ba/future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05", size = 1228490, upload-time = "2024-02-21T11:52:38.461Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/da/71/ae30dadffc90b9006d77af76b393cb9dfbfc9629f339fc1574a1c52e6806/future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216", size = 491326, upload-time = "2024-02-21T11:52:35.956Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "greenlet"
|
||||
version = "3.3.0"
|
||||
|
|
@ -2609,19 +2535,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/fe/3f/57e3c7e3daf7cc8509eb139f4faca9198474f8c4f50871d8fe9479adf3da/homeassistant-2026.1.0-py3-none-any.whl", hash = "sha256:29148b15f12fdf398ed8290ad1c23e5241011b225d2f96febcc7390855f18061", size = 50115149, upload-time = "2026-01-07T18:15:19.236Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "htmltools"
|
||||
version = "0.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "packaging" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/cd/1d/c568d17e9fb5ad5aa0ca3531c58d36fe69deb8eee4e53ff6425c1f99f210/htmltools-0.6.0.tar.gz", hash = "sha256:e8a3fb023d748935035db7ff17f620612ffc814a6a80b6ae388f7b7ab182adf7", size = 97152, upload-time = "2024-10-29T20:21:43.378Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/ba/aa99706246f1938ca905eb6eeb7db832ac2e157aa4b805acb5cd4cd1791a/htmltools-0.6.0-py3-none-any.whl", hash = "sha256:072a274ff5e2851e0acce13fc5bb2bbdbbad8268dc8b123f881c05012ce7dce0", size = 84954, upload-time = "2024-10-29T20:21:42.067Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.9"
|
||||
|
|
@ -3016,18 +2929,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/03/ba/f6f6573bb21e51b838f1e7b0e8ef831d50db6d0530a5afaba700a34d9e12/license_expression-30.4.3-py3-none-any.whl", hash = "sha256:fd3db53418133e0eef917606623bc125fbad3d1225ba8d23950999ee87c99280", size = 117085, upload-time = "2025-06-25T13:02:24.503Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linkify-it-py"
|
||||
version = "2.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "uc-micro-py" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2a/ae/bb56c6828e4797ba5a4821eec7c43b8bf40f69cda4d4f5f8c8a2810ec96a/linkify-it-py-2.0.3.tar.gz", hash = "sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048", size = 27946, upload-time = "2024-02-04T14:48:04.179Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/1e/b832de447dee8b582cac175871d2f6c3d5077cc56d5575cadba1fd1cccfa/linkify_it_py-2.0.3-py3-none-any.whl", hash = "sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79", size = 19820, upload-time = "2024-02-04T14:48:02.496Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "litellm"
|
||||
version = "1.80.15"
|
||||
|
|
@ -3073,57 +2974,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/bd/18/06d9710cb0a0d3634f8501e4bdcc07abe64a32e404d82895a6a36fab97f6/lru_dict-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:cf9da32ef2582434842ab6ba6e67290debfae72771255a8e8ab16f3e006de0aa", size = 13811, upload-time = "2023-11-06T01:39:21.599Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzstring"
|
||||
version = "1.0.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "future" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ab/0c/28347673b45e5f0975cdf1f6d69ede6ad049be873194c4e164d79aecd34c/lzstring-1.0.4.tar.gz", hash = "sha256:1afa61e598193fbcc211e0899f09a9679e33f9102bccc37fbfda0b7fef4d9ea2", size = 4256, upload-time = "2018-06-01T02:32:12.639Z" }
|
||||
|
||||
[[package]]
|
||||
name = "markdown"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/7dd27d9d863b3376fcf23a5a13cb5d024aed1db46f963f1b5735ae43b3be/markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e", size = 364931, upload-time = "2025-11-03T19:51:15.007Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c", size = 107678, upload-time = "2025-11-03T19:51:13.887Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-code-runner"
|
||||
version = "2.7.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/28/d1/2a7753e05dcc711552721048a34341b63a6a2b09e70ac738c7a4c81ca414/markdown_code_runner-2.7.0.tar.gz", hash = "sha256:b36f9314839c0db3ee5e5d644e1b4471454af8f624eb15bd5a5d68dbc6430afe", size = 99832, upload-time = "2026-01-24T21:20:04.772Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/92/9d7fa0567cf3d38b551bb1a30c177285e0e42ae2b10c16946af7e8a38e73/markdown_code_runner-2.7.0-py3-none-any.whl", hash = "sha256:fad5d5fbad9c49687141ab9c39ed7e054f857b97aa79d11f031de157afd21c20", size = 14692, upload-time = "2026-01-24T21:20:03.382Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-gfm-admonition"
|
||||
version = "0.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markdown" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/59/5b/1e7114e8fac6aadf2a25dab2e24a1eba54acd504d6a5747928a3eb09d7fd/markdown_gfm_admonition-0.3.0.tar.gz", hash = "sha256:20a37febc79222badb6dfbfcbf0a74b94c0a6259b0f27e9f783601fea59094b6", size = 5817, upload-time = "2025-11-28T09:01:38.849Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/86/ce4288122111c11bb2483a962357baa9793817d48ac1e99ce5ff47384efe/markdown_gfm_admonition-0.3.0-py3-none-any.whl", hash = "sha256:8e49bfea892f4c220b7f7b9479462360b69c68ae7cae7739e288b5382d0ae9b5", size = 6416, upload-time = "2025-11-28T09:01:37.543Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "4.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mdurl" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markupsafe"
|
||||
version = "3.0.3"
|
||||
|
|
@ -3199,27 +3049,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/f8/2d/edc147aa1dce9e0e377687d453e62fdfcbccc08cd35d0b7413e3485c4b92/mashumaro-3.17-py3-none-any.whl", hash = "sha256:3964e2c804f62de9e4c58fb985de71dcd716f9507cc18374b1bd5c4f1a1b879b", size = 94198, upload-time = "2025-10-03T21:09:25.436Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdit-py-plugins"
|
||||
version = "0.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markdown-it-py" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b2/fd/a756d36c0bfba5f6e39a1cdbdbfdd448dc02692467d83816dff4592a1ebc/mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6", size = 44655, upload-time = "2025-08-11T07:25:49.083Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/86/dd6e5db36df29e76c7a7699123569a4a18c1623ce68d826ed96c62643cae/mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f", size = 57205, upload-time = "2025-08-11T07:25:47.597Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdurl"
|
||||
version = "0.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mock-open"
|
||||
version = "1.4.0"
|
||||
|
|
@ -3376,15 +3205,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "narwhals"
|
||||
version = "2.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/47/6d/b57c64e5038a8cf071bce391bb11551657a74558877ac961e7fa905ece27/narwhals-2.15.0.tar.gz", hash = "sha256:a9585975b99d95084268445a1fdd881311fa26ef1caa18020d959d5b2ff9a965", size = 603479, upload-time = "2026-01-06T08:10:13.27Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/2e/cf2ffeb386ac3763526151163ad7da9f1b586aac96d2b4f7de1eaebf0c61/narwhals-2.15.0-py3-none-any.whl", hash = "sha256:cbfe21ca19d260d9fd67f995ec75c44592d1f106933b03ddd375df7ac841f9d6", size = 432856, upload-time = "2026-01-06T08:10:11.511Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.10.0"
|
||||
|
|
@ -3722,55 +3542,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/c4/cb/00451c3cf31790287768bb12c6bec834f5d292eaf3022afc88e14b8afc94/paho_mqtt-2.1.0-py3-none-any.whl", hash = "sha256:6db9ba9b34ed5bc6b6e3812718c7e06e2fd7444540df2455d2c51bd58808feee", size = 67219, upload-time = "2024-04-29T19:52:48.345Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pandas"
|
||||
version = "2.3.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy", version = "2.1.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
|
||||
{ name = "numpy", version = "2.2.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' and python_full_version < '3.13.2'" },
|
||||
{ name = "numpy", version = "2.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13.2'" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "pytz" },
|
||||
{ name = "tzdata" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/fb/231d89e8637c808b997d172b18e9d4a4bc7bf31296196c260526055d1ea0/pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53", size = 11597846, upload-time = "2025-09-29T23:19:48.856Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/bd/bf8064d9cfa214294356c2d6702b716d3cf3bb24be59287a6a21e24cae6b/pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35", size = 10729618, upload-time = "2025-09-29T23:39:08.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/56/cf2dbe1a3f5271370669475ead12ce77c61726ffd19a35546e31aa8edf4e/pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908", size = 11737212, upload-time = "2025-09-29T23:19:59.765Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/63/cd7d615331b328e287d8233ba9fdf191a9c2d11b6af0c7a59cfcec23de68/pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89", size = 12362693, upload-time = "2025-09-29T23:20:14.098Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/de/8b1895b107277d52f2b42d3a6806e69cfef0d5cf1d0ba343470b9d8e0a04/pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98", size = 12771002, upload-time = "2025-09-29T23:20:26.76Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/21/84072af3187a677c5893b170ba2c8fbe450a6ff911234916da889b698220/pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084", size = 13450971, upload-time = "2025-09-29T23:20:41.344Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/41/585a168330ff063014880a80d744219dbf1dd7a1c706e75ab3425a987384/pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b", size = 10992722, upload-time = "2025-09-29T23:20:54.139Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "1.0.3"
|
||||
|
|
@ -4030,18 +3801,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prompt-toolkit"
|
||||
version = "3.0.52"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "wcwidth" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "propcache"
|
||||
version = "0.2.1"
|
||||
|
|
@ -4588,20 +4347,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/94/0e/bf3473d86648a17e6dd6ee9e6abce526b077169031177f4f2031368f864a/pylint_per_file_ignores-1.4.0-py3-none-any.whl", hash = "sha256:0cd82d22551738b4e63a0aa1dab2a1fc4016e8f27f1429159616483711e122fd", size = 4888, upload-time = "2025-01-17T21:35:00.371Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymdown-extensions"
|
||||
version = "10.20"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "markdown" },
|
||||
{ name = "pyyaml", version = "6.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13.2'" },
|
||||
{ name = "pyyaml", version = "6.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13.2'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3e/35/e3814a5b7df295df69d035cfb8aab78b2967cdf11fcfae7faed726b66664/pymdown_extensions-10.20.tar.gz", hash = "sha256:5c73566ab0cf38c6ba084cb7c5ea64a119ae0500cce754ccb682761dfea13a52", size = 852774, upload-time = "2025-12-31T19:59:42.211Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/10/47caf89cbb52e5bb764696fd52a8c591a2f0e851a93270c05a17f36000b5/pymdown_extensions-10.20-py3-none-any.whl", hash = "sha256:ea9e62add865da80a271d00bfa1c0fa085b20d133fb3fc97afdc88e682f60b2f", size = 268733, upload-time = "2025-12-31T19:59:40.652Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymicro-vad"
|
||||
version = "1.0.1"
|
||||
|
|
@ -5313,15 +5058,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-multipart"
|
||||
version = "0.0.21"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/78/96/804520d0850c7db98e5ccb70282e29208723f0964e88ffd9d0da2f52ea09/python_multipart-0.0.21.tar.gz", hash = "sha256:7137ebd4d3bbf70ea1622998f902b97a29434a9e8dc40eb203bbcf7c2a2cba92", size = 37196, upload-time = "2025-12-17T09:24:22.446Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/76/03af049af4dcee5d27442f71b6924f01f3efb5d2bd34f23fcd563f2cc5f5/python_multipart-0.0.21-py3-none-any.whl", hash = "sha256:cf7a6713e01c87aa35387f4774e812c4361150938d20d232800f75ffcf266090", size = 24541, upload-time = "2025-12-17T09:24:21.153Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-slugify"
|
||||
version = "8.0.4"
|
||||
|
|
@ -5433,18 +5169,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "questionary"
|
||||
version = "2.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "prompt-toolkit" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f6/45/eafb0bba0f9988f6a2520f9ca2df2c82ddfa8d67c95d6625452e97b204a5/questionary-2.1.1.tar.gz", hash = "sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d", size = 25845, upload-time = "2025-08-28T19:00:20.851Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59", size = 36753, upload-time = "2025-08-28T19:00:19.56Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "referencing"
|
||||
version = "0.37.0"
|
||||
|
|
@ -5804,70 +5528,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shiny"
|
||||
version = "1.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "asgiref" },
|
||||
{ name = "click", marker = "sys_platform != 'emscripten'" },
|
||||
{ name = "htmltools" },
|
||||
{ name = "linkify-it-py" },
|
||||
{ name = "markdown-it-py" },
|
||||
{ name = "mdit-py-plugins" },
|
||||
{ name = "narwhals" },
|
||||
{ name = "orjson", version = "3.10.12", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" },
|
||||
{ name = "orjson", version = "3.10.16", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13' and python_full_version < '3.13.2'" },
|
||||
{ name = "orjson", version = "3.11.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13.2'" },
|
||||
{ name = "packaging" },
|
||||
{ name = "platformdirs" },
|
||||
{ name = "prompt-toolkit", marker = "sys_platform != 'emscripten'" },
|
||||
{ name = "python-multipart", marker = "sys_platform != 'emscripten'" },
|
||||
{ name = "questionary", marker = "sys_platform != 'emscripten'" },
|
||||
{ name = "setuptools" },
|
||||
{ name = "shinychat" },
|
||||
{ name = "starlette" },
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
|
||||
{ name = "watchfiles", marker = "sys_platform != 'emscripten'" },
|
||||
{ name = "websockets" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/8c/570fb0c8aa3b3f2b30e2f401bbe4048e7c39fb5ffb70994520fdff32a8da/shiny-1.5.1.tar.gz", hash = "sha256:482fa54635a6dc7e914cdbaa9099fe445790af3053d849b4e9a81e0f61677d37", size = 4941243, upload-time = "2025-12-08T18:18:23.763Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/09/2d/c955cbc6e66aff92645a7af35fa017001dffecb849b764f609fdc68da088/shiny-1.5.1-py3-none-any.whl", hash = "sha256:5ed60168e94fce0b7fc65bc04b92398e2611a2410acbcb850f8ae3001b99de40", size = 3943136, upload-time = "2025-12-08T18:18:21.654Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shinychat"
|
||||
version = "0.2.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "htmltools" },
|
||||
{ name = "shiny" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a3/c6/6887a3618842e65794e5dcfb345825ccd43d58c56fefa9d31286d8e14d16/shinychat-0.2.8.tar.gz", hash = "sha256:d27f28ddf1d512a05ef2cc2f0cffbb75b5b6e3157d5e3690ce4e63d18bfa7492", size = 547318, upload-time = "2025-09-11T20:13:20.367Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/16/01/8658eaffa920f4c621f05acc42ea98248147706079287b3a7ab4e47e1ece/shinychat-0.2.8-py3-none-any.whl", hash = "sha256:6742a2354257280458269a8b5675f1254e5583be34b6eb1a626de44c0323286a", size = 561057, upload-time = "2025-09-11T20:13:18.683Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shinylive"
|
||||
version = "0.8.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "appdirs" },
|
||||
{ name = "chevron" },
|
||||
{ name = "click" },
|
||||
{ name = "lzstring" },
|
||||
{ name = "setuptools" },
|
||||
{ name = "shiny" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1c/b4/a741e01b756d76bf5839d47c54562563353fd5c5849e0cbb8b5b8ea23d8b/shinylive-0.8.5.tar.gz", hash = "sha256:d485efa14a4053be0e6ec19a21a49e5d0b6bd8b99cd2f5cb81b0b04f57a1c249", size = 29519, upload-time = "2025-12-08T21:08:27.076Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/bb/8dc375e7fb90737fe64a3aa150441a667225672d5d4b735880e4a41f1686/shinylive-0.8.5-py3-none-any.whl", hash = "sha256:85ac83b5b86adf181f79937a50c997315d30cd944a565a31d1a99abc8d715dcd", size = 29432, upload-time = "2025-12-08T21:08:25.868Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
|
|
@ -6069,19 +5729,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/33/85/a1808451ac0b36c61dffe8aea21e45c64ba7da28f6cb0d269171298c6281/standard_telnetlib-3.13.0-py3-none-any.whl", hash = "sha256:b268060a3220c80c7887f2ad9df91cd81e865f0c5052332b81d80ffda8677691", size = 9995, upload-time = "2024-10-30T16:01:29.289Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "starlette"
|
||||
version = "0.51.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/65/5a1fadcc40c5fdc7df421a7506b79633af8f5d5e3a95c3e72acacec644b9/starlette-0.51.0.tar.gz", hash = "sha256:4c4fda9b1bc67f84037d3d14a5112e523509c369d9d47b111b2f984b0cc5ba6c", size = 2647658, upload-time = "2026-01-10T20:23:15.043Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/c4/09985a03dba389d4fe16a9014147a7b02fa76ef3519bf5846462a485876d/starlette-0.51.0-py3-none-any.whl", hash = "sha256:fb460a3d6fd3c958d729fdd96aee297f89a51b0181f16401fe8fd4cb6129165d", size = 74133, upload-time = "2026-01-10T20:23:13.445Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syrupy"
|
||||
version = "4.7.2"
|
||||
|
|
@ -6129,15 +5776,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/9d/9a/6c68aad2ccfce6e2eeebbf5bb709d0240592eb51ff142ec4c8fbf3c2460a/syrupy-5.0.0-py3-none-any.whl", hash = "sha256:c848e1a980ca52a28715cd2d2b4d434db424699c05653bd1158fb31cf56e9546", size = 49087, upload-time = "2025-09-28T21:15:11.639Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabulate"
|
||||
version = "0.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "3.3.0"
|
||||
|
|
@ -6314,15 +5952,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/12/64/edf33c2d7fba7d6bf057c9dc4235bfc699517ea4c996240a1a9c2bf51c29/uart_devices-0.1.1-py3-none-any.whl", hash = "sha256:55bc8cce66465e90b298f0910e5c496bc7be021341c5455954cf61c6253dc123", size = 4827, upload-time = "2025-02-22T16:47:04.286Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uc-micro-py"
|
||||
version = "1.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/91/7a/146a99696aee0609e3712f2b44c6274566bc368dfe8375191278045186b8/uc-micro-py-1.0.3.tar.gz", hash = "sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a", size = 6043, upload-time = "2024-02-09T16:52:01.654Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/37/87/1f677586e8ac487e29672e4b17455758fce261de06a0d086167bb760361a/uc_micro_py-1.0.3-py3-none-any.whl", hash = "sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5", size = 6229, upload-time = "2024-02-09T16:52:00.371Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ulid-transform"
|
||||
version = "1.0.2"
|
||||
|
|
@ -6547,19 +6176,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/37/ef/813cfedda3c8e49d8b59a41c14fcc652174facfd7a1caf9fee162b40ccbd/uv-0.9.17-py3-none-win_arm64.whl", hash = "sha256:6761076b27a763d0ede2f5e72455d2a46968ff334badf8312bb35988c5254831", size = 20435751, upload-time = "2025-12-09T23:01:19.732Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.40.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c3/d1/8f3c683c9561a4e6689dd3b1d345c815f10f86acd044ee1fb9a4dcd0b8c5/uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea", size = 81761, upload-time = "2025-12-21T14:16:22.45Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/d8/2083a1daa7439a66f3a48589a57d576aa117726762618f6bb09fe3798796/uvicorn-0.40.0-py3-none-any.whl", hash = "sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee", size = 68502, upload-time = "2025-12-21T14:16:21.041Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.36.1"
|
||||
|
|
@ -6681,85 +6297,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/f7/41/d536d9cf39821c35cc13aff403728e60e32b2fd711c240b6b9980af1c03f/voluptuous_serialize-2.7.0-py3-none-any.whl", hash = "sha256:ee3ebecace6136f38d0bf8c20ee97155db2486c6b2d0795563fafd04a519e76f", size = 7850, upload-time = "2025-08-17T10:43:03.498Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "watchfiles"
|
||||
version = "1.1.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hash = "sha256:a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2", size = 94440, upload-time = "2025-10-14T15:06:21.08Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/74/d5/f039e7e3c639d9b1d09b07ea412a6806d38123f0508e5f9b48a87b0a76cc/watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8c89f9f2f740a6b7dcc753140dd5e1ab9215966f7a3530d0c0705c83b401bd7d", size = 404745, upload-time = "2025-10-14T15:04:46.731Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/96/a881a13aa1349827490dab2d363c8039527060cfcc2c92cc6d13d1b1049e/watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd404be08018c37350f0d6e34676bd1e2889990117a2b90070b3007f172d0610", size = 391769, upload-time = "2025-10-14T15:04:48.003Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/5b/d3b460364aeb8da471c1989238ea0e56bec24b6042a68046adf3d9ddb01c/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8526e8f916bb5b9a0a777c8317c23ce65de259422bba5b31325a6fa6029d33af", size = 449374, upload-time = "2025-10-14T15:04:49.179Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/44/5769cb62d4ed055cb17417c0a109a92f007114a4e07f30812a73a4efdb11/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2edc3553362b1c38d9f06242416a5d8e9fe235c204a4072e988ce2e5bb1f69f6", size = 459485, upload-time = "2025-10-14T15:04:50.155Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/0c/286b6301ded2eccd4ffd0041a1b726afda999926cf720aab63adb68a1e36/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30f7da3fb3f2844259cba4720c3fc7138eb0f7b659c38f3bfa65084c7fc7abce", size = 488813, upload-time = "2025-10-14T15:04:51.059Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/2b/8530ed41112dd4a22f4dcfdb5ccf6a1baad1ff6eed8dc5a5f09e7e8c41c7/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa", size = 594816, upload-time = "2025-10-14T15:04:52.031Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/d2/f5f9fb49489f184f18470d4f99f4e862a4b3e9ac2865688eb2099e3d837a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcc5c24523771db3a294c77d94771abcfcb82a0e0ee8efd910c37c59ec1b31bb", size = 475186, upload-time = "2025-10-14T15:04:53.064Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/68/5707da262a119fb06fbe214d82dd1fe4a6f4af32d2d14de368d0349eb52a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db5d7ae38ff20153d542460752ff397fcf5c96090c1230803713cf3147a6803", size = 456812, upload-time = "2025-10-14T15:04:55.174Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/ab/3cbb8756323e8f9b6f9acb9ef4ec26d42b2109bce830cc1f3468df20511d/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:28475ddbde92df1874b6c5c8aaeb24ad5be47a11f87cde5a28ef3835932e3e94", size = 630196, upload-time = "2025-10-14T15:04:56.22Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/46/7152ec29b8335f80167928944a94955015a345440f524d2dfe63fc2f437b/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:36193ed342f5b9842edd3532729a2ad55c4160ffcfa3700e0d54be496b70dd43", size = 622657, upload-time = "2025-10-14T15:04:57.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/bf/95895e78dd75efe9a7f31733607f384b42eb5feb54bd2eb6ed57cc2e94f4/watchfiles-1.1.1-cp312-cp312-win32.whl", hash = "sha256:859e43a1951717cc8de7f4c77674a6d389b106361585951d9e69572823f311d9", size = 272042, upload-time = "2025-10-14T15:04:59.046Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/0a/90eb755f568de2688cb220171c4191df932232c20946966c27a59c400850/watchfiles-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:91d4c9a823a8c987cce8fa2690923b069966dabb196dd8d137ea2cede885fde9", size = 288410, upload-time = "2025-10-14T15:05:00.081Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/76/f322701530586922fbd6723c4f91ace21364924822a8772c549483abed13/watchfiles-1.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:a625815d4a2bdca61953dbba5a39d60164451ef34c88d751f6c368c3ea73d404", size = 278209, upload-time = "2025-10-14T15:05:01.168Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/f4/f750b29225fe77139f7ae5de89d4949f5a99f934c65a1f1c0b248f26f747/watchfiles-1.1.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:130e4876309e8686a5e37dba7d5e9bc77e6ed908266996ca26572437a5271e18", size = 404321, upload-time = "2025-10-14T15:05:02.063Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/f9/f07a295cde762644aa4c4bb0f88921d2d141af45e735b965fb2e87858328/watchfiles-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f3bde70f157f84ece3765b42b4a52c6ac1a50334903c6eaf765362f6ccca88a", size = 391783, upload-time = "2025-10-14T15:05:03.052Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/11/fc2502457e0bea39a5c958d86d2cb69e407a4d00b85735ca724bfa6e0d1a/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e0b1fe858430fc0251737ef3824c54027bedb8c37c38114488b8e131cf8219", size = 449279, upload-time = "2025-10-14T15:05:04.004Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/1f/d66bc15ea0b728df3ed96a539c777acfcad0eb78555ad9efcaa1274688f0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f27db948078f3823a6bb3b465180db8ebecf26dd5dae6f6180bd87383b6b4428", size = 459405, upload-time = "2025-10-14T15:05:04.942Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/90/9f4a65c0aec3ccf032703e6db02d89a157462fbb2cf20dd415128251cac0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059098c3a429f62fc98e8ec62b982230ef2c8df68c79e826e37b895bc359a9c0", size = 488976, upload-time = "2025-10-14T15:05:05.905Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/57/ee347af605d867f712be7029bb94c8c071732a4b44792e3176fa3c612d39/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfb5862016acc9b869bb57284e6cb35fdf8e22fe59f7548858e2f971d045f150", size = 595506, upload-time = "2025-10-14T15:05:06.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/78/cc5ab0b86c122047f75e8fc471c67a04dee395daf847d3e59381996c8707/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:319b27255aacd9923b8a276bb14d21a5f7ff82564c744235fc5eae58d95422ae", size = 474936, upload-time = "2025-10-14T15:05:07.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/da/def65b170a3815af7bd40a3e7010bf6ab53089ef1b75d05dd5385b87cf08/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c755367e51db90e75b19454b680903631d41f9e3607fbd941d296a020c2d752d", size = 456147, upload-time = "2025-10-14T15:05:09.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/99/da6573ba71166e82d288d4df0839128004c67d2778d3b566c138695f5c0b/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c22c776292a23bfc7237a98f791b9ad3144b02116ff10d820829ce62dff46d0b", size = 630007, upload-time = "2025-10-14T15:05:10.117Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/51/7439c4dd39511368849eb1e53279cd3454b4a4dbace80bab88feeb83c6b5/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3a476189be23c3686bc2f4321dd501cb329c0a0469e77b7b534ee10129ae6374", size = 622280, upload-time = "2025-10-14T15:05:11.146Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/9c/8ed97d4bba5db6fdcdb2b298d3898f2dd5c20f6b73aee04eabe56c59677e/watchfiles-1.1.1-cp313-cp313-win32.whl", hash = "sha256:bf0a91bfb5574a2f7fc223cf95eeea79abfefa404bf1ea5e339c0c1560ae99a0", size = 272056, upload-time = "2025-10-14T15:05:12.156Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1f/f3/c14e28429f744a260d8ceae18bf58c1d5fa56b50d006a7a9f80e1882cb0d/watchfiles-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:52e06553899e11e8074503c8e716d574adeeb7e68913115c4b3653c53f9bae42", size = 288162, upload-time = "2025-10-14T15:05:13.208Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/61/fe0e56c40d5cd29523e398d31153218718c5786b5e636d9ae8ae79453d27/watchfiles-1.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:ac3cc5759570cd02662b15fbcd9d917f7ecd47efe0d6b40474eafd246f91ea18", size = 277909, upload-time = "2025-10-14T15:05:14.49Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/79/42/e0a7d749626f1e28c7108a99fb9bf524b501bbbeb9b261ceecde644d5a07/watchfiles-1.1.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:563b116874a9a7ce6f96f87cd0b94f7faf92d08d0021e837796f0a14318ef8da", size = 403389, upload-time = "2025-10-14T15:05:15.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/49/08732f90ce0fbbc13913f9f215c689cfc9ced345fb1bcd8829a50007cc8d/watchfiles-1.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3ad9fe1dae4ab4212d8c91e80b832425e24f421703b5a42ef2e4a1e215aff051", size = 389964, upload-time = "2025-10-14T15:05:16.85Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/0d/7c315d4bd5f2538910491a0393c56bf70d333d51bc5b34bee8e68e8cea19/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce70f96a46b894b36eba678f153f052967a0d06d5b5a19b336ab0dbbd029f73e", size = 448114, upload-time = "2025-10-14T15:05:17.876Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/24/9e096de47a4d11bc4df41e9d1e61776393eac4cb6eb11b3e23315b78b2cc/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cb467c999c2eff23a6417e58d75e5828716f42ed8289fe6b77a7e5a91036ca70", size = 460264, upload-time = "2025-10-14T15:05:18.962Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/0f/e8dea6375f1d3ba5fcb0b3583e2b493e77379834c74fd5a22d66d85d6540/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:836398932192dae4146c8f6f737d74baeac8b70ce14831a239bdb1ca882fc261", size = 487877, upload-time = "2025-10-14T15:05:20.094Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/5b/df24cfc6424a12deb41503b64d42fbea6b8cb357ec62ca84a5a3476f654a/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:743185e7372b7bc7c389e1badcc606931a827112fbbd37f14c537320fca08620", size = 595176, upload-time = "2025-10-14T15:05:21.134Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/b5/853b6757f7347de4e9b37e8cc3289283fb983cba1ab4d2d7144694871d9c/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afaeff7696e0ad9f02cbb8f56365ff4686ab205fcf9c4c5b6fdfaaa16549dd04", size = 473577, upload-time = "2025-10-14T15:05:22.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/f7/0a4467be0a56e80447c8529c9fce5b38eab4f513cb3d9bf82e7392a5696b/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7eb7da0eb23aa2ba036d4f616d46906013a68caf61b7fdbe42fc8b25132e77", size = 455425, upload-time = "2025-10-14T15:05:23.348Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/e0/82583485ea00137ddf69bc84a2db88bd92ab4a6e3c405e5fb878ead8d0e7/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:831a62658609f0e5c64178211c942ace999517f5770fe9436be4c2faeba0c0ef", size = 628826, upload-time = "2025-10-14T15:05:24.398Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/9a/a785356fccf9fae84c0cc90570f11702ae9571036fb25932f1242c82191c/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f9a2ae5c91cecc9edd47e041a930490c31c3afb1f5e6d71de3dc671bfaca02bf", size = 622208, upload-time = "2025-10-14T15:05:25.45Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/f4/0872229324ef69b2c3edec35e84bd57a1289e7d3fe74588048ed8947a323/watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:d1715143123baeeaeadec0528bb7441103979a1d5f6fd0e1f915383fea7ea6d5", size = 404315, upload-time = "2025-10-14T15:05:26.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/22/16d5331eaed1cb107b873f6ae1b69e9ced582fcf0c59a50cd84f403b1c32/watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:39574d6370c4579d7f5d0ad940ce5b20db0e4117444e39b6d8f99db5676c52fd", size = 390869, upload-time = "2025-10-14T15:05:27.649Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/7e/5643bfff5acb6539b18483128fdc0ef2cccc94a5b8fbda130c823e8ed636/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7365b92c2e69ee952902e8f70f3ba6360d0d596d9299d55d7d386df84b6941fb", size = 449919, upload-time = "2025-10-14T15:05:28.701Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/2e/c410993ba5025a9f9357c376f48976ef0e1b1aefb73b97a5ae01a5972755/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bfff9740c69c0e4ed32416f013f3c45e2ae42ccedd1167ef2d805c000b6c71a5", size = 460845, upload-time = "2025-10-14T15:05:30.064Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/a4/2df3b404469122e8680f0fcd06079317e48db58a2da2950fb45020947734/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b27cf2eb1dda37b2089e3907d8ea92922b673c0c427886d4edc6b94d8dfe5db3", size = 489027, upload-time = "2025-10-14T15:05:31.064Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/84/4587ba5b1f267167ee715b7f66e6382cca6938e0a4b870adad93e44747e6/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:526e86aced14a65a5b0ec50827c745597c782ff46b571dbfe46192ab9e0b3c33", size = 595615, upload-time = "2025-10-14T15:05:32.074Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/0f/c6988c91d06e93cd0bb3d4a808bcf32375ca1904609835c3031799e3ecae/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04e78dd0b6352db95507fd8cb46f39d185cf8c74e4cf1e4fbad1d3df96faf510", size = 474836, upload-time = "2025-10-14T15:05:33.209Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/36/ded8aebea91919485b7bbabbd14f5f359326cb5ec218cd67074d1e426d74/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c85794a4cfa094714fb9c08d4a218375b2b95b8ed1666e8677c349906246c05", size = 455099, upload-time = "2025-10-14T15:05:34.189Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/e0/8c9bdba88af756a2fce230dd365fab2baf927ba42cd47521ee7498fd5211/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:74d5012b7630714b66be7b7b7a78855ef7ad58e8650c73afc4c076a1f480a8d6", size = 630626, upload-time = "2025-10-14T15:05:35.216Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/84/a95db05354bf2d19e438520d92a8ca475e578c647f78f53197f5a2f17aaf/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:8fbe85cb3201c7d380d3d0b90e63d520f15d6afe217165d7f98c9c649654db81", size = 622519, upload-time = "2025-10-14T15:05:36.259Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/ce/d8acdc8de545de995c339be67711e474c77d643555a9bb74a9334252bd55/watchfiles-1.1.1-cp314-cp314-win32.whl", hash = "sha256:3fa0b59c92278b5a7800d3ee7733da9d096d4aabcfabb9a928918bd276ef9b9b", size = 272078, upload-time = "2025-10-14T15:05:37.63Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/c9/a74487f72d0451524be827e8edec251da0cc1fcf111646a511ae752e1a3d/watchfiles-1.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:c2047d0b6cea13b3316bdbafbfa0c4228ae593d995030fda39089d36e64fc03a", size = 287664, upload-time = "2025-10-14T15:05:38.95Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/b8/8ac000702cdd496cdce998c6f4ee0ca1f15977bba51bdf07d872ebdfc34c/watchfiles-1.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:842178b126593addc05acf6fce960d28bc5fae7afbaa2c6c1b3a7b9460e5be02", size = 277154, upload-time = "2025-10-14T15:05:39.954Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/a8/e3af2184707c29f0f14b1963c0aace6529f9d1b8582d5b99f31bbf42f59e/watchfiles-1.1.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:88863fbbc1a7312972f1c511f202eb30866370ebb8493aef2812b9ff28156a21", size = 403820, upload-time = "2025-10-14T15:05:40.932Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/ec/e47e307c2f4bd75f9f9e8afbe3876679b18e1bcec449beca132a1c5ffb2d/watchfiles-1.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:55c7475190662e202c08c6c0f4d9e345a29367438cf8e8037f3155e10a88d5a5", size = 390510, upload-time = "2025-10-14T15:05:41.945Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/a0/ad235642118090f66e7b2f18fd5c42082418404a79205cdfca50b6309c13/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f53fa183d53a1d7a8852277c92b967ae99c2d4dcee2bfacff8868e6e30b15f7", size = 448408, upload-time = "2025-10-14T15:05:43.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/85/97fa10fd5ff3332ae17e7e40e20784e419e28521549780869f1413742e9d/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6aae418a8b323732fa89721d86f39ec8f092fc2af67f4217a2b07fd3e93c6101", size = 458968, upload-time = "2025-10-14T15:05:44.404Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/c2/9059c2e8966ea5ce678166617a7f75ecba6164375f3b288e50a40dc6d489/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f096076119da54a6080e8920cbdaac3dbee667eb91dcc5e5b78840b87415bd44", size = 488096, upload-time = "2025-10-14T15:05:45.398Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/44/d90a9ec8ac309bc26db808a13e7bfc0e4e78b6fc051078a554e132e80160/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c", size = 596040, upload-time = "2025-10-14T15:05:46.502Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/68/4e3479b20ca305cfc561db3ed207a8a1c745ee32bf24f2026a129d0ddb6e/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a55f3e9e493158d7bfdb60a1165035f1cf7d320914e7b7ea83fe22c6023b58fc", size = 473847, upload-time = "2025-10-14T15:05:47.484Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/55/2af26693fd15165c4ff7857e38330e1b61ab8c37d15dc79118cdba115b7a/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c91ed27800188c2ae96d16e3149f199d62f86c7af5f5f4d2c61a3ed8cd3666c", size = 455072, upload-time = "2025-10-14T15:05:48.928Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/1d/d0d200b10c9311ec25d2273f8aad8c3ef7cc7ea11808022501811208a750/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:311ff15a0bae3714ffb603e6ba6dbfba4065ab60865d15a6ec544133bdb21099", size = 629104, upload-time = "2025-10-14T15:05:49.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01", size = 622112, upload-time = "2025-10-14T15:05:50.941Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.2.14"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrtc-models"
|
||||
version = "0.3.0"
|
||||
|
|
@ -6775,51 +6312,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/f2/e7/62f29980c9e8d75af93b642a0c37aa8e201fd5268ba3a7179c172549bac3/webrtc_models-0.3.0-py3-none-any.whl", hash = "sha256:8fddded3ffd7ca837de878033501927580799a2c1b7829f7ae8a0f43b49004ea", size = 7476, upload-time = "2024-11-18T17:43:44.165Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websockets"
|
||||
version = "16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winrt-runtime"
|
||||
version = "3.2.1"
|
||||
|
|
@ -7150,35 +6642,6 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff", size = 46814, upload-time = "2025-10-06T14:12:53.872Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zensical"
|
||||
version = "0.0.15"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "deepmerge" },
|
||||
{ name = "markdown" },
|
||||
{ name = "pygments" },
|
||||
{ name = "pymdown-extensions" },
|
||||
{ name = "pyyaml", version = "6.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13.2'" },
|
||||
{ name = "pyyaml", version = "6.0.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13.2'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fd/ad/87b7b591551c74de67b08dcf172532fbb6df6f0e626dce9f220aae293052/zensical-0.0.15.tar.gz", hash = "sha256:b3200c91b30370671c50b8b4aa41c20e55ff2814b9003ee23c9b6f923a0c19be", size = 3816831, upload-time = "2025-12-24T11:15:49.058Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/07/ede00d39ff6cff7ab4971d15caa04a6710b126cbf0c8342add0337f4db89/zensical-0.0.15-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:13f205d24baeb4a77d096c3d385a8496850567b45c397cd54dde7c22dcbf0da8", size = 11934661, upload-time = "2025-12-24T11:15:09.019Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/32/24449c59f90a6a17dd0d9740ee44f245887d0c177c9c1dc452b9eb812024/zensical-0.0.15-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:99702504d38d8f7da4bf9a69513d2f65a0371dcb8f0e9f180c861cb285adb61f", size = 11820384, upload-time = "2025-12-24T11:15:12.265Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/db/64fed914788f2f5a8880dcc9a08ce25bcf1a7f2586a09e5d7d61003fd652/zensical-0.0.15-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:051ea368d268ffebf7ed7b6422f211a57680b2810fcde7f251816eb5c8d2f488", size = 12128961, upload-time = "2025-12-24T11:15:16.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/ca/04fd676880acad9571736e470e1f7bd8e6a2391f09952e69800f1b77fc75/zensical-0.0.15-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31a333afaf54d042bb51ac7dc623bd1b3bbe173c0ce4c7b72764cdef143ff4e2", size = 12098586, upload-time = "2025-12-24T11:15:19.452Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/02/6a6ecad3b4cb07e11c8d160882cc937f8e3e96868f598c371892f1e594d7/zensical-0.0.15-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:072f80b7346ad4657a4c23008ae5cd3b3511e3bfac8d6bb277cbb6b3c11b6387", size = 12418552, upload-time = "2025-12-24T11:15:23.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/b7/2a7205dfbeeb8612fbb1e22ad9f770804a07e440b276dcf23cbce3592da4/zensical-0.0.15-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec1b146adb3ee4146a3f800e0a4e6c8e681092d87ac51c60e35e99b68a724b31", size = 12193618, upload-time = "2025-12-24T11:15:26.359Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/f4/5f38022d09e668622e49e8b5606bbfb5177d42ab1b4e91706ef0d38e2422/zensical-0.0.15-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:07a24e11a0e00d14f37d209cc37df446f91908109ca86ab3fe41c0b981e32668", size = 12308805, upload-time = "2025-12-24T11:15:29.602Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/f2/6dd7657d6e1c1cd4b01ad531cea6a95eb660a2f960b03415d2184720a283/zensical-0.0.15-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:cc2bc9b4f89863d8b3443b0b9446ccaf5181085c3fc7a7e1bbc4708afe864f7d", size = 12367060, upload-time = "2025-12-24T11:15:32.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/83/781bdfbf459ec84b085085b142f433541de70d642d665227442a4deb9360/zensical-0.0.15-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:a3809be6d5f25bbd69dbe43715a60bf9d0186c51a1ec821e02f106e660e632b4", size = 12493255, upload-time = "2025-12-24T11:15:36.126Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/10/0440e848658b97467c15c356f9038906fa90ac52b7f969ed1cce5deaf017/zensical-0.0.15-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4fd9382db77eff79eb347d4d0b6194c1c285e4151ad104bc9c8f65a27cb71d7f", size = 12430315, upload-time = "2025-12-24T11:15:39.697Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/19/d9/50f3e833075e678047cd6e302f731b4b992762d366949124c2eeed6bd96c/zensical-0.0.15-cp310-abi3-win32.whl", hash = "sha256:1d29712dd4659e26b351417534e2ad6364f506514e168ac4c0ed42093b3a9469", size = 11559368, upload-time = "2025-12-24T11:15:42.893Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/07/cf06fc620dd94b2ffaa3e9df47b174603e0234096fd857b25dcda6c4a538/zensical-0.0.15-cp310-abi3-win_amd64.whl", hash = "sha256:0d0b303ec8a7aec2e733239f21d3602ce29e0eaabe4e4d60c9bcccb5c2d162dc", size = 11740088, upload-time = "2025-12-24T11:15:45.631Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroconf"
|
||||
version = "0.146.0"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,18 @@
|
|||
> ### ⚠️ Not used by the CDiT fork
|
||||
>
|
||||
> This Shiny webapp is the **upstream** Adaptive Lighting simulator. It
|
||||
> models the upstream curve (with `brightness_mode`, `brightness_mode_time_*`,
|
||||
> sleep mode, etc.) — features the CDiT fork has **removed**.
|
||||
>
|
||||
> The CDiT fork uses a fixed-tanh curve with a hardcoded 30-minute half-width,
|
||||
> anchored at the user's configured `sunrise_entity` / `sunset_entity`.
|
||||
> The simulator's outputs will not match what the integration computes.
|
||||
>
|
||||
> Kept here for upstream-merge hygiene. Not built or deployed by the fork's
|
||||
> CI. See [`../README.md`](../README.md) for the fork's actual behavior.
|
||||
|
||||
---
|
||||
|
||||
To run this app locally, install the requirements and run `shiny run`.
|
||||
|
||||
```
|
||||
|
|
|
|||
120
zensical.toml
120
zensical.toml
|
|
@ -1,120 +0,0 @@
|
|||
# Adaptive Lighting Documentation Site Configuration
|
||||
# Built with Zensical - https://zensical.org
|
||||
|
||||
[project]
|
||||
site_name = "Adaptive Lighting"
|
||||
site_description = "Automatically adjust brightness and color of lights based on the sun position"
|
||||
site_author = "Bas Nijholt"
|
||||
site_url = "https://adaptive-lighting.nijho.lt/"
|
||||
copyright = "Copyright © 2020-2026 Bas Nijholt"
|
||||
|
||||
repo_url = "https://github.com/basnijholt/adaptive-lighting"
|
||||
repo_name = "GitHub"
|
||||
edit_uri = "edit/main/docs"
|
||||
|
||||
nav = [
|
||||
{ "Home" = "index.md" },
|
||||
{ "Getting Started" = "getting-started.md" },
|
||||
{ "Configuration" = "configuration.md" },
|
||||
{ "Services" = "services.md" },
|
||||
{ "Automation Examples" = "automation-examples.md" },
|
||||
{ "Troubleshooting" = "troubleshooting.md" },
|
||||
{ "Advanced" = [
|
||||
{ "Brightness Modes" = "advanced/brightness-modes.md" },
|
||||
{ "Manual Control" = "advanced/manual-control.md" },
|
||||
{ "Sleep Mode" = "advanced/sleep-mode.md" },
|
||||
] },
|
||||
{ "See Also" = "see-also.md" },
|
||||
]
|
||||
|
||||
[project.theme]
|
||||
custom_dir = "docs/overrides"
|
||||
language = "en"
|
||||
logo = "assets/logo.png"
|
||||
|
||||
features = [
|
||||
"announce.dismiss",
|
||||
"content.action.edit",
|
||||
"content.action.view",
|
||||
"content.code.annotate",
|
||||
"content.code.copy",
|
||||
"content.code.select",
|
||||
"content.footnote.tooltips",
|
||||
"content.tabs.link",
|
||||
"content.tooltips",
|
||||
"navigation.footer",
|
||||
"navigation.indexes",
|
||||
"navigation.instant",
|
||||
"navigation.instant.prefetch",
|
||||
"navigation.path",
|
||||
"navigation.top",
|
||||
"navigation.tracking",
|
||||
"search.highlight",
|
||||
]
|
||||
|
||||
# Three-way toggle: system preference -> light -> dark -> system preference
|
||||
[[project.theme.palette]]
|
||||
media = "(prefers-color-scheme)"
|
||||
toggle.icon = "lucide/sun-moon"
|
||||
toggle.name = "Switch to light mode"
|
||||
|
||||
[[project.theme.palette]]
|
||||
media = "(prefers-color-scheme: light)"
|
||||
scheme = "default"
|
||||
primary = "amber"
|
||||
accent = "orange"
|
||||
toggle.icon = "lucide/sun"
|
||||
toggle.name = "Switch to dark mode"
|
||||
|
||||
[[project.theme.palette]]
|
||||
media = "(prefers-color-scheme: dark)"
|
||||
scheme = "slate"
|
||||
primary = "amber"
|
||||
accent = "orange"
|
||||
toggle.icon = "lucide/moon-star"
|
||||
toggle.name = "Switch to system preference"
|
||||
|
||||
[project.theme.font]
|
||||
text = "Inter"
|
||||
code = "JetBrains Mono"
|
||||
|
||||
[project.theme.icon]
|
||||
repo = "lucide/github"
|
||||
|
||||
[project.extra]
|
||||
generator = false
|
||||
|
||||
[project.extra.analytics]
|
||||
provider = "custom"
|
||||
|
||||
[[project.extra.social]]
|
||||
icon = "fontawesome/brands/github"
|
||||
link = "https://github.com/basnijholt/adaptive-lighting"
|
||||
|
||||
[[project.extra.social]]
|
||||
icon = "fontawesome/brands/discord"
|
||||
link = "https://discord.gg/home-assistant"
|
||||
|
||||
# Enable GitHub-style admonitions (> [!NOTE], > [!TIP], etc.)
|
||||
[project.markdown_extensions.gfm_admonition]
|
||||
|
||||
# Enable markdown inside HTML blocks (e.g., <details>)
|
||||
[project.markdown_extensions.md_in_html]
|
||||
|
||||
# Enable attribute lists for adding CSS classes (e.g., {.md-button})
|
||||
[project.markdown_extensions.attr_list]
|
||||
|
||||
# Enable syntax highlighting for fenced code blocks
|
||||
[project.markdown_extensions.pymdownx.highlight]
|
||||
anchor_linenums = true
|
||||
|
||||
[project.markdown_extensions.pymdownx.superfences]
|
||||
|
||||
# Enable tabs (=== "Tab Name" syntax)
|
||||
[project.markdown_extensions.pymdownx.tabbed]
|
||||
alternate_style = true
|
||||
|
||||
# Enable emoji/icon support
|
||||
[project.markdown_extensions.pymdownx.emoji]
|
||||
emoji_index = "zensical.extensions.emoji.twemoji"
|
||||
emoji_generator = "zensical.extensions.emoji.to_svg"
|
||||
Loading…
Add table
Add a link
Reference in a new issue