1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-07 02:21:51 +00:00

Compare commits

..

13 Commits

Author SHA1 Message Date
Jesse Hills
a9a17ee89d Merge pull request #5737 from esphome/bump-2023.11.0b4
2023.11.0b4
2023-11-13 11:25:42 +13:00
Jesse Hills
f094702a16 Bump version to 2023.11.0b4 2023-11-13 10:23:28 +13:00
J. Nick Koston
908f56ff46 Bump zeroconf to 0.123.0 (#5736) 2023-11-13 10:23:28 +13:00
J. Nick Koston
bd5905c59a Migrate to using aioesphomeapi for the log runner to fix multiple issues (#5733) 2023-11-13 10:23:28 +13:00
dependabot[bot]
91299f05f7 Bump aioesphomeapi from 18.2.7 to 18.4.0 (#5735)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-13 10:23:27 +13:00
Mike La Spina
30e5ff9fff Missed ifdefs (#5727) 2023-11-13 10:23:27 +13:00
J. Nick Koston
163b38e153 Fix zeroconf name resolution refactoring error (#5725) 2023-11-13 10:23:27 +13:00
Jesse Hills
3b486084c8 Add resistance_sampler interface for config validation (#5718) 2023-11-13 10:23:27 +13:00
Jesse Hills
9d453f0ba2 Merge pull request #5714 from esphome/bump-2023.11.0b3
2023.11.0b3
2023-11-10 08:16:33 +13:00
dependabot[bot]
799851a83a Bump zeroconf from 0.120.0 to 0.122.3 (#5715) 2023-11-10 07:29:44 +13:00
Jesse Hills
7a9866f1b6 Bump version to 2023.11.0b3 2023-11-09 22:14:22 +13:00
J. Nick Koston
3d30f1f733 Update Dockerfile to use piwheels for armv7 (#5709) 2023-11-09 22:14:22 +13:00
J. Nick Koston
1e55764d52 Bump aioesphomeapi to 18.2.7 (#5706) 2023-11-09 22:14:22 +13:00
13 changed files with 118 additions and 79 deletions

View File

@@ -246,6 +246,7 @@ esphome/components/radon_eye_rd200/* @jeffeb3
esphome/components/rc522/* @glmnet esphome/components/rc522/* @glmnet
esphome/components/rc522_i2c/* @glmnet esphome/components/rc522_i2c/* @glmnet
esphome/components/rc522_spi/* @glmnet esphome/components/rc522_spi/* @glmnet
esphome/components/resistance_sampler/* @jesserockz
esphome/components/restart/* @esphome/core esphome/components/restart/* @esphome/core
esphome/components/rf_bridge/* @jesserockz esphome/components/rf_bridge/* @jesserockz
esphome/components/rgbct/* @jesserockz esphome/components/rgbct/* @jesserockz

View File

@@ -5,6 +5,7 @@
# One of "docker", "hassio" # One of "docker", "hassio"
ARG BASEIMGTYPE=docker ARG BASEIMGTYPE=docker
# https://github.com/hassio-addons/addon-debian-base/releases # https://github.com/hassio-addons/addon-debian-base/releases
FROM ghcr.io/hassio-addons/debian-base:7.2.0 AS base-hassio FROM ghcr.io/hassio-addons/debian-base:7.2.0 AS base-hassio
# https://hub.docker.com/_/debian?tab=tags&page=1&name=bookworm # https://hub.docker.com/_/debian?tab=tags&page=1&name=bookworm
@@ -12,9 +13,10 @@ FROM debian:12.2-slim AS base-docker
FROM base-${BASEIMGTYPE} AS base FROM base-${BASEIMGTYPE} AS base
ARG TARGETARCH ARG TARGETARCH
ARG TARGETVARIANT ARG TARGETVARIANT
ARG PIP_EXTRA_INDEX_URL
# Note that --break-system-packages is used below because # Note that --break-system-packages is used below because
# https://peps.python.org/pep-0668/ added a safety check that prevents # https://peps.python.org/pep-0668/ added a safety check that prevents
@@ -59,8 +61,7 @@ ENV \
# Fix click python3 lang warning https://click.palletsprojects.com/en/7.x/python3/ # Fix click python3 lang warning https://click.palletsprojects.com/en/7.x/python3/
LANG=C.UTF-8 LC_ALL=C.UTF-8 \ LANG=C.UTF-8 LC_ALL=C.UTF-8 \
# Store globally installed pio libs in /piolibs # Store globally installed pio libs in /piolibs
PLATFORMIO_GLOBALLIB_DIR=/piolibs \ PLATFORMIO_GLOBALLIB_DIR=/piolibs
PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL}
# Support legacy binaries on Debian multiarch system. There is no "correct" way # Support legacy binaries on Debian multiarch system. There is no "correct" way
# to do this, other than using properly built toolchains... # to do this, other than using properly built toolchains...
@@ -72,7 +73,11 @@ RUN \
RUN \ RUN \
# Ubuntu python3-pip is missing wheel # Ubuntu python3-pip is missing wheel
pip3 install --break-system-packages --no-cache-dir \ if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir \
platformio==6.1.11 \ platformio==6.1.11 \
# Change some platformio settings # Change some platformio settings
&& platformio settings set enable_telemetry No \ && platformio settings set enable_telemetry No \
@@ -84,8 +89,12 @@ RUN \
# tmpfs is for https://github.com/rust-lang/cargo/issues/8719 # tmpfs is for https://github.com/rust-lang/cargo/issues/8719
COPY requirements.txt requirements_optional.txt script/platformio_install_deps.py platformio.ini / COPY requirements.txt requirements_optional.txt script/platformio_install_deps.py platformio.ini /
RUN --mount=type=tmpfs,target=/root/.cargo CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse CARGO_HOME=/root/.cargo \ RUN --mount=type=tmpfs,target=/root/.cargo if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
pip3 install --break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \ export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse CARGO_HOME=/root/.cargo \
pip3 install \
--break-system-packages --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
&& /platformio_install_deps.py /platformio.ini --libraries && /platformio_install_deps.py /platformio.ini --libraries
@@ -94,7 +103,11 @@ FROM base AS docker
# Copy esphome and install # Copy esphome and install
COPY . /esphome COPY . /esphome
RUN pip3 install --break-system-packages --no-cache-dir --no-use-pep517 -e /esphome RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir --no-use-pep517 -e /esphome
# Settings for dashboard # Settings for dashboard
ENV USERNAME="" PASSWORD="" ENV USERNAME="" PASSWORD=""
@@ -140,7 +153,11 @@ COPY docker/ha-addon-rootfs/ /
# Copy esphome and install # Copy esphome and install
COPY . /esphome COPY . /esphome
RUN pip3 install --break-system-packages --no-cache-dir --no-use-pep517 -e /esphome RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir --no-use-pep517 -e /esphome
# Labels # Labels
LABEL \ LABEL \
@@ -176,7 +193,11 @@ RUN \
/var/lib/apt/lists/* /var/lib/apt/lists/*
COPY requirements_test.txt / COPY requirements_test.txt /
RUN pip3 install --break-system-packages --no-cache-dir -r /requirements_test.txt RUN if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
export PIP_EXTRA_INDEX_URL="https://www.piwheels.org/simple"; \
fi; \
pip3 install \
--break-system-packages --no-cache-dir -r /requirements_test.txt
VOLUME ["/esphome"] VOLUME ["/esphome"]
WORKDIR /esphome WORKDIR /esphome

View File

@@ -143,25 +143,15 @@ def main():
imgs = [f"{params.build_to}:{tag}" for tag in tags_to_push] imgs = [f"{params.build_to}:{tag}" for tag in tags_to_push]
imgs += [f"ghcr.io/{params.build_to}:{tag}" for tag in tags_to_push] imgs += [f"ghcr.io/{params.build_to}:{tag}" for tag in tags_to_push]
build_args = [
"--build-arg",
f"BASEIMGTYPE={params.baseimgtype}",
"--build-arg",
f"BUILD_VERSION={args.tag}",
]
if args.arch == ARCH_ARMV7:
build_args += [
"--build-arg",
"PIP_EXTRA_INDEX_URL=https://www.piwheels.org/simple",
]
# 3. build # 3. build
cmd = [ cmd = [
"docker", "docker",
"buildx", "buildx",
"build", "build",
*build_args, "--build-arg",
f"BASEIMGTYPE={params.baseimgtype}",
"--build-arg",
f"BUILD_VERSION={args.tag}",
"--cache-from", "--cache-from",
f"type=registry,ref={cache_img}", f"type=registry,ref={cache_img}",
"--file", "--file",

View File

@@ -1,71 +1,65 @@
from __future__ import annotations
import asyncio import asyncio
import logging import logging
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Any
from aioesphomeapi import APIClient, ReconnectLogic, APIConnectionError, LogLevel from aioesphomeapi import APIClient
import zeroconf from aioesphomeapi.api_pb2 import SubscribeLogsResponse
from aioesphomeapi.log_runner import async_run
from zeroconf.asyncio import AsyncZeroconf
from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__
from esphome.core import CORE
from esphome.const import CONF_KEY, CONF_PORT, CONF_PASSWORD, __version__
from esphome.util import safe_print
from . import CONF_ENCRYPTION from . import CONF_ENCRYPTION
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
async def async_run_logs(config, address): async def async_run_logs(config, address):
"""Run the logs command in the event loop."""
conf = config["api"] conf = config["api"]
port: int = int(conf[CONF_PORT]) port: int = int(conf[CONF_PORT])
password: str = conf[CONF_PASSWORD] password: str = conf[CONF_PASSWORD]
noise_psk: Optional[str] = None noise_psk: str | None = None
if CONF_ENCRYPTION in conf: if CONF_ENCRYPTION in conf:
noise_psk = conf[CONF_ENCRYPTION][CONF_KEY] noise_psk = conf[CONF_ENCRYPTION][CONF_KEY]
_LOGGER.info("Starting log output from %s using esphome API", address) _LOGGER.info("Starting log output from %s using esphome API", address)
aiozc = AsyncZeroconf()
cli = APIClient( cli = APIClient(
address, address,
port, port,
password, password,
client_info=f"ESPHome Logs {__version__}", client_info=f"ESPHome Logs {__version__}",
noise_psk=noise_psk, noise_psk=noise_psk,
zeroconf_instance=aiozc.zeroconf,
) )
first_connect = True dashboard = CORE.dashboard
def on_log(msg): def on_log(msg: SubscribeLogsResponse) -> None:
time_ = datetime.now().time().strftime("[%H:%M:%S]") """Handle a new log message."""
text = msg.message.decode("utf8", "backslashreplace") time_ = datetime.now()
safe_print(time_ + text) message: bytes = msg.message
text = message.decode("utf8", "backslashreplace")
async def on_connect(): if dashboard:
nonlocal first_connect text = text.replace("\033", "\\033")
try: print(f"[{time_.hour:02}:{time_.minute:02}:{time_.second:02}]{text}")
await cli.subscribe_logs(
on_log,
log_level=LogLevel.LOG_LEVEL_VERY_VERBOSE,
dump_config=first_connect,
)
first_connect = False
except APIConnectionError:
cli.disconnect()
async def on_disconnect(expected_disconnect: bool) -> None:
_LOGGER.warning("Disconnected from API")
zc = zeroconf.Zeroconf()
reconnect = ReconnectLogic(
client=cli,
on_connect=on_connect,
on_disconnect=on_disconnect,
zeroconf_instance=zc,
)
await reconnect.start()
stop = await async_run(cli, on_log, aio_zeroconf_instance=aiozc)
try: try:
while True: while True:
await asyncio.sleep(60) await asyncio.sleep(60)
except KeyboardInterrupt: finally:
await reconnect.stop() await aiozc.async_close()
zc.close() await stop()
def run_logs(config, address): def run_logs(config: dict[str, Any], address: str) -> None:
"""Run the logs command."""
try:
asyncio.run(async_run_logs(config, address)) asyncio.run(async_run_logs(config, address))
except KeyboardInterrupt:
pass

View File

@@ -68,6 +68,7 @@ void LD2420Component::dump_config() {
ESP_LOGCONFIG(TAG, "LD2420:"); ESP_LOGCONFIG(TAG, "LD2420:");
ESP_LOGCONFIG(TAG, " Firmware Version : %7s", this->ld2420_firmware_ver_); ESP_LOGCONFIG(TAG, " Firmware Version : %7s", this->ld2420_firmware_ver_);
ESP_LOGCONFIG(TAG, "LD2420 Number:"); ESP_LOGCONFIG(TAG, "LD2420 Number:");
#ifdef USE_NUMBER
LOG_NUMBER(TAG, " Gate Timeout:", this->gate_timeout_number_); LOG_NUMBER(TAG, " Gate Timeout:", this->gate_timeout_number_);
LOG_NUMBER(TAG, " Gate Max Distance:", this->max_gate_distance_number_); LOG_NUMBER(TAG, " Gate Max Distance:", this->max_gate_distance_number_);
LOG_NUMBER(TAG, " Gate Min Distance:", this->min_gate_distance_number_); LOG_NUMBER(TAG, " Gate Min Distance:", this->min_gate_distance_number_);
@@ -76,10 +77,13 @@ void LD2420Component::dump_config() {
LOG_NUMBER(TAG, " Gate Move Threshold:", this->gate_move_threshold_numbers_[gate]); LOG_NUMBER(TAG, " Gate Move Threshold:", this->gate_move_threshold_numbers_[gate]);
LOG_NUMBER(TAG, " Gate Still Threshold::", this->gate_still_threshold_numbers_[gate]); LOG_NUMBER(TAG, " Gate Still Threshold::", this->gate_still_threshold_numbers_[gate]);
} }
#endif
#ifdef USE_BUTTON
LOG_BUTTON(TAG, " Apply Config:", this->apply_config_button_); LOG_BUTTON(TAG, " Apply Config:", this->apply_config_button_);
LOG_BUTTON(TAG, " Revert Edits:", this->revert_config_button_); LOG_BUTTON(TAG, " Revert Edits:", this->revert_config_button_);
LOG_BUTTON(TAG, " Factory Reset:", this->factory_reset_button_); LOG_BUTTON(TAG, " Factory Reset:", this->factory_reset_button_);
LOG_BUTTON(TAG, " Restart Module:", this->restart_module_button_); LOG_BUTTON(TAG, " Restart Module:", this->restart_module_button_);
#endif
ESP_LOGCONFIG(TAG, "LD2420 Select:"); ESP_LOGCONFIG(TAG, "LD2420 Select:");
LOG_SELECT(TAG, " Operating Mode", this->operating_selector_); LOG_SELECT(TAG, " Operating Mode", this->operating_selector_);
if (this->get_firmware_int_(ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) { if (this->get_firmware_int_(ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) {
@@ -183,9 +187,11 @@ void LD2420Component::factory_reset_action() {
return; return;
} }
this->set_min_max_distances_timeout(FACTORY_MAX_GATE, FACTORY_MIN_GATE, FACTORY_TIMEOUT); this->set_min_max_distances_timeout(FACTORY_MAX_GATE, FACTORY_MIN_GATE, FACTORY_TIMEOUT);
#ifdef USE_NUMBER
this->gate_timeout_number_->state = FACTORY_TIMEOUT; this->gate_timeout_number_->state = FACTORY_TIMEOUT;
this->min_gate_distance_number_->state = FACTORY_MIN_GATE; this->min_gate_distance_number_->state = FACTORY_MIN_GATE;
this->max_gate_distance_number_->state = FACTORY_MAX_GATE; this->max_gate_distance_number_->state = FACTORY_MAX_GATE;
#endif
for (uint8_t gate = 0; gate < LD2420_TOTAL_GATES; gate++) { for (uint8_t gate = 0; gate < LD2420_TOTAL_GATES; gate++) {
this->new_config.move_thresh[gate] = FACTORY_MOVE_THRESH[gate]; this->new_config.move_thresh[gate] = FACTORY_MOVE_THRESH[gate];
this->new_config.still_thresh[gate] = FACTORY_STILL_THRESH[gate]; this->new_config.still_thresh[gate] = FACTORY_STILL_THRESH[gate];

View File

@@ -2,7 +2,7 @@ from math import log
import esphome.config_validation as cv import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from esphome.components import sensor from esphome.components import sensor, resistance_sampler
from esphome.const import ( from esphome.const import (
CONF_CALIBRATION, CONF_CALIBRATION,
CONF_REFERENCE_RESISTANCE, CONF_REFERENCE_RESISTANCE,
@@ -15,6 +15,8 @@ from esphome.const import (
UNIT_CELSIUS, UNIT_CELSIUS,
) )
AUTO_LOAD = ["resistance_sampler"]
ntc_ns = cg.esphome_ns.namespace("ntc") ntc_ns = cg.esphome_ns.namespace("ntc")
NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor) NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor)
@@ -124,7 +126,7 @@ CONFIG_SCHEMA = (
) )
.extend( .extend(
{ {
cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), cv.Required(CONF_SENSOR): cv.use_id(resistance_sampler.ResistanceSampler),
cv.Required(CONF_CALIBRATION): process_calibration, cv.Required(CONF_CALIBRATION): process_calibration,
} }
) )

View File

@@ -1,7 +1,8 @@
#pragma once #pragma once
#include "esphome/core/component.h" #include "esphome/components/resistance_sampler/resistance_sampler.h"
#include "esphome/components/sensor/sensor.h" #include "esphome/components/sensor/sensor.h"
#include "esphome/core/component.h"
namespace esphome { namespace esphome {
namespace resistance { namespace resistance {
@@ -11,7 +12,7 @@ enum ResistanceConfiguration {
DOWNSTREAM, DOWNSTREAM,
}; };
class ResistanceSensor : public Component, public sensor::Sensor { class ResistanceSensor : public Component, public sensor::Sensor, resistance_sampler::ResistanceSampler {
public: public:
void set_sensor(Sensor *sensor) { sensor_ = sensor; } void set_sensor(Sensor *sensor) { sensor_ = sensor; }
void set_configuration(ResistanceConfiguration configuration) { configuration_ = configuration; } void set_configuration(ResistanceConfiguration configuration) { configuration_ = configuration; }

View File

@@ -1,6 +1,6 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import sensor from esphome.components import sensor, resistance_sampler
from esphome.const import ( from esphome.const import (
CONF_SENSOR, CONF_SENSOR,
STATE_CLASS_MEASUREMENT, STATE_CLASS_MEASUREMENT,
@@ -8,8 +8,15 @@ from esphome.const import (
ICON_FLASH, ICON_FLASH,
) )
AUTO_LOAD = ["resistance_sampler"]
resistance_ns = cg.esphome_ns.namespace("resistance") resistance_ns = cg.esphome_ns.namespace("resistance")
ResistanceSensor = resistance_ns.class_("ResistanceSensor", cg.Component, sensor.Sensor) ResistanceSensor = resistance_ns.class_(
"ResistanceSensor",
cg.Component,
sensor.Sensor,
resistance_sampler.ResistanceSampler,
)
CONF_REFERENCE_VOLTAGE = "reference_voltage" CONF_REFERENCE_VOLTAGE = "reference_voltage"
CONF_CONFIGURATION = "configuration" CONF_CONFIGURATION = "configuration"

View File

@@ -0,0 +1,6 @@
import esphome.codegen as cg
resistance_sampler_ns = cg.esphome_ns.namespace("resistance_sampler")
ResistanceSampler = resistance_sampler_ns.class_("ResistanceSampler")
CODEOWNERS = ["@jesserockz"]

View File

@@ -0,0 +1,10 @@
#pragma once
namespace esphome {
namespace resistance_sampler {
/// Abstract interface to mark components that provide resistance values.
class ResistanceSampler {};
} // namespace resistance_sampler
} // namespace esphome

View File

@@ -1,6 +1,6 @@
"""Constants used by esphome.""" """Constants used by esphome."""
__version__ = "2023.11.0b2" __version__ = "2023.11.0b4"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
VALID_SUBSTITUTIONS_CHARACTERS = ( VALID_SUBSTITUTIONS_CHARACTERS = (

View File

@@ -147,12 +147,13 @@ class DashboardImportDiscovery:
class EsphomeZeroconf(Zeroconf): class EsphomeZeroconf(Zeroconf):
def resolve_host(self, host: str, timeout=3.0): def resolve_host(self, host: str, timeout: float = 3.0) -> str | None:
"""Resolve a host name to an IP address.""" """Resolve a host name to an IP address."""
name = host.partition(".")[0] name = host.partition(".")[0]
info = HostResolver(f"{name}.{ESPHOME_SERVICE_TYPE}", ESPHOME_SERVICE_TYPE) info = HostResolver(ESPHOME_SERVICE_TYPE, f"{name}.{ESPHOME_SERVICE_TYPE}")
if (info.load_from_cache(self) or info.request(self, timeout * 1000)) and ( if (
addresses := info.ip_addresses_by_version(IPVersion.V4Only) info.load_from_cache(self)
): or (timeout and info.request(self, timeout * 1000))
) and (addresses := info.ip_addresses_by_version(IPVersion.V4Only)):
return str(addresses[0]) return str(addresses[0])
return None return None

View File

@@ -10,8 +10,8 @@ platformio==6.1.11 # When updating platformio, also update Dockerfile
esptool==4.6.2 esptool==4.6.2
click==8.1.7 click==8.1.7
esphome-dashboard==20231107.0 esphome-dashboard==20231107.0
aioesphomeapi==18.2.4 aioesphomeapi==18.4.0
zeroconf==0.120.0 zeroconf==0.123.0
# esp-idf requires this, but doesn't bundle it by default # esp-idf requires this, but doesn't bundle it by default
# https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24 # https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24