mirror of
https://github.com/esphome/esphome.git
synced 2025-09-08 06:12:20 +01:00
Merge branch 'esphome:dev' into dev
This commit is contained in:
8
.github/workflows/ci-docker.yml
vendored
8
.github/workflows/ci-docker.yml
vendored
@@ -33,11 +33,11 @@ concurrency:
|
|||||||
jobs:
|
jobs:
|
||||||
check-docker:
|
check-docker:
|
||||||
name: Build docker containers
|
name: Build docker containers
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
arch: [amd64, aarch64]
|
os: ["ubuntu-latest", "ubuntu-24.04-arm"]
|
||||||
build_type: ["ha-addon", "docker", "lint"]
|
build_type: ["ha-addon", "docker", "lint"]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.7
|
- uses: actions/checkout@v4.1.7
|
||||||
@@ -47,8 +47,6 @@ jobs:
|
|||||||
python-version: "3.9"
|
python-version: "3.9"
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3.9.0
|
uses: docker/setup-buildx-action@v3.9.0
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3.4.0
|
|
||||||
|
|
||||||
- name: Set TAG
|
- name: Set TAG
|
||||||
run: |
|
run: |
|
||||||
@@ -58,6 +56,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
docker/build.py \
|
docker/build.py \
|
||||||
--tag "${TAG}" \
|
--tag "${TAG}" \
|
||||||
--arch "${{ matrix.arch }}" \
|
--arch "${{ matrix.os == 'ubuntu-24.04-arm' && 'aarch64' || 'amd64' }}" \
|
||||||
--build-type "${{ matrix.build_type }}" \
|
--build-type "${{ matrix.build_type }}" \
|
||||||
build
|
build
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any
|
import logging
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from aioesphomeapi import APIClient
|
from aioesphomeapi import APIClient
|
||||||
from aioesphomeapi.api_pb2 import SubscribeLogsResponse
|
|
||||||
from aioesphomeapi.log_runner import async_run
|
from aioesphomeapi.log_runner import async_run
|
||||||
|
|
||||||
from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__
|
from esphome.const import CONF_KEY, CONF_PASSWORD, CONF_PORT, __version__
|
||||||
@@ -14,6 +13,12 @@ from esphome.core import CORE
|
|||||||
|
|
||||||
from . import CONF_ENCRYPTION
|
from . import CONF_ENCRYPTION
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from aioesphomeapi.api_pb2 import (
|
||||||
|
SubscribeLogsResponse, # pylint: disable=no-name-in-module
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@ void DHT::dump_config() {
|
|||||||
} else {
|
} else {
|
||||||
ESP_LOGCONFIG(TAG, " Model: DHT22 (or equivalent)");
|
ESP_LOGCONFIG(TAG, " Model: DHT22 (or equivalent)");
|
||||||
}
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, " Internal Pull-up: %s", ONOFF(this->pin_->get_flags() & gpio::FLAG_PULLUP));
|
||||||
|
|
||||||
LOG_UPDATE_INTERVAL(this);
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r
|
|||||||
} else {
|
} else {
|
||||||
delayMicroseconds(800);
|
delayMicroseconds(800);
|
||||||
}
|
}
|
||||||
this->pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
this->pin_->pin_mode(this->pin_->get_flags());
|
||||||
|
|
||||||
{
|
{
|
||||||
InterruptLock lock;
|
InterruptLock lock;
|
||||||
|
@@ -34,7 +34,7 @@ DHT = dht_ns.class_("DHT", cg.PollingComponent)
|
|||||||
CONFIG_SCHEMA = cv.Schema(
|
CONFIG_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(DHT),
|
cv.GenerateID(): cv.declare_id(DHT),
|
||||||
cv.Required(CONF_PIN): pins.internal_gpio_input_pin_schema,
|
cv.Required(CONF_PIN): pins.internal_gpio_input_pullup_pin_schema,
|
||||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||||
unit_of_measurement=UNIT_CELSIUS,
|
unit_of_measurement=UNIT_CELSIUS,
|
||||||
accuracy_decimals=1,
|
accuracy_decimals=1,
|
||||||
|
@@ -815,8 +815,20 @@ void Display::test_card() {
|
|||||||
|
|
||||||
DisplayPage::DisplayPage(display_writer_t writer) : writer_(std::move(writer)) {}
|
DisplayPage::DisplayPage(display_writer_t writer) : writer_(std::move(writer)) {}
|
||||||
void DisplayPage::show() { this->parent_->show_page(this); }
|
void DisplayPage::show() { this->parent_->show_page(this); }
|
||||||
void DisplayPage::show_next() { this->next_->show(); }
|
void DisplayPage::show_next() {
|
||||||
void DisplayPage::show_prev() { this->prev_->show(); }
|
if (this->next_ == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "no next page");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->next_->show();
|
||||||
|
}
|
||||||
|
void DisplayPage::show_prev() {
|
||||||
|
if (this->prev_ == nullptr) {
|
||||||
|
ESP_LOGE(TAG, "no previous page");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->prev_->show();
|
||||||
|
}
|
||||||
void DisplayPage::set_parent(Display *parent) { this->parent_ = parent; }
|
void DisplayPage::set_parent(Display *parent) { this->parent_ = parent; }
|
||||||
void DisplayPage::set_prev(DisplayPage *prev) { this->prev_ = prev; }
|
void DisplayPage::set_prev(DisplayPage *prev) { this->prev_ = prev; }
|
||||||
void DisplayPage::set_next(DisplayPage *next) { this->next_ = next; }
|
void DisplayPage::set_next(DisplayPage *next) { this->next_ = next; }
|
||||||
|
@@ -7,13 +7,16 @@
|
|||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
#include <esp32-hal-dac.h>
|
#include <esp32-hal-dac.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ESP_IDF
|
|
||||||
#include <driver/dac.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_dac {
|
namespace esp32_dac {
|
||||||
|
|
||||||
|
#ifdef USE_ESP32_VARIANT_ESP32S2
|
||||||
|
static constexpr uint8_t DAC0_PIN = 17;
|
||||||
|
#else
|
||||||
|
static constexpr uint8_t DAC0_PIN = 25;
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *const TAG = "esp32_dac";
|
static const char *const TAG = "esp32_dac";
|
||||||
|
|
||||||
void ESP32DAC::setup() {
|
void ESP32DAC::setup() {
|
||||||
@@ -22,8 +25,15 @@ void ESP32DAC::setup() {
|
|||||||
this->turn_off();
|
this->turn_off();
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
|
const dac_channel_t channel = this->pin_->get_pin() == DAC0_PIN ? DAC_CHAN_0 : DAC_CHAN_1;
|
||||||
dac_output_enable(channel);
|
const dac_oneshot_config_t oneshot_cfg{channel};
|
||||||
|
dac_oneshot_new_channel(&oneshot_cfg, &this->dac_handle_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESP32DAC::on_safe_shutdown() {
|
||||||
|
#ifdef USE_ESP_IDF
|
||||||
|
dac_oneshot_del_channel(this->dac_handle_);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +50,7 @@ void ESP32DAC::write_state(float state) {
|
|||||||
state = state * 255;
|
state = state * 255;
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
auto channel = pin_->get_pin() == 25 ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
|
dac_oneshot_output_voltage(this->dac_handle_, state);
|
||||||
dac_output_voltage(channel, (uint8_t) state);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
dacWrite(this->pin_->get_pin(), state);
|
dacWrite(this->pin_->get_pin(), state);
|
||||||
|
@@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
#ifdef USE_ESP_IDF
|
||||||
|
#include <driver/dac_oneshot.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_dac {
|
namespace esp32_dac {
|
||||||
|
|
||||||
@@ -16,6 +20,7 @@ class ESP32DAC : public output::FloatOutput, public Component {
|
|||||||
|
|
||||||
/// Initialize pin
|
/// Initialize pin
|
||||||
void setup() override;
|
void setup() override;
|
||||||
|
void on_safe_shutdown() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
/// HARDWARE setup_priority
|
/// HARDWARE setup_priority
|
||||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||||
@@ -24,6 +29,9 @@ class ESP32DAC : public output::FloatOutput, public Component {
|
|||||||
void write_state(float state) override;
|
void write_state(float state) override;
|
||||||
|
|
||||||
InternalGPIOPin *pin_;
|
InternalGPIOPin *pin_;
|
||||||
|
#ifdef USE_ESP_IDF
|
||||||
|
dac_oneshot_handle_t dac_handle_;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace esp32_dac
|
} // namespace esp32_dac
|
||||||
|
@@ -1,15 +1,27 @@
|
|||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
from esphome import pins
|
from esphome import pins
|
||||||
from esphome.components import output
|
from esphome.components import output
|
||||||
import esphome.config_validation as cv
|
from esphome.components.esp32 import get_esp32_variant
|
||||||
import esphome.codegen as cg
|
from esphome.components.esp32.const import VARIANT_ESP32, VARIANT_ESP32S2
|
||||||
from esphome.const import CONF_ID, CONF_NUMBER, CONF_PIN
|
from esphome.const import CONF_ID, CONF_NUMBER, CONF_PIN
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
|
|
||||||
|
DAC_PINS = {
|
||||||
|
VARIANT_ESP32: (25, 26),
|
||||||
|
VARIANT_ESP32S2: (17, 18),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def valid_dac_pin(value):
|
def valid_dac_pin(value):
|
||||||
num = value[CONF_NUMBER]
|
variant = get_esp32_variant()
|
||||||
cv.one_of(25, 26)(num)
|
try:
|
||||||
|
valid_pins = DAC_PINS[variant]
|
||||||
|
except KeyError as ex:
|
||||||
|
raise cv.Invalid(f"DAC is not supported on {variant}") from ex
|
||||||
|
given_pin = value[CONF_NUMBER]
|
||||||
|
cv.one_of(*valid_pins)(given_pin)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
@@ -5,8 +5,8 @@ import os
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
import esphome_glyphsets as glyphsets
|
||||||
import freetype
|
import freetype
|
||||||
import glyphsets
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from esphome import core, external_files
|
from esphome import core, external_files
|
||||||
|
@@ -247,8 +247,8 @@ async def to_code(config):
|
|||||||
)
|
)
|
||||||
cg.add(log.pre_setup())
|
cg.add(log.pre_setup())
|
||||||
|
|
||||||
for tag, level in config[CONF_LOGS].items():
|
for tag, log_level in config[CONF_LOGS].items():
|
||||||
cg.add(log.set_log_level(tag, LOG_LEVELS[level]))
|
cg.add(log.set_log_level(tag, LOG_LEVELS[log_level]))
|
||||||
|
|
||||||
cg.add_define("USE_LOGGER")
|
cg.add_define("USE_LOGGER")
|
||||||
this_severity = LOG_LEVEL_SEVERITY.index(level)
|
this_severity = LOG_LEVEL_SEVERITY.index(level)
|
||||||
|
@@ -102,9 +102,6 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int HOT Logger::level_for(const char *tag) {
|
int HOT Logger::level_for(const char *tag) {
|
||||||
// Uses std::vector<> for low memory footprint, though the vector
|
|
||||||
// could be sorted to minimize lookup times. This feature isn't used that
|
|
||||||
// much anyway so it doesn't matter too much.
|
|
||||||
if (this->log_levels_.count(tag) != 0)
|
if (this->log_levels_.count(tag) != 0)
|
||||||
return this->log_levels_[tag];
|
return this->log_levels_[tag];
|
||||||
return this->current_level_;
|
return this->current_level_;
|
||||||
|
@@ -75,7 +75,7 @@ CONFIG_SCHEMA = (
|
|||||||
cv.Optional(CONF_UPDATE_INTERVAL, default="60s"): cv.All(
|
cv.Optional(CONF_UPDATE_INTERVAL, default="60s"): cv.All(
|
||||||
cv.positive_time_period_seconds,
|
cv.positive_time_period_seconds,
|
||||||
cv.Range(
|
cv.Range(
|
||||||
min=core.TimePeriod(seconds=1), max=core.TimePeriod(seconds=1800)
|
min=core.TimePeriod(seconds=2), max=core.TimePeriod(seconds=1800)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@@ -853,7 +853,7 @@ class InfoRequestHandler(BaseHandler):
|
|||||||
dashboard = DASHBOARD
|
dashboard = DASHBOARD
|
||||||
entry = dashboard.entries.get(yaml_path)
|
entry = dashboard.entries.get(yaml_path)
|
||||||
|
|
||||||
if not entry:
|
if not entry or entry.storage is None:
|
||||||
self.set_status(404)
|
self.set_status(404)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@@ -13,11 +13,11 @@ platformio==6.1.16 # When updating platformio, also update Dockerfile
|
|||||||
esptool==4.7.0
|
esptool==4.7.0
|
||||||
click==8.1.7
|
click==8.1.7
|
||||||
esphome-dashboard==20250212.0
|
esphome-dashboard==20250212.0
|
||||||
aioesphomeapi==24.6.2
|
aioesphomeapi==29.1.0
|
||||||
zeroconf==0.144.1
|
zeroconf==0.144.3
|
||||||
puremagic==1.27
|
puremagic==1.27
|
||||||
ruamel.yaml==0.18.6 # dashboard_import
|
ruamel.yaml==0.18.6 # dashboard_import
|
||||||
glyphsets==1.0.0
|
esphome-glyphsets==0.1.0
|
||||||
pillow==10.4.0
|
pillow==10.4.0
|
||||||
freetype-py==2.5.1
|
freetype-py==2.5.1
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user