mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 18:22:48 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a70f565a22 | ||
|
|
1e45d1893c | ||
|
|
c4c19a00e0 | ||
|
|
0f8d26e1dd | ||
|
|
522395de11 | ||
|
|
39d63a3166 | ||
|
|
36cfe5c785 | ||
|
|
d8dd8cf36c | ||
|
|
12c35c1545 | ||
|
|
0e8a3dfb6f | ||
|
|
00f8e89f28 | ||
|
|
5326d1dfe9 | ||
|
|
ba9705e19b | ||
|
|
543a818307 | ||
|
|
b31bedd464 | ||
|
|
c8d331d44b | ||
|
|
62f79e007a | ||
|
|
b989221c71 | ||
|
|
096921cddb | ||
|
|
e3d33df379 | ||
|
|
c263852df9 | ||
|
|
7c58d26d13 | ||
|
|
88f7fc7454 | ||
|
|
140488723d | ||
|
|
b626711d50 | ||
|
|
a6cb560e90 | ||
|
|
a721574706 | ||
|
|
568934cc91 | ||
|
|
13057b7ae3 | ||
|
|
b4289aee59 | ||
|
|
93aecdd435 | ||
|
|
afac871938 | ||
|
|
4c6e6b5447 | ||
|
|
b5c06efb2f | ||
|
|
5cbdf26993 | ||
|
|
6f5108eb70 | ||
|
|
4ef86fe534 |
@@ -32,7 +32,7 @@ runs:
|
||||
# detects the activated venv via ``VIRTUAL_ENV`` so the venv layout
|
||||
# downstream jobs rely on is preserved.
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
||||
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
||||
with:
|
||||
enable-cache: true
|
||||
# Pull request saves land in per-PR scopes nothing else can
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Set up uv
|
||||
# ``--system`` (below) installs into the setup-python interpreter;
|
||||
# no venv is created or restored by this workflow.
|
||||
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
||||
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
||||
with:
|
||||
enable-cache: true
|
||||
# Pull-request-only workflow: a save could never be shared and
|
||||
@@ -97,7 +97,7 @@ jobs:
|
||||
run: git diff
|
||||
- if: failure()
|
||||
name: Archive artifacts
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: generated-proto-files
|
||||
path: |
|
||||
|
||||
@@ -128,7 +128,7 @@ jobs:
|
||||
|
||||
- name: Upload compile-test image artifact
|
||||
if: matrix.os == 'ubuntu-24.04' && matrix.build_type == 'docker'
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
# The tar is already compressed, so upload it as-is. archive: false
|
||||
# skips the redundant zip and makes the file name the artifact name
|
||||
@@ -210,7 +210,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Download image artifact
|
||||
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: compile-test-image.tar.zst
|
||||
- name: Load image
|
||||
|
||||
+11
-11
@@ -49,7 +49,7 @@ jobs:
|
||||
# detects the activated venv via ``VIRTUAL_ENV`` so downstream jobs
|
||||
# that ``. venv/bin/activate`` see an identical layout.
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
||||
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
||||
with:
|
||||
enable-cache: true
|
||||
# Pull request saves land in per-PR scopes nothing else can
|
||||
@@ -438,7 +438,7 @@ jobs:
|
||||
- name: Set up uv
|
||||
# Only needed on cache miss to populate the venv.
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
||||
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
||||
with:
|
||||
enable-cache: true
|
||||
# Pull request saves land in per-PR scopes nothing else can
|
||||
@@ -477,7 +477,7 @@ jobs:
|
||||
# Tests that compare rendered output write the image they actually got here, so a
|
||||
# failure can be looked at without reproducing the whole build locally.
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: integration-test-artifacts-${{ matrix.bucket.name }}
|
||||
path: test_artifacts/
|
||||
@@ -488,7 +488,7 @@ jobs:
|
||||
# script/update_integration_test_durations.py; only full matrix dev
|
||||
# runs produce usable data.
|
||||
if: github.ref == 'refs/heads/dev' && needs.determine-jobs.outputs.integration-run-all == 'true'
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: junit-integration-${{ strategy.job-index }}
|
||||
path: junit-integration.xml
|
||||
@@ -528,7 +528,7 @@ jobs:
|
||||
script/check_import_time.py --check --har importtime.har
|
||||
- name: Upload waterfall HAR
|
||||
if: always()
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: import-time-waterfall
|
||||
path: importtime.har
|
||||
@@ -626,7 +626,7 @@ jobs:
|
||||
apt-get install -y libc6-dbg
|
||||
|
||||
- name: Run CodSpeed benchmarks
|
||||
uses: CodSpeedHQ/action@f842b9a3ffe213dbb81768fd7f7eeb4dfcf1c369 # v5.4.2
|
||||
uses: CodSpeedHQ/action@c4fd08a3a159bd0cc208da1e0edf32b8c47d75e5 # v5.4.0
|
||||
with:
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
@@ -1448,7 +1448,7 @@ jobs:
|
||||
# install step (order-of-magnitude faster on cold boots,
|
||||
# with its own wheel cache). actions/setup-python still
|
||||
# provides the interpreter.
|
||||
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
||||
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
||||
with:
|
||||
enable-cache: true
|
||||
# Pull request saves land in per-PR scopes nothing else can
|
||||
@@ -1647,7 +1647,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Upload memory analysis JSON
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: memory-analysis-target
|
||||
path: memory-analysis-target.json
|
||||
@@ -1710,7 +1710,7 @@ jobs:
|
||||
--platform "$platform"
|
||||
|
||||
- name: Upload memory analysis JSON
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: memory-analysis-pr
|
||||
path: memory-analysis-pr.json
|
||||
@@ -1740,13 +1740,13 @@ jobs:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
cache-key: ${{ needs.common.outputs.cache-key }}
|
||||
- name: Download target analysis JSON
|
||||
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: memory-analysis-target
|
||||
path: ./memory-analysis
|
||||
continue-on-error: true
|
||||
- name: Download PR analysis JSON
|
||||
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: memory-analysis-pr
|
||||
path: ./memory-analysis
|
||||
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
@@ -84,6 +84,6 @@ jobs:
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
|
||||
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -162,7 +162,7 @@ jobs:
|
||||
# version: ${{ needs.init.outputs.tag }}
|
||||
|
||||
- name: Upload digests
|
||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: digests-${{ matrix.platform.arch }}
|
||||
path: /tmp/digests
|
||||
@@ -195,7 +195,7 @@ jobs:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: digests-*
|
||||
path: /tmp/digests
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
# setup-python interpreter so subsequent ``prek`` /
|
||||
# ``script/run-in-env.py`` steps find the deps without a
|
||||
# ``uv run`` prefix.
|
||||
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
||||
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
||||
with:
|
||||
enable-cache: true
|
||||
# Pin uv version so the action does not have to fetch the
|
||||
|
||||
@@ -10,7 +10,7 @@ ci:
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.17.0
|
||||
rev: v0.16.10
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
@@ -36,7 +36,7 @@ repos:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v3.22.0
|
||||
rev: v3.21.2
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py312-plus]
|
||||
|
||||
@@ -144,9 +144,6 @@ file does, and it is the authority when they disagree. The most useful starting
|
||||
|
||||
* **C++ Preprocessor Directives:**
|
||||
* **Avoid `#define` for constants:** Using `#define` for constants is discouraged and should be replaced with `const` variables or enums.
|
||||
* **A constant with a compile-time initializer is `static constexpr`,** not `static const`, at namespace scope
|
||||
and inside functions; `static const` is only for a value computed at run time. A function-local
|
||||
`static constexpr` table is a static constant to clang-tidy, so it is `UPPER_SNAKE_CASE` too.
|
||||
* **Use `#define` only for:**
|
||||
- Conditional compilation (`#ifdef`, `#ifndef`)
|
||||
- Compile-time sizes calculated during Python code generation (e.g., configuring `std::array` or `StaticVector` dimensions via `cg.add_define()`)
|
||||
@@ -220,9 +217,6 @@ file does, and it is the authority when they disagree. The most useful starting
|
||||
listener base (a second vptr per entity).
|
||||
* **A global feature define** says the code is compiled in, not that this instance uses it: keep the
|
||||
per-instance check (`if (this->aux_device_ == ...)`) inside the `#ifdef`.
|
||||
* **Model-specific code** sits behind a define the Python side emits only for configs that use that model
|
||||
(`cg.add_define("USE_SELEC_METER_EM4M")`), so the other models' builds leave it out; the runtime model check
|
||||
stays inside the `#ifdef`.
|
||||
* **Failures after `setup()`:** `mark_failed()` is for `setup()` only. A runtime read or write failure
|
||||
sets `status_set_warning()` and the next success clears it; writes skip work when `is_failed()`.
|
||||
* **Fixed platform facts compile to nothing:** gate on `#ifdef USE_ESP8266` and friends, not on a
|
||||
@@ -573,9 +567,6 @@ file does, and it is the authority when they disagree. The most useful starting
|
||||
An intentionally empty body (an unused `register_dumper` builder, for example) gets a one-line docstring, not `pass`.
|
||||
|
||||
* **Configuration Validation:**
|
||||
* **One schema per model:** when a component's options depend on a `model` key, use `cv.typed_schema({...},
|
||||
key=CONF_MODEL, default_type=...)` with each model's own keys and defaults, not one schema plus a validator
|
||||
that rejects keys and fills defaults afterwards.
|
||||
* **Reuse existing validators:** Before writing a custom validator, check for an existing one in `config_validation.py` and compose it in `cv.All(...)` rather than duplicating logic across components. For example, rename a config key with `cv.rename_key(CONF_OLD, CONF_NEW, removed_in="2026.6.0")`, and reject mutually-exclusive keys with `cv.has_at_most_one_key(...)` / `cv.has_exactly_one_key(...)`. See how `api` composes `cv.has_exactly_one_key` + `cv.rename_key`.
|
||||
* **Common Validators:** `cv.int_`, `cv.float_`, `cv.string`, `cv.boolean`, `cv.int_range(min=0, max=100)`, `cv.positive_int`, `cv.percentage`.
|
||||
* **Complex Validation:** `cv.All(cv.string, cv.Length(min=1, max=50))`, `cv.Any(cv.int_, cv.string)`.
|
||||
@@ -618,9 +609,6 @@ file does, and it is the authority when they disagree. The most useful starting
|
||||
`on_tx` lambda with a static counter and `inject_to_rx_buffer` (see `uart_mock_ld2412_requery_after_giveup.yaml`).
|
||||
* **Keep build-test variants few:** one `test.<platform>.yaml` per platform the code actually differs
|
||||
on. A variant per board for platform-identical code only adds CI time.
|
||||
* **A test that needs a shared component in a particular state** (`esp32_ble` security settings, an option
|
||||
that PSRAM rejects) cannot be grouped: the merged block wins and the whole batch fails. Add the component to
|
||||
`ISOLATED_COMPONENTS` in `script/analyze_component_buses.py`, or move the option to a `test-<variant>` file.
|
||||
* **Component Tests:** YAML-based compilation tests are located in `tests/`. The structure is as follows:
|
||||
```
|
||||
tests/
|
||||
|
||||
@@ -212,10 +212,8 @@ esphome/components/factory_reset/* @anatoly-savchenkov
|
||||
esphome/components/fastled_base/* @OttoWinter
|
||||
esphome/components/feedback/* @ianchi
|
||||
esphome/components/file/* @esphome/core
|
||||
esphome/components/filter_lifetime/* @tuct
|
||||
esphome/components/fingerprint_grow/* @alexborro @loongyh @OnFreund
|
||||
esphome/components/font/* @clydebarrow @esphome/core
|
||||
esphome/components/friedrich/* @rwrozelle
|
||||
esphome/components/fs3000/* @kahrendt
|
||||
esphome/components/ft5x06/* @clydebarrow
|
||||
esphome/components/ft63x6/* @gpambrozio
|
||||
@@ -243,9 +241,6 @@ esphome/components/haier/button/* @paveldn
|
||||
esphome/components/haier/sensor/* @paveldn
|
||||
esphome/components/haier/switch/* @paveldn
|
||||
esphome/components/haier/text_sensor/* @paveldn
|
||||
esphome/components/haier_tundra/* @fauxpark
|
||||
esphome/components/haier_tundra/button/* @fauxpark
|
||||
esphome/components/haier_tundra/switch/* @fauxpark
|
||||
esphome/components/havells_solar/* @sourabhjaiswal
|
||||
esphome/components/hbridge/fan/* @WeekendWarrior
|
||||
esphome/components/hbridge/light/* @DotNetDann
|
||||
@@ -290,7 +285,6 @@ esphome/components/i2s_audio/microphone/* @jesserockz
|
||||
esphome/components/i2s_audio/speaker/* @jesserockz @kahrendt
|
||||
esphome/components/i2s_clockless_led_strip/* @j9brown
|
||||
esphome/components/iaqcore/* @yozik04
|
||||
esphome/components/icm20689/* @lboue
|
||||
esphome/components/icnt86/* @danepowell
|
||||
esphome/components/ili9xxx/* @clydebarrow @nielsnl68
|
||||
esphome/components/improv_base/* @esphome/core
|
||||
@@ -439,7 +433,6 @@ esphome/components/ota/* @esphome/core
|
||||
esphome/components/output/* @esphome/core
|
||||
esphome/components/packet_transport/* @clydebarrow
|
||||
esphome/components/pca6416a/* @Mat931
|
||||
esphome/components/pca9505/* @ajfriesen @ssieb
|
||||
esphome/components/pca9554/* @bdraco @clydebarrow @hwstar
|
||||
esphome/components/pcf85063/* @brogon
|
||||
esphome/components/pcf8563/* @KoenBreeman
|
||||
|
||||
+18
-16
@@ -483,9 +483,12 @@ def has_ota() -> bool:
|
||||
|
||||
def has_native_ota() -> bool:
|
||||
"""Check if native API OTA upload is available (``platform: esphome``)."""
|
||||
from esphome.espota2 import esphome_ota_items
|
||||
|
||||
return bool(esphome_ota_items(CORE.config))
|
||||
if CONF_OTA not in CORE.config:
|
||||
return False
|
||||
return any(
|
||||
ota_item.get(CONF_PLATFORM) == CONF_ESPHOME
|
||||
for ota_item in CORE.config[CONF_OTA]
|
||||
)
|
||||
|
||||
|
||||
def has_web_server_ota() -> bool:
|
||||
@@ -1356,17 +1359,14 @@ def _choose_ota_platform(config: ConfigType, requested: str | None) -> str:
|
||||
return CONF_WEB_SERVER
|
||||
|
||||
|
||||
def _esphome_ota_conf(config: ConfigType) -> ConfigType | None:
|
||||
"""The validated esphome OTA platform block, if configured."""
|
||||
from esphome.espota2 import esphome_ota_items
|
||||
|
||||
return next(iter(esphome_ota_items(config)), None)
|
||||
|
||||
|
||||
def _upload_via_native_api(
|
||||
config: ConfigType, network_devices: list[str], args: ArgsProtocol
|
||||
) -> tuple[int, str | None]:
|
||||
ota_conf = _esphome_ota_conf(config) or {}
|
||||
ota_conf: ConfigType = {}
|
||||
for ota_item in config.get(CONF_OTA, []):
|
||||
if ota_item.get(CONF_PLATFORM) == CONF_ESPHOME:
|
||||
ota_conf = ota_item
|
||||
break
|
||||
|
||||
from esphome import espota2
|
||||
from esphome.components.noise import static_encryption_key
|
||||
@@ -1457,8 +1457,10 @@ def _old_key_notice(config: ConfigType) -> None:
|
||||
`upload` may send a stale image that still carries the previous key."""
|
||||
from esphome import espota2
|
||||
|
||||
for item in espota2.esphome_ota_items(config):
|
||||
if (item.get(CONF_ENCRYPTION) or {}).get(espota2.CONF_OLD_KEY):
|
||||
for item in config.get(CONF_OTA, []):
|
||||
if item.get(CONF_PLATFORM) == CONF_ESPHOME and (
|
||||
item.get(CONF_ENCRYPTION) or {}
|
||||
).get(espota2.CONF_OLD_KEY):
|
||||
_LOGGER.warning(espota2.OLD_KEY_REMOVE_NOTICE)
|
||||
|
||||
|
||||
@@ -1466,12 +1468,12 @@ def _upload_via_web_server(
|
||||
config: ConfigType, network_devices: list[str], binary: Path
|
||||
) -> tuple[int, str | None]:
|
||||
from esphome import web_server_ota
|
||||
from esphome.espota2 import esphome_ota_items
|
||||
from esphome.web_server_helpers import get_web_server_connection
|
||||
|
||||
if any(
|
||||
ota_item.get(CONF_ENCRYPTION) is not None
|
||||
for ota_item in esphome_ota_items(config)
|
||||
ota_item.get(CONF_PLATFORM) == CONF_ESPHOME
|
||||
and ota_item.get(CONF_ENCRYPTION) is not None
|
||||
for ota_item in config.get(CONF_OTA, [])
|
||||
):
|
||||
_LOGGER.warning(
|
||||
"This config has OTA encryption, but the web_server OTA path sends "
|
||||
|
||||
+1
-16
@@ -906,21 +906,6 @@ async def while_action_to_code(
|
||||
return var
|
||||
|
||||
|
||||
def _shadow_iteration(args: TemplateArgsType) -> TemplateArgsType:
|
||||
"""Rename an inherited `iteration` so the inner repeat's own counter can shadow it."""
|
||||
names = {name for _, name in args}
|
||||
renamed: TemplateArgsType = []
|
||||
for type_, name in args:
|
||||
if name == "iteration":
|
||||
depth = 1
|
||||
while f"iteration_{depth}" in names:
|
||||
depth += 1
|
||||
name = f"iteration_{depth}"
|
||||
names.add(name)
|
||||
renamed.append((type_, name))
|
||||
return renamed
|
||||
|
||||
|
||||
@register_action(
|
||||
"repeat",
|
||||
RepeatAction,
|
||||
@@ -944,7 +929,7 @@ async def repeat_action_to_code(
|
||||
actions = await build_action_list(
|
||||
config[CONF_THEN],
|
||||
cg.TemplateArguments(cg.uint32, *template_arg.args),
|
||||
[(cg.uint32, "iteration"), *_shadow_iteration(args)],
|
||||
[(cg.uint32, "iteration"), *args],
|
||||
)
|
||||
for action in actions:
|
||||
cg.add(var.add_then_action(action))
|
||||
|
||||
@@ -10,7 +10,7 @@ void AbsoluteHumidityComponent::setup() {
|
||||
this->temperature_ = state;
|
||||
this->enable_loop();
|
||||
});
|
||||
ESP_LOGD(TAG, " Added callback for temperature '%s'", this->temperature_sensor_->get_name().c_str());
|
||||
ESP_LOGD(TAG, " Added callback for temperature '%s'", LOG_STR_ARG(this->temperature_sensor_->get_log_name()));
|
||||
// Get initial value
|
||||
if (this->temperature_sensor_->has_state()) {
|
||||
this->temperature_ = this->temperature_sensor_->get_state();
|
||||
@@ -20,7 +20,7 @@ void AbsoluteHumidityComponent::setup() {
|
||||
this->humidity_ = state;
|
||||
this->enable_loop();
|
||||
});
|
||||
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", this->humidity_sensor_->get_name().c_str());
|
||||
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
|
||||
// Get initial value
|
||||
if (this->humidity_sensor_->has_state()) {
|
||||
this->humidity_ = this->humidity_sensor_->get_state();
|
||||
@@ -49,7 +49,8 @@ void AbsoluteHumidityComponent::dump_config() {
|
||||
"Sources\n"
|
||||
" Temperature: '%s'\n"
|
||||
" Relative Humidity: '%s'",
|
||||
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
|
||||
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
|
||||
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
|
||||
}
|
||||
|
||||
void AbsoluteHumidityComponent::loop() {
|
||||
|
||||
@@ -66,7 +66,7 @@ template class Aggregator<uint32_t>;
|
||||
|
||||
void ADCSensor::update() {
|
||||
float value_v = this->sample();
|
||||
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", this->get_name().c_str(), value_v);
|
||||
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", LOG_STR_ARG(this->get_log_name()), value_v);
|
||||
this->publish_state(value_v);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ float ADS1115Sensor::sample() {
|
||||
void ADS1115Sensor::update() {
|
||||
float v = this->sample();
|
||||
if (!std::isnan(v)) {
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
|
||||
this->publish_state(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ float ADS1118Sensor::sample() {
|
||||
void ADS1118Sensor::update() {
|
||||
float v = this->sample();
|
||||
if (!std::isnan(v)) {
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
|
||||
this->publish_state(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
|
||||
this->last_update_ = millis();
|
||||
if (state != this->current_state_) {
|
||||
auto prev_state = this->current_state_;
|
||||
ESP_LOGV(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(),
|
||||
ESP_LOGV(TAG, "'%s' >> %s (was %s)", LOG_STR_ARG(this->get_log_name()),
|
||||
LOG_STR_ARG(alarm_control_panel_state_to_string(state)),
|
||||
LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state)));
|
||||
this->current_state_ = state;
|
||||
|
||||
@@ -30,9 +30,9 @@ void Am43Component::loop() {
|
||||
auto status =
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "[%s] Logging into AM43", LOG_STR_ARG(this->get_log_name()));
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
} else {
|
||||
this->logged_in_ = true;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ CoverTraits Am43Component::get_traits() {
|
||||
|
||||
void Am43Component::control(const CoverCall &call) {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
if (call.get_stop()) {
|
||||
@@ -59,7 +59,7 @@ void Am43Component::control(const CoverCall &call) {
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
}
|
||||
}
|
||||
auto opt_pos = call.get_position();
|
||||
@@ -73,7 +73,8 @@ void Am43Component::control(const CoverCall &call) {
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,9 +90,9 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
|
||||
if (chr == nullptr) {
|
||||
if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
|
||||
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
|
||||
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", LOG_STR_ARG(this->get_log_name()));
|
||||
} else {
|
||||
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", this->get_name().c_str());
|
||||
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", LOG_STR_ARG(this->get_log_name()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -100,7 +101,8 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
|
||||
chr->handle);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -126,25 +128,26 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
|
||||
if (this->decoder_->has_pin_response()) {
|
||||
if (this->decoder_->pin_ok_) {
|
||||
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", LOG_STR_ARG(this->get_log_name()));
|
||||
auto *packet = this->encoder_->get_position_request();
|
||||
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
|
||||
this->char_handle_, packet->length, packet->data,
|
||||
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", LOG_STR_ARG(this->get_log_name()));
|
||||
}
|
||||
}
|
||||
|
||||
if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", LOG_STR_ARG(this->get_log_name()));
|
||||
}
|
||||
|
||||
if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", LOG_STR_ARG(this->get_log_name()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -67,8 +67,9 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
|
||||
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
||||
auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
|
||||
if (chr == nullptr) {
|
||||
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
break;
|
||||
}
|
||||
this->char_handle_ = chr->handle;
|
||||
@@ -76,7 +77,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
|
||||
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
|
||||
chr->handle);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -552,7 +552,7 @@ message ListEntitiesBinarySensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string device_class = 5 [(max_data_length) = 47];
|
||||
@@ -586,7 +586,7 @@ message ListEntitiesCoverResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool assumed_state = 5;
|
||||
@@ -670,7 +670,7 @@ message ListEntitiesFanResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool supports_oscillation = 5;
|
||||
@@ -758,7 +758,7 @@ message ListEntitiesLightResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
repeated ColorMode supported_color_modes = 12 [(container_pointer_no_template) = "light::ColorModeMask"];
|
||||
@@ -863,7 +863,7 @@ message ListEntitiesSensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -904,7 +904,7 @@ message ListEntitiesSwitchResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -949,7 +949,7 @@ message ListEntitiesTextSensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1220,7 +1220,7 @@ message ListEntitiesCameraResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
bool disabled_by_default = 5;
|
||||
string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1312,7 +1312,7 @@ message ListEntitiesClimateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool supports_current_temperature = 5; // Deprecated: use feature_flags
|
||||
@@ -1328,9 +1328,9 @@ message ListEntitiesClimateResponse {
|
||||
bool supports_action = 12; // Deprecated: use feature_flags
|
||||
repeated ClimateFanMode supported_fan_modes = 13 [(container_pointer_no_template) = "climate::ClimateFanModeMask"];
|
||||
repeated ClimateSwingMode supported_swing_modes = 14 [(container_pointer_no_template) = "climate::ClimateSwingModeMask"];
|
||||
repeated string supported_custom_fan_modes = 15 [(container_pointer_no_template) = "ConstVector<const char *, true>"];
|
||||
repeated string supported_custom_fan_modes = 15 [(container_pointer_no_template) = "std::vector<const char *>"];
|
||||
repeated ClimatePreset supported_presets = 16 [(container_pointer_no_template) = "climate::ClimatePresetMask"];
|
||||
repeated string supported_custom_presets = 17 [(container_pointer_no_template) = "ConstVector<const char *, true>"];
|
||||
repeated string supported_custom_presets = 17 [(container_pointer_no_template) = "std::vector<const char *>"];
|
||||
bool disabled_by_default = 18;
|
||||
string icon = 19 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
EntityCategory entity_category = 20;
|
||||
@@ -1427,7 +1427,7 @@ message ListEntitiesWaterHeaterResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
@@ -1507,7 +1507,7 @@ message ListEntitiesNumberResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1556,7 +1556,7 @@ message ListEntitiesSelectResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1600,7 +1600,7 @@ message ListEntitiesSirenResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1665,7 +1665,7 @@ message ListEntitiesLockResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1714,7 +1714,7 @@ message ListEntitiesButtonResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1781,7 +1781,7 @@ message ListEntitiesMediaPlayerResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2373,7 +2373,7 @@ message ListEntitiesAlarmControlPanelResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 6;
|
||||
@@ -2420,7 +2420,7 @@ message ListEntitiesTextResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 6;
|
||||
@@ -2468,7 +2468,7 @@ message ListEntitiesDateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2515,7 +2515,7 @@ message ListEntitiesTimeResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2562,7 +2562,7 @@ message ListEntitiesEventResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2593,7 +2593,7 @@ message ListEntitiesValveResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2648,7 +2648,7 @@ message ListEntitiesDateTimeResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2691,7 +2691,7 @@ message ListEntitiesUpdateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2791,7 +2791,7 @@ message ListEntitiesInfraredResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
@@ -2860,7 +2860,7 @@ message ListEntitiesRadioFrequencyResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
|
||||
@@ -474,7 +474,7 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
|
||||
msg.key = entity->get_object_id_hash();
|
||||
|
||||
if (entity->has_own_name()) {
|
||||
msg.name = entity->get_name();
|
||||
msg.name = entity->get_name_progmem();
|
||||
}
|
||||
|
||||
// Set common EntityBase properties
|
||||
|
||||
@@ -123,7 +123,7 @@ extend google.protobuf.FieldOptions {
|
||||
// from an absent one (e.g. a UTC ParsedTimezone, which is all zeros).
|
||||
optional bool track_presence = 50020 [default=false];
|
||||
|
||||
// progmem: The pointer_to_buffer bytes field points into flash (PROGMEM).
|
||||
// progmem: The string field, or pointer_to_buffer bytes field, points into flash (PROGMEM).
|
||||
// The generated encode and dump copy it with progmem_memcpy, as ESP8266
|
||||
// cannot read flash with ordinary loads.
|
||||
optional bool progmem = 50021 [default=false];
|
||||
|
||||
@@ -401,7 +401,7 @@ uint8_t *ListEntitiesBinarySensorResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesBinarySensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.device_class);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.is_status_binary_sensor);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.disabled_by_default);
|
||||
@@ -459,7 +459,7 @@ uint8_t *ListEntitiesCoverResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesCoverResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.assumed_state);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_position);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_tilt);
|
||||
@@ -558,7 +558,7 @@ uint8_t *ListEntitiesFanResponse::encode_msg(const void *self, uint8_t *__restri
|
||||
const auto &msg = *static_cast<const ListEntitiesFanResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_oscillation);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_speed);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_direction);
|
||||
@@ -678,7 +678,7 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesLightResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
for (const auto &it : *msg.supported_color_modes) {
|
||||
pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(it));
|
||||
}
|
||||
@@ -884,7 +884,7 @@ uint8_t *ListEntitiesSensorResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -954,7 +954,7 @@ uint8_t *ListEntitiesSwitchResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSwitchResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1030,7 +1030,7 @@ uint8_t *ListEntitiesTextSensorResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesTextSensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1478,7 +1478,7 @@ uint8_t *ListEntitiesCameraResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesCameraResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.icon);
|
||||
@@ -1544,7 +1544,7 @@ uint8_t *ListEntitiesClimateResponse::encode_msg(const void *self, uint8_t *__re
|
||||
const auto &msg = *static_cast<const ListEntitiesClimateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_current_temperature);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_two_point_target_temperature);
|
||||
for (const auto &it : *msg.supported_modes) {
|
||||
@@ -1781,7 +1781,7 @@ uint8_t *ListEntitiesWaterHeaterResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesWaterHeaterResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
@@ -1908,7 +1908,7 @@ uint8_t *ListEntitiesNumberResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesNumberResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1999,7 +1999,7 @@ uint8_t *ListEntitiesSelectResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSelectResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2078,7 +2078,7 @@ uint8_t *ListEntitiesSirenResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesSirenResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2180,7 +2180,7 @@ uint8_t *ListEntitiesLockResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesLockResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2263,7 +2263,7 @@ uint8_t *ListEntitiesButtonResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesButtonResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2332,7 +2332,7 @@ uint8_t *ListEntitiesMediaPlayerResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesMediaPlayerResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3178,7 +3178,7 @@ uint8_t *ListEntitiesAlarmControlPanelResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesAlarmControlPanelResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3258,7 +3258,7 @@ uint8_t *ListEntitiesTextResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesTextResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3337,7 +3337,7 @@ uint8_t *ListEntitiesDateResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesDateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3418,7 +3418,7 @@ uint8_t *ListEntitiesTimeResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesTimeResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3499,7 +3499,7 @@ uint8_t *ListEntitiesEventResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesEventResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3561,7 +3561,7 @@ uint8_t *ListEntitiesValveResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesValveResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3649,7 +3649,7 @@ uint8_t *ListEntitiesDateTimeResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesDateTimeResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3722,7 +3722,7 @@ uint8_t *ListEntitiesUpdateResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesUpdateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3878,7 +3878,7 @@ uint8_t *ListEntitiesInfraredResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesInfraredResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
@@ -3996,7 +3996,7 @@ uint8_t *ListEntitiesRadioFrequencyResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesRadioFrequencyResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
|
||||
@@ -399,7 +399,7 @@ class InfoResponseProtoMessage : public ProtoMessage {
|
||||
public:
|
||||
StringRef object_id{};
|
||||
uint32_t key{0};
|
||||
StringRef name{};
|
||||
ProgmemStringRef name{};
|
||||
bool disabled_by_default{false};
|
||||
#ifdef USE_ENTITY_ICON
|
||||
StringRef icon{nullptr, 0}; // null until set, encode only
|
||||
@@ -1776,9 +1776,9 @@ class ListEntitiesClimateResponse final : public InfoResponseProtoMessage {
|
||||
bool supports_action{false};
|
||||
const climate::ClimateFanModeMask *supported_fan_modes{};
|
||||
const climate::ClimateSwingModeMask *supported_swing_modes{};
|
||||
const ConstVector<const char *, true> *supported_custom_fan_modes{};
|
||||
const std::vector<const char *> *supported_custom_fan_modes{};
|
||||
const climate::ClimatePresetMask *supported_presets{};
|
||||
const ConstVector<const char *, true> *supported_custom_presets{};
|
||||
const std::vector<const char *> *supported_custom_presets{};
|
||||
float visual_current_temperature_step{0.0f};
|
||||
bool supports_current_humidity{false};
|
||||
bool supports_target_humidity{false};
|
||||
|
||||
@@ -12,8 +12,9 @@ namespace esphome::api {
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
// Out-of-line to avoid inlining strlen_P/memcpy_P at every call site
|
||||
void DumpBuffer::append_p_esp8266(const char *str) {
|
||||
size_t len = strlen_P(str);
|
||||
void DumpBuffer::append_p_esp8266(const char *str) { this->append_p_esp8266(str, strlen_P(str)); }
|
||||
|
||||
void DumpBuffer::append_p_esp8266(const char *str, size_t len) {
|
||||
size_t space = CAPACITY - 1 - pos_;
|
||||
if (len > space)
|
||||
len = space;
|
||||
@@ -134,6 +135,13 @@ static void dump_progmem_bytes_field(DumpBuffer &out, const char *field_name, co
|
||||
progmem_memcpy(data_buf, data, len);
|
||||
dump_bytes_field(out, field_name, data_buf, len, indent);
|
||||
}
|
||||
|
||||
// Helper for string fields in flash
|
||||
static void dump_progmem_string_field(DumpBuffer &out, const char *field_name, const ProgmemStringRef &value,
|
||||
int indent = 2) {
|
||||
append_field_prefix(out, field_name, indent);
|
||||
out.append("'").append_p(value.progmem_ptr(), value.size()).append("'\n");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
template<> const char *proto_enum_to_string<enums::DisconnectReason>(enums::DisconnectReason value) {
|
||||
@@ -1182,7 +1190,7 @@ const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesBinarySensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
|
||||
dump_field(out, ESPHOME_PSTR("is_status_binary_sensor"), this->is_status_binary_sensor);
|
||||
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
|
||||
@@ -1211,7 +1219,7 @@ const char *ListEntitiesCoverResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCoverResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state);
|
||||
dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position);
|
||||
dump_field(out, ESPHOME_PSTR("supports_tilt"), this->supports_tilt);
|
||||
@@ -1257,7 +1265,7 @@ const char *ListEntitiesFanResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesFanResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("supports_oscillation"), this->supports_oscillation);
|
||||
dump_field(out, ESPHOME_PSTR("supports_speed"), this->supports_speed);
|
||||
dump_field(out, ESPHOME_PSTR("supports_direction"), this->supports_direction);
|
||||
@@ -1312,7 +1320,7 @@ const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLightResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
for (const auto &it : *this->supported_color_modes) {
|
||||
dump_field(out, ESPHOME_PSTR("supported_color_modes"), static_cast<enums::ColorMode>(it), 4);
|
||||
}
|
||||
@@ -1391,7 +1399,7 @@ const char *ListEntitiesSensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1423,7 +1431,7 @@ const char *ListEntitiesSwitchResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSwitchResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1461,7 +1469,7 @@ const char *ListEntitiesTextSensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextSensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1692,7 +1700,7 @@ const char *ListEntitiesCameraResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCameraResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
@@ -1725,7 +1733,7 @@ const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesClimateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("supports_current_temperature"), this->supports_current_temperature);
|
||||
dump_field(out, ESPHOME_PSTR("supports_two_point_target_temperature"), this->supports_two_point_target_temperature);
|
||||
for (const auto &it : *this->supported_modes) {
|
||||
@@ -1823,7 +1831,7 @@ const char *ListEntitiesWaterHeaterResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesWaterHeaterResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1877,7 +1885,7 @@ const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesNumberResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1919,7 +1927,7 @@ const char *ListEntitiesSelectResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSelectResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1958,7 +1966,7 @@ const char *ListEntitiesSirenResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSirenResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2005,7 +2013,7 @@ const char *ListEntitiesLockResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLockResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2046,7 +2054,7 @@ const char *ListEntitiesButtonResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesButtonResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2081,7 +2089,7 @@ const char *ListEntitiesMediaPlayerResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesMediaPlayerResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2471,7 +2479,7 @@ const char *ListEntitiesAlarmControlPanelResponse::dump_to(DumpBuffer &out) cons
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesAlarmControlPanelResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2510,7 +2518,7 @@ const char *ListEntitiesTextResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2550,7 +2558,7 @@ const char *ListEntitiesDateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2590,7 +2598,7 @@ const char *ListEntitiesTimeResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTimeResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2630,7 +2638,7 @@ const char *ListEntitiesEventResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesEventResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2660,7 +2668,7 @@ const char *ListEntitiesValveResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesValveResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2702,7 +2710,7 @@ const char *ListEntitiesDateTimeResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateTimeResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2738,7 +2746,7 @@ const char *ListEntitiesUpdateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesUpdateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2801,7 +2809,7 @@ const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesInfraredResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2859,7 +2867,7 @@ const char *ListEntitiesRadioFrequencyResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesRadioFrequencyResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
|
||||
@@ -409,6 +409,10 @@ class ProtoEncode {
|
||||
/// Tag must be a single-byte varint (< 128). Always encodes (no zero check).
|
||||
[[nodiscard]] static inline uint8_t *encode_short_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint8_t tag, const StringRef &ref) {
|
||||
#ifdef USE_ESP8266
|
||||
// memcpy_P reads RAM too, and sharing the progmem copy is smaller than an inline memcpy
|
||||
return encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, tag, ProgmemStringRef(ref));
|
||||
#else
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
assert(ref.size() < 128 && "encode_short_string_force: string exceeds max_data_length < 128");
|
||||
#endif
|
||||
@@ -417,6 +421,19 @@ class ProtoEncode {
|
||||
pos[1] = static_cast<uint8_t>(ref.size());
|
||||
std::memcpy(pos + 2, ref.c_str(), ref.size());
|
||||
return pos + 2 + ref.size();
|
||||
#endif
|
||||
}
|
||||
/// encode_short_string_force for a string that may be in flash (PROGMEM).
|
||||
[[nodiscard]] static inline uint8_t *encode_short_progmem_string_force(
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, const ProgmemStringRef &ref) {
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
assert(ref.size() < 128 && "encode_short_progmem_string_force: string exceeds max_data_length < 128");
|
||||
#endif
|
||||
PROTO_ENCODE_CHECK_BOUNDS(pos, 2 + ref.size());
|
||||
pos[0] = tag;
|
||||
pos[1] = static_cast<uint8_t>(ref.size());
|
||||
progmem_memcpy(pos + 2, ref.progmem_ptr(), ref.size());
|
||||
return pos + 2 + ref.size();
|
||||
}
|
||||
/// Write a precomputed tag byte + 32-bit value. Outlined on embedded: one copy beats inline stores per field.
|
||||
[[nodiscard]] static PROTO_OUTLINE_FOR_SIZE uint8_t *write_tag_and_fixed32(
|
||||
@@ -481,6 +498,17 @@ class ProtoEncode {
|
||||
progmem_memcpy(pos, data, len);
|
||||
return pos + len;
|
||||
}
|
||||
/// encode_progmem_bytes for a string field that may be in flash.
|
||||
[[nodiscard]] static inline uint8_t *encode_progmem_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, const ProgmemStringRef &ref) {
|
||||
return encode_progmem_bytes(pos PROTO_ENCODE_DEBUG_ARG, field_id,
|
||||
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
|
||||
}
|
||||
[[nodiscard]] static inline uint8_t *encode_progmem_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, const ProgmemStringRef &ref) {
|
||||
return encode_progmem_bytes_force(pos PROTO_ENCODE_DEBUG_ARG, field_id,
|
||||
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
|
||||
}
|
||||
[[nodiscard]] static inline uint8_t *encode_uint32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, uint32_t value) {
|
||||
pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0);
|
||||
@@ -680,9 +708,20 @@ class DumpBuffer {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Append len bytes of a PROGMEM string
|
||||
DumpBuffer &append_p(const char *str, size_t len) {
|
||||
#ifdef USE_ESP8266
|
||||
append_p_esp8266(str, len);
|
||||
#else
|
||||
append_impl_(str, len);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
/// Out-of-line ESP8266 PROGMEM append to avoid inlining strlen_P/memcpy_P at every call site
|
||||
void append_p_esp8266(const char *str);
|
||||
void append_p_esp8266(const char *str, size_t len);
|
||||
#endif
|
||||
|
||||
const char *c_str() const { return buf_; }
|
||||
|
||||
@@ -30,10 +30,10 @@ void AQISensor::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, " Extended Range: %s",
|
||||
this->extended_range_ ? LOG_STR_LITERAL("enabled") : LOG_STR_LITERAL("disabled"));
|
||||
if (this->pm_2_5_sensor_ != nullptr) {
|
||||
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", this->pm_2_5_sensor_->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", LOG_STR_ARG(this->pm_2_5_sensor_->get_log_name()));
|
||||
}
|
||||
if (this->pm_10_0_sensor_ != nullptr) {
|
||||
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", this->pm_10_0_sensor_->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", LOG_STR_ARG(this->pm_10_0_sensor_->get_log_name()));
|
||||
}
|
||||
LOG_SENSOR(" ", "AQI", this);
|
||||
}
|
||||
|
||||
@@ -1289,7 +1289,7 @@ void ATM90E32Component::check_phase_status() {
|
||||
if (!status.empty()) {
|
||||
status.pop_back(); // remove space
|
||||
status.pop_back(); // remove semicolon
|
||||
ESP_LOGW(TAG, "%s: %s", sensor->get_name().c_str(), status.c_str());
|
||||
ESP_LOGW(TAG, "%s: %s", LOG_STR_ARG(sensor->get_log_name()), status.c_str());
|
||||
sensor->publish_state(status);
|
||||
} else {
|
||||
sensor->publish_state("Okay");
|
||||
|
||||
@@ -8,11 +8,12 @@ ESPHOME_LOG_TAG(TAG, "atm90e32.button");
|
||||
|
||||
void ATM90E32GainCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Gain Calibration button [%s]", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Gain Calibration button [%s]",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG,
|
||||
"[CALIBRATION] Use gain_ct: & gain_voltage: under each phase_x: in your config file to save these values");
|
||||
this->parent_->run_gain_calibrations();
|
||||
@@ -20,21 +21,22 @@ void ATM90E32GainCalibrationButton::press_action() {
|
||||
|
||||
void ATM90E32ClearGainCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Gain button [%s]", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Gain button [%s]", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
this->parent_->clear_gain_calibrations();
|
||||
}
|
||||
|
||||
void ATM90E32OffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Offset Calibration button [%s]", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Offset Calibration button [%s]",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "[CALIBRATION] **NOTE: CTs and ACVs must be 0 during this process. USB power only**");
|
||||
ESP_LOGI(TAG, "[CALIBRATION] Use offset_voltage: & offset_current: under each phase_x: in your config file to save "
|
||||
"these values");
|
||||
@@ -43,21 +45,22 @@ void ATM90E32OffsetCalibrationButton::press_action() {
|
||||
|
||||
void ATM90E32ClearOffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Offset button [%s]", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Offset button [%s]", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
this->parent_->clear_offset_calibrations();
|
||||
}
|
||||
|
||||
void ATM90E32PowerOffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Power Calibration button [%s]", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Power Calibration button [%s]",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "[CALIBRATION] **NOTE: CTs must be 0 during this process. Voltage reference should be present**");
|
||||
ESP_LOGI(TAG, "[CALIBRATION] Use offset_active_power: & offset_reactive_power: under each phase_x: in your config "
|
||||
"file to save these values");
|
||||
@@ -66,11 +69,11 @@ void ATM90E32PowerOffsetCalibrationButton::press_action() {
|
||||
|
||||
void ATM90E32ClearPowerOffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Power button [%s]", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Power button [%s]", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
this->parent_->clear_power_offset_calibrations();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::bedjet {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "bedjet");
|
||||
static const char *const TAG = "bedjet";
|
||||
|
||||
/// Converts a BedJet fan step to a speed percentage, in the range of 5% to 100%.
|
||||
inline static uint8_t bedjet_fan_step_to_speed(const uint8_t fan) {
|
||||
|
||||
@@ -61,7 +61,7 @@ void BedJetClimate::dump_config() {
|
||||
|
||||
void BedJetClimate::setup() {
|
||||
// Set custom modes once during setup — stored on Climate base class, wired via get_traits()
|
||||
this->set_supported_custom_fan_modes_static(BEDJET_FAN_STEP_NAMES, BEDJET_FAN_SPEED_COUNT);
|
||||
this->set_supported_custom_fan_modes(BEDJET_FAN_STEP_NAMES);
|
||||
this->set_supported_custom_presets({
|
||||
this->heating_mode_ == HEAT_MODE_EXTENDED ? "LTD HT" : "EXT HT",
|
||||
"M1",
|
||||
@@ -211,7 +211,7 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
} else if (fan_mode == CLIMATE_FAN_HIGH) {
|
||||
result = this->parent_->set_fan_speed(75);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", this->get_name().c_str(),
|
||||
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", LOG_STR_ARG(this->get_log_name()),
|
||||
LOG_STR_ARG(climate_fan_mode_to_string(fan_mode)));
|
||||
return;
|
||||
}
|
||||
@@ -223,7 +223,7 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
auto fan_mode = call.get_custom_fan_mode();
|
||||
auto fan_index = bedjet_fan_speed_to_step(fan_mode.c_str());
|
||||
if (fan_index <= 19) {
|
||||
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", this->get_name().c_str(),
|
||||
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", LOG_STR_ARG(this->get_log_name()),
|
||||
(int) fan_mode.size(), fan_mode.c_str(), fan_index);
|
||||
bool result = this->parent_->set_fan_index(fan_index);
|
||||
if (result) {
|
||||
@@ -236,7 +236,7 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
void BedJetClimate::on_bedjet_state(bool is_ready) {}
|
||||
|
||||
void BedJetClimate::on_status(const BedjetStatusPacket *data) {
|
||||
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
|
||||
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
|
||||
|
||||
auto converted_temp = bedjet_temp_to_c(data->target_temp_step);
|
||||
if (converted_temp > 0)
|
||||
@@ -310,11 +310,11 @@ void BedJetClimate::on_status(const BedjetStatusPacket *data) {
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", this->get_name().c_str(), data->mode);
|
||||
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", LOG_STR_ARG(this->get_log_name()), data->mode);
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", this->get_name().c_str(),
|
||||
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", LOG_STR_ARG(this->get_log_name()),
|
||||
LOG_STR_ARG(climate_mode_to_string(this->mode)));
|
||||
// FIXME: compare new state to previous state.
|
||||
this->publish_state();
|
||||
@@ -351,11 +351,11 @@ bool BedJetClimate::update_status_() {
|
||||
}
|
||||
|
||||
void BedJetClimate::update() {
|
||||
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
|
||||
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
|
||||
// TODO: if the hub component is already polling, do we also need to include polling?
|
||||
// We're already going to get on_status() at the hub's polling interval.
|
||||
auto result = this->update_status_();
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
|
||||
}
|
||||
|
||||
} // namespace esphome::bedjet
|
||||
|
||||
@@ -53,7 +53,7 @@ void BedJetFan::control(const fan::FanCall &call) {
|
||||
}
|
||||
|
||||
void BedJetFan::on_status(const BedjetStatusPacket *data) {
|
||||
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
|
||||
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
|
||||
bool did_change = false;
|
||||
bool new_state = data->mode != MODE_STANDBY && data->mode != MODE_WAIT;
|
||||
|
||||
@@ -96,11 +96,11 @@ bool BedJetFan::update_status_() {
|
||||
}
|
||||
|
||||
void BedJetFan::update() {
|
||||
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
|
||||
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
|
||||
// TODO: if the hub component is already polling, do we also need to include polling?
|
||||
// We're already going to get on_status() at the hub's polling interval.
|
||||
auto result = this->update_status_();
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
|
||||
}
|
||||
|
||||
/** Resets states to defaults. */
|
||||
|
||||
@@ -75,7 +75,7 @@ void BH1750Sensor::dump_config() {
|
||||
LOG_SENSOR("", "BH1750", this);
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, this->get_name().c_str());
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, LOG_STR_ARG(this->get_log_name()));
|
||||
}
|
||||
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
@@ -154,7 +154,7 @@ void BH1750Sensor::loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), lx);
|
||||
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", LOG_STR_ARG(this->get_log_name()), lx);
|
||||
this->status_clear_warning();
|
||||
this->publish_state(lx);
|
||||
this->state_ = IDLE;
|
||||
|
||||
@@ -13,7 +13,7 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, LOG_STR_ARG(obj->get_log_name()));
|
||||
LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ bool BinarySensor::set_new_state(const optional<bool> &new_state) {
|
||||
#if defined(USE_BINARY_SENSOR) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_binary_sensor_update(this);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state));
|
||||
ESP_LOGV(TAG, "'%s' >> %s", LOG_STR_ARG(this->get_log_name()), ONOFFMAYBE(new_state));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -47,7 +47,7 @@ void BinarySensorMap::process_group_() {
|
||||
}
|
||||
} else if (this->last_mask_ != 0ULL) {
|
||||
// no buttons are pressed and the states have changed since last run, so publish NAN
|
||||
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
|
||||
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", LOG_STR_ARG(this->get_log_name()));
|
||||
this->publish_state(NAN);
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ float BL0940::update_temp_(sensor::Sensor *sensor, uint16_le_t temperature) cons
|
||||
if (sensor != nullptr) {
|
||||
if (sensor->has_state() && std::abs(converted_temp - sensor->get_state()) > max_temperature_diff_) {
|
||||
ESP_LOGD(TAG, "Invalid temperature change. Sensor: '%s', Old temperature: %f, New temperature: %f",
|
||||
sensor->get_name().c_str(), sensor->get_state(), converted_temp);
|
||||
LOG_STR_ARG(sensor->get_log_name()), sensor->get_state(), converted_temp);
|
||||
return 0.0f;
|
||||
}
|
||||
sensor->publish_state(converted_temp);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace esphome::ble_client {
|
||||
|
||||
const char *const Automation::TAG = "ble_client.automation"; // NOLINT: ble_client never builds for ESP8266
|
||||
const char *const Automation::TAG = "ble_client.automation";
|
||||
|
||||
} // namespace esphome::ble_client
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
|
||||
|
||||
void BLEClientRSSISensor::update() {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
this->should_update_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -37,13 +37,13 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
|
||||
switch (event) {
|
||||
case ESP_GATTC_OPEN_EVT: {
|
||||
if (param->open.status == ESP_GATT_OK) {
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_CLOSE_EVT: {
|
||||
ESP_LOGW(TAG, "[%s] Disconnected!", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Disconnected!", LOG_STR_ARG(this->get_log_name()));
|
||||
this->status_set_warning();
|
||||
this->publish_state(NAN);
|
||||
break;
|
||||
@@ -102,10 +102,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
|
||||
}
|
||||
case ESP_GATTC_NOTIFY_EVT: {
|
||||
if (param->notify.value_len == 0) {
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
|
||||
break;
|
||||
}
|
||||
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
|
||||
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
|
||||
param->notify.handle, param->notify.value[0]);
|
||||
if (param->notify.handle != this->handle)
|
||||
break;
|
||||
@@ -143,11 +143,11 @@ float BLESensor::parse_data_(uint8_t *value, uint16_t value_len) {
|
||||
|
||||
void BLESensor::update() {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
if (this->handle == 0) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ void BLESensor::update() {
|
||||
if (status) {
|
||||
this->status_set_warning();
|
||||
this->publish_state(NAN);
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
switch (event) {
|
||||
case ESP_GATTC_OPEN_EVT: {
|
||||
if (param->open.status == ESP_GATT_OK) {
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -104,10 +104,10 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
if (param->notify.handle != this->handle)
|
||||
break;
|
||||
if (param->notify.value_len == 0) {
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
|
||||
break;
|
||||
}
|
||||
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
|
||||
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
|
||||
param->notify.handle, param->notify.value[0]);
|
||||
this->publish_state(reinterpret_cast<const char *>(param->notify.value), param->notify.value_len);
|
||||
break;
|
||||
@@ -124,11 +124,11 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
|
||||
void BLETextSensor::update() {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
if (this->handle == 0) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ void BLETextSensor::update() {
|
||||
if (status) {
|
||||
this->status_set_warning();
|
||||
this->publish_state("");
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
#include "esphome/components/bme280_base/bme280_base.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::bme280_i2c {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "bme280_i2c.sensor");
|
||||
static const char *const TAG = "bme280_i2c.sensor";
|
||||
|
||||
class BME280I2CComponent final : public esphome::bme280_base::BME280Component, public i2c::I2CDevice {
|
||||
bool read_byte(uint8_t a_register, uint8_t *data) override;
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
#include "esphome/components/bmp280_base/bmp280_base.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::bmp280_i2c {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "bmp280_i2c.sensor");
|
||||
static const char *const TAG = "bmp280_i2c.sensor";
|
||||
|
||||
/// This class implements support for the BMP280 Temperature+Pressure i2c sensor.
|
||||
class BMP280I2CComponent final : public esphome::bmp280_base::BMP280Component, public i2c::I2CDevice {
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
#include "esphome/components/bmp581_base/bmp581_base.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::bmp581_i2c {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "bmp581_i2c.sensor");
|
||||
static const char *const TAG = "bmp581_i2c.sensor";
|
||||
|
||||
/// This class implements support for the BMP581 Temperature+Pressure i2c sensor.
|
||||
class BMP581I2CComponent final : public esphome::bmp581_base::BMP581Component, public i2c::I2CDevice {
|
||||
|
||||
@@ -11,12 +11,12 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, LOG_STR_ARG(obj->get_log_name()));
|
||||
LOG_ENTITY_ICON(tag, prefix, *obj);
|
||||
}
|
||||
|
||||
void Button::press() {
|
||||
ESP_LOGV(TAG, "'%s' Pressed.", this->get_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s' Pressed.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->press_action();
|
||||
this->press_callback_.call();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace esphome::chsc6x {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "chsc6x.touchscreen");
|
||||
static const char *const TAG = "chsc6x.touchscreen";
|
||||
|
||||
static const uint8_t CHSC6X_REG_STATUS = 0x00;
|
||||
static const uint8_t CHSC6X_REG_STATUS_TOUCH = 0x00;
|
||||
|
||||
@@ -442,24 +442,6 @@ async def setup_climate_core_(var: MockObj, config: ConfigType) -> None:
|
||||
await web_server.add_entity_config(var, web_server_config)
|
||||
|
||||
|
||||
def set_custom_fan_modes(var: MockObj, modes: list[str]) -> None:
|
||||
"""Point the climate at a shared flash table of custom fan modes."""
|
||||
if modes:
|
||||
table = cg.shared_progmem_array(
|
||||
"climate_custom_fan_modes", cg.const_char_ptr, modes
|
||||
)
|
||||
cg.add(var.set_supported_custom_fan_modes_static(table, len(modes)))
|
||||
|
||||
|
||||
def set_custom_presets(var: MockObj, presets: list[str]) -> None:
|
||||
"""Point the climate at a shared flash table of custom presets."""
|
||||
if presets:
|
||||
table = cg.shared_progmem_array(
|
||||
"climate_custom_presets", cg.const_char_ptr, presets
|
||||
)
|
||||
cg.add(var.set_supported_custom_presets_static(table, len(presets)))
|
||||
|
||||
|
||||
async def register_climate(var: MockObj, config: ConfigType) -> None:
|
||||
if not CORE.has_id(config[CONF_ID]):
|
||||
var = cg.Pvariable(config[CONF_ID], var)
|
||||
|
||||
@@ -46,7 +46,7 @@ constexpr StringToUint8 CLIMATE_SWING_MODES_BY_STR[] = {
|
||||
|
||||
void ClimateCall::perform() {
|
||||
this->parent_->control_callback_.call(*this);
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
this->validate_();
|
||||
if (this->mode_.has_value()) {
|
||||
const LogString *mode_s = climate_mode_to_string(*this->mode_);
|
||||
@@ -183,7 +183,7 @@ ClimateCall &ClimateCall::set_mode(const char *mode, size_t len) {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", this->parent_->get_name().c_str(), (int) len, mode);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len, mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -214,7 +214,8 @@ ClimateCall &ClimateCall::set_fan_mode(const char *custom_fan_mode, size_t len)
|
||||
this->fan_mode_.reset();
|
||||
return *this;
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", this->parent_->get_name().c_str(), (int) len, custom_fan_mode);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
|
||||
custom_fan_mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -252,7 +253,8 @@ ClimateCall &ClimateCall::set_preset(const char *custom_preset, size_t len) {
|
||||
this->preset_.reset();
|
||||
return *this;
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", this->parent_->get_name().c_str(), (int) len, custom_preset);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
|
||||
custom_preset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -280,7 +282,8 @@ ClimateCall &ClimateCall::set_swing_mode(const char *swing_mode, size_t len) {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", this->parent_->get_name().c_str(), (int) len, swing_mode);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
|
||||
swing_mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -428,7 +431,7 @@ void Climate::save_state_(const ClimateTraits &traits) {
|
||||
|
||||
void Climate::publish_state() {
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
|
||||
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
|
||||
auto traits = this->get_traits();
|
||||
|
||||
ESP_LOGV(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
|
||||
@@ -479,8 +482,10 @@ void Climate::publish_state() {
|
||||
ClimateTraits Climate::get_traits() {
|
||||
auto traits = this->traits();
|
||||
// Wire custom mode pointers from Climate-owned storage
|
||||
traits.set_supported_custom_fan_modes_(&this->supported_custom_fan_modes_);
|
||||
traits.set_supported_custom_presets_(&this->supported_custom_presets_);
|
||||
if (this->supported_custom_fan_modes_)
|
||||
traits.set_supported_custom_fan_modes_(this->supported_custom_fan_modes_);
|
||||
if (this->supported_custom_presets_)
|
||||
traits.set_supported_custom_presets_(this->supported_custom_presets_);
|
||||
#ifdef USE_CLIMATE_VISUAL_OVERRIDES
|
||||
if (!std::isnan(this->visual_min_temperature_override_)) {
|
||||
traits.set_visual_min_temperature(this->visual_min_temperature_override_);
|
||||
@@ -547,7 +552,7 @@ void ClimateDeviceRestoreState::apply(Climate *climate) {
|
||||
if (traits.supports_mode(this->mode)) {
|
||||
climate->mode = this->mode;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", climate->get_name().c_str(),
|
||||
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", LOG_STR_ARG(climate->get_log_name()),
|
||||
LOG_STR_ARG(climate_mode_to_string(this->mode)), LOG_STR_ARG(climate_mode_to_string(climate->mode)));
|
||||
}
|
||||
if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
|
||||
@@ -626,7 +631,7 @@ template<typename T> bool set_primary_mode(optional<T> &primary, const char *&cu
|
||||
* After: fan_mode=nullopt, custom_fan_mode_="Turbo" (pointer from traits)
|
||||
*
|
||||
* Lifetime Safety:
|
||||
* - found_ptr must come from Climate::find_custom_*_()
|
||||
* - found_ptr must come from traits.find_custom_*_mode_()
|
||||
* - Only pointers found in traits are stored, ensuring they remain valid
|
||||
* - Prevents dangling pointers from temporary strings
|
||||
*
|
||||
@@ -682,7 +687,11 @@ const char *Climate::find_custom_fan_mode_(const char *custom_fan_mode) {
|
||||
}
|
||||
|
||||
const char *Climate::find_custom_fan_mode_(const char *custom_fan_mode, size_t len) {
|
||||
return vector_find(this->supported_custom_fan_modes_, custom_fan_mode, len);
|
||||
if (this->supported_custom_fan_modes_) {
|
||||
return vector_find(*this->supported_custom_fan_modes_, custom_fan_mode, len);
|
||||
}
|
||||
// Fallback for deprecated path: external components may set modes on ClimateTraits directly
|
||||
return this->get_traits().find_custom_fan_mode_(custom_fan_mode, len);
|
||||
}
|
||||
|
||||
const char *Climate::find_custom_preset_(const char *custom_preset) {
|
||||
@@ -690,7 +699,11 @@ const char *Climate::find_custom_preset_(const char *custom_preset) {
|
||||
}
|
||||
|
||||
const char *Climate::find_custom_preset_(const char *custom_preset, size_t len) {
|
||||
return vector_find(this->supported_custom_presets_, custom_preset, len);
|
||||
if (this->supported_custom_presets_) {
|
||||
return vector_find(*this->supported_custom_presets_, custom_preset, len);
|
||||
}
|
||||
// Fallback for deprecated path: external components may set modes on ClimateTraits directly
|
||||
return this->get_traits().find_custom_preset_(custom_preset, len);
|
||||
}
|
||||
|
||||
void Climate::dump_traits_(const char *tag) {
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::climate {
|
||||
|
||||
#define LOG_CLIMATE(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
}
|
||||
|
||||
class Climate;
|
||||
@@ -246,34 +246,26 @@ class Climate : public EntityBase {
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Set the supported custom fan modes; the list is copied (stored on Climate, referenced by ClimateTraits).
|
||||
/// Set the supported custom fan modes (stored on Climate, referenced by ClimateTraits).
|
||||
void set_supported_custom_fan_modes(std::initializer_list<const char *> modes) {
|
||||
this->supported_custom_fan_modes_.assign_copy(modes.begin(), modes.size());
|
||||
this->ensure_custom_fan_modes_().assign(modes.begin(), modes.end());
|
||||
}
|
||||
void set_supported_custom_fan_modes(const std::vector<const char *> &modes) {
|
||||
this->supported_custom_fan_modes_.assign_copy(modes.data(), modes.size());
|
||||
this->ensure_custom_fan_modes_() = modes;
|
||||
}
|
||||
template<size_t N> void set_supported_custom_fan_modes(const char *const (&modes)[N]) {
|
||||
this->supported_custom_fan_modes_.assign_copy(modes, N);
|
||||
}
|
||||
/// Points at a static table that outlives the climate (codegen); call before any runtime copy.
|
||||
void set_supported_custom_fan_modes_static(const char *const *modes, size_t count) {
|
||||
this->supported_custom_fan_modes_.assign_static(modes, count);
|
||||
this->ensure_custom_fan_modes_().assign(modes, modes + N);
|
||||
}
|
||||
|
||||
/// Set the supported custom presets; the list is copied (stored on Climate, referenced by ClimateTraits).
|
||||
/// Set the supported custom presets (stored on Climate, referenced by ClimateTraits).
|
||||
void set_supported_custom_presets(std::initializer_list<const char *> presets) {
|
||||
this->supported_custom_presets_.assign_copy(presets.begin(), presets.size());
|
||||
this->ensure_custom_presets_().assign(presets.begin(), presets.end());
|
||||
}
|
||||
void set_supported_custom_presets(const std::vector<const char *> &presets) {
|
||||
this->supported_custom_presets_.assign_copy(presets.data(), presets.size());
|
||||
this->ensure_custom_presets_() = presets;
|
||||
}
|
||||
template<size_t N> void set_supported_custom_presets(const char *const (&presets)[N]) {
|
||||
this->supported_custom_presets_.assign_copy(presets, N);
|
||||
}
|
||||
/// Points at a static table that outlives the climate (codegen); call before any runtime copy.
|
||||
void set_supported_custom_presets_static(const char *const *presets, size_t count) {
|
||||
this->supported_custom_presets_.assign_static(presets, count);
|
||||
this->ensure_custom_presets_().assign(presets, presets + N);
|
||||
}
|
||||
|
||||
/// Check if a custom fan mode is currently active.
|
||||
@@ -396,8 +388,22 @@ class Climate : public EntityBase {
|
||||
#endif
|
||||
|
||||
private:
|
||||
ClimateCustomModes supported_custom_fan_modes_;
|
||||
ClimateCustomModes supported_custom_presets_;
|
||||
/// Lazy-allocate custom mode vectors (never freed — entity lives forever).
|
||||
std::vector<const char *> &ensure_custom_fan_modes_() {
|
||||
if (!this->supported_custom_fan_modes_) {
|
||||
this->supported_custom_fan_modes_ = new std::vector<const char *>(); // NOLINT
|
||||
}
|
||||
return *this->supported_custom_fan_modes_;
|
||||
}
|
||||
std::vector<const char *> &ensure_custom_presets_() {
|
||||
if (!this->supported_custom_presets_) {
|
||||
this->supported_custom_presets_ = new std::vector<const char *>(); // NOLINT
|
||||
}
|
||||
return *this->supported_custom_presets_;
|
||||
}
|
||||
|
||||
std::vector<const char *> *supported_custom_fan_modes_{nullptr};
|
||||
std::vector<const char *> *supported_custom_presets_{nullptr};
|
||||
|
||||
/** The active custom fan mode (private - enforces use of safe setters).
|
||||
*
|
||||
|
||||
@@ -2,16 +2,31 @@
|
||||
|
||||
namespace esphome::climate {
|
||||
|
||||
ClimateTraits::ClimateTraits() = default;
|
||||
// Compat: shared empty vector for getters when no custom modes are set.
|
||||
// Remove in 2026.11.0 when deprecated ClimateTraits setters are removed
|
||||
// and getters can return const vector * instead of const vector &.
|
||||
static const std::vector<const char *> EMPTY_CUSTOM_MODES; // NOLINT
|
||||
|
||||
static const ClimateCustomModes EMPTY_CUSTOM_MODES; // NOLINT
|
||||
|
||||
const ClimateCustomModes &ClimateTraits::get_supported_custom_fan_modes() const {
|
||||
return this->supported_custom_fan_modes_ != nullptr ? *this->supported_custom_fan_modes_ : EMPTY_CUSTOM_MODES;
|
||||
const std::vector<const char *> &ClimateTraits::get_supported_custom_fan_modes() const {
|
||||
if (this->supported_custom_fan_modes_) {
|
||||
return *this->supported_custom_fan_modes_;
|
||||
}
|
||||
// Compat: fall back to owned vector from deprecated setters. Remove in 2026.11.0.
|
||||
if (!this->compat_custom_fan_modes_.empty()) {
|
||||
return this->compat_custom_fan_modes_;
|
||||
}
|
||||
return EMPTY_CUSTOM_MODES;
|
||||
}
|
||||
|
||||
const ClimateCustomModes &ClimateTraits::get_supported_custom_presets() const {
|
||||
return this->supported_custom_presets_ != nullptr ? *this->supported_custom_presets_ : EMPTY_CUSTOM_MODES;
|
||||
const std::vector<const char *> &ClimateTraits::get_supported_custom_presets() const {
|
||||
if (this->supported_custom_presets_) {
|
||||
return *this->supported_custom_presets_;
|
||||
}
|
||||
// Compat: fall back to owned vector from deprecated setters. Remove in 2026.11.0.
|
||||
if (!this->compat_custom_presets_.empty()) {
|
||||
return this->compat_custom_presets_;
|
||||
}
|
||||
return EMPTY_CUSTOM_MODES;
|
||||
}
|
||||
|
||||
int8_t ClimateTraits::get_target_temperature_accuracy_decimals() const {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include "climate_mode.h"
|
||||
#include "esphome/core/finite_set_mask.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
@@ -18,12 +18,9 @@ using ClimateSwingModeMask =
|
||||
FiniteSetMask<ClimateSwingMode, DefaultBitPolicy<ClimateSwingMode, CLIMATE_SWING_HORIZONTAL + 1>>;
|
||||
using ClimatePresetMask = FiniteSetMask<ClimatePreset, DefaultBitPolicy<ClimatePreset, CLIMATE_PRESET_ACTIVITY + 1>>;
|
||||
|
||||
/// Custom fan modes and custom presets: a flash table from codegen, or an owned copy set at runtime.
|
||||
using ClimateCustomModes = ConstVector<const char *, true>;
|
||||
|
||||
// Lightweight linear search for small lists (1-20 items) of const char* pointers
|
||||
// Lightweight linear search for small vectors (1-20 items) of const char* pointers
|
||||
// Avoids std::find template overhead
|
||||
template<typename List> inline bool vector_contains(const List &vec, const char *value, size_t len) {
|
||||
inline bool vector_contains(const std::vector<const char *> &vec, const char *value, size_t len) {
|
||||
for (const char *item : vec) {
|
||||
if (strncmp(item, value, len) == 0 && item[len] == '\0')
|
||||
return true;
|
||||
@@ -31,12 +28,12 @@ template<typename List> inline bool vector_contains(const List &vec, const char
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename List> inline bool vector_contains(const List &vec, const char *value) {
|
||||
inline bool vector_contains(const std::vector<const char *> &vec, const char *value) {
|
||||
return vector_contains(vec, value, strlen(value));
|
||||
}
|
||||
|
||||
// Find and return matching pointer from a list, or nullptr if not found
|
||||
template<typename List> inline const char *vector_find(const List &vec, const char *value, size_t len) {
|
||||
// Find and return matching pointer from vector, or nullptr if not found
|
||||
inline const char *vector_find(const std::vector<const char *> &vec, const char *value, size_t len) {
|
||||
for (const char *item : vec) {
|
||||
if (strncmp(item, value, len) == 0 && item[len] == '\0')
|
||||
return item;
|
||||
@@ -74,13 +71,9 @@ template<typename List> inline const char *vector_find(const List &vec, const ch
|
||||
class Climate; // Forward declaration
|
||||
|
||||
class ClimateTraits {
|
||||
friend class Climate; // Climate wires its custom mode lists into traits
|
||||
friend class Climate; // Allow Climate to access protected find methods
|
||||
|
||||
public:
|
||||
// Out of line on purpose: an inlined default init makes GCC copy the defaults from a .rodata
|
||||
// template per traits() override, and .rodata is RAM on ESP8266.
|
||||
ClimateTraits();
|
||||
|
||||
/// Get/set feature flags (see ClimateFeatures enum in climate_mode.h)
|
||||
uint32_t get_feature_flags() const { return this->feature_flags_; }
|
||||
void add_feature_flags(uint32_t feature_flags) { this->feature_flags_ |= feature_flags; }
|
||||
@@ -100,14 +93,42 @@ class ClimateTraits {
|
||||
if (!this->supported_fan_modes_.empty()) {
|
||||
return true;
|
||||
}
|
||||
return this->supported_custom_fan_modes_ != nullptr && !this->supported_custom_fan_modes_->empty();
|
||||
// Same precedence as get_supported_custom_fan_modes() getter
|
||||
if (this->supported_custom_fan_modes_) {
|
||||
return !this->supported_custom_fan_modes_->empty();
|
||||
}
|
||||
return !this->compat_custom_fan_modes_.empty(); // Compat: remove in 2026.11.0
|
||||
}
|
||||
const ClimateFanModeMask &get_supported_fan_modes() const { return this->supported_fan_modes_; }
|
||||
|
||||
/// Empty when the climate has no custom fan modes. Set them on the Climate entity.
|
||||
const ClimateCustomModes &get_supported_custom_fan_modes() const;
|
||||
// Remove before 2026.11.0
|
||||
ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
|
||||
void set_supported_custom_fan_modes(std::initializer_list<const char *> modes) {
|
||||
// Compat: store in owned vector. Copies copy the vector (deprecated path still copies this vector).
|
||||
this->compat_custom_fan_modes_ = modes;
|
||||
}
|
||||
// Remove before 2026.11.0
|
||||
ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
|
||||
void set_supported_custom_fan_modes(const std::vector<const char *> &modes) {
|
||||
this->compat_custom_fan_modes_ = modes;
|
||||
}
|
||||
// Remove before 2026.11.0
|
||||
template<size_t N>
|
||||
ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
|
||||
void set_supported_custom_fan_modes(const char *const (&modes)[N]) {
|
||||
this->compat_custom_fan_modes_.assign(modes, modes + N);
|
||||
}
|
||||
|
||||
// Deleted overloads to catch incorrect std::string usage at compile time with clear error messages
|
||||
void set_supported_custom_fan_modes(const std::vector<std::string> &modes) = delete;
|
||||
void set_supported_custom_fan_modes(std::initializer_list<std::string> modes) = delete;
|
||||
|
||||
// Compat: returns const ref with empty fallback. In 2026.11.0 change to return const vector *.
|
||||
const std::vector<const char *> &get_supported_custom_fan_modes() const;
|
||||
bool supports_custom_fan_mode(const char *custom_fan_mode) const {
|
||||
return vector_contains(this->get_supported_custom_fan_modes(), custom_fan_mode);
|
||||
return (this->supported_custom_fan_modes_ &&
|
||||
vector_contains(*this->supported_custom_fan_modes_, custom_fan_mode)) ||
|
||||
vector_contains(this->compat_custom_fan_modes_, custom_fan_mode); // Compat: remove in 2026.11.0
|
||||
}
|
||||
bool supports_custom_fan_mode(const std::string &custom_fan_mode) const {
|
||||
return this->supports_custom_fan_mode(custom_fan_mode.c_str());
|
||||
@@ -119,10 +140,32 @@ class ClimateTraits {
|
||||
bool get_supports_presets() const { return !this->supported_presets_.empty(); }
|
||||
const ClimatePresetMask &get_supported_presets() const { return this->supported_presets_; }
|
||||
|
||||
/// Empty when the climate has no custom presets. Set them on the Climate entity.
|
||||
const ClimateCustomModes &get_supported_custom_presets() const;
|
||||
// Remove before 2026.11.0
|
||||
ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
|
||||
void set_supported_custom_presets(std::initializer_list<const char *> presets) {
|
||||
this->compat_custom_presets_ = presets;
|
||||
}
|
||||
// Remove before 2026.11.0
|
||||
ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
|
||||
void set_supported_custom_presets(const std::vector<const char *> &presets) {
|
||||
this->compat_custom_presets_ = presets;
|
||||
}
|
||||
// Remove before 2026.11.0
|
||||
template<size_t N>
|
||||
ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
|
||||
void set_supported_custom_presets(const char *const (&presets)[N]) {
|
||||
this->compat_custom_presets_.assign(presets, presets + N);
|
||||
}
|
||||
|
||||
// Deleted overloads to catch incorrect std::string usage at compile time with clear error messages
|
||||
void set_supported_custom_presets(const std::vector<std::string> &presets) = delete;
|
||||
void set_supported_custom_presets(std::initializer_list<std::string> presets) = delete;
|
||||
|
||||
// Compat: returns const ref with empty fallback. In 2026.11.0 change to return const vector *.
|
||||
const std::vector<const char *> &get_supported_custom_presets() const;
|
||||
bool supports_custom_preset(const char *custom_preset) const {
|
||||
return vector_contains(this->get_supported_custom_presets(), custom_preset);
|
||||
return (this->supported_custom_presets_ && vector_contains(*this->supported_custom_presets_, custom_preset)) ||
|
||||
vector_contains(this->compat_custom_presets_, custom_preset); // Compat: remove in 2026.11.0
|
||||
}
|
||||
bool supports_custom_preset(const std::string &custom_preset) const {
|
||||
return this->supports_custom_preset(custom_preset.c_str());
|
||||
@@ -189,8 +232,38 @@ class ClimateTraits {
|
||||
}
|
||||
|
||||
/// Set custom mode pointers (only Climate::get_traits() should call these).
|
||||
void set_supported_custom_fan_modes_(const ClimateCustomModes *modes) { this->supported_custom_fan_modes_ = modes; }
|
||||
void set_supported_custom_presets_(const ClimateCustomModes *presets) { this->supported_custom_presets_ = presets; }
|
||||
void set_supported_custom_fan_modes_(const std::vector<const char *> *modes) {
|
||||
this->supported_custom_fan_modes_ = modes;
|
||||
}
|
||||
void set_supported_custom_presets_(const std::vector<const char *> *presets) {
|
||||
this->supported_custom_presets_ = presets;
|
||||
}
|
||||
|
||||
/// Find and return the matching custom fan mode pointer from supported modes, or nullptr if not found
|
||||
/// This is protected as it's an implementation detail - use Climate::find_custom_fan_mode_() instead
|
||||
const char *find_custom_fan_mode_(const char *custom_fan_mode) const {
|
||||
return this->find_custom_fan_mode_(custom_fan_mode, strlen(custom_fan_mode));
|
||||
}
|
||||
const char *find_custom_fan_mode_(const char *custom_fan_mode, size_t len) const {
|
||||
if (this->supported_custom_fan_modes_) {
|
||||
return vector_find(*this->supported_custom_fan_modes_, custom_fan_mode, len);
|
||||
}
|
||||
// Compat: check owned vector from deprecated setters. Remove in 2026.11.0.
|
||||
return vector_find(this->compat_custom_fan_modes_, custom_fan_mode, len);
|
||||
}
|
||||
|
||||
/// Find and return the matching custom preset pointer from supported presets, or nullptr if not found
|
||||
/// This is protected as it's an implementation detail - use Climate::find_custom_preset_() instead
|
||||
const char *find_custom_preset_(const char *custom_preset) const {
|
||||
return this->find_custom_preset_(custom_preset, strlen(custom_preset));
|
||||
}
|
||||
const char *find_custom_preset_(const char *custom_preset, size_t len) const {
|
||||
if (this->supported_custom_presets_) {
|
||||
return vector_find(*this->supported_custom_presets_, custom_preset, len);
|
||||
}
|
||||
// Compat: check owned vector from deprecated setters. Remove in 2026.11.0.
|
||||
return vector_find(this->compat_custom_presets_, custom_preset, len);
|
||||
}
|
||||
|
||||
uint32_t feature_flags_{0};
|
||||
float visual_min_temperature_{10};
|
||||
@@ -206,10 +279,17 @@ class ClimateTraits {
|
||||
climate::ClimatePresetMask supported_presets_;
|
||||
TemperatureUnit temperature_unit_{TemperatureUnit::CELSIUS};
|
||||
|
||||
/// Owned by the Climate entity; get_traits() wires these pointers.
|
||||
const ClimateCustomModes *supported_custom_fan_modes_{nullptr};
|
||||
const ClimateCustomModes *supported_custom_presets_{nullptr};
|
||||
/** Custom mode storage - pointers to vectors owned by the Climate base class.
|
||||
*
|
||||
* ClimateTraits does not own this data; Climate stores the vectors and
|
||||
* get_traits() wires these pointers automatically.
|
||||
*/
|
||||
const std::vector<const char *> *supported_custom_fan_modes_{nullptr};
|
||||
const std::vector<const char *> *supported_custom_presets_{nullptr};
|
||||
// Compat: owned storage for deprecated setters. Copies copy the vector (copies include this vector).
|
||||
// Remove in 2026.11.0.
|
||||
std::vector<const char *> compat_custom_fan_modes_;
|
||||
std::vector<const char *> compat_custom_presets_;
|
||||
};
|
||||
static_assert(std::is_trivially_copyable_v<ClimateTraits>, "ClimateTraits is copied on every traits() call");
|
||||
|
||||
} // namespace esphome::climate
|
||||
|
||||
@@ -30,14 +30,14 @@ void CombinationOneParameterComponent::add_source(Sensor *sensor, float value) {
|
||||
void CombinationNoParameterComponent::log_source_sensors() {
|
||||
ESP_LOGCONFIG(TAG, " Source Sensors:");
|
||||
for (const auto &sensor : this->sensors_) {
|
||||
ESP_LOGCONFIG(TAG, " - %s", sensor->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(sensor->get_log_name()));
|
||||
}
|
||||
}
|
||||
|
||||
void CombinationOneParameterComponent::log_source_sensors() {
|
||||
ESP_LOGCONFIG(TAG, " Source Sensors:");
|
||||
for (const auto &source : this->sensor_sources_) {
|
||||
ESP_LOGCONFIG(TAG, " - %s", source.sensor->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(source.sensor->get_log_name()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ CoverCall &CoverCall::set_command(const char *command) {
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TOGGLE")) == 0) {
|
||||
this->set_command_toggle();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", LOG_STR_ARG(this->parent_->get_log_name()), command);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ CoverCall &CoverCall::set_tilt(float tilt) {
|
||||
return *this;
|
||||
}
|
||||
void CoverCall::perform() {
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
auto traits = this->parent_->get_traits();
|
||||
this->validate_();
|
||||
if (this->stop_) {
|
||||
@@ -94,7 +94,7 @@ const optional<float> &CoverCall::get_tilt() const { return this->tilt_; }
|
||||
const optional<bool> &CoverCall::get_toggle() const { return this->toggle_; }
|
||||
void CoverCall::validate_() {
|
||||
auto traits = this->parent_->get_traits();
|
||||
const char *name = this->parent_->get_name().c_str();
|
||||
const char *name = LOG_STR_ARG(this->parent_->get_log_name());
|
||||
|
||||
if (this->position_.has_value()) {
|
||||
auto pos = *this->position_;
|
||||
@@ -139,7 +139,7 @@ void Cover::publish_state(bool save) {
|
||||
this->position = clamp(this->position, 0.0f, 1.0f);
|
||||
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
|
||||
|
||||
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
|
||||
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
|
||||
auto traits = this->get_traits();
|
||||
if (traits.get_supports_position()) {
|
||||
ESP_LOGV(TAG, " Position: %.0f%%", this->position * 100.0f);
|
||||
|
||||
@@ -15,7 +15,7 @@ static constexpr float COVER_CLOSED = 0.0f;
|
||||
|
||||
#define LOG_COVER(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
auto traits_ = (obj)->get_traits(); \
|
||||
if (traits_.get_is_assumed_state()) { \
|
||||
ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace esphome::cst816 {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "cst816.touchscreen");
|
||||
static const char *const TAG = "cst816.touchscreen";
|
||||
|
||||
static const uint8_t REG_STATUS = 0x00;
|
||||
static const uint8_t REG_TOUCH_NUM = 0x02;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace esphome::cst9220 {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "cst9220.touchscreen");
|
||||
static const char *const TAG = "cst9220.touchscreen";
|
||||
|
||||
// The CST92xx family uses 16-bit (big-endian) register addresses.
|
||||
static const uint16_t REG_TOUCH_DATA = 0xD000; // touch report
|
||||
|
||||
@@ -40,7 +40,8 @@ void CTClampSensor::update() {
|
||||
if (rms_ac_squared > 0)
|
||||
rms_ac = std::sqrt(rms_ac_squared);
|
||||
ESP_LOGD(TAG, "'%s' - Raw AC Value: %.3fA after %" PRIu32 " different samples (%" PRIu32 " SPS)",
|
||||
this->name_.c_str(), rms_ac, this->num_samples_, 1000 * this->num_samples_ / this->sample_duration_);
|
||||
LOG_STR_ARG(this->get_log_name()), rms_ac, this->num_samples_,
|
||||
1000 * this->num_samples_ / this->sample_duration_);
|
||||
this->publish_state(rms_ac);
|
||||
});
|
||||
|
||||
|
||||
@@ -70,20 +70,20 @@ void CurrentBasedCover::loop() {
|
||||
this->direction_idle_();
|
||||
this->malfunction_trigger_.trigger();
|
||||
ESP_LOGI(TAG, "'%s' - Malfunction detected during opening. Current flow detected in close circuit",
|
||||
this->name_.c_str());
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
} else if (this->is_opening_blocked_()) { // Blocked
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->direction_idle_();
|
||||
if (this->obstacle_rollback_ != 0) {
|
||||
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->target_position_ = clamp(this->position - this->obstacle_rollback_, 0.0F, 1.0F);
|
||||
this->start_direction_(COVER_OPERATION_CLOSING);
|
||||
});
|
||||
}
|
||||
} else if (this->is_initial_delay_finished_() && !this->is_opening_()) { // End reached
|
||||
auto dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
this->direction_idle_(COVER_OPEN);
|
||||
}
|
||||
} else if (this->current_operation == COVER_OPERATION_CLOSING) {
|
||||
@@ -91,25 +91,25 @@ void CurrentBasedCover::loop() {
|
||||
this->direction_idle_();
|
||||
this->malfunction_trigger_.trigger();
|
||||
ESP_LOGI(TAG, "'%s' - Malfunction detected during closing. Current flow detected in open circuit",
|
||||
this->name_.c_str());
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
} else if (this->is_closing_blocked_()) { // Blocked
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->direction_idle_();
|
||||
if (this->obstacle_rollback_ != 0) {
|
||||
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->target_position_ = clamp(this->position + this->obstacle_rollback_, 0.0F, 1.0F);
|
||||
this->start_direction_(COVER_OPERATION_OPENING);
|
||||
});
|
||||
}
|
||||
} else if (this->is_initial_delay_finished_() && !this->is_closing_()) { // End reached
|
||||
auto dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
this->direction_idle_(COVER_CLOSED);
|
||||
}
|
||||
}
|
||||
if (now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->direction_idle_();
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ void DallasTemperatureSensor::update() {
|
||||
}
|
||||
|
||||
float tempc = this->get_temp_c_();
|
||||
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", this->get_name().c_str(), tempc);
|
||||
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", LOG_STR_ARG(this->get_log_name()), tempc);
|
||||
this->publish_state(tempc);
|
||||
});
|
||||
}
|
||||
@@ -65,7 +65,7 @@ bool DallasTemperatureSensor::read_scratch_pad_() {
|
||||
i = this->bus_->read8();
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", LOG_STR_ARG(this->get_log_name()));
|
||||
this->status_set_warning(LOG_STR("bus reset failed"));
|
||||
}
|
||||
return success;
|
||||
|
||||
@@ -30,7 +30,7 @@ void DateEntity::publish_state() {
|
||||
return;
|
||||
}
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_);
|
||||
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_, this->day_);
|
||||
this->state_callback_.call();
|
||||
#if defined(USE_DATETIME_DATE) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_date_update(this);
|
||||
@@ -81,7 +81,7 @@ void DateCall::validate_() {
|
||||
|
||||
void DateCall::perform() {
|
||||
this->validate_();
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
|
||||
if (this->year_.has_value()) {
|
||||
ESP_LOGV(TAG, " Year: %d", *this->year_);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::datetime {
|
||||
|
||||
#define LOG_DATETIME_DATE(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ void DateTimeEntity::publish_state() {
|
||||
return;
|
||||
}
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_,
|
||||
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_,
|
||||
this->day_, this->hour_, this->minute_, this->second_);
|
||||
this->state_callback_.call();
|
||||
#if defined(USE_DATETIME_DATETIME) && defined(USE_CONTROLLER_REGISTRY)
|
||||
@@ -125,7 +125,7 @@ void DateTimeCall::validate_() {
|
||||
|
||||
void DateTimeCall::perform() {
|
||||
this->validate_();
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
|
||||
if (this->year_.has_value()) {
|
||||
ESP_LOGV(TAG, " Year: %d", *this->year_);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::datetime {
|
||||
|
||||
#define LOG_DATETIME_DATETIME(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ void TimeEntity::publish_state() {
|
||||
return;
|
||||
}
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_);
|
||||
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->hour_, this->minute_, this->second_);
|
||||
this->state_callback_.call();
|
||||
#if defined(USE_DATETIME_TIME) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_time_update(this);
|
||||
@@ -50,7 +50,7 @@ void TimeCall::validate_() {
|
||||
|
||||
void TimeCall::perform() {
|
||||
this->validate_();
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
if (this->hour_.has_value()) {
|
||||
ESP_LOGV(TAG, " Hour: %d", *this->hour_);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::datetime {
|
||||
|
||||
#define LOG_DATETIME_TIME(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -143,8 +143,6 @@ def validate_wakeup_pin(
|
||||
processed_pins: list[ConfigType] = [{CONF_PIN: value}]
|
||||
else:
|
||||
processed_pins = list(value)
|
||||
if not processed_pins:
|
||||
raise cv.Invalid("'wakeup_pin' needs at least one entry")
|
||||
|
||||
for i, pin_config in enumerate(processed_pins):
|
||||
# now validate each item
|
||||
@@ -156,34 +154,29 @@ def validate_wakeup_pin(
|
||||
|
||||
|
||||
def validate_config(config: ConfigType) -> ConfigType:
|
||||
wakeup_pins = config.get(CONF_WAKEUP_PIN)
|
||||
has_pin_mode = CONF_WAKEUP_PIN_MODE in config
|
||||
if has_pin_mode and wakeup_pins is None:
|
||||
# right now only BK72XX supports the list format for wakeup pins
|
||||
if CORE.is_bk72xx:
|
||||
if CONF_WAKEUP_PIN_MODE in config:
|
||||
wakeup_pins = config.get(CONF_WAKEUP_PIN, [])
|
||||
if len(wakeup_pins) > 1:
|
||||
raise cv.Invalid(
|
||||
"You need to remove the global wakeup_pin_mode and define it per pin"
|
||||
)
|
||||
if wakeup_pins:
|
||||
if CONF_WAKEUP_PIN_MODE in wakeup_pins[0]:
|
||||
raise cv.Invalid(
|
||||
"Specify wakeup_pin_mode either at the top level under deep_sleep "
|
||||
"or under the pin entry, not both"
|
||||
)
|
||||
wakeup_pins[0][CONF_WAKEUP_PIN_MODE] = config.pop(CONF_WAKEUP_PIN_MODE)
|
||||
elif (
|
||||
isinstance(config.get(CONF_WAKEUP_PIN), list)
|
||||
and len(config[CONF_WAKEUP_PIN]) > 1
|
||||
):
|
||||
raise cv.Invalid(
|
||||
"'wakeup_pin_mode' requires 'wakeup_pin'", path=[CONF_WAKEUP_PIN_MODE]
|
||||
"Your platform does not support providing multiple entries in wakeup_pin"
|
||||
)
|
||||
multiple_pins = wakeup_pins is not None and len(wakeup_pins) > 1
|
||||
# wakeup_pin is limited to ESP32 and BK72XX, and only BK72XX accepts a list
|
||||
if not CORE.is_bk72xx:
|
||||
if multiple_pins:
|
||||
raise cv.Invalid(
|
||||
"ESP32 does not support multiple entries for 'wakeup_pin'",
|
||||
path=[CONF_WAKEUP_PIN],
|
||||
)
|
||||
elif has_pin_mode:
|
||||
if multiple_pins:
|
||||
raise cv.Invalid(
|
||||
"Remove the global 'wakeup_pin_mode' and define it per pin",
|
||||
path=[CONF_WAKEUP_PIN_MODE],
|
||||
)
|
||||
if CONF_WAKEUP_PIN_MODE in (pin := wakeup_pins[0]):
|
||||
raise cv.Invalid(
|
||||
"Specify 'wakeup_pin_mode' either at the top level under 'deep_sleep' "
|
||||
"or under the pin entry, not both",
|
||||
path=[CONF_WAKEUP_PIN, 0, CONF_WAKEUP_PIN_MODE],
|
||||
)
|
||||
# Move the global mode into the single pin entry, which to_code() reads
|
||||
pin[CONF_WAKEUP_PIN_MODE] = config.pop(CONF_WAKEUP_PIN_MODE)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
@@ -210,11 +203,11 @@ def _validate_sleep_duration(value: core.TimePeriod) -> core.TimePeriod:
|
||||
if CORE.is_bk72xx:
|
||||
max_duration = core.TimePeriod(hours=36)
|
||||
if value > max_duration:
|
||||
raise cv.Invalid("'sleep_duration' cannot be more than 36 hours on BK72XX")
|
||||
raise cv.Invalid("sleep duration cannot be more than 36 hours on BK72XX")
|
||||
elif CORE.using_zephyr:
|
||||
max_duration = core.TimePeriod(days=49)
|
||||
if value > max_duration:
|
||||
raise cv.Invalid("'sleep_duration' cannot be more than 49 days on Zephyr")
|
||||
raise cv.Invalid("sleep duration cannot be more than 49 days on Zephyr")
|
||||
return value
|
||||
|
||||
|
||||
@@ -297,10 +290,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.positive_time_period_milliseconds,
|
||||
_validate_sleep_duration,
|
||||
),
|
||||
cv.Optional(CONF_WAKEUP_PIN): cv.All(
|
||||
cv.only_on([PLATFORM_ESP32, PLATFORM_BK72XX]),
|
||||
validate_wakeup_pin,
|
||||
),
|
||||
cv.Optional(CONF_WAKEUP_PIN): validate_wakeup_pin,
|
||||
cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All(
|
||||
cv.only_on([PLATFORM_ESP32, PLATFORM_BK72XX]),
|
||||
cv.enum(WAKEUP_PIN_MODES, upper=True),
|
||||
@@ -357,10 +347,11 @@ async def to_code(config: ConfigType) -> None:
|
||||
|
||||
if CONF_SLEEP_DURATION in config:
|
||||
cg.add(var.set_sleep_duration(config[CONF_SLEEP_DURATION]))
|
||||
if (wakeup_pins := config.get(CONF_WAKEUP_PIN)) is not None:
|
||||
if CONF_WAKEUP_PIN in config:
|
||||
pins_as_list = config.get(CONF_WAKEUP_PIN, [])
|
||||
if CORE.is_bk72xx:
|
||||
cg.add(var.init_wakeup_pins(len(wakeup_pins)))
|
||||
for item in wakeup_pins:
|
||||
cg.add(var.init_wakeup_pins(len(pins_as_list)))
|
||||
for item in pins_as_list:
|
||||
cg.add(
|
||||
var.add_wakeup_pin(
|
||||
await cg.gpio_pin_expression(item[CONF_PIN]),
|
||||
@@ -370,7 +361,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
)
|
||||
)
|
||||
else:
|
||||
pin = await cg.gpio_pin_expression(wakeup_pins[0][CONF_PIN])
|
||||
pin = await cg.gpio_pin_expression(pins_as_list[0][CONF_PIN])
|
||||
cg.add(var.set_wakeup_pin(pin))
|
||||
if CONF_WAKEUP_PIN_MODE in config:
|
||||
cg.add(var.set_wakeup_pin_mode(config[CONF_WAKEUP_PIN_MODE]))
|
||||
|
||||
@@ -36,7 +36,8 @@ void DewPointComponent::dump_config() {
|
||||
"Sources\n"
|
||||
" Temperature: '%s'\n"
|
||||
" Humidity: '%s'",
|
||||
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
|
||||
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
|
||||
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
|
||||
}
|
||||
|
||||
float DewPointComponent::get_setup_priority() const { return setup_priority::DATA; }
|
||||
@@ -75,8 +76,8 @@ void DewPointComponent::loop() {
|
||||
// Publish the calculated dew point
|
||||
this->publish_state(dew_point);
|
||||
|
||||
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", this->get_name().c_str(), dew_point, this->temperature_value_,
|
||||
this->humidity_value_);
|
||||
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", LOG_STR_ARG(this->get_log_name()), dew_point,
|
||||
this->temperature_value_, this->humidity_value_);
|
||||
}
|
||||
|
||||
} // namespace esphome::dew_point
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include "esphome/core/color.h"
|
||||
|
||||
namespace esphome::display {
|
||||
@@ -156,54 +154,4 @@ class ColorUtil {
|
||||
return color;
|
||||
}
|
||||
};
|
||||
|
||||
/** Rec.601 luma weights (0.299/0.587/0.114), scaled by 256 */
|
||||
static constexpr uint16_t REC601_LUMA_R = 77;
|
||||
static constexpr uint16_t REC601_LUMA_G = 150;
|
||||
static constexpr uint16_t REC601_LUMA_B = 29;
|
||||
|
||||
/** Rec.601 luma of an RGB color, for optimum perceptual brightness */
|
||||
constexpr uint8_t rec601_luma(Color color) {
|
||||
return (uint8_t) ((REC601_LUMA_R * color.r + REC601_LUMA_G * color.g + REC601_LUMA_B * color.b + 128u) >> 8);
|
||||
}
|
||||
|
||||
/** Map an RGB color to a single monochrome bit: 1 = white, 0 = black */
|
||||
constexpr uint8_t color_to_mono(Color color) { return rec601_luma(color) >= 128 ? 1 : 0; }
|
||||
|
||||
/** color_to_mono() of an RGB565 value as ColorUtil::to_color() reads it, from table lookups instead of a division
|
||||
* per channel.
|
||||
*/
|
||||
class Rgb565ToMono {
|
||||
public:
|
||||
explicit Rgb565ToMono(ColorOrder order) {
|
||||
// Rec.601 weight of the 5-bit, 6-bit and 5-bit fields, by the channel each one holds in this order
|
||||
uint16_t high = REC601_LUMA_R, middle = REC601_LUMA_G, low = REC601_LUMA_B;
|
||||
if (order == COLOR_ORDER_BGR) {
|
||||
high = REC601_LUMA_B;
|
||||
low = REC601_LUMA_R;
|
||||
} else if (order == COLOR_ORDER_GRB) {
|
||||
high = REC601_LUMA_G;
|
||||
middle = REC601_LUMA_R;
|
||||
}
|
||||
// Each field value scaled to 0..255, then weighted
|
||||
for (unsigned i = 0; i != 32; i++) {
|
||||
this->high_[i] = high * esp_scale(i, 31);
|
||||
this->low_[i] = low * esp_scale(i, 31);
|
||||
}
|
||||
for (unsigned i = 0; i != 64; i++)
|
||||
this->middle_[i] = middle * esp_scale(i, 63);
|
||||
}
|
||||
|
||||
uint8_t operator()(uint16_t value) const {
|
||||
const uint32_t weighted = this->high_[value >> 11] + this->middle_[(value >> 5) & 0x3F] + this->low_[value & 0x1F];
|
||||
return ((weighted + 128u) >> 8) >= 128 ? 1 : 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Weighted contribution of each value of each field
|
||||
std::array<uint16_t, 32> high_{};
|
||||
std::array<uint16_t, 64> middle_{};
|
||||
std::array<uint16_t, 32> low_{};
|
||||
};
|
||||
|
||||
} // namespace esphome::display
|
||||
|
||||
@@ -36,7 +36,7 @@ void DutyCycleSensor::update() {
|
||||
const float total_time = float(now - this->last_update_);
|
||||
|
||||
const float value = (on_time * 100.0f) / total_time;
|
||||
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", this->get_name().c_str(), value);
|
||||
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", LOG_STR_ARG(this->get_log_name()), value);
|
||||
this->publish_state(value);
|
||||
}
|
||||
this->last_update_ = now;
|
||||
|
||||
@@ -23,18 +23,11 @@ DEPENDENCIES = ["uart"]
|
||||
|
||||
emontx_ns = cg.esphome_ns.namespace("emontx")
|
||||
EmonTx = emontx_ns.class_("EmonTx", cg.Component, uart.UARTDevice)
|
||||
LockOnReboot = emontx_ns.enum("LockOnReboot", is_class=True)
|
||||
|
||||
CONF_EMONTX_ID = "emontx_id"
|
||||
CONF_TAG_NAME = "tag_name"
|
||||
CONF_ON_JSON = "on_json"
|
||||
CONF_LOCK_ON_REBOOT = "lock_on_reboot"
|
||||
LOCK_ON_REBOOT_AUTO = "auto"
|
||||
LOCK_ON_REBOOT_MODES = {
|
||||
LOCK_ON_REBOOT_AUTO: LockOnReboot.LOCK_ON_REBOOT_AUTO,
|
||||
True: LockOnReboot.LOCK_ON_REBOOT_ALWAYS,
|
||||
False: LockOnReboot.LOCK_ON_REBOOT_NEVER,
|
||||
}
|
||||
|
||||
DOMAIN = "emontx"
|
||||
|
||||
@@ -66,9 +59,7 @@ CONFIG_SCHEMA = (
|
||||
cv.GenerateID(): cv.declare_id(EmonTx),
|
||||
cv.Optional(CONF_ON_JSON): _synchronous_automation_schema(),
|
||||
cv.Optional(CONF_ON_DATA): _synchronous_automation_schema(),
|
||||
cv.Optional(CONF_LOCK_ON_REBOOT, default=LOCK_ON_REBOOT_AUTO): cv.Any(
|
||||
cv.boolean, cv.one_of(LOCK_ON_REBOOT_AUTO, lower=True)
|
||||
),
|
||||
cv.Optional(CONF_LOCK_ON_REBOOT, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
@@ -144,11 +135,8 @@ async def to_code(config: ConfigType) -> None:
|
||||
await uart.register_uart_device(var, config)
|
||||
await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS)
|
||||
|
||||
lock = config[CONF_LOCK_ON_REBOOT]
|
||||
cg.add(var.set_lock_on_reboot(LOCK_ON_REBOOT_MODES[lock]))
|
||||
if lock == LOCK_ON_REBOOT_AUTO:
|
||||
# Locking depends on the firmware version the emonTx reports
|
||||
cg.add_define("USE_EMONTX_VERSION")
|
||||
if config[CONF_LOCK_ON_REBOOT]:
|
||||
cg.add(var.set_lock_on_reboot(True))
|
||||
|
||||
|
||||
# Action: emontx.send_command
|
||||
|
||||
@@ -1,91 +1,23 @@
|
||||
#include "emontx.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/components/json/json_util.h"
|
||||
|
||||
namespace esphome::emontx {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "emontx");
|
||||
|
||||
static constexpr uint32_t UNLOCK_ID = 0;
|
||||
// The emonTx joins bytes received while a command is pending into that command, so the next one waits
|
||||
static constexpr uint32_t COMMAND_GAP_MS = 250;
|
||||
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
static constexpr uint32_t VERSION_REQUEST_ID = 1;
|
||||
// Without a reply, 'v' is sent again every VERSION_RETRY_FRAMES data lines, VERSION_MAX_ATTEMPTS times in all
|
||||
static constexpr uint8_t VERSION_RETRY_FRAMES = 2;
|
||||
static constexpr uint8_t VERSION_MAX_ATTEMPTS = 3;
|
||||
// Line of the 'v' reply (and of the boot banner) carrying the release, e.g. " - Version: v1.1.1"
|
||||
static const char VERSION_PREFIX[] PROGMEM = " - Version:";
|
||||
// Every data line starts with the message counter, in JSON or text format
|
||||
static const char MSG_JSON_PREFIX[] PROGMEM = "{\"MSG\":";
|
||||
static const char MSG_TEXT_PREFIX[] PROGMEM = "MSG:";
|
||||
// First firmware with 'emonlock' and 'emonunlock'; older firmware takes them for the bootloader command
|
||||
static constexpr uint32_t LOCK_MIN_MAJOR = 1;
|
||||
static constexpr uint32_t LOCK_MIN_MINOR = 2;
|
||||
|
||||
// True if line starts with the PROGMEM prefix and has more after it
|
||||
static bool starts_with(const char *line, size_t len, const char *prefix, size_t prefix_len) {
|
||||
return len > prefix_len && ESPHOME_strncmp_P(line, prefix, prefix_len) == 0;
|
||||
}
|
||||
|
||||
// Reads the decimal number (up to 9 digits) at pos and moves pos past it; false if there is none
|
||||
static bool read_number(const char *&pos, const char *end, uint32_t &value) {
|
||||
const char *start = pos;
|
||||
value = 0;
|
||||
while (pos < end && pos - start < 9 && *pos >= '0' && *pos <= '9')
|
||||
value = value * 10 + (*pos++ - '0');
|
||||
return pos != start;
|
||||
}
|
||||
|
||||
// True for a release such as "v1.2.0" or "v1.3.0-rc1" from LOCK_MIN_MAJOR.LOCK_MIN_MINOR on
|
||||
static bool supports_lock(const char *version, const char *end) {
|
||||
if (version < end && (*version == 'v' || *version == 'V'))
|
||||
version++;
|
||||
uint32_t major;
|
||||
if (!read_number(version, end, major) || version == end || *version != '.')
|
||||
return false;
|
||||
version++;
|
||||
uint32_t minor;
|
||||
if (!read_number(version, end, minor))
|
||||
return false;
|
||||
return major > LOCK_MIN_MAJOR || (major == LOCK_MIN_MAJOR && minor >= LOCK_MIN_MINOR);
|
||||
}
|
||||
#endif
|
||||
|
||||
void EmonTx::setup() {
|
||||
this->buffer_pos_ = 0;
|
||||
if (this->lock_on_reboot_ == LockOnReboot::LOCK_ON_REBOOT_ALWAYS) {
|
||||
// The line feed ends any boot noise
|
||||
this->write_byte('\n');
|
||||
this->set_timeout(UNLOCK_ID, COMMAND_GAP_MS, [this]() {
|
||||
this->unlock_();
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
if (this->wants_version_())
|
||||
this->request_version_();
|
||||
#endif
|
||||
});
|
||||
if (!this->lock_on_reboot_)
|
||||
return;
|
||||
}
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
// With AUTO, the reply decides whether to unlock
|
||||
if (this->wants_version_())
|
||||
this->request_version_();
|
||||
#endif
|
||||
}
|
||||
|
||||
void EmonTx::unlock_() {
|
||||
ESP_LOGI(TAG, "Unlocking emonTx");
|
||||
// The line feed ends any boot noise first
|
||||
ESP_LOGI(TAG, "Unlocking emonTx after boot");
|
||||
this->write_byte('\n');
|
||||
this->send_command("emonunlock");
|
||||
}
|
||||
|
||||
void EmonTx::on_shutdown() {
|
||||
bool lock = this->lock_on_reboot_ == LockOnReboot::LOCK_ON_REBOOT_ALWAYS;
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
lock |= this->lock_on_reboot_ == LockOnReboot::LOCK_ON_REBOOT_AUTO && this->lock_supported_;
|
||||
#endif
|
||||
if (!lock)
|
||||
if (!this->lock_on_reboot_)
|
||||
return;
|
||||
if (this->is_paused()) {
|
||||
ESP_LOGW(TAG, "Not locking emonTx before shutdown, UART is paused");
|
||||
@@ -116,11 +48,6 @@ void EmonTx::loop() {
|
||||
uint8_t dropped;
|
||||
while (this->available() > 0 && this->read_byte(&dropped))
|
||||
this->discarding_line_ = dropped != '\n';
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
// The emonTx may have been flashed, or a request dropped, during the pause
|
||||
if (this->wants_version_())
|
||||
this->request_version_();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Read all available data to prevent UART buffer overflow
|
||||
@@ -150,12 +77,6 @@ void EmonTx::loop() {
|
||||
ESP_LOGV(TAG, "Line is JSON, parsing...");
|
||||
this->parse_json_(this->buffer_.data(), len);
|
||||
}
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
if (this->wants_version_()) {
|
||||
this->parse_msg_number_(this->buffer_.data(), len);
|
||||
this->parse_version_line_(this->buffer_.data(), len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (received == '\r' || this->discarding_line_) {
|
||||
// Ignore CR, and the rest of a line that overflowed or was interrupted by a pause
|
||||
@@ -191,91 +112,12 @@ void EmonTx::parse_json_(const char *data, size_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
void EmonTx::request_version_() {
|
||||
// The firmware may have changed; until the reply, an unknown version gets no lock commands
|
||||
this->lock_supported_ = false;
|
||||
this->version_frames_left_ = VERSION_RETRY_FRAMES * VERSION_MAX_ATTEMPTS;
|
||||
this->send_version_request_();
|
||||
}
|
||||
|
||||
// The line feed ends any pending input; the reply is picked up in loop() by parse_version_line_()
|
||||
void EmonTx::send_version_request_() {
|
||||
if (this->is_paused())
|
||||
return;
|
||||
this->write_byte('\n');
|
||||
this->set_timeout(VERSION_REQUEST_ID, COMMAND_GAP_MS, [this]() { this->send_command("v"); });
|
||||
}
|
||||
|
||||
void EmonTx::parse_msg_number_(const char *line, size_t len) {
|
||||
const char *pos;
|
||||
if (starts_with(line, len, MSG_JSON_PREFIX, sizeof(MSG_JSON_PREFIX) - 1)) {
|
||||
pos = line + sizeof(MSG_JSON_PREFIX) - 1;
|
||||
} else if (starts_with(line, len, MSG_TEXT_PREFIX, sizeof(MSG_TEXT_PREFIX) - 1)) {
|
||||
pos = line + sizeof(MSG_TEXT_PREFIX) - 1;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
uint32_t msg_number;
|
||||
if (!read_number(pos, line + len, msg_number))
|
||||
return;
|
||||
|
||||
// MSG restarts at 1 when the emonTx reboots, as it does after a firmware update
|
||||
if (msg_number <= this->last_msg_number_) {
|
||||
this->request_version_();
|
||||
} else if (this->version_frames_left_ > 0) {
|
||||
if (--this->version_frames_left_ == 0) {
|
||||
ESP_LOGW(TAG, "No firmware version from the emonTx, it may still be locked");
|
||||
} else if (this->version_frames_left_ % VERSION_RETRY_FRAMES == 0) {
|
||||
this->send_version_request_();
|
||||
}
|
||||
}
|
||||
this->last_msg_number_ = msg_number;
|
||||
}
|
||||
|
||||
void EmonTx::parse_version_line_(const char *line, size_t len) {
|
||||
constexpr size_t prefix_len = sizeof(VERSION_PREFIX) - 1;
|
||||
if (!starts_with(line, len, VERSION_PREFIX, prefix_len))
|
||||
return;
|
||||
const char *version = line + prefix_len;
|
||||
const char *end = line + len;
|
||||
while (version < end && *version == ' ')
|
||||
version++;
|
||||
if (version == end)
|
||||
return;
|
||||
ESP_LOGI(TAG, "emonTx firmware version: %.*s", static_cast<int>(end - version), version);
|
||||
this->version_frames_left_ = 0;
|
||||
#ifdef USE_EMONTX_VERSION_TEXT_SENSOR
|
||||
if (this->version_text_sensor_ != nullptr)
|
||||
this->version_text_sensor_->publish_state(version, end - version);
|
||||
#endif
|
||||
|
||||
bool supported = supports_lock(version, end);
|
||||
if (this->lock_on_reboot_ == LockOnReboot::LOCK_ON_REBOOT_AUTO && supported && !this->unlock_sent_) {
|
||||
// Once the rest of the reply has gone out; a pause drops it, and the version request on resume retries
|
||||
this->set_timeout(UNLOCK_ID, COMMAND_GAP_MS, [this]() {
|
||||
if (this->is_paused())
|
||||
return;
|
||||
this->unlock_();
|
||||
this->unlock_sent_ = true;
|
||||
});
|
||||
}
|
||||
this->lock_supported_ = supported;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Logs the EmonTx component configuration details.
|
||||
*/
|
||||
void EmonTx::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "EmonTx:");
|
||||
const char *lock = LOG_STR_LITERAL("no");
|
||||
if (this->lock_on_reboot_ == LockOnReboot::LOCK_ON_REBOOT_ALWAYS) {
|
||||
lock = LOG_STR_LITERAL("yes");
|
||||
} else if (this->lock_on_reboot_ == LockOnReboot::LOCK_ON_REBOOT_AUTO) {
|
||||
lock = LOG_STR_LITERAL("auto");
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Lock on reboot: %s", lock);
|
||||
ESP_LOGCONFIG(TAG, " Lock on reboot: %s", YESNO(this->lock_on_reboot_));
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
ESP_LOGCONFIG(TAG, " Registered sensors: %zu", this->sensors_.size());
|
||||
@@ -285,9 +127,6 @@ void EmonTx::dump_config() {
|
||||
#else
|
||||
ESP_LOGCONFIG(TAG, " Sensor support: DISABLED");
|
||||
#endif
|
||||
#ifdef USE_EMONTX_VERSION_TEXT_SENSOR
|
||||
LOG_TEXT_SENSOR(" ", "Firmware version", this->version_text_sensor_);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,21 +13,12 @@
|
||||
#ifdef USE_SENSOR
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#endif
|
||||
#ifdef USE_EMONTX_VERSION_TEXT_SENSOR
|
||||
#include "esphome/components/text_sensor/text_sensor.h"
|
||||
#endif
|
||||
|
||||
namespace esphome::emontx {
|
||||
|
||||
/// Maximum line length in bytes (plus one byte reserved for null terminator)
|
||||
static constexpr size_t MAX_LINE_LENGTH = 1024;
|
||||
|
||||
enum class LockOnReboot : uint8_t {
|
||||
LOCK_ON_REBOOT_NEVER,
|
||||
LOCK_ON_REBOOT_ALWAYS,
|
||||
LOCK_ON_REBOOT_AUTO, // Only when the emonTx reports firmware v1.2.0 or later
|
||||
};
|
||||
|
||||
/**
|
||||
* @class EmonTx
|
||||
* @brief Main class for the EmonTx component.
|
||||
@@ -36,9 +27,6 @@ enum class LockOnReboot : uint8_t {
|
||||
* extracts tags and values, and publishes them to registered sensors.
|
||||
*/
|
||||
class EmonTx final : public Component, public uart::UARTDevice {
|
||||
#ifdef USE_EMONTX_VERSION_TEXT_SENSOR
|
||||
SUB_TEXT_SENSOR(version)
|
||||
#endif
|
||||
public:
|
||||
EmonTx() = default;
|
||||
|
||||
@@ -62,8 +50,8 @@ class EmonTx final : public Component, public uart::UARTDevice {
|
||||
bool is_paused() const { return this->paused_.load(std::memory_order_relaxed); }
|
||||
|
||||
/// Lock the emonTx ('emonlock') before a reboot, so serial garbage during the reboot is not taken
|
||||
/// as a command, and unlock it after boot. Needs emonTx firmware v1.2.0 or later, which AUTO checks.
|
||||
void set_lock_on_reboot(LockOnReboot lock_on_reboot) { this->lock_on_reboot_ = lock_on_reboot; }
|
||||
/// as a command, and unlock it in setup(). Needs emonTx firmware v1.2.0 or later.
|
||||
void set_lock_on_reboot(bool lock_on_reboot) { this->lock_on_reboot_ = lock_on_reboot; }
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
void init_sensors(size_t count) { this->sensors_.init(count); }
|
||||
@@ -72,20 +60,6 @@ class EmonTx final : public Component, public uart::UARTDevice {
|
||||
|
||||
protected:
|
||||
void parse_json_(const char *data, size_t len);
|
||||
void unlock_();
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
bool wants_version_() const {
|
||||
#ifdef USE_EMONTX_VERSION_TEXT_SENSOR
|
||||
if (this->version_text_sensor_ != nullptr)
|
||||
return true;
|
||||
#endif
|
||||
return this->lock_on_reboot_ == LockOnReboot::LOCK_ON_REBOOT_AUTO;
|
||||
}
|
||||
void request_version_();
|
||||
void send_version_request_();
|
||||
void parse_msg_number_(const char *line, size_t len);
|
||||
void parse_version_line_(const char *line, size_t len);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
FixedVector<std::pair<const char *, sensor::Sensor *>> sensors_{};
|
||||
@@ -95,14 +69,8 @@ class EmonTx final : public Component, public uart::UARTDevice {
|
||||
uint16_t buffer_pos_{0};
|
||||
std::atomic<bool> paused_{false};
|
||||
bool was_paused_{false};
|
||||
LockOnReboot lock_on_reboot_{LockOnReboot::LOCK_ON_REBOOT_NEVER};
|
||||
bool lock_on_reboot_{false};
|
||||
bool discarding_line_{false}; // Set after an overflow or a pause until the end of that line
|
||||
#ifdef USE_EMONTX_VERSION
|
||||
bool lock_supported_{false}; // The last version reported is v1.2.0 or later
|
||||
bool unlock_sent_{false}; // AUTO has sent 'emonunlock' since boot
|
||||
uint8_t version_frames_left_{0}; // Data lines still to wait for a version reply; 0 when none is owed
|
||||
uint32_t last_msg_number_{0};
|
||||
#endif
|
||||
std::array<char, MAX_LINE_LENGTH + 1> buffer_{};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import text_sensor
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_VERSION, ENTITY_CATEGORY_DIAGNOSTIC, ICON_CHIP
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .. import CONF_EMONTX_ID, EmonTx
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_EMONTX_ID): cv.use_id(EmonTx),
|
||||
cv.Optional(CONF_VERSION): text_sensor.text_sensor_schema(
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon=ICON_CHIP
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
hub = await cg.get_variable(config[CONF_EMONTX_ID])
|
||||
text_sensors = text_sensor.sub_text_sensors(config)
|
||||
if await text_sensors(CONF_VERSION, hub.set_version_text_sensor) is not None:
|
||||
cg.add_define("USE_EMONTX_VERSION")
|
||||
cg.add_define("USE_EMONTX_VERSION_TEXT_SENSOR")
|
||||
@@ -70,20 +70,20 @@ void EndstopCover::loop() {
|
||||
|
||||
if (this->current_operation == COVER_OPERATION_OPENING && this->is_open_()) {
|
||||
float dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->position = COVER_OPEN;
|
||||
this->publish_state();
|
||||
} else if (this->current_operation == COVER_OPERATION_CLOSING && this->is_closed_()) {
|
||||
float dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->position = COVER_CLOSED;
|
||||
this->publish_state();
|
||||
} else if (now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include "esphome/components/display/display_color_utils.h"
|
||||
#include "esphome/core/color.h"
|
||||
|
||||
/* Utility for converting internal \a Color RGB representation to supported IC hardware color keys
|
||||
@@ -14,15 +13,21 @@
|
||||
|
||||
namespace esphome::epaper_spi {
|
||||
|
||||
// The Rec.601 luma helpers and the RGB565 mono lookup live in the shared display utilities, so other
|
||||
// drivers (e.g. it8951 in its 1 bit per pixel mode) can use them too.
|
||||
using display::color_to_mono;
|
||||
using display::rec601_luma;
|
||||
using display::Rgb565ToMono;
|
||||
|
||||
/** Delta for when to regard as gray */
|
||||
static constexpr uint8_t COLORCONV_GRAY_THRESHOLD = 50;
|
||||
|
||||
/** Rec.601 luma (0.299/0.587/0.114 weights, scaled by 256) for optimum perceptual brightness */
|
||||
constexpr uint8_t rec601_luma(Color color) {
|
||||
return (uint8_t) ((77u * color.r + 150u * color.g + 29u * color.b + 128u) >> 8);
|
||||
}
|
||||
|
||||
/** Map RGB color to a single monochrome bit
|
||||
*
|
||||
* @param color RGB color to convert from
|
||||
* @return 1 = white, 0 = black
|
||||
*/
|
||||
constexpr uint8_t color_to_mono(Color color) { return rec601_luma(color) >= 128 ? 1 : 0; }
|
||||
|
||||
/** Map RGB color to one of 4 discrete gray levels (2 bits per pixel)
|
||||
*
|
||||
* @param color RGB color to convert from
|
||||
|
||||
@@ -131,7 +131,9 @@ void EPaperBase::update() {
|
||||
}
|
||||
|
||||
void EPaperBase::wait_for_idle_(bool should_wait) {
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
this->waiting_for_idle_start_ = millis();
|
||||
#endif
|
||||
this->waiting_for_idle_ = should_wait;
|
||||
}
|
||||
|
||||
@@ -154,10 +156,6 @@ void EPaperBase::loop() {
|
||||
ESP_LOGV(TAG, "Screen was busy for %u ms", (unsigned) (millis() - this->waiting_for_idle_start_));
|
||||
#endif
|
||||
} else {
|
||||
if (now - this->waiting_for_idle_start_ > this->busy_timeout_seconds_ * 1000u) {
|
||||
this->abandon_update_();
|
||||
return;
|
||||
}
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
if (now - this->waiting_for_idle_last_print_ >= 1000) {
|
||||
ESP_LOGV(TAG, "Waiting for idle in state %s", this->epaper_state_to_string_());
|
||||
@@ -170,20 +168,6 @@ void EPaperBase::loop() {
|
||||
this->process_state_();
|
||||
}
|
||||
|
||||
// The busy pin never cleared: give up on this update so later ones are not refused, and make the next one full
|
||||
void EPaperBase::abandon_update_() {
|
||||
ESP_LOGE(TAG, "Display stayed busy for %u s in state %s; check the busy pin", (unsigned) this->busy_timeout_seconds_,
|
||||
this->epaper_state_to_string_());
|
||||
this->status_set_warning(LOG_STR("Busy pin timeout"));
|
||||
if (this->state_ == EPaperState::TRANSFER_DATA)
|
||||
this->abort_transfer();
|
||||
// Leave the panel powered down rather than with its high-voltage drivers enabled
|
||||
this->power_off();
|
||||
this->full_update_requested_ = true;
|
||||
this->current_data_index_ = 0;
|
||||
this->set_state_(EPaperState::IDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the state machine.
|
||||
* Typical state sequence:
|
||||
@@ -258,7 +242,6 @@ void EPaperBase::process_state_() {
|
||||
break;
|
||||
case EPaperState::DEEP_SLEEP:
|
||||
this->deep_sleep();
|
||||
this->status_clear_warning();
|
||||
this->set_state_(EPaperState::IDLE);
|
||||
ESP_LOGD(TAG, "Display update took %" PRIu32 " ms", millis() - this->update_start_time_);
|
||||
break;
|
||||
@@ -362,120 +345,6 @@ void HOT EPaperBase::draw_pixel_at(int x, int y, Color color) {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// One source row of an RGB565 block, written into a contiguous 1 bit per pixel buffer. Without SwapAxes the row lies
|
||||
// along a buffer row and the bit moves by step; with it the row lies along a bit column and the byte moves by step
|
||||
// rows.
|
||||
template<bool SwapAxes, bool BigEndianSource>
|
||||
void HOT write_rgb565_row(uint8_t *byte, uint8_t mask, int step, size_t row_width, const uint8_t *source, int count,
|
||||
const Rgb565ToMono &to_mono) {
|
||||
const ptrdiff_t byte_step = SwapAxes ? step * static_cast<ptrdiff_t>(row_width) : 0;
|
||||
for (; count != 0; count--, source += 2) {
|
||||
const uint16_t value = BigEndianSource ? (source[0] << 8) | source[1] : source[0] | (source[1] << 8);
|
||||
if (to_mono(value)) {
|
||||
*byte |= mask;
|
||||
} else {
|
||||
*byte &= ~mask;
|
||||
}
|
||||
if constexpr (SwapAxes) {
|
||||
byte += byte_step;
|
||||
} else if (step > 0) {
|
||||
mask >>= 1;
|
||||
if (mask == 0) {
|
||||
mask = 0x80;
|
||||
byte++;
|
||||
}
|
||||
} else {
|
||||
mask <<= 1;
|
||||
if (mask == 0) {
|
||||
mask = 0x01;
|
||||
byte--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Each source column maps to one buffer coordinate and each source row to the other, each moving by 1 per pixel, so
|
||||
// the visible part of a block and its dirty area are worked out once for the whole block.
|
||||
void HOT EPaperBase::draw_rgb565_block_(uint8_t *buffer, int x_start, int y_start, int w, int h, const uint8_t *ptr,
|
||||
ColorOrder order, bool big_endian, int x_offset, int y_offset, int x_pad) {
|
||||
const bool swap = this->effective_transform_ & SWAP_XY;
|
||||
const bool mirror_x = this->effective_transform_ & MIRROR_X;
|
||||
const bool mirror_y = this->effective_transform_ & MIRROR_Y;
|
||||
// The buffer axis a source column moves along, and the one a source row moves along
|
||||
const int column_limit = swap ? this->height_ : this->width_;
|
||||
const int row_limit = swap ? this->width_ : this->height_;
|
||||
const bool column_mirrored = swap ? mirror_y : mirror_x;
|
||||
const bool row_mirrored = swap ? mirror_x : mirror_y;
|
||||
const int first_column = std::max(0, -x_start);
|
||||
const int end_column = std::min(w, column_limit - x_start);
|
||||
const int first_row = std::max(0, -y_start);
|
||||
const int end_row = std::min(h, row_limit - y_start);
|
||||
if (first_column >= end_column || first_row >= end_row)
|
||||
return;
|
||||
auto column_to_buffer = [&](int column) {
|
||||
const int u = x_start + column;
|
||||
return column_mirrored ? column_limit - 1 - u : u;
|
||||
};
|
||||
auto row_to_buffer = [&](int row) {
|
||||
const int v = y_start + row;
|
||||
return row_mirrored ? row_limit - 1 - v : v;
|
||||
};
|
||||
|
||||
const int column_low = std::min(column_to_buffer(first_column), column_to_buffer(end_column - 1));
|
||||
const int row_low = std::min(row_to_buffer(first_row), row_to_buffer(end_row - 1));
|
||||
const int columns = end_column - first_column;
|
||||
const int rows = end_row - first_row;
|
||||
const int x_low = swap ? row_low : column_low;
|
||||
const int y_low = swap ? column_low : row_low;
|
||||
const int x_high = x_low + (swap ? rows : columns);
|
||||
const int y_high = y_low + (swap ? columns : rows);
|
||||
|
||||
const Rgb565ToMono to_mono(order);
|
||||
const size_t line_stride = x_offset + w + x_pad;
|
||||
const size_t row_width = this->row_width_;
|
||||
const int step = column_mirrored ? -1 : 1;
|
||||
for (int row = first_row; row != end_row; row++) {
|
||||
const uint8_t *source = ptr + ((y_offset + row) * line_stride + x_offset + first_column) * 2;
|
||||
const int along = column_to_buffer(first_column);
|
||||
const int across = row_to_buffer(row);
|
||||
const int x = swap ? across : along;
|
||||
const int y = swap ? along : across;
|
||||
uint8_t *byte = buffer + y * row_width + x / 8;
|
||||
const uint8_t mask = 0x80u >> (x % 8);
|
||||
if (swap) {
|
||||
if (big_endian) {
|
||||
write_rgb565_row<true, true>(byte, mask, step, row_width, source, columns, to_mono);
|
||||
} else {
|
||||
write_rgb565_row<true, false>(byte, mask, step, row_width, source, columns, to_mono);
|
||||
}
|
||||
} else if (big_endian) {
|
||||
write_rgb565_row<false, true>(byte, mask, step, row_width, source, columns, to_mono);
|
||||
} else {
|
||||
write_rgb565_row<false, false>(byte, mask, step, row_width, source, columns, to_mono);
|
||||
}
|
||||
}
|
||||
this->x_low_ = clamp_at_most(this->x_low_, x_low);
|
||||
this->x_high_ = clamp_at_least(this->x_high_, x_high);
|
||||
this->y_low_ = clamp_at_most(this->y_low_, y_low);
|
||||
this->y_high_ = clamp_at_least(this->y_high_, y_high);
|
||||
}
|
||||
|
||||
// Writes an RGB565 block of pixels, as LVGL sends them, straight into a 1 bit per pixel buffer that is one block (the
|
||||
// usual case): the same result as draw_pixel_at() for each pixel. Anything else goes through draw_pixel_at().
|
||||
void HOT EPaperBase::draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
|
||||
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) {
|
||||
size_t contiguous_length;
|
||||
uint8_t *contiguous = this->buffer_.get_span(0, contiguous_length);
|
||||
if (!this->buffer_is_mono() || this->get_clipping().is_set() || bitness != COLOR_BITNESS_565 ||
|
||||
contiguous_length != this->buffer_length_) {
|
||||
Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad);
|
||||
return;
|
||||
}
|
||||
this->draw_rgb565_block_(contiguous, x_start, y_start, w, h, ptr, order, big_endian, x_offset, y_offset, x_pad);
|
||||
}
|
||||
|
||||
void EPaperBase::dump_config() {
|
||||
LOG_DISPLAY("", "E-Paper SPI", this);
|
||||
ESP_LOGCONFIG(TAG,
|
||||
|
||||
@@ -107,8 +107,6 @@ class EPaperBase : public Display,
|
||||
int get_width() override { return this->effective_transform_ & SWAP_XY ? this->height_ : this->width_; }
|
||||
int get_height() override { return this->effective_transform_ & SWAP_XY ? this->width_ : this->height_; }
|
||||
void draw_pixel_at(int x, int y, Color color) override;
|
||||
void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
|
||||
ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override;
|
||||
// Make the next update a full one. Applied when that update starts, so one in progress is not affected.
|
||||
void request_full_update() { this->full_update_requested_ = true; }
|
||||
// True from the start of an update until the display has refreshed and gone back to sleep.
|
||||
@@ -127,14 +125,9 @@ class EPaperBase : public Display,
|
||||
virtual bool initialise(bool partial);
|
||||
void send_init_sequence_(const uint8_t *sequence, size_t length);
|
||||
void wait_for_idle_(bool should_wait);
|
||||
void abandon_update_();
|
||||
bool init_buffer_(size_t buffer_length);
|
||||
void update_effective_transform_();
|
||||
bool rotate_coordinates_(int &x, int &y);
|
||||
void draw_rgb565_block_(uint8_t *buffer, int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order,
|
||||
bool big_endian, int x_offset, int y_offset, int x_pad);
|
||||
// Whether the buffer holds 1 bit per pixel as draw_pixel_at() writes it, so draw_pixels_at() can write it directly
|
||||
virtual bool buffer_is_mono() const { return false; }
|
||||
|
||||
/**
|
||||
* Methods that must be implemented by concrete classes to control the display
|
||||
@@ -144,8 +137,6 @@ class EPaperBase : public Display,
|
||||
* @return true if done, false if it should be called next loop
|
||||
*/
|
||||
virtual bool transfer_data() = 0;
|
||||
// Called when an update is abandoned in the middle of transfer_data(), to release anything it left open
|
||||
virtual void abort_transfer() {}
|
||||
/**
|
||||
* Refresh the screen after data transfer
|
||||
*/
|
||||
@@ -196,20 +187,18 @@ class EPaperBase : public Display,
|
||||
// point to the pixel past the last one updated, i.e. may range up to width/height.
|
||||
uint16_t x_low_{}, y_low_{}, x_high_{}, y_high_{};
|
||||
|
||||
uint32_t waiting_for_idle_start_{};
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
uint32_t waiting_for_idle_last_print_{};
|
||||
uint32_t waiting_for_idle_start_{};
|
||||
#endif
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG
|
||||
uint32_t update_start_time_{};
|
||||
#endif
|
||||
|
||||
// properties with specific initialisers go last
|
||||
uint32_t reset_duration_{10};
|
||||
// Longer than any panel takes to refresh; past it the busy pin is assumed stuck
|
||||
uint16_t busy_timeout_seconds_{120};
|
||||
uint8_t full_update_every_{1};
|
||||
EPaperState state_{EPaperState::IDLE};
|
||||
uint32_t reset_duration_{10};
|
||||
uint8_t full_update_every_{1};
|
||||
};
|
||||
|
||||
} // namespace esphome::epaper_spi
|
||||
|
||||
@@ -15,7 +15,6 @@ class EPaperMono : public EPaperBase {
|
||||
}
|
||||
|
||||
protected:
|
||||
bool buffer_is_mono() const override { return true; }
|
||||
void refresh_screen(bool partial) override;
|
||||
void power_on() override {}
|
||||
void power_off() override{};
|
||||
|
||||
@@ -58,9 +58,7 @@ bool HOT EPaperSSD1677::transfer_data() {
|
||||
// A full update ignores 0x26, and the copy may not hold a real frame yet (first update after
|
||||
// boot): send the new frame to both planes.
|
||||
const bool send_copy = this->plane_ == 0 && this->update_count_ != 0;
|
||||
// A mono buffer already holds the frame as a RAM plane does, so it can be sent as it is; a deeper
|
||||
// buffer (the four-level model) returns false and packs the plane in plane_row().
|
||||
const bool direct = send_copy || this->buffer_is_mono();
|
||||
const bool direct = send_copy || this->buffer_is_plane();
|
||||
const auto &source = send_copy ? this->sent_ : this->buffer_;
|
||||
const size_t row_length = this->plane_row_length_();
|
||||
const size_t plane_length = row_length * this->height_;
|
||||
|
||||
@@ -34,6 +34,9 @@ class EPaperSSD1677 : public EPaperMono {
|
||||
void init_comparison_frame_();
|
||||
// Bytes in one row of a RAM plane: 8 pixels per byte, whatever the buffer holds.
|
||||
size_t plane_row_length_() const { return (this->width_ + 7) / 8; }
|
||||
// Whether the buffer already holds the frame as a RAM plane does, so it can be sent as it is.
|
||||
// A subclass with a deeper buffer returns false and overrides plane_row().
|
||||
virtual bool buffer_is_plane() const { return true; }
|
||||
// Row y of the frame as a RAM plane holds it, 1 bit per pixel with 1 = white.
|
||||
virtual void plane_row(size_t y, uint8_t *out);
|
||||
bool reset() override;
|
||||
|
||||
@@ -38,9 +38,9 @@ class EPaperSSD1677Gray4 : public EPaperSSD1677 {
|
||||
void draw_pixel_at(int x, int y, Color color) override;
|
||||
|
||||
protected:
|
||||
bool buffer_is_mono() const override { return false; }
|
||||
// A partial update if partial updates are enabled and this is not a full one.
|
||||
bool is_partial_push_() const { return this->update_count_ != 0 && this->sent_.is_valid(); }
|
||||
bool buffer_is_plane() const override { return false; }
|
||||
void plane_row(size_t y, uint8_t *out) override;
|
||||
void refresh_screen(bool partial) override;
|
||||
bool transfer_data() override;
|
||||
|
||||
@@ -364,15 +364,6 @@ bool HOT EPaperT133A01::transfer_data() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void EPaperT133A01::abort_transfer() {
|
||||
// A data stream is open, with one of the chip selects held low, whenever transfer_data() has started sending rows
|
||||
if (this->current_data_index_ == 0)
|
||||
return;
|
||||
this->disable();
|
||||
this->cs_pin_->digital_write(true);
|
||||
this->cs1_pin_->digital_write(true);
|
||||
}
|
||||
|
||||
void EPaperT133A01::dump_config() {
|
||||
EPaperBase::dump_config();
|
||||
LOG_PIN(" CS Pin: ", this->cs_pin_);
|
||||
|
||||
@@ -46,7 +46,6 @@ class EPaperT133A01 : public EPaperBase {
|
||||
void deep_sleep() override;
|
||||
|
||||
bool transfer_data() override;
|
||||
void abort_transfer() override;
|
||||
|
||||
/**
|
||||
* Send a command (and optional data) selecting one or both controllers.
|
||||
|
||||
@@ -37,7 +37,6 @@ class EPaperUC8179 final : public EPaperBase {
|
||||
}
|
||||
|
||||
protected:
|
||||
bool buffer_is_mono() const override { return true; }
|
||||
bool initialise(bool partial) override;
|
||||
bool transfer_data() override;
|
||||
void refresh_screen(bool partial) override;
|
||||
|
||||
@@ -87,38 +87,6 @@ jd79660.extend(
|
||||
),
|
||||
)
|
||||
|
||||
# Waveshare 2.13-G (V2 hardware/init revision, PCB marked "rev 2.1" or later)
|
||||
#
|
||||
# Vendor init derived from vendor sample code
|
||||
# <https://github.com/waveshareteam/e-Paper/blob/master/E-paper_Separate_Program/2in13_e-Paper_G/ESP32/EPD_2in13g_V2.cpp>
|
||||
# Compatible MIT license, see esphome/LICENSE file.
|
||||
#
|
||||
# Note: busy pin uses LOW=busy, HIGH=idle. Configure with inverted: true in YAML.
|
||||
# Note: panel is 122px wide, but vendor code declares the TRES register as a fixed
|
||||
# 124 on this revision. width=124 is declared here (rather than 122) purely so the
|
||||
# transferred bytes-per-row matches what the vendor init tells the IC to expect; the
|
||||
# extra 2 columns fall outside the visible glass. The model width must equal the
|
||||
# TRES value in initsequence, so overriding dimensions: in YAML brings the shear back.
|
||||
#
|
||||
# fmt: off
|
||||
jd79660.extend(
|
||||
"Waveshare-2.13in-G",
|
||||
width=124,
|
||||
height=250,
|
||||
|
||||
initsequence=(
|
||||
(0x61, 0x00, 0x7C, 0x00, 0xFA,), # TRES: 124x250 fixed (124 = TRES stride value)
|
||||
(0xE9, 0x01,),
|
||||
# Power On (0x04): Must be early part of init seq = Disabled later!
|
||||
(0x04,),
|
||||
),
|
||||
fast_update=(
|
||||
(0xE0, 0x02,),
|
||||
(0xE6, 0x5A,),
|
||||
(0xA5,),
|
||||
),
|
||||
)
|
||||
|
||||
# Waveshare 7.5-H
|
||||
#
|
||||
# Vendor init derived from vendor sample code
|
||||
@@ -162,7 +130,7 @@ jd79660.extend(
|
||||
# Note: busy pin uses LOW=busy, HIGH=idle.
|
||||
#
|
||||
# fmt: off
|
||||
gdey0213f51 = jd79660.extend(
|
||||
jd79660.extend(
|
||||
"goodisplay-gdey0213f51-2.13",
|
||||
width=128,
|
||||
height=250,
|
||||
@@ -186,13 +154,3 @@ gdey0213f51 = jd79660.extend(
|
||||
(0x04,),
|
||||
),
|
||||
)
|
||||
|
||||
# Waveshare 2.13-G (V1 hardware/init revision, older stock): the same panel and init as the Good
|
||||
# Display entry above, byte for byte, so it only adds the name. Vendor sample:
|
||||
# <https://github.com/waveshareteam/e-Paper/blob/master/E-paper_Separate_Program/2in13_e-Paper_G/ESP32/EPD_2in13g.cpp>
|
||||
# Compatible MIT license, see esphome/LICENSE file.
|
||||
#
|
||||
# Note: busy pin uses LOW=busy, HIGH=idle. Configure with inverted: true in YAML.
|
||||
# Note: width=128 is the TRES value the init sequence programs, not the 122 visible columns; overriding
|
||||
# dimensions: in YAML shears the image. Not tested on V1 hardware.
|
||||
gdey0213f51.extend("Waveshare-2.13in-G-V1")
|
||||
|
||||
@@ -24,11 +24,3 @@ WaveshareB(
|
||||
data_rate="10MHz",
|
||||
minimum_update_interval="1s",
|
||||
)
|
||||
|
||||
WaveshareB(
|
||||
"waveshare-2.66in-b",
|
||||
width=152,
|
||||
height=296,
|
||||
data_rate="10MHz",
|
||||
minimum_update_interval="15s",
|
||||
)
|
||||
|
||||
@@ -111,36 +111,24 @@ void ES8388::setup() {
|
||||
// Power on ADC, Enable LIN&RIN, Power off MICBIAS, set int1lp to low power mode
|
||||
ES8388_ERROR_FAILED(this->write_byte(ES8388_ADCPOWER, 0x09));
|
||||
|
||||
#ifdef USE_ES8388_SELECT
|
||||
#ifdef USE_SELECT
|
||||
if (this->dac_output_select_ != nullptr) {
|
||||
if (this->dac_output_initial_.has_value()) {
|
||||
const DacOutputLine line = this->dac_output_initial_.value();
|
||||
ES8388_ERROR_FAILED(this->set_dac_output(line));
|
||||
this->dac_output_select_->publish_state(static_cast<size_t>(line));
|
||||
} else {
|
||||
auto dac_power = this->get_dac_power();
|
||||
if (dac_power.has_value()) {
|
||||
if (this->dac_output_select_->has_index(dac_power.value())) {
|
||||
this->dac_output_select_->publish_state(dac_power.value());
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown DAC output power value: %d", dac_power.value());
|
||||
}
|
||||
auto dac_power = this->get_dac_power();
|
||||
if (dac_power.has_value()) {
|
||||
if (this->dac_output_select_->has_index(dac_power.value())) {
|
||||
this->dac_output_select_->publish_state(dac_power.value());
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown DAC output power value: %d", dac_power.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this->adc_input_mic_select_ != nullptr) {
|
||||
if (this->adc_input_mic_initial_.has_value()) {
|
||||
const AdcInputMicLine line = this->adc_input_mic_initial_.value();
|
||||
ES8388_ERROR_FAILED(this->set_adc_input_mic(line));
|
||||
this->adc_input_mic_select_->publish_state(static_cast<size_t>(line));
|
||||
} else {
|
||||
auto mic_input = this->get_mic_input();
|
||||
if (mic_input.has_value()) {
|
||||
if (this->adc_input_mic_select_->has_index(mic_input.value())) {
|
||||
this->adc_input_mic_select_->publish_state(mic_input.value());
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown ADC input mic value: %d", mic_input.value());
|
||||
}
|
||||
auto mic_input = this->get_mic_input();
|
||||
if (mic_input.has_value()) {
|
||||
if (this->adc_input_mic_select_->has_index(mic_input.value())) {
|
||||
this->adc_input_mic_select_->publish_state(mic_input.value());
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown ADC input mic value: %d", mic_input.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +138,7 @@ void ES8388::setup() {
|
||||
void ES8388::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "ES8388 Audio Codec:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
#ifdef USE_ES8388_SELECT
|
||||
#ifdef USE_SELECT
|
||||
LOG_SELECT(" ", "DacOutputSelect", this->dac_output_select_);
|
||||
LOG_SELECT(" ", "ADCInputMicSelect", this->adc_input_mic_select_);
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "esphome/components/audio_dac/audio_dac.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/component.h"
|
||||
#ifdef USE_ES8388_SELECT
|
||||
#ifdef USE_SELECT
|
||||
#include "esphome/components/select/select.h"
|
||||
#endif
|
||||
|
||||
@@ -26,7 +26,7 @@ enum AdcInputMicLine : uint8_t {
|
||||
};
|
||||
|
||||
class ES8388 final : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
|
||||
#ifdef USE_ES8388_SELECT
|
||||
#ifdef USE_SELECT
|
||||
SUB_SELECT(dac_output)
|
||||
SUB_SELECT(adc_input_mic)
|
||||
#endif
|
||||
@@ -68,22 +68,11 @@ class ES8388 final : public audio_dac::AudioDac, public Component, public i2c::I
|
||||
bool set_dac_output(DacOutputLine line);
|
||||
bool set_adc_input_mic(AdcInputMicLine line);
|
||||
|
||||
#ifdef USE_ES8388_SELECT
|
||||
/// Line to apply in setup() instead of keeping what the codec reports.
|
||||
void set_dac_output_initial(DacOutputLine line) { this->dac_output_initial_ = line; }
|
||||
void set_adc_input_mic_initial(AdcInputMicLine line) { this->adc_input_mic_initial_ = line; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/// @brief Mutes or unmutes the DAC audio out
|
||||
/// @param mute_state True to mute, false to unmute
|
||||
/// @return True if successful and false otherwise
|
||||
bool set_mute_state_(bool mute_state);
|
||||
|
||||
#ifdef USE_ES8388_SELECT
|
||||
optional<DacOutputLine> dac_output_initial_{};
|
||||
optional<AdcInputMicLine> adc_input_mic_initial_{};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace esphome::es8388
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import select
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_INITIAL_OPTION,
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
ICON_CHIP, # noqa: F401
|
||||
)
|
||||
from esphome.const import ENTITY_CATEGORY_CONFIG, ICON_CHIP # noqa: F401
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from ..audio_dac import CONF_ES8388_ID, ES8388, es8388_ns
|
||||
@@ -13,21 +9,6 @@ from ..audio_dac import CONF_ES8388_ID, ES8388, es8388_ns
|
||||
CONF_DAC_OUTPUT = "dac_output"
|
||||
CONF_ADC_INPUT_MIC = "adc_input_mic"
|
||||
|
||||
DacOutputLine = es8388_ns.enum("DacOutputLine")
|
||||
DAC_OUTPUT_OPTIONS = {
|
||||
"LINE1": DacOutputLine.DAC_OUTPUT_LINE1,
|
||||
"LINE2": DacOutputLine.DAC_OUTPUT_LINE2,
|
||||
"BOTH": DacOutputLine.DAC_OUTPUT_BOTH,
|
||||
}
|
||||
DAC_OUTPUT_OPTION_NAMES = list(DAC_OUTPUT_OPTIONS)
|
||||
AdcInputMicLine = es8388_ns.enum("AdcInputMicLine")
|
||||
ADC_INPUT_MIC_OPTIONS = {
|
||||
"LINE1": AdcInputMicLine.ADC_INPUT_MIC_LINE1,
|
||||
"LINE2": AdcInputMicLine.ADC_INPUT_MIC_LINE2,
|
||||
"DIFFERENCE": AdcInputMicLine.ADC_INPUT_MIC_DIFFERENCE,
|
||||
}
|
||||
ADC_INPUT_MIC_OPTION_NAMES = list(ADC_INPUT_MIC_OPTIONS)
|
||||
|
||||
DacOutputSelect = es8388_ns.class_("DacOutputSelect", select.Select)
|
||||
ADCInputMicSelect = es8388_ns.class_("ADCInputMicSelect", select.Select)
|
||||
|
||||
@@ -38,45 +19,24 @@ CONFIG_SCHEMA = cv.All(
|
||||
DacOutputSelect,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
icon=ICON_CHIP,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_INITIAL_OPTION): cv.enum(
|
||||
DAC_OUTPUT_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ADC_INPUT_MIC): select.select_schema(
|
||||
ADCInputMicSelect,
|
||||
entity_category=ENTITY_CATEGORY_CONFIG,
|
||||
icon=ICON_CHIP,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_INITIAL_OPTION): cv.enum(
|
||||
ADC_INPUT_MIC_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
cg.add_define("USE_ES8388_SELECT")
|
||||
hub = await cg.get_variable(config[CONF_ES8388_ID])
|
||||
selects = select.sub_selects(config, parent=hub)
|
||||
await selects(
|
||||
CONF_DAC_OUTPUT, hub.set_dac_output_select, options=DAC_OUTPUT_OPTION_NAMES
|
||||
CONF_DAC_OUTPUT, hub.set_dac_output_select, options=["LINE1", "LINE2", "BOTH"]
|
||||
)
|
||||
await selects(
|
||||
CONF_ADC_INPUT_MIC,
|
||||
hub.set_adc_input_mic_select,
|
||||
options=ADC_INPUT_MIC_OPTION_NAMES,
|
||||
options=["LINE1", "LINE2", "DIFFERENCE"],
|
||||
)
|
||||
if (
|
||||
initial := config.get(CONF_DAC_OUTPUT, {}).get(CONF_INITIAL_OPTION)
|
||||
) is not None:
|
||||
cg.add(hub.set_dac_output_initial(initial))
|
||||
if (
|
||||
initial := config.get(CONF_ADC_INPUT_MIC, {}).get(CONF_INITIAL_OPTION)
|
||||
) is not None:
|
||||
cg.add(hub.set_adc_input_mic_initial(initial))
|
||||
|
||||
@@ -132,9 +132,9 @@ void ESP32Camera::dump_config() {
|
||||
" External Clock: Pin:%d Frequency:%u\n"
|
||||
" I2C Pins: SDA:%d SCL:%d\n"
|
||||
" Reset Pin: %d",
|
||||
this->name_.c_str(), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2, conf.pin_d3,
|
||||
conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href, conf.pin_pclk,
|
||||
conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
|
||||
LOG_STR_ARG(this->get_log_name()), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2,
|
||||
conf.pin_d3, conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href,
|
||||
conf.pin_pclk, conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
|
||||
|
||||
ESP_LOGCONFIG(TAG, " Resolution: %s", frame_size_to_str(this->config_.frame_size));
|
||||
ESP_LOGCONFIG(TAG, " Pixel Format: %s", pixel_format_to_str(this->config_.pixel_format));
|
||||
@@ -282,7 +282,7 @@ void ESP32Camera::loop() {
|
||||
}
|
||||
this->frame_count_++;
|
||||
if (now - this->last_log_time_ >= FRAME_LOG_INTERVAL_MS) {
|
||||
ESP_LOGD(TAG, "Received %u images in last %" PRIu32 "s", this->frame_count_, FRAME_LOG_INTERVAL_MS / 1000);
|
||||
ESP_LOGD(TAG, "Received %u images in last %us", this->frame_count_, FRAME_LOG_INTERVAL_MS / 1000);
|
||||
this->last_log_time_ = now;
|
||||
this->frame_count_ = 0;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import esphome.codegen as cg
|
||||
from esphome.components import canbus
|
||||
from esphome.components.canbus import CONF_BIT_RATE, CanbusComponent, CanSpeed
|
||||
from esphome.components.esp32 import (
|
||||
CONF_MINIMUM_CHIP_REVISION,
|
||||
KEY_ESP32,
|
||||
VARIANT_ESP32,
|
||||
VARIANT_ESP32C3,
|
||||
VARIANT_ESP32C5,
|
||||
@@ -22,8 +20,6 @@ from esphome.components.esp32 import (
|
||||
)
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ADVANCED,
|
||||
CONF_FRAMEWORK,
|
||||
CONF_ID,
|
||||
CONF_MODE,
|
||||
CONF_RX_PIN,
|
||||
@@ -31,7 +27,6 @@ from esphome.const import (
|
||||
CONF_TX_PIN,
|
||||
CONF_TX_QUEUE_LEN,
|
||||
)
|
||||
import esphome.final_validate as fv
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@Sympatron"]
|
||||
@@ -54,7 +49,6 @@ CAN_MODES = {
|
||||
# See ESP-IDF Programming Guide --> API Reference --> Two-Wire Automotive Interface (TWAI)
|
||||
|
||||
CAN_SPEEDS_ESP32 = {
|
||||
"20KBPS": CanSpeed.CAN_20KBPS,
|
||||
"25KBPS": CanSpeed.CAN_25KBPS,
|
||||
"50KBPS": CanSpeed.CAN_50KBPS,
|
||||
"100KBPS": CanSpeed.CAN_100KBPS,
|
||||
@@ -120,22 +114,6 @@ CONFIG_SCHEMA = canbus.CANBUS_SCHEMA.extend(
|
||||
)
|
||||
|
||||
|
||||
def _final_validate(config: ConfigType) -> None:
|
||||
if get_esp32_variant() == VARIANT_ESP32 and config[CONF_BIT_RATE] == "20KBPS":
|
||||
esp32_config = fv.full_config.get()[KEY_ESP32]
|
||||
min_revision = esp32_config[CONF_FRAMEWORK][CONF_ADVANCED].get(
|
||||
CONF_MINIMUM_CHIP_REVISION
|
||||
)
|
||||
if min_revision is None or min_revision < "2.0":
|
||||
raise cv.Invalid(
|
||||
"20KBPS on ESP32 requires esp32.framework.advanced.minimum_chip_revision: '2.0' or higher",
|
||||
path=[CONF_BIT_RATE],
|
||||
)
|
||||
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||
|
||||
|
||||
def get_default_tx_enqueue_timeout(bit_rate: str) -> int:
|
||||
bit_rate_numeric = canbus.get_rate(bit_rate)
|
||||
bits_per_packet = 140 # ~max CAN message length
|
||||
|
||||
@@ -33,10 +33,6 @@ static bool get_bitrate(canbus::CanSpeed bitrate, twai_timing_config_t *t_config
|
||||
case canbus::CAN_16KBPS:
|
||||
*t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_16KBITS();
|
||||
return true;
|
||||
#endif
|
||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || \
|
||||
defined(USE_ESP32_VARIANT_ESP32H2) || defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || \
|
||||
defined(USE_ESP32_VARIANT_ESP32S3) || (defined(USE_ESP32_VARIANT_ESP32) && CONFIG_ESP32_REV_MIN_FULL >= 200)
|
||||
case canbus::CAN_20KBPS:
|
||||
*t_config = (twai_timing_config_t) TWAI_TIMING_CONFIG_20KBITS();
|
||||
return true;
|
||||
|
||||
@@ -346,13 +346,13 @@ void ESP32TouchComponent::loop() {
|
||||
child->publish_state(new_state);
|
||||
#ifdef USE_ESP32_VARIANT_ESP32
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: %s (value: %" PRIu32 ", threshold: %" PRIu32 ")",
|
||||
child->get_name().c_str(), ONOFF(new_state), value, child->get_threshold());
|
||||
LOG_STR_ARG(child->get_log_name()), ONOFF(new_state), value, child->get_threshold());
|
||||
#else
|
||||
if (new_state) {
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 ", benchmark: %" PRIu32 ", threshold: %" PRIu32 ")",
|
||||
child->get_name().c_str(), value, benchmark, child->get_threshold());
|
||||
LOG_STR_ARG(child->get_log_name()), value, benchmark, child->get_threshold());
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", child->get_name().c_str());
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", LOG_STR_ARG(child->get_log_name()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -475,7 +475,8 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) {
|
||||
child->value_ = smooth_value;
|
||||
|
||||
#ifdef USE_ESP32_VARIANT_ESP32
|
||||
ESP_LOGD(TAG, "Touch Pad '%s' (Ch%d): %" PRIu32, child->get_name().c_str(), child->channel_id_, smooth_value);
|
||||
ESP_LOGD(TAG, "Touch Pad '%s' (Ch%d): %" PRIu32, LOG_STR_ARG(child->get_log_name()), child->channel_id_,
|
||||
smooth_value);
|
||||
#else
|
||||
uint32_t benchmark = 0;
|
||||
touch_channel_read_data(child->chan_handle_, TOUCH_CHAN_DATA_TYPE_BENCHMARK, &benchmark);
|
||||
@@ -484,7 +485,7 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) {
|
||||
ESP_LOGD(TAG,
|
||||
"Touch Pad '%s' (Ch%d): value=%" PRIu32 ", benchmark=%" PRIu32 ", difference=%" PRId32
|
||||
" (set threshold < %" PRId32 " to detect touch)",
|
||||
child->get_name().c_str(), child->channel_id_, smooth_value, benchmark, difference, difference);
|
||||
LOG_STR_ARG(child->get_log_name()), child->channel_id_, smooth_value, benchmark, difference, difference);
|
||||
#endif
|
||||
}
|
||||
this->setup_mode_last_log_print_ = now;
|
||||
@@ -496,7 +497,7 @@ void ESP32TouchComponent::publish_initial_state_if_needed_(ESP32TouchBinarySenso
|
||||
if (now > INITIAL_STATE_DELAY_MS) {
|
||||
child->publish_initial_state(false);
|
||||
child->initial_state_published_ = true;
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", child->get_name().c_str());
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", LOG_STR_ARG(child->get_log_name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ void Event::trigger(const char *event_type) {
|
||||
}
|
||||
}
|
||||
if (found == nullptr) {
|
||||
ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", this->get_name().c_str(), event_type);
|
||||
ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", LOG_STR_ARG(this->get_log_name()), event_type);
|
||||
return;
|
||||
}
|
||||
this->last_event_type_ = found;
|
||||
ESP_LOGV(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_);
|
||||
ESP_LOGV(TAG, "'%s' >> '%s'", LOG_STR_ARG(this->get_log_name()), this->last_event_type_);
|
||||
this->event_callback_.call(StringRef(found));
|
||||
#if defined(USE_EVENT) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_event(this);
|
||||
|
||||
@@ -16,7 +16,7 @@ using EventTypes = ConstVector<const char *, true>;
|
||||
|
||||
#define LOG_EVENT(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
LOG_ENTITY_DEVICE_CLASS(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <deque>
|
||||
|
||||
namespace esphome::ezo {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "ezo.sensor");
|
||||
static const char *const TAG = "ezo.sensor";
|
||||
|
||||
enum EzoCommandType : uint8_t {
|
||||
EZO_READ = 0,
|
||||
|
||||
@@ -52,14 +52,15 @@ FanCall &FanCall::set_preset_mode(const char *preset_mode, size_t len) {
|
||||
this->preset_mode_ = validated_mode; // Store pointer from traits
|
||||
} else {
|
||||
// Preset mode not found in traits - log warning and don't set
|
||||
ESP_LOGW(TAG, "%s: Preset mode '%.*s' not supported", this->parent_.get_name().c_str(), (int) len, preset_mode);
|
||||
ESP_LOGW(TAG, "%s: Preset mode '%.*s' not supported", LOG_STR_ARG(this->parent_.get_log_name()), (int) len,
|
||||
preset_mode);
|
||||
this->preset_mode_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void FanCall::perform() {
|
||||
ESP_LOGV(TAG, "'%s' - Setting:", this->parent_.get_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s' - Setting:", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
this->validate_();
|
||||
if (this->binary_state_.has_value()) {
|
||||
ESP_LOGV(TAG, " State: %s", ONOFF(*this->binary_state_));
|
||||
@@ -103,17 +104,17 @@ void FanCall::validate_() {
|
||||
}
|
||||
|
||||
if (this->oscillating_.has_value() && !traits.supports_oscillation()) {
|
||||
ESP_LOGW(TAG, "%s: Oscillation not supported", this->parent_.get_name().c_str());
|
||||
ESP_LOGW(TAG, "%s: Oscillation not supported", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
this->oscillating_.reset();
|
||||
}
|
||||
|
||||
if (this->speed_.has_value() && !traits.supports_speed()) {
|
||||
ESP_LOGW(TAG, "%s: Speed control not supported", this->parent_.get_name().c_str());
|
||||
ESP_LOGW(TAG, "%s: Speed control not supported", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
this->speed_.reset();
|
||||
}
|
||||
|
||||
if (this->direction_.has_value() && !traits.supports_direction()) {
|
||||
ESP_LOGW(TAG, "%s: Direction control not supported", this->parent_.get_name().c_str());
|
||||
ESP_LOGW(TAG, "%s: Direction control not supported", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
this->direction_.reset();
|
||||
}
|
||||
}
|
||||
@@ -221,7 +222,7 @@ void Fan::publish_state() {
|
||||
ESP_LOGV(TAG,
|
||||
"'%s' >>\n"
|
||||
" State: %s",
|
||||
this->name_.c_str(), ONOFF(this->state));
|
||||
LOG_STR_ARG(this->get_log_name()), ONOFF(this->state));
|
||||
if (traits.supports_speed()) {
|
||||
ESP_LOGV(TAG, " Speed: %d", this->speed);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace esphome::fan {
|
||||
|
||||
#define LOG_FAN(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
(obj)->dump_traits_(TAG, prefix); \
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ void FeedbackCover::set_open_sensor(binary_sensor::BinarySensor *open_feedback)
|
||||
|
||||
// setup callbacks to react to sensor changes
|
||||
open_feedback->add_on_state_callback([this](bool state) {
|
||||
ESP_LOGD(TAG, "'%s' - Open feedback '%s'.", this->name_.c_str(),
|
||||
ESP_LOGD(TAG, "'%s' - Open feedback '%s'.", LOG_STR_ARG(this->get_log_name()),
|
||||
state ? LOG_STR_LITERAL("STARTED") : LOG_STR_LITERAL("ENDED"));
|
||||
this->recompute_position_();
|
||||
if (!state && this->infer_endstop_ && this->current_trigger_operation_ == COVER_OPERATION_OPENING) {
|
||||
@@ -112,7 +112,7 @@ void FeedbackCover::set_close_sensor(binary_sensor::BinarySensor *close_feedback
|
||||
this->close_feedback_ = close_feedback;
|
||||
|
||||
close_feedback->add_on_state_callback([this](bool state) {
|
||||
ESP_LOGD(TAG, "'%s' - Close feedback '%s'.", this->name_.c_str(),
|
||||
ESP_LOGD(TAG, "'%s' - Close feedback '%s'.", LOG_STR_ARG(this->get_log_name()),
|
||||
state ? LOG_STR_LITERAL("STARTED") : LOG_STR_LITERAL("ENDED"));
|
||||
this->recompute_position_();
|
||||
if (!state && this->infer_endstop_ && this->current_trigger_operation_ == COVER_OPERATION_CLOSING) {
|
||||
@@ -151,7 +151,7 @@ void FeedbackCover::endstop_reached_(bool open_endstop) {
|
||||
// from a position slightly past the endpoint
|
||||
if (this->current_trigger_operation_ == (open_endstop ? COVER_OPERATION_OPENING : COVER_OPERATION_CLOSING)) {
|
||||
float dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(),
|
||||
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()),
|
||||
open_endstop ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"), dur);
|
||||
|
||||
// if there is no external mechanism, stop the cover
|
||||
@@ -198,7 +198,7 @@ void FeedbackCover::set_close_obstacle_sensor(binary_sensor::BinarySensor *close
|
||||
close_obstacle->add_on_state_callback([this](bool state) {
|
||||
if (state && (this->current_operation == COVER_OPERATION_CLOSING ||
|
||||
this->current_trigger_operation_ == COVER_OPERATION_CLOSING)) {
|
||||
ESP_LOGD(TAG, "'%s' - Close obstacle detected.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Close obstacle detected.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
|
||||
if (this->obstacle_rollback_) {
|
||||
@@ -215,7 +215,7 @@ void FeedbackCover::set_open_obstacle_sensor(binary_sensor::BinarySensor *open_o
|
||||
open_obstacle->add_on_state_callback([this](bool state) {
|
||||
if (state && (this->current_operation == COVER_OPERATION_OPENING ||
|
||||
this->current_trigger_operation_ == COVER_OPERATION_OPENING)) {
|
||||
ESP_LOGD(TAG, "'%s' - Open obstacle detected.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Open obstacle detected.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
|
||||
if (this->obstacle_rollback_) {
|
||||
@@ -251,7 +251,7 @@ void FeedbackCover::loop() {
|
||||
this->start_overshoot_time_ = now;
|
||||
} else if (now - this->start_overshoot_time_ > this->overshoot_duration_ ||
|
||||
now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Overshoot duration reached. Stopping cover.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Overshoot duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
}
|
||||
#endif
|
||||
@@ -259,7 +259,7 @@ void FeedbackCover::loop() {
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
}
|
||||
} else if (now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
}
|
||||
}
|
||||
@@ -390,7 +390,7 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
|
||||
// check if there is an obstacle to start the new operation -> abort without any change
|
||||
// the case when an obstacle appears while moving is handled in the callback
|
||||
if (obstacle != nullptr && obstacle->state) {
|
||||
ESP_LOGD(TAG, "'%s' - %s obstacle detected. Action not started.", this->name_.c_str(),
|
||||
ESP_LOGD(TAG, "'%s' - %s obstacle detected. Action not started.", LOG_STR_ARG(this->get_log_name()),
|
||||
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"));
|
||||
return;
|
||||
}
|
||||
@@ -401,13 +401,13 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
|
||||
if (this->direction_change_waittime_.has_value() && dir != COVER_OPERATION_IDLE &&
|
||||
this->current_operation != COVER_OPERATION_IDLE && dir != this->current_operation) {
|
||||
const uint32_t waittime = *this->direction_change_waittime_;
|
||||
ESP_LOGD(TAG, "'%s' - Reversing direction.", this->name_.c_str());
|
||||
ESP_LOGD(TAG, "'%s' - Reversing direction.", LOG_STR_ARG(this->get_log_name()));
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->set_timeout(DIRECTION_CHANGE_TIMEOUT_ID, waittime, [this, dir]() { this->start_direction_(dir); });
|
||||
} else {
|
||||
this->set_current_operation_(dir, true);
|
||||
this->prev_command_trigger_ = trig;
|
||||
ESP_LOGD(TAG, "'%s' - Firing '%s' trigger.", this->name_.c_str(),
|
||||
ESP_LOGD(TAG, "'%s' - Firing '%s' trigger.", LOG_STR_ARG(this->get_log_name()),
|
||||
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("OPEN")
|
||||
: dir == COVER_OPERATION_CLOSING ? LOG_STR_LITERAL("CLOSE")
|
||||
: LOG_STR_LITERAL("STOP"));
|
||||
|
||||
@@ -330,9 +330,7 @@ async def write_image(
|
||||
if byte_order is not None:
|
||||
# Check for valid type has already been done in validate_settings
|
||||
encoder.set_big_endian(byte_order == "BIG_ENDIAN")
|
||||
pixels = encoder.convert(
|
||||
image.resize((width, height)), path
|
||||
).get_flattened_data()
|
||||
pixels = encoder.convert(image.resize((width, height)), path).getdata()
|
||||
for row in range(height):
|
||||
for col in range(width):
|
||||
encoder.encode(pixels[row * width + col])
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
CODEOWNERS = ["@tuct"]
|
||||
DOMAIN = "filter_lifetime"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user