1
0
mirror of https://github.com/esphome/esphome.git synced 2025-11-02 16:11:53 +00:00

Compare commits

...

14 Commits

Author SHA1 Message Date
Jesse Hills
69fe18f1ef Fix small index compare bug in modbus 2022-12-16 16:21:04 +13:00
Jesse Hills
39af967433 Fix i2s_audio media_player compiling for esp32-s2 (#4195) 2022-12-16 10:38:52 +13:00
Jesse Hills
83b5e01a28 Mark ESP32-S2 as not having Bluetooth (#4194) 2022-12-16 10:09:07 +13:00
Stefan Agner
1eacbd50fa Support non-multiarch toolchains on 32-bit ARM (#4191)
fixes https://github.com/esphome/issues/issues/3904
2022-12-16 09:27:59 +13:00
Jesse Hills
9bf7c97775 Revert camera config change for esp-idf (#4182) 2022-12-14 11:45:51 +13:00
Jesse Hills
24bf3674f3 Remove warnings when falling through switch cases on purpose (#4181) 2022-12-14 11:45:43 +13:00
J. Nick Koston
c47dc09d34 Speed up bluetooth proxy connections when using esp-idf (#4171) 2022-12-13 13:57:12 +13:00
Jesse Hills
db3096c6e1 Remove internal pin restriction from cd74hc4067 (#4179) 2022-12-13 13:44:52 +13:00
Jesse Hills
eef578f4b8 Bump esphome-dashboard to 20221213.0 (#4176) 2022-12-13 08:14:18 +13:00
Jesse Hills
d4e232f267 Increase watchdog timeout when starting OTA (#4172) 2022-12-12 16:16:24 +13:00
Björn Stenberg
cc45945fcf climate: Add features to generic Toshiba model (#3912)
Add fan speed modes, dry and fan-only operation modes.
This reduce differences between generic and PT14111 models.
2022-12-08 14:13:10 -06:00
Jesse Hills
0c24d951ff Fix ble parsing with zero padded advertisements (#4162) 2022-12-08 13:39:33 +13:00
John Britton
92e44b8238 Expose lambda action to reset a cycle in slow_pwm (#4158) 2022-12-07 19:27:14 +13:00
Jesse Hills
34387adbcd Bump version to 2023.1.0-dev 2022-12-07 17:00:11 +13:00
22 changed files with 137 additions and 37 deletions

View File

@@ -12,6 +12,9 @@ FROM debian:bullseye-20221024-slim AS base-docker
FROM base-${BASEIMGTYPE} AS base
ARG TARGETARCH
ARG TARGETVARIANT
RUN \
apt-get update \
# Use pinned versions so that we get updates with build caching
@@ -36,6 +39,14 @@ ENV \
# Store globally installed pio libs in /piolibs
PLATFORMIO_GLOBALLIB_DIR=/piolibs
# Support legacy binaries on Debian multiarch system. There is no "correct" way
# to do this, other than using properly built toolchains...
# See: https://unix.stackexchange.com/questions/553743/correct-way-to-add-lib-ld-linux-so-3-in-debian
RUN \
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
ln -s /lib/arm-linux-gnueabihf/ld-linux.so.3 /lib/ld-linux.so.3; \
fi
RUN \
# Ubuntu python3-pip is missing wheel
pip3 install --no-cache-dir \

View File

@@ -2,11 +2,13 @@ from esphome.components import esp32_ble_tracker, esp32_ble_client
import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.const import CONF_ACTIVE, CONF_ID
from esphome.components.esp32 import add_idf_sdkconfig_option
AUTO_LOAD = ["esp32_ble_client", "esp32_ble_tracker"]
DEPENDENCIES = ["api", "esp32"]
CODEOWNERS = ["@jesserockz"]
CONF_CACHE_SERVICES = "cache_services"
CONF_CONNECTIONS = "connections"
MAX_CONNECTIONS = 3
@@ -47,6 +49,9 @@ CONFIG_SCHEMA = cv.All(
{
cv.GenerateID(): cv.declare_id(BluetoothProxy),
cv.Optional(CONF_ACTIVE, default=False): cv.boolean,
cv.SplitDefault(CONF_CACHE_SERVICES, esp32_idf=True): cv.All(
cv.only_with_esp_idf, cv.boolean
),
cv.Optional(CONF_CONNECTIONS): cv.All(
cv.ensure_list(CONNECTION_SCHEMA),
cv.Length(min=1, max=MAX_CONNECTIONS),
@@ -72,4 +77,7 @@ async def to_code(config):
cg.add(var.register_connection(connection_var))
await esp32_ble_tracker.register_client(connection_var, connection_conf)
if config.get(CONF_CACHE_SERVICES):
add_idf_sdkconfig_option("CONFIG_BT_GATTC_CACHE_NVS_FLASH", True)
cg.add_define("USE_BLUETOOTH_PROXY")

View File

@@ -27,10 +27,10 @@ DEFAULT_DELAY = "2ms"
CONFIG_SCHEMA = cv.Schema(
{
cv.GenerateID(): cv.declare_id(CD74HC4067Component),
cv.Required(CONF_PIN_S0): pins.internal_gpio_output_pin_schema,
cv.Required(CONF_PIN_S1): pins.internal_gpio_output_pin_schema,
cv.Required(CONF_PIN_S2): pins.internal_gpio_output_pin_schema,
cv.Required(CONF_PIN_S3): pins.internal_gpio_output_pin_schema,
cv.Required(CONF_PIN_S0): pins.gpio_output_pin_schema,
cv.Required(CONF_PIN_S1): pins.gpio_output_pin_schema,
cv.Required(CONF_PIN_S2): pins.gpio_output_pin_schema,
cv.Required(CONF_PIN_S3): pins.gpio_output_pin_schema,
cv.Optional(
CONF_DELAY, default=DEFAULT_DELAY
): cv.positive_time_period_milliseconds,

View File

@@ -19,22 +19,22 @@ class CD74HC4067Component : public Component {
void activate_pin(uint8_t pin);
/// set the pin connected to multiplexer control pin 0
void set_pin_s0(InternalGPIOPin *pin) { this->pin_s0_ = pin; }
void set_pin_s0(GPIOPin *pin) { this->pin_s0_ = pin; }
/// set the pin connected to multiplexer control pin 1
void set_pin_s1(InternalGPIOPin *pin) { this->pin_s1_ = pin; }
void set_pin_s1(GPIOPin *pin) { this->pin_s1_ = pin; }
/// set the pin connected to multiplexer control pin 2
void set_pin_s2(InternalGPIOPin *pin) { this->pin_s2_ = pin; }
void set_pin_s2(GPIOPin *pin) { this->pin_s2_ = pin; }
/// set the pin connected to multiplexer control pin 3
void set_pin_s3(InternalGPIOPin *pin) { this->pin_s3_ = pin; }
void set_pin_s3(GPIOPin *pin) { this->pin_s3_ = pin; }
/// set the delay needed after an input switch
void set_switch_delay(uint32_t switch_delay) { this->switch_delay_ = switch_delay; }
private:
InternalGPIOPin *pin_s0_;
InternalGPIOPin *pin_s1_;
InternalGPIOPin *pin_s2_;
InternalGPIOPin *pin_s3_;
GPIOPin *pin_s0_;
GPIOPin *pin_s1_;
GPIOPin *pin_s2_;
GPIOPin *pin_s3_;
/// the currently active pin
uint8_t active_pin_;
uint32_t switch_delay_;

View File

@@ -398,11 +398,11 @@ spiffs, data, spiffs, 0x391000, 0x00F000
IDF_PARTITIONS_CSV = """\
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, , 0x4000,
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
app0, app, ota_0, , 0x1C0000,
app1, app, ota_1, , 0x1C0000,
nvs, data, nvs, , 0x6d000,
"""

View File

@@ -2,12 +2,14 @@ import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import CONF_ID
from esphome.core import CORE
from esphome.components.esp32 import add_idf_sdkconfig_option
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const
DEPENDENCIES = ["esp32"]
CODEOWNERS = ["@jesserockz"]
CONFLICTS_WITH = ["esp32_ble_tracker", "esp32_ble_beacon"]
NO_BLUTOOTH_VARIANTS = [const.VARIANT_ESP32S2]
esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble")
ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component)
@@ -19,6 +21,15 @@ CONFIG_SCHEMA = cv.Schema(
).extend(cv.COMPONENT_SCHEMA)
def validate_variant(_):
variant = get_esp32_variant()
if variant in NO_BLUTOOTH_VARIANTS:
raise cv.Invalid(f"{variant} does not support Bluetooth")
FINAL_VALIDATE_SCHEMA = validate_variant
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config)

View File

@@ -3,6 +3,7 @@ import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_TYPE, CONF_UUID, CONF_TX_POWER
from esphome.core import CORE, TimePeriod
from esphome.components.esp32 import add_idf_sdkconfig_option
from esphome.components import esp32_ble
DEPENDENCIES = ["esp32"]
CONFLICTS_WITH = ["esp32_ble_tracker"]
@@ -54,6 +55,8 @@ CONFIG_SCHEMA = cv.All(
validate_config,
)
FINAL_VALIDATE_SCHEMA = esp32_ble.validate_variant
async def to_code(config):
uuid = config[CONF_UUID].hex

View File

@@ -95,7 +95,9 @@ void BLEClientBase::release_services() {
for (auto &svc : this->services_)
delete svc; // NOLINT(cppcoreguidelines-owning-memory)
this->services_.clear();
#ifndef CONFIG_BT_GATTC_CACHE_NVS_FLASH
esp_ble_gattc_cache_clean(this->remote_bda_);
#endif
}
bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t esp_gattc_if,
@@ -288,14 +290,17 @@ float BLEClientBase::parse_char_value(uint8_t *value, uint16_t length) {
if (length > 2) {
return (float) encode_uint16(value[1], value[2]);
}
// fall through
case 0x7: // uint24.
if (length > 3) {
return (float) encode_uint24(value[1], value[2], value[3]);
}
// fall through
case 0x8: // uint32.
if (length > 4) {
return (float) encode_uint32(value[1], value[2], value[3], value[4]);
}
// fall through
case 0xC: // int8.
return (float) ((int8_t) value[1]);
case 0xD: // int12.
@@ -303,10 +308,12 @@ float BLEClientBase::parse_char_value(uint8_t *value, uint16_t length) {
if (length > 2) {
return (float) ((int16_t)(value[1] << 8) + (int16_t) value[2]);
}
// fall through
case 0xF: // int24.
if (length > 3) {
return (float) ((int32_t)(value[1] << 16) + (int32_t)(value[2] << 8) + (int32_t)(value[3]));
}
// fall through
case 0x10: // int32.
if (length > 4) {
return (float) ((int32_t)(value[1] << 24) + (int32_t)(value[2] << 16) + (int32_t)(value[3] << 8) +

View File

@@ -17,6 +17,7 @@ from esphome.const import (
)
from esphome.core import CORE
from esphome.components.esp32 import add_idf_sdkconfig_option
from esphome.components import esp32_ble
DEPENDENCIES = ["esp32"]
@@ -187,6 +188,8 @@ CONFIG_SCHEMA = cv.Schema(
}
).extend(cv.COMPONENT_SCHEMA)
FINAL_VALIDATE_SCHEMA = esp32_ble.validate_variant
ESP_BLE_DEVICE_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_id(ESP32BLETracker),

View File

@@ -705,8 +705,13 @@ void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_p
while (offset + 2 < len) {
const uint8_t field_length = payload[offset++]; // First byte is length of adv record
if (field_length == 0)
if (field_length == 0) {
if (offset < param.adv_data_len && param.scan_rsp_len > 0) { // Zero padded advertisement data
offset = param.adv_data_len;
continue;
}
break;
}
// first byte of adv record is adv record type
const uint8_t record_type = payload[offset++];

View File

@@ -54,7 +54,11 @@ void ESP32Camera::dump_config() {
ESP_LOGCONFIG(TAG, " HREF Pin: %d", conf.pin_href);
ESP_LOGCONFIG(TAG, " Pixel Clock Pin: %d", conf.pin_pclk);
ESP_LOGCONFIG(TAG, " External Clock: Pin:%d Frequency:%u", conf.pin_xclk, conf.xclk_freq_hz);
#ifdef USE_ESP_IDF // Temporary until the espressif/esp32-camera library is updated
ESP_LOGCONFIG(TAG, " I2C Pins: SDA:%d SCL:%d", conf.pin_sscb_sda, conf.pin_sscb_scl);
#else
ESP_LOGCONFIG(TAG, " I2C Pins: SDA:%d SCL:%d", conf.pin_sccb_sda, conf.pin_sccb_scl);
#endif
ESP_LOGCONFIG(TAG, " Reset Pin: %d", conf.pin_reset);
switch (this->config_.frame_size) {
case FRAMESIZE_QQVGA:
@@ -209,8 +213,13 @@ void ESP32Camera::set_external_clock(uint8_t pin, uint32_t frequency) {
this->config_.xclk_freq_hz = frequency;
}
void ESP32Camera::set_i2c_pins(uint8_t sda, uint8_t scl) {
#ifdef USE_ESP_IDF // Temporary until the espressif/esp32-camera library is updated
this->config_.pin_sscb_sda = sda;
this->config_.pin_sscb_scl = scl;
#else
this->config_.pin_sccb_sda = sda;
this->config_.pin_sccb_scl = scl;
#endif
}
void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }

View File

@@ -103,9 +103,11 @@ void I2SAudioMediaPlayer::stop_() {
void I2SAudioMediaPlayer::setup() {
ESP_LOGCONFIG(TAG, "Setting up Audio...");
#if SOC_I2S_SUPPORTS_DAC
if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) {
this->audio_ = make_unique<Audio>(true, this->internal_dac_mode_);
} else {
#endif
this->audio_ = make_unique<Audio>(false);
this->audio_->setPinout(this->bclk_pin_, this->lrclk_pin_, this->dout_pin_);
this->audio_->forceMono(this->external_dac_channels_ == 1);
@@ -113,7 +115,9 @@ void I2SAudioMediaPlayer::setup() {
this->mute_pin_->setup();
this->mute_pin_->digital_write(false);
}
#if SOC_I2S_SUPPORTS_DAC
}
#endif
this->state = media_player::MEDIA_PLAYER_STATE_IDLE;
}
@@ -137,6 +141,7 @@ void I2SAudioMediaPlayer::dump_config() {
ESP_LOGCONFIG(TAG, "Audio failed to initialize!");
return;
}
#if SOC_I2S_SUPPORTS_DAC
if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) {
switch (this->internal_dac_mode_) {
case I2S_DAC_CHANNEL_LEFT_EN:
@@ -152,6 +157,7 @@ void I2SAudioMediaPlayer::dump_config() {
break;
}
}
#endif
}
} // namespace i2s_audio

View File

@@ -25,7 +25,9 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer {
void set_bclk_pin(uint8_t pin) { this->bclk_pin_ = pin; }
void set_lrclk_pin(uint8_t pin) { this->lrclk_pin_ = pin; }
void set_mute_pin(GPIOPin *mute_pin) { this->mute_pin_ = mute_pin; }
#if SOC_I2S_SUPPORTS_DAC
void set_internal_dac_mode(i2s_dac_mode_t mode) { this->internal_dac_mode_ = mode; }
#endif
void set_external_dac_channels(uint8_t channels) { this->external_dac_channels_ = channels; }
media_player::MediaPlayerTraits get_traits() override;
@@ -51,7 +53,9 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer {
bool muted_{false};
float unmuted_volume_{0};
#if SOC_I2S_SUPPORTS_DAC
i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE};
#endif
uint8_t external_dac_channels_;
HighFrequencyLoopRequester high_freq_;

View File

@@ -1,5 +1,5 @@
import esphome.codegen as cg
from esphome.components import media_player
from esphome.components import media_player, esp32
import esphome.config_validation as cv
from esphome import pins
@@ -33,6 +33,18 @@ INTERNAL_DAC_OPTIONS = {
EXTERNAL_DAC_OPTIONS = ["mono", "stereo"]
NO_INTERNAL_DAC_VARIANTS = [esp32.const.VARIANT_ESP32S2]
def validate_esp32_variant(config):
if config[CONF_DAC_TYPE] != "internal":
return config
variant = esp32.get_esp32_variant()
if variant in NO_INTERNAL_DAC_VARIANTS:
raise cv.Invalid(f"{variant} does not have an internal DAC")
return config
CONFIG_SCHEMA = cv.All(
cv.typed_schema(
{
@@ -68,6 +80,7 @@ CONFIG_SCHEMA = cv.All(
key=CONF_DAC_TYPE,
),
cv.only_with_arduino,
validate_esp32_variant,
)

View File

@@ -47,7 +47,7 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) {
uint8_t function_code = raw[1];
// Byte 2: Size (with modbus rtu function code 4/3)
// See also https://en.wikipedia.org/wiki/Modbus
if (at == 2)
if (at <= 2)
return true;
uint8_t data_len = raw[2];

View File

@@ -1,6 +1,8 @@
#include "esphome/core/defines.h"
#ifdef USE_ESP_IDF
#include <esp_task_wdt.h>
#include "ota_backend_esp_idf.h"
#include "ota_component.h"
#include <esp_ota_ops.h>
@@ -14,7 +16,9 @@ OTAResponseTypes IDFOTABackend::begin(size_t image_size) {
if (this->partition_ == nullptr) {
return OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION;
}
esp_task_wdt_init(15, false); // The following function takes longer than the 5 seconds timeout of WDT
esp_err_t err = esp_ota_begin(this->partition_, image_size, &this->update_handle_);
esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false); // Set the WDT back to the configured timeout
if (err != ESP_OK) {
esp_ota_abort(this->update_handle_);
this->update_handle_ = 0;

View File

@@ -70,7 +70,7 @@ void SlowPWMOutput::dump_config() {
void SlowPWMOutput::write_state(float state) {
this->state_ = state;
if (this->restart_cycle_on_state_change_)
this->period_start_time_ = millis();
this->restart_cycle();
}
} // namespace slow_pwm

View File

@@ -14,6 +14,7 @@ class SlowPWMOutput : public output::FloatOutput, public Component {
void set_restart_cycle_on_state_change(bool restart_cycle_on_state_change) {
restart_cycle_on_state_change_ = restart_cycle_on_state_change;
}
void restart_cycle() { this->period_start_time_ = millis(); }
/// Initialize pin
void setup() override;

View File

@@ -124,9 +124,6 @@ void ToshibaClimate::setup() {
// Set supported modes & temperatures based on model
this->minimum_temperature_ = this->temperature_min_();
this->maximum_temperature_ = this->temperature_max_();
this->supports_dry_ = this->toshiba_supports_dry_();
this->supports_fan_only_ = this->toshiba_supports_fan_only_();
this->fan_modes_ = this->toshiba_fan_modes_();
this->swing_modes_ = this->toshiba_swing_modes_();
// Never send nan to HA
if (std::isnan(this->target_temperature))
@@ -178,12 +175,39 @@ void ToshibaClimate::transmit_generic_() {
mode = TOSHIBA_MODE_COOL;
break;
case climate::CLIMATE_MODE_DRY:
mode = TOSHIBA_MODE_DRY;
break;
case climate::CLIMATE_MODE_FAN_ONLY:
mode = TOSHIBA_MODE_FAN_ONLY;
break;
case climate::CLIMATE_MODE_HEAT_COOL:
default:
mode = TOSHIBA_MODE_AUTO;
}
message[6] |= mode | TOSHIBA_FAN_SPEED_AUTO;
uint8_t fan;
switch (this->fan_mode.value()) {
case climate::CLIMATE_FAN_LOW:
fan = TOSHIBA_FAN_SPEED_1;
break;
case climate::CLIMATE_FAN_MEDIUM:
fan = TOSHIBA_FAN_SPEED_3;
break;
case climate::CLIMATE_FAN_HIGH:
fan = TOSHIBA_FAN_SPEED_5;
break;
case climate::CLIMATE_FAN_AUTO:
default:
fan = TOSHIBA_FAN_SPEED_AUTO;
break;
}
message[6] = fan | mode;
// Zero
message[7] = 0x00;

View File

@@ -22,7 +22,10 @@ const float TOSHIBA_RAC_PT1411HWRU_TEMP_F_MAX = 86.0;
class ToshibaClimate : public climate_ir::ClimateIR {
public:
ToshibaClimate() : climate_ir::ClimateIR(TOSHIBA_GENERIC_TEMP_C_MIN, TOSHIBA_GENERIC_TEMP_C_MAX, 1.0f) {}
ToshibaClimate()
: climate_ir::ClimateIR(TOSHIBA_GENERIC_TEMP_C_MIN, TOSHIBA_GENERIC_TEMP_C_MAX, 1.0f, true, true,
{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM,
climate::CLIMATE_FAN_HIGH}) {}
void setup() override;
void set_model(Model model) { this->model_ = model; }
@@ -46,18 +49,6 @@ class ToshibaClimate : public climate_ir::ClimateIR {
float temperature_max_() {
return (this->model_ == MODEL_GENERIC) ? TOSHIBA_GENERIC_TEMP_C_MAX : TOSHIBA_RAC_PT1411HWRU_TEMP_C_MAX;
}
bool toshiba_supports_dry_() {
return ((this->model_ == MODEL_RAC_PT1411HWRU_C) || (this->model_ == MODEL_RAC_PT1411HWRU_F));
}
bool toshiba_supports_fan_only_() {
return ((this->model_ == MODEL_RAC_PT1411HWRU_C) || (this->model_ == MODEL_RAC_PT1411HWRU_F));
}
std::set<climate::ClimateFanMode> toshiba_fan_modes_() {
return (this->model_ == MODEL_GENERIC)
? std::set<climate::ClimateFanMode>{}
: std::set<climate::ClimateFanMode>{climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW,
climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH};
}
std::set<climate::ClimateSwingMode> toshiba_swing_modes_() {
return (this->model_ == MODEL_GENERIC)
? std::set<climate::ClimateSwingMode>{}

View File

@@ -1,6 +1,6 @@
"""Constants used by esphome."""
__version__ = "2022.12.0-dev"
__version__ = "2023.1.0-dev"
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"

View File

@@ -9,7 +9,7 @@ pyserial==3.5
platformio==6.1.5 # When updating platformio, also update Dockerfile
esptool==4.4
click==8.1.3
esphome-dashboard==20221207.0
esphome-dashboard==20221213.0
aioesphomeapi==13.0.1
zeroconf==0.39.4