mirror of
				https://github.com/esphome/esphome.git
				synced 2025-11-04 00:51:49 +00:00 
			
		
		
		
	Compare commits
	
		
			77 Commits
		
	
	
		
			jesserockz
			...
			2023.8.0b3
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f44e5d3142 | ||
| 
						 | 
					532163738e | ||
| 
						 | 
					63fa922547 | ||
| 
						 | 
					48e4cb5ae2 | ||
| 
						 | 
					ff8a73c2d1 | ||
| 
						 | 
					afd26c6f1a | ||
| 
						 | 
					67b06a88b2 | ||
| 
						 | 
					265e019381 | ||
| 
						 | 
					560e36a65c | ||
| 
						 | 
					b05a3fbb55 | ||
| 
						 | 
					3a899e28dc | ||
| 
						 | 
					f26238e824 | ||
| 
						 | 
					3717e34bba | ||
| 
						 | 
					be6f95d43e | ||
| 
						 | 
					99a765dc06 | ||
| 
						 | 
					351e7ea16b | ||
| 
						 | 
					2fa79a2e2f | ||
| 
						 | 
					44a917929d | ||
| 
						 | 
					21ebc7f95b | ||
| 
						 | 
					72e72d7d4b | ||
| 
						 | 
					02ed2c0ebe | ||
| 
						 | 
					0f506ea8eb | ||
| 
						 | 
					b914d6e305 | ||
| 
						 | 
					956e19be7d | ||
| 
						 | 
					b3d5a4dfdb | ||
| 
						 | 
					c63cdae84f | ||
| 
						 | 
					dec044ad8b | ||
| 
						 | 
					2a12ec09fb | ||
| 
						 | 
					91e920c498 | ||
| 
						 | 
					9b19c45735 | ||
| 
						 | 
					3843d21dbf | ||
| 
						 | 
					73db164fb1 | ||
| 
						 | 
					ab32dd7420 | ||
| 
						 | 
					2a7aa2fc0d | ||
| 
						 | 
					f5e98eb86f | ||
| 
						 | 
					362a19c2e1 | ||
| 
						 | 
					f4a4956dd4 | ||
| 
						 | 
					746488cabf | ||
| 
						 | 
					4449248c6f | ||
| 
						 | 
					036e14ab7f | ||
| 
						 | 
					f840eee1b7 | ||
| 
						 | 
					553132443f | ||
| 
						 | 
					d20242f589 | ||
| 
						 | 
					68affce274 | ||
| 
						 | 
					c4b9065749 | ||
| 
						 | 
					d57a5d1793 | ||
| 
						 | 
					74e062fdb3 | ||
| 
						 | 
					6bdc0c92fe | ||
| 
						 | 
					d7945de001 | ||
| 
						 | 
					3ba2a29e54 | ||
| 
						 | 
					76b438f79c | ||
| 
						 | 
					bc14f06a07 | ||
| 
						 | 
					feee075122 | ||
| 
						 | 
					a77cf1beec | ||
| 
						 | 
					d7bfdd0efc | ||
| 
						 | 
					62aee36f82 | ||
| 
						 | 
					0709367587 | ||
| 
						 | 
					98277f6ceb | ||
| 
						 | 
					8dd509ba53 | ||
| 
						 | 
					8df455f55b | ||
| 
						 | 
					36782f13bf | ||
| 
						 | 
					e823067a6b | ||
| 
						 | 
					c3ef12d580 | ||
| 
						 | 
					321155eb40 | ||
| 
						 | 
					d34c074b92 | ||
| 
						 | 
					abc8e903c1 | ||
| 
						 | 
					832ba38f1b | ||
| 
						 | 
					70de2f5278 | ||
| 
						 | 
					604d4eec79 | ||
| 
						 | 
					b806eb6a61 | ||
| 
						 | 
					39948db59a | ||
| 
						 | 
					fbfb4e2a73 | ||
| 
						 | 
					595ac84779 | ||
| 
						 | 
					746f72a279 | ||
| 
						 | 
					dec6f04499 | ||
| 
						 | 
					a90d266017 | ||
| 
						 | 
					df9fcf9850 | 
							
								
								
									
										10
									
								
								CODEOWNERS
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								CODEOWNERS
									
									
									
									
									
								
							@@ -54,7 +54,7 @@ esphome/components/bp1658cj/* @Cossid
 | 
			
		||||
esphome/components/bp5758d/* @Cossid
 | 
			
		||||
esphome/components/button/* @esphome/core
 | 
			
		||||
esphome/components/canbus/* @danielschramm @mvturnho
 | 
			
		||||
esphome/components/cap1188/* @mreditor97
 | 
			
		||||
esphome/components/cap1188/* @MrEditor97
 | 
			
		||||
esphome/components/captive_portal/* @OttoWinter
 | 
			
		||||
esphome/components/ccs811/* @habbie
 | 
			
		||||
esphome/components/cd74hc4067/* @asoehlke
 | 
			
		||||
@@ -87,13 +87,12 @@ esphome/components/ens210/* @itn3rd77
 | 
			
		||||
esphome/components/esp32/* @esphome/core
 | 
			
		||||
esphome/components/esp32_ble/* @jesserockz
 | 
			
		||||
esphome/components/esp32_ble_client/* @jesserockz
 | 
			
		||||
esphome/components/esp32_ble_server/* @clydebarrow @jesserockz
 | 
			
		||||
esphome/components/esp32_ble_server/* @jesserockz
 | 
			
		||||
esphome/components/esp32_camera_web_server/* @ayufan
 | 
			
		||||
esphome/components/esp32_can/* @Sympatron
 | 
			
		||||
esphome/components/esp32_improv/* @jesserockz
 | 
			
		||||
esphome/components/esp32_rmt_led_strip/* @jesserockz
 | 
			
		||||
esphome/components/esp8266/* @esphome/core
 | 
			
		||||
esphome/components/esp_adf/* @jesserockz
 | 
			
		||||
esphome/components/ethernet_info/* @gtjadsonsantos
 | 
			
		||||
esphome/components/exposure_notifications/* @OttoWinter
 | 
			
		||||
esphome/components/ezo/* @ssieb
 | 
			
		||||
@@ -133,7 +132,7 @@ esphome/components/i2s_audio/speaker/* @jesserockz
 | 
			
		||||
esphome/components/ili9xxx/* @nielsnl68
 | 
			
		||||
esphome/components/improv_base/* @esphome/core
 | 
			
		||||
esphome/components/improv_serial/* @esphome/core
 | 
			
		||||
esphome/components/ina260/* @mreditor97
 | 
			
		||||
esphome/components/ina260/* @MrEditor97
 | 
			
		||||
esphome/components/inkbird_ibsth1_mini/* @fkirill
 | 
			
		||||
esphome/components/inkplate6/* @jesserockz
 | 
			
		||||
esphome/components/integration/* @OttoWinter
 | 
			
		||||
@@ -169,7 +168,7 @@ esphome/components/mcp2515/* @danielschramm @mvturnho
 | 
			
		||||
esphome/components/mcp3204/* @rsumner
 | 
			
		||||
esphome/components/mcp4728/* @berfenger
 | 
			
		||||
esphome/components/mcp47a1/* @jesserockz
 | 
			
		||||
esphome/components/mcp9600/* @mreditor97
 | 
			
		||||
esphome/components/mcp9600/* @MrEditor97
 | 
			
		||||
esphome/components/mcp9808/* @k7hpn
 | 
			
		||||
esphome/components/md5/* @esphome/core
 | 
			
		||||
esphome/components/mdns/* @esphome/core
 | 
			
		||||
@@ -213,7 +212,6 @@ esphome/components/pid/* @OttoWinter
 | 
			
		||||
esphome/components/pipsolar/* @andreashergert1984
 | 
			
		||||
esphome/components/pm1006/* @habbie
 | 
			
		||||
esphome/components/pmsa003i/* @sjtrny
 | 
			
		||||
esphome/components/pmwcs3/* @SeByDocKy
 | 
			
		||||
esphome/components/pn532/* @OttoWinter @jesserockz
 | 
			
		||||
esphome/components/pn532_i2c/* @OttoWinter @jesserockz
 | 
			
		||||
esphome/components/pn532_spi/* @OttoWinter @jesserockz
 | 
			
		||||
 
 | 
			
		||||
@@ -28,15 +28,14 @@ RUN \
 | 
			
		||||
        git=1:2.30.2-1+deb11u2 \
 | 
			
		||||
        curl=7.74.0-1.3+deb11u7 \
 | 
			
		||||
        openssh-client=1:8.4p1-5+deb11u1 \
 | 
			
		||||
        python3-cffi=1.14.5-1 \
 | 
			
		||||
        libcairo2=1.16.0-5; \
 | 
			
		||||
        python3-cffi=1.14.5-1; \
 | 
			
		||||
    if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
 | 
			
		||||
        apt-get install -y --no-install-recommends \
 | 
			
		||||
          build-essential=12.9 \
 | 
			
		||||
          python3-dev=3.9.2-3 \
 | 
			
		||||
          zlib1g-dev=1:1.2.11.dfsg-2+deb11u2 \
 | 
			
		||||
          libjpeg-dev=1:2.0.6-4 \
 | 
			
		||||
          libfreetype-dev=2.10.4+dfsg-1+deb11u1; \
 | 
			
		||||
          libcairo2=1.16.0-5; \
 | 
			
		||||
    fi; \
 | 
			
		||||
    rm -rf \
 | 
			
		||||
        /tmp/* \
 | 
			
		||||
@@ -61,7 +60,7 @@ RUN \
 | 
			
		||||
    # Ubuntu python3-pip is missing wheel
 | 
			
		||||
    pip3 install --no-cache-dir \
 | 
			
		||||
        wheel==0.37.1 \
 | 
			
		||||
        platformio==6.1.10 \
 | 
			
		||||
        platformio==6.1.7 \
 | 
			
		||||
    # Change some platformio settings
 | 
			
		||||
    && platformio settings set enable_telemetry No \
 | 
			
		||||
    && platformio settings set check_platformio_interval 1000000 \
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,7 @@ from esphome.core import CORE
 | 
			
		||||
from esphome.components.esp32 import get_esp32_variant
 | 
			
		||||
from esphome.components.esp32.const import (
 | 
			
		||||
    VARIANT_ESP32,
 | 
			
		||||
    VARIANT_ESP32C2,
 | 
			
		||||
    VARIANT_ESP32C3,
 | 
			
		||||
    VARIANT_ESP32C6,
 | 
			
		||||
    VARIANT_ESP32H2,
 | 
			
		||||
    VARIANT_ESP32S2,
 | 
			
		||||
    VARIANT_ESP32S3,
 | 
			
		||||
@@ -72,22 +70,6 @@ ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = {
 | 
			
		||||
        3: adc1_channel_t.ADC1_CHANNEL_3,
 | 
			
		||||
        4: adc1_channel_t.ADC1_CHANNEL_4,
 | 
			
		||||
    },
 | 
			
		||||
    VARIANT_ESP32C2: {
 | 
			
		||||
        0: adc1_channel_t.ADC1_CHANNEL_0,
 | 
			
		||||
        1: adc1_channel_t.ADC1_CHANNEL_1,
 | 
			
		||||
        2: adc1_channel_t.ADC1_CHANNEL_2,
 | 
			
		||||
        3: adc1_channel_t.ADC1_CHANNEL_3,
 | 
			
		||||
        4: adc1_channel_t.ADC1_CHANNEL_4,
 | 
			
		||||
    },
 | 
			
		||||
    VARIANT_ESP32C6: {
 | 
			
		||||
        0: adc1_channel_t.ADC1_CHANNEL_0,
 | 
			
		||||
        1: adc1_channel_t.ADC1_CHANNEL_1,
 | 
			
		||||
        2: adc1_channel_t.ADC1_CHANNEL_2,
 | 
			
		||||
        3: adc1_channel_t.ADC1_CHANNEL_3,
 | 
			
		||||
        4: adc1_channel_t.ADC1_CHANNEL_4,
 | 
			
		||||
        5: adc1_channel_t.ADC1_CHANNEL_5,
 | 
			
		||||
        6: adc1_channel_t.ADC1_CHANNEL_6,
 | 
			
		||||
    },
 | 
			
		||||
    VARIANT_ESP32H2: {
 | 
			
		||||
        0: adc1_channel_t.ADC1_CHANNEL_0,
 | 
			
		||||
        1: adc1_channel_t.ADC1_CHANNEL_1,
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ CONF_ALLOW_MULTIPLE_TOUCHES = "allow_multiple_touches"
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ["i2c"]
 | 
			
		||||
AUTO_LOAD = ["binary_sensor", "output"]
 | 
			
		||||
CODEOWNERS = ["@mreditor97"]
 | 
			
		||||
CODEOWNERS = ["@MrEditor97"]
 | 
			
		||||
 | 
			
		||||
cap1188_ns = cg.esphome_ns.namespace("cap1188")
 | 
			
		||||
CONF_CAP1188_ID = "cap1188_id"
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ void CurrentBasedCover::control(const CoverCall &call) {
 | 
			
		||||
  }
 | 
			
		||||
  if (call.get_position().has_value()) {
 | 
			
		||||
    auto pos = *call.get_position();
 | 
			
		||||
    if (fabsf(this->position - pos) < 0.01) {
 | 
			
		||||
    if (pos == this->position) {
 | 
			
		||||
      // already at target
 | 
			
		||||
    } else {
 | 
			
		||||
      auto op = pos < this->position ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,15 +12,11 @@
 | 
			
		||||
#include <esp_heap_caps.h>
 | 
			
		||||
#include <esp_system.h>
 | 
			
		||||
 | 
			
		||||
#include <esp_chip_info.h>
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
#include <esp32/rom/rtc.h>
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32C3)
 | 
			
		||||
#include <esp32c3/rom/rtc.h>
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32S2)
 | 
			
		||||
#include <esp32s2/rom/rtc.h>
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
#include <esp32s3/rom/rtc.h>
 | 
			
		||||
#include <esp_chip_info.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <rom/rtc.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // USE_ESP32
 | 
			
		||||
@@ -113,19 +109,13 @@ void DebugComponent::dump_config() {
 | 
			
		||||
  esp_chip_info_t info;
 | 
			
		||||
  esp_chip_info(&info);
 | 
			
		||||
  const char *model;
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
  model = "ESP32";
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32C3)
 | 
			
		||||
  model = "ESP32-C3";
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32S2)
 | 
			
		||||
  model = "ESP32-S2";
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
  model = "ESP32-S3";
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32H2)
 | 
			
		||||
  model = "ESP32-H2";
 | 
			
		||||
#else
 | 
			
		||||
  model = "UNKNOWN";
 | 
			
		||||
#endif
 | 
			
		||||
  switch (info.model) {
 | 
			
		||||
    case CHIP_ESP32:
 | 
			
		||||
      model = "ESP32";
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      model = "UNKNOWN";
 | 
			
		||||
  }
 | 
			
		||||
  std::string features;
 | 
			
		||||
  if (info.features & CHIP_FEATURE_EMB_FLASH) {
 | 
			
		||||
    features += "EMB_FLASH,";
 | 
			
		||||
@@ -167,26 +157,18 @@ void DebugComponent::dump_config() {
 | 
			
		||||
    case POWERON_RESET:
 | 
			
		||||
      reset_reason = "Power On Reset";
 | 
			
		||||
      break;
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
    case SW_RESET:
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
    case RTC_SW_SYS_RESET:
 | 
			
		||||
#endif
 | 
			
		||||
      reset_reason = "Software Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
    case OWDT_RESET:
 | 
			
		||||
      reset_reason = "Watch Dog Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
    case DEEPSLEEP_RESET:
 | 
			
		||||
      reset_reason = "Deep Sleep Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
    case SDIO_RESET:
 | 
			
		||||
      reset_reason = "SLC Module Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
    case TG0WDT_SYS_RESET:
 | 
			
		||||
      reset_reason = "Timer Group 0 Watch Dog Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
@@ -199,61 +181,24 @@ void DebugComponent::dump_config() {
 | 
			
		||||
    case INTRUSION_RESET:
 | 
			
		||||
      reset_reason = "Intrusion Reset CPU";
 | 
			
		||||
      break;
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
    case TGWDT_CPU_RESET:
 | 
			
		||||
      reset_reason = "Timer Group Reset CPU";
 | 
			
		||||
      break;
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
    case TG0WDT_CPU_RESET:
 | 
			
		||||
      reset_reason = "Timer Group 0 Reset CPU";
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
    case SW_CPU_RESET:
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
    case RTC_SW_CPU_RESET:
 | 
			
		||||
#endif
 | 
			
		||||
      reset_reason = "Software Reset CPU";
 | 
			
		||||
      break;
 | 
			
		||||
    case RTCWDT_CPU_RESET:
 | 
			
		||||
      reset_reason = "RTC Watch Dog Reset CPU";
 | 
			
		||||
      break;
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32)
 | 
			
		||||
    case EXT_CPU_RESET:
 | 
			
		||||
      reset_reason = "External CPU Reset";
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
    case RTCWDT_BROWN_OUT_RESET:
 | 
			
		||||
      reset_reason = "Voltage Unstable Reset";
 | 
			
		||||
      break;
 | 
			
		||||
    case RTCWDT_RTC_RESET:
 | 
			
		||||
      reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module";
 | 
			
		||||
      break;
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
    case TG1WDT_CPU_RESET:
 | 
			
		||||
      reset_reason = "Timer Group 1 Reset CPU";
 | 
			
		||||
      break;
 | 
			
		||||
    case SUPER_WDT_RESET:
 | 
			
		||||
      reset_reason = "Super Watchdog Reset Digital Core And RTC Module";
 | 
			
		||||
      break;
 | 
			
		||||
    case GLITCH_RTC_RESET:
 | 
			
		||||
      reset_reason = "Glitch Reset Digital Core And RTC Module";
 | 
			
		||||
      break;
 | 
			
		||||
    case EFUSE_RESET:
 | 
			
		||||
      reset_reason = "eFuse Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
    case USB_UART_CHIP_RESET:
 | 
			
		||||
      reset_reason = "USB UART Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
    case USB_JTAG_CHIP_RESET:
 | 
			
		||||
      reset_reason = "USB JTAG Reset Digital Core";
 | 
			
		||||
      break;
 | 
			
		||||
    case POWER_GLITCH_RESET:
 | 
			
		||||
      reset_reason = "Power Glitch Reset Digital Core And RTC Module";
 | 
			
		||||
      break;
 | 
			
		||||
#endif
 | 
			
		||||
    default:
 | 
			
		||||
      reset_reason = "Unknown Reset Reason";
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,6 @@ from esphome.components.esp32.const import (
 | 
			
		||||
    VARIANT_ESP32C3,
 | 
			
		||||
    VARIANT_ESP32S2,
 | 
			
		||||
    VARIANT_ESP32S3,
 | 
			
		||||
    VARIANT_ESP32C2,
 | 
			
		||||
    VARIANT_ESP32C6,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
WAKEUP_PINS = {
 | 
			
		||||
@@ -96,8 +94,6 @@ WAKEUP_PINS = {
 | 
			
		||||
        20,
 | 
			
		||||
        21,
 | 
			
		||||
    ],
 | 
			
		||||
    VARIANT_ESP32C2: [0, 1, 2, 3, 4, 5],
 | 
			
		||||
    VARIANT_ESP32C6: [0, 1, 2, 3, 4, 5, 6, 7],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,7 @@ from .const import (  # noqa
 | 
			
		||||
    KEY_SDKCONFIG_OPTIONS,
 | 
			
		||||
    KEY_SUBMODULES,
 | 
			
		||||
    KEY_VARIANT,
 | 
			
		||||
    VARIANT_ESP32C3,
 | 
			
		||||
    VARIANT_FRIENDLY,
 | 
			
		||||
    VARIANTS,
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,17 +14,13 @@ KEY_SUBMODULES = "submodules"
 | 
			
		||||
VARIANT_ESP32 = "ESP32"
 | 
			
		||||
VARIANT_ESP32S2 = "ESP32S2"
 | 
			
		||||
VARIANT_ESP32S3 = "ESP32S3"
 | 
			
		||||
VARIANT_ESP32C2 = "ESP32C2"
 | 
			
		||||
VARIANT_ESP32C3 = "ESP32C3"
 | 
			
		||||
VARIANT_ESP32C6 = "ESP32C6"
 | 
			
		||||
VARIANT_ESP32H2 = "ESP32H2"
 | 
			
		||||
VARIANTS = [
 | 
			
		||||
    VARIANT_ESP32,
 | 
			
		||||
    VARIANT_ESP32S2,
 | 
			
		||||
    VARIANT_ESP32S3,
 | 
			
		||||
    VARIANT_ESP32C2,
 | 
			
		||||
    VARIANT_ESP32C3,
 | 
			
		||||
    VARIANT_ESP32C6,
 | 
			
		||||
    VARIANT_ESP32H2,
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@@ -32,9 +28,7 @@ VARIANT_FRIENDLY = {
 | 
			
		||||
    VARIANT_ESP32: "ESP32",
 | 
			
		||||
    VARIANT_ESP32S2: "ESP32-S2",
 | 
			
		||||
    VARIANT_ESP32S3: "ESP32-S3",
 | 
			
		||||
    VARIANT_ESP32C2: "ESP32-C2",
 | 
			
		||||
    VARIANT_ESP32C3: "ESP32-C3",
 | 
			
		||||
    VARIANT_ESP32C6: "ESP32-C6",
 | 
			
		||||
    VARIANT_ESP32H2: "ESP32-H2",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,9 @@
 | 
			
		||||
#include <esp_timer.h>
 | 
			
		||||
#include <soc/rtc.h>
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
#include <hal/cpu_hal.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ARDUINO
 | 
			
		||||
#include <esp32-hal.h>
 | 
			
		||||
@@ -53,7 +55,15 @@ void arch_init() {
 | 
			
		||||
void IRAM_ATTR HOT arch_feed_wdt() { esp_task_wdt_reset(); }
 | 
			
		||||
 | 
			
		||||
uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; }
 | 
			
		||||
uint32_t arch_get_cpu_cycle_count() { return cpu_hal_get_cycle_count(); }
 | 
			
		||||
uint32_t arch_get_cpu_cycle_count() {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
  return cpu_hal_get_cycle_count();
 | 
			
		||||
#else
 | 
			
		||||
  uint32_t ccount;
 | 
			
		||||
  __asm__ __volatile__("esync; rsr %0,ccount" : "=a"(ccount));
 | 
			
		||||
  return ccount;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
uint32_t arch_get_cpu_freq_hz() { return rtc_clk_apb_freq_get(); }
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP_IDF
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,6 @@ from .const import (
 | 
			
		||||
    VARIANT_ESP32C3,
 | 
			
		||||
    VARIANT_ESP32S2,
 | 
			
		||||
    VARIANT_ESP32S3,
 | 
			
		||||
    VARIANT_ESP32C2,
 | 
			
		||||
    VARIANT_ESP32C6,
 | 
			
		||||
    VARIANT_ESP32H2,
 | 
			
		||||
    esp32_ns,
 | 
			
		||||
)
 | 
			
		||||
@@ -37,8 +35,6 @@ from .gpio_esp32 import esp32_validate_gpio_pin, esp32_validate_supports
 | 
			
		||||
from .gpio_esp32_s2 import esp32_s2_validate_gpio_pin, esp32_s2_validate_supports
 | 
			
		||||
from .gpio_esp32_c3 import esp32_c3_validate_gpio_pin, esp32_c3_validate_supports
 | 
			
		||||
from .gpio_esp32_s3 import esp32_s3_validate_gpio_pin, esp32_s3_validate_supports
 | 
			
		||||
from .gpio_esp32_c2 import esp32_c2_validate_gpio_pin, esp32_c2_validate_supports
 | 
			
		||||
from .gpio_esp32_c6 import esp32_c6_validate_gpio_pin, esp32_c6_validate_supports
 | 
			
		||||
from .gpio_esp32_h2 import esp32_h2_validate_gpio_pin, esp32_h2_validate_supports
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -99,14 +95,6 @@ _esp32_validations = {
 | 
			
		||||
        pin_validation=esp32_s3_validate_gpio_pin,
 | 
			
		||||
        usage_validation=esp32_s3_validate_supports,
 | 
			
		||||
    ),
 | 
			
		||||
    VARIANT_ESP32C2: ESP32ValidationFunctions(
 | 
			
		||||
        pin_validation=esp32_c2_validate_gpio_pin,
 | 
			
		||||
        usage_validation=esp32_c2_validate_supports,
 | 
			
		||||
    ),
 | 
			
		||||
    VARIANT_ESP32C6: ESP32ValidationFunctions(
 | 
			
		||||
        pin_validation=esp32_c6_validate_gpio_pin,
 | 
			
		||||
        usage_validation=esp32_c6_validate_supports,
 | 
			
		||||
    ),
 | 
			
		||||
    VARIANT_ESP32H2: ESP32ValidationFunctions(
 | 
			
		||||
        pin_validation=esp32_h2_validate_gpio_pin,
 | 
			
		||||
        usage_validation=esp32_h2_validate_supports,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,37 +0,0 @@
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER
 | 
			
		||||
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
 | 
			
		||||
_ESP32C2_STRAPPING_PINS = {8, 9}
 | 
			
		||||
 | 
			
		||||
_LOGGER = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def esp32_c2_validate_gpio_pin(value):
 | 
			
		||||
    if value < 0 or value > 20:
 | 
			
		||||
        raise cv.Invalid(f"Invalid pin number: {value} (must be 0-20)")
 | 
			
		||||
    if value in _ESP32C2_STRAPPING_PINS:
 | 
			
		||||
        _LOGGER.warning(
 | 
			
		||||
            "GPIO%d is a Strapping PIN and should be avoided.\n"
 | 
			
		||||
            "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n"
 | 
			
		||||
            "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins",
 | 
			
		||||
            value,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def esp32_c2_validate_supports(value):
 | 
			
		||||
    num = value[CONF_NUMBER]
 | 
			
		||||
    mode = value[CONF_MODE]
 | 
			
		||||
    is_input = mode[CONF_INPUT]
 | 
			
		||||
 | 
			
		||||
    if num < 0 or num > 20:
 | 
			
		||||
        raise cv.Invalid(f"Invalid pin number: {value} (must be 0-20)")
 | 
			
		||||
 | 
			
		||||
    if is_input:
 | 
			
		||||
        # All ESP32 pins support input mode
 | 
			
		||||
        pass
 | 
			
		||||
    return value
 | 
			
		||||
@@ -1,50 +0,0 @@
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER
 | 
			
		||||
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
 | 
			
		||||
_ESP32C6_SPI_PSRAM_PINS = {
 | 
			
		||||
    24: "SPICS0",
 | 
			
		||||
    25: "SPIQ",
 | 
			
		||||
    26: "SPIWP",
 | 
			
		||||
    27: "VDD_SPI",
 | 
			
		||||
    28: "SPIHD",
 | 
			
		||||
    29: "SPICLK",
 | 
			
		||||
    30: "SPID",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
_ESP32C6_STRAPPING_PINS = {8, 9, 15}
 | 
			
		||||
 | 
			
		||||
_LOGGER = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def esp32_c6_validate_gpio_pin(value):
 | 
			
		||||
    if value < 0 or value > 23:
 | 
			
		||||
        raise cv.Invalid(f"Invalid pin number: {value} (must be 0-23)")
 | 
			
		||||
    if value in _ESP32C6_SPI_PSRAM_PINS:
 | 
			
		||||
        raise cv.Invalid(
 | 
			
		||||
            f"This pin cannot be used on ESP32-C6s and is already used by the SPI/PSRAM interface (function: {_ESP32C6_SPI_PSRAM_PINS[value]})"
 | 
			
		||||
        )
 | 
			
		||||
    if value in _ESP32C6_STRAPPING_PINS:
 | 
			
		||||
        _LOGGER.warning(
 | 
			
		||||
            "GPIO%d is a Strapping PIN and should be avoided.\n"
 | 
			
		||||
            "Attaching external pullup/down resistors to strapping pins can cause unexpected failures.\n"
 | 
			
		||||
            "See https://esphome.io/guides/faq.html#why-am-i-getting-a-warning-about-strapping-pins",
 | 
			
		||||
            value,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def esp32_c6_validate_supports(value):
 | 
			
		||||
    num = value[CONF_NUMBER]
 | 
			
		||||
    mode = value[CONF_MODE]
 | 
			
		||||
    is_input = mode[CONF_INPUT]
 | 
			
		||||
 | 
			
		||||
    if num < 0 or num > 23:
 | 
			
		||||
        raise cv.Invalid(f"Invalid pin number: {value} (must be 0-23)")
 | 
			
		||||
    if is_input:
 | 
			
		||||
        # All ESP32 pins support input mode
 | 
			
		||||
        pass
 | 
			
		||||
    return value
 | 
			
		||||
@@ -42,15 +42,9 @@ void BLEAdvertising::remove_service_uuid(ESPBTUUID uuid) {
 | 
			
		||||
                                 this->advertising_uuids_.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BLEAdvertising::set_manufacturer_data(const std::vector<uint8_t> &data) {
 | 
			
		||||
  delete[] this->advertising_data_.p_manufacturer_data;
 | 
			
		||||
  this->advertising_data_.p_manufacturer_data = nullptr;
 | 
			
		||||
  this->advertising_data_.manufacturer_len = data.size();
 | 
			
		||||
  if (!data.empty()) {
 | 
			
		||||
    // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
 | 
			
		||||
    this->advertising_data_.p_manufacturer_data = new uint8_t[data.size()];
 | 
			
		||||
    memcpy(this->advertising_data_.p_manufacturer_data, data.data(), data.size());
 | 
			
		||||
  }
 | 
			
		||||
void BLEAdvertising::set_manufacturer_data(uint8_t *data, uint16_t size) {
 | 
			
		||||
  this->advertising_data_.p_manufacturer_data = data;
 | 
			
		||||
  this->advertising_data_.manufacturer_len = size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BLEAdvertising::start() {
 | 
			
		||||
@@ -80,21 +74,16 @@ void BLEAdvertising::start() {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (this->scan_response_) {
 | 
			
		||||
    memcpy(&this->scan_response_data_, &this->advertising_data_, sizeof(esp_ble_adv_data_t));
 | 
			
		||||
    this->scan_response_data_.set_scan_rsp = true;
 | 
			
		||||
    this->scan_response_data_.include_name = true;
 | 
			
		||||
    this->scan_response_data_.include_txpower = true;
 | 
			
		||||
    this->scan_response_data_.min_interval = 0;
 | 
			
		||||
    this->scan_response_data_.max_interval = 0;
 | 
			
		||||
    this->scan_response_data_.manufacturer_len = 0;
 | 
			
		||||
    this->scan_response_data_.appearance = 0;
 | 
			
		||||
    this->scan_response_data_.flag = 0;
 | 
			
		||||
    err = esp_ble_gap_config_adv_data(&this->scan_response_data_);
 | 
			
		||||
    if (err != ESP_OK) {
 | 
			
		||||
      ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Scan response): %d", err);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  memcpy(&this->scan_response_data_, &this->advertising_data_, sizeof(esp_ble_adv_data_t));
 | 
			
		||||
  this->scan_response_data_.set_scan_rsp = true;
 | 
			
		||||
  this->scan_response_data_.include_name = true;
 | 
			
		||||
  this->scan_response_data_.include_txpower = true;
 | 
			
		||||
  this->scan_response_data_.appearance = 0;
 | 
			
		||||
  this->scan_response_data_.flag = 0;
 | 
			
		||||
  err = esp_ble_gap_config_adv_data(&this->scan_response_data_);
 | 
			
		||||
  if (err != ESP_OK) {
 | 
			
		||||
    ESP_LOGE(TAG, "esp_ble_gap_config_adv_data failed (Scan response): %d", err);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (this->advertising_data_.service_uuid_len > 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ class BLEAdvertising {
 | 
			
		||||
  void remove_service_uuid(ESPBTUUID uuid);
 | 
			
		||||
  void set_scan_response(bool scan_response) { this->scan_response_ = scan_response; }
 | 
			
		||||
  void set_min_preferred_interval(uint16_t interval) { this->advertising_data_.min_interval = interval; }
 | 
			
		||||
  void set_manufacturer_data(const std::vector<uint8_t> &data);
 | 
			
		||||
  void set_manufacturer_data(uint8_t *data, uint16_t size);
 | 
			
		||||
 | 
			
		||||
  void start();
 | 
			
		||||
  void stop();
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,11 @@ from esphome.core import CORE
 | 
			
		||||
from esphome.components.esp32 import add_idf_sdkconfig_option
 | 
			
		||||
 | 
			
		||||
AUTO_LOAD = ["esp32_ble"]
 | 
			
		||||
CODEOWNERS = ["@jesserockz", "@clydebarrow"]
 | 
			
		||||
CODEOWNERS = ["@jesserockz"]
 | 
			
		||||
CONFLICTS_WITH = ["esp32_ble_beacon"]
 | 
			
		||||
DEPENDENCIES = ["esp32"]
 | 
			
		||||
 | 
			
		||||
CONF_MANUFACTURER = "manufacturer"
 | 
			
		||||
CONF_MANUFACTURER_DATA = "manufacturer_data"
 | 
			
		||||
 | 
			
		||||
esp32_ble_server_ns = cg.esphome_ns.namespace("esp32_ble_server")
 | 
			
		||||
BLEServer = esp32_ble_server_ns.class_(
 | 
			
		||||
@@ -28,7 +27,6 @@ CONFIG_SCHEMA = cv.Schema(
 | 
			
		||||
        cv.GenerateID(): cv.declare_id(BLEServer),
 | 
			
		||||
        cv.GenerateID(esp32_ble.CONF_BLE_ID): cv.use_id(esp32_ble.ESP32BLE),
 | 
			
		||||
        cv.Optional(CONF_MANUFACTURER, default="ESPHome"): cv.string,
 | 
			
		||||
        cv.Optional(CONF_MANUFACTURER_DATA): cv.Schema([cv.hex_uint8_t]),
 | 
			
		||||
        cv.Optional(CONF_MODEL): cv.string,
 | 
			
		||||
    }
 | 
			
		||||
).extend(cv.COMPONENT_SCHEMA)
 | 
			
		||||
@@ -44,8 +42,6 @@ async def to_code(config):
 | 
			
		||||
    cg.add(var.set_parent(parent))
 | 
			
		||||
 | 
			
		||||
    cg.add(var.set_manufacturer(config[CONF_MANUFACTURER]))
 | 
			
		||||
    if CONF_MANUFACTURER_DATA in config:
 | 
			
		||||
        cg.add(var.set_manufacturer_data(config[CONF_MANUFACTURER_DATA]))
 | 
			
		||||
    if CONF_MODEL in config:
 | 
			
		||||
        cg.add(var.set_model(config[CONF_MODEL]))
 | 
			
		||||
    cg.add_define("USE_ESP32_BLE_SERVER")
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,6 @@ void BLEServer::loop() {
 | 
			
		||||
      if (this->device_information_service_->is_running()) {
 | 
			
		||||
        this->state_ = RUNNING;
 | 
			
		||||
        this->can_proceed_ = true;
 | 
			
		||||
        this->restart_advertising_();
 | 
			
		||||
        ESP_LOGD(TAG, "BLE server setup successfully");
 | 
			
		||||
      } else if (!this->device_information_service_->is_starting()) {
 | 
			
		||||
        this->device_information_service_->start();
 | 
			
		||||
@@ -78,13 +77,6 @@ void BLEServer::loop() {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BLEServer::restart_advertising_() {
 | 
			
		||||
  if (this->state_ == RUNNING) {
 | 
			
		||||
    esp32_ble::global_ble->get_advertising()->set_manufacturer_data(this->manufacturer_data_);
 | 
			
		||||
    esp32_ble::global_ble->get_advertising()->start();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool BLEServer::create_device_characteristics_() {
 | 
			
		||||
  if (this->model_.has_value()) {
 | 
			
		||||
    BLECharacteristic *model =
 | 
			
		||||
 
 | 
			
		||||
@@ -45,10 +45,6 @@ class BLEServer : public Component, public GATTsEventHandler, public Parented<ES
 | 
			
		||||
 | 
			
		||||
  void set_manufacturer(const std::string &manufacturer) { this->manufacturer_ = manufacturer; }
 | 
			
		||||
  void set_model(const std::string &model) { this->model_ = model; }
 | 
			
		||||
  void set_manufacturer_data(const std::vector<uint8_t> &data) {
 | 
			
		||||
    this->manufacturer_data_ = data;
 | 
			
		||||
    this->restart_advertising_();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::shared_ptr<BLEService> create_service(const uint8_t *uuid, bool advertise = false);
 | 
			
		||||
  std::shared_ptr<BLEService> create_service(uint16_t uuid, bool advertise = false);
 | 
			
		||||
@@ -67,7 +63,6 @@ class BLEServer : public Component, public GATTsEventHandler, public Parented<ES
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  bool create_device_characteristics_();
 | 
			
		||||
  void restart_advertising_();
 | 
			
		||||
 | 
			
		||||
  void add_client_(uint16_t conn_id, void *client) {
 | 
			
		||||
    this->clients_.insert(std::pair<uint16_t, void *>(conn_id, client));
 | 
			
		||||
@@ -78,7 +73,6 @@ class BLEServer : public Component, public GATTsEventHandler, public Parented<ES
 | 
			
		||||
 | 
			
		||||
  std::string manufacturer_;
 | 
			
		||||
  optional<std::string> model_;
 | 
			
		||||
  std::vector<uint8_t> manufacturer_data_;
 | 
			
		||||
  esp_gatt_if_t gatts_if_{0};
 | 
			
		||||
  bool registered_{false};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,6 @@ RMT_CHANNELS = {
 | 
			
		||||
    esp32.const.VARIANT_ESP32S2: [0, 1, 2, 3],
 | 
			
		||||
    esp32.const.VARIANT_ESP32S3: [0, 1, 2, 3],
 | 
			
		||||
    esp32.const.VARIANT_ESP32C3: [0, 1],
 | 
			
		||||
    esp32.const.VARIANT_ESP32C6: [0, 1],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,11 @@
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
#include <driver/touch_sensor.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <driver/touch_pad.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace esp32_touch {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
 | 
			
		||||
from esphome.components import esp32
 | 
			
		||||
 | 
			
		||||
from esphome.const import CONF_ID
 | 
			
		||||
 | 
			
		||||
CONFLICTS_WITH = ["i2s_audio"]
 | 
			
		||||
CODEOWNERS = ["@jesserockz"]
 | 
			
		||||
DEPENDENCIES = ["esp32"]
 | 
			
		||||
 | 
			
		||||
CONF_ESP_ADF_ID = "esp_adf_id"
 | 
			
		||||
 | 
			
		||||
esp_adf_ns = cg.esphome_ns.namespace("esp_adf")
 | 
			
		||||
ESPADF = esp_adf_ns.class_("ESPADF", cg.Component)
 | 
			
		||||
ESPADFPipeline = esp_adf_ns.class_("ESPADFPipeline", cg.Parented.template(ESPADF))
 | 
			
		||||
 | 
			
		||||
SUPPORTED_BOARDS = {"esp32s3box": "CONFIG_ESP32_S3_BOX_BOARD"}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _validate_board(config):
 | 
			
		||||
    board = esp32.get_board()
 | 
			
		||||
    if board not in SUPPORTED_BOARDS:
 | 
			
		||||
        raise cv.Invalid(f"Board {board} is not supported by esp-adf")
 | 
			
		||||
    return config
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    cv.Schema({cv.GenerateID(): cv.declare_id(ESPADF)}),
 | 
			
		||||
    _validate_board,
 | 
			
		||||
    cv.only_with_esp_idf,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
			
		||||
    await cg.register_component(var, config)
 | 
			
		||||
 | 
			
		||||
    cg.add_define("USE_ESP_ADF")
 | 
			
		||||
 | 
			
		||||
    cg.add_platformio_option("build_unflags", "-Wl,--end-group")
 | 
			
		||||
 | 
			
		||||
    esp32.add_idf_component(
 | 
			
		||||
        name="esp-adf",
 | 
			
		||||
        repo="https://github.com/espressif/esp-adf",
 | 
			
		||||
        path="components",
 | 
			
		||||
        ref="v2.5",
 | 
			
		||||
        components=["*"],
 | 
			
		||||
        submodules=["components/esp-sr", "components/esp-adf-libs"],
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    esp32.add_idf_component(
 | 
			
		||||
        name="esp-dsp",
 | 
			
		||||
        repo="https://github.com/espressif/esp-dsp",
 | 
			
		||||
        ref="v1.2.0",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    cg.add_platformio_option(
 | 
			
		||||
        "board_build.embed_txtfiles", "components/dueros_service/duer_profile"
 | 
			
		||||
    )
 | 
			
		||||
    esp32.add_idf_sdkconfig_option(SUPPORTED_BOARDS[esp32.get_board()], True)
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
#include "esp_adf.h"
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP_IDF
 | 
			
		||||
 | 
			
		||||
#include <board.h>
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace esp_adf {
 | 
			
		||||
 | 
			
		||||
static const char *const TAG = "esp_adf";
 | 
			
		||||
 | 
			
		||||
void ESPADF::setup() {
 | 
			
		||||
  ESP_LOGI(TAG, "Start codec chip");
 | 
			
		||||
 | 
			
		||||
  audio_board_handle_t board_handle = audio_board_init();
 | 
			
		||||
  audio_hal_ctrl_codec(board_handle->audio_hal, AUDIO_HAL_CODEC_MODE_BOTH, AUDIO_HAL_CTRL_START);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float ESPADF::get_setup_priority() const { return setup_priority::HARDWARE; }
 | 
			
		||||
 | 
			
		||||
}  // namespace esp_adf
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,31 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP_IDF
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/core/helpers.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace esp_adf {
 | 
			
		||||
class ESPADF;
 | 
			
		||||
 | 
			
		||||
class ESPADFPipeline : public Parented<ESPADF> {};
 | 
			
		||||
 | 
			
		||||
class ESPADF : public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void setup() override;
 | 
			
		||||
 | 
			
		||||
  float get_setup_priority() const override;
 | 
			
		||||
 | 
			
		||||
  void lock() { this->lock_.lock(); }
 | 
			
		||||
  bool try_lock() { return this->lock_.try_lock(); }
 | 
			
		||||
  void unlock() { this->lock_.unlock(); }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  Mutex lock_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace esp_adf
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import microphone
 | 
			
		||||
from esphome.const import CONF_ID
 | 
			
		||||
 | 
			
		||||
from .. import CONF_ESP_ADF_ID, ESPADF, ESPADFPipeline, esp_adf_ns
 | 
			
		||||
 | 
			
		||||
AUTO_LOAD = ["esp_adf"]
 | 
			
		||||
DEPENDENCIES = ["esp32"]
 | 
			
		||||
 | 
			
		||||
ESPADFMicrophone = esp_adf_ns.class_(
 | 
			
		||||
    "ESPADFMicrophone", ESPADFPipeline, microphone.Microphone, cg.Component
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    microphone.MICROPHONE_SCHEMA.extend(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(ESPADFMicrophone),
 | 
			
		||||
            cv.GenerateID(CONF_ESP_ADF_ID): cv.use_id(ESPADF),
 | 
			
		||||
        }
 | 
			
		||||
    ).extend(cv.COMPONENT_SCHEMA),
 | 
			
		||||
    cv.only_with_esp_idf,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
			
		||||
    await cg.register_component(var, config)
 | 
			
		||||
    await cg.register_parented(var, config[CONF_ESP_ADF_ID])
 | 
			
		||||
 | 
			
		||||
    await microphone.register_microphone(var, config)
 | 
			
		||||
@@ -1,192 +0,0 @@
 | 
			
		||||
#include "esp_adf_microphone.h"
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP32
 | 
			
		||||
 | 
			
		||||
#include <driver/i2s.h>
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/hal.h"
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
 | 
			
		||||
#include <audio_hal.h>
 | 
			
		||||
#include <filter_resample.h>
 | 
			
		||||
#include <i2s_stream.h>
 | 
			
		||||
#include <raw_stream.h>
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace esp_adf {
 | 
			
		||||
 | 
			
		||||
static const size_t BUFFER_SIZE = 1024;
 | 
			
		||||
 | 
			
		||||
static const char *const TAG = "esp_adf.microphone";
 | 
			
		||||
 | 
			
		||||
void ESPADFMicrophone::start() {
 | 
			
		||||
  if (this->is_failed())
 | 
			
		||||
    return;
 | 
			
		||||
  if (this->state_ == microphone::STATE_STOPPING) {
 | 
			
		||||
    ESP_LOGW(TAG, "Microphone is stopping, cannot start.");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  this->state_ = microphone::STATE_STARTING;
 | 
			
		||||
}
 | 
			
		||||
void ESPADFMicrophone::start_() {
 | 
			
		||||
  if (!this->parent_->try_lock()) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  i2s_driver_config_t i2s_config = {
 | 
			
		||||
      .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX),
 | 
			
		||||
      .sample_rate = 44100,
 | 
			
		||||
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
 | 
			
		||||
      .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
 | 
			
		||||
      .communication_format = I2S_COMM_FORMAT_STAND_I2S,
 | 
			
		||||
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_IRAM,
 | 
			
		||||
      .dma_buf_count = 3,
 | 
			
		||||
      .dma_buf_len = 300,
 | 
			
		||||
      .use_apll = false,
 | 
			
		||||
      .tx_desc_auto_clear = true,
 | 
			
		||||
      .fixed_mclk = 0,
 | 
			
		||||
      .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
 | 
			
		||||
      .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Init pipeline");
 | 
			
		||||
  audio_pipeline_cfg_t pipeline_cfg = {
 | 
			
		||||
      .rb_size = 8 * 1024,
 | 
			
		||||
  };
 | 
			
		||||
  this->pipeline_ = audio_pipeline_init(&pipeline_cfg);
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Init i2s stream");
 | 
			
		||||
  i2s_stream_cfg_t i2s_cfg = {
 | 
			
		||||
      .type = AUDIO_STREAM_READER,
 | 
			
		||||
      .i2s_config = i2s_config,
 | 
			
		||||
      .i2s_port = I2S_NUM_0,
 | 
			
		||||
      .use_alc = false,
 | 
			
		||||
      .volume = 0,
 | 
			
		||||
      .out_rb_size = I2S_STREAM_RINGBUFFER_SIZE,
 | 
			
		||||
      .task_stack = I2S_STREAM_TASK_STACK,
 | 
			
		||||
      .task_core = I2S_STREAM_TASK_CORE,
 | 
			
		||||
      .task_prio = I2S_STREAM_TASK_PRIO,
 | 
			
		||||
      .stack_in_ext = false,
 | 
			
		||||
      .multi_out_num = 0,
 | 
			
		||||
      .uninstall_drv = true,
 | 
			
		||||
      .need_expand = false,
 | 
			
		||||
      .expand_src_bits = I2S_BITS_PER_SAMPLE_16BIT,
 | 
			
		||||
  };
 | 
			
		||||
  this->i2s_stream_reader_ = i2s_stream_init(&i2s_cfg);
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Init filter");
 | 
			
		||||
  rsp_filter_cfg_t rsp_cfg = {
 | 
			
		||||
      .src_rate = 44100,
 | 
			
		||||
      .src_ch = 2,
 | 
			
		||||
      .dest_rate = 16000,
 | 
			
		||||
      .dest_bits = 16,
 | 
			
		||||
      .dest_ch = 1,
 | 
			
		||||
      .src_bits = 16,
 | 
			
		||||
      .mode = RESAMPLE_DECODE_MODE,
 | 
			
		||||
      .max_indata_bytes = RSP_FILTER_BUFFER_BYTE,
 | 
			
		||||
      .out_len_bytes = RSP_FILTER_BUFFER_BYTE,
 | 
			
		||||
      .type = ESP_RESAMPLE_TYPE_AUTO,
 | 
			
		||||
      .complexity = 2,
 | 
			
		||||
      .down_ch_idx = 0,
 | 
			
		||||
      .prefer_flag = ESP_RSP_PREFER_TYPE_SPEED,
 | 
			
		||||
      .out_rb_size = RSP_FILTER_RINGBUFFER_SIZE,
 | 
			
		||||
      .task_stack = RSP_FILTER_TASK_STACK,
 | 
			
		||||
      .task_core = RSP_FILTER_TASK_CORE,
 | 
			
		||||
      .task_prio = RSP_FILTER_TASK_PRIO,
 | 
			
		||||
      .stack_in_ext = true,
 | 
			
		||||
  };
 | 
			
		||||
  this->filter_ = rsp_filter_init(&rsp_cfg);
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Init raw stream");
 | 
			
		||||
  raw_stream_cfg_t raw_cfg = {
 | 
			
		||||
      .type = AUDIO_STREAM_READER,
 | 
			
		||||
      .out_rb_size = 8 * 1024,
 | 
			
		||||
  };
 | 
			
		||||
  this->raw_read_ = raw_stream_init(&raw_cfg);
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Register all elements to audio pipeline");
 | 
			
		||||
  audio_pipeline_register(this->pipeline_, this->i2s_stream_reader_, "i2s");
 | 
			
		||||
  audio_pipeline_register(this->pipeline_, this->filter_, "filter");
 | 
			
		||||
  audio_pipeline_register(this->pipeline_, this->raw_read_, "raw");
 | 
			
		||||
 | 
			
		||||
  const char *link_tag[3] = {"i2s", "filter", "raw"};
 | 
			
		||||
  audio_pipeline_link(this->pipeline_, &link_tag[0], 3);
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Starting pipeline");
 | 
			
		||||
  audio_pipeline_run(this->pipeline_);
 | 
			
		||||
 | 
			
		||||
  this->state_ = microphone::STATE_RUNNING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFMicrophone::stop() {
 | 
			
		||||
  if (this->state_ == microphone::STATE_STOPPED || this->is_failed())
 | 
			
		||||
    return;
 | 
			
		||||
  if (this->state_ == microphone::STATE_STARTING) {
 | 
			
		||||
    this->state_ = microphone::STATE_STOPPED;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  this->state_ = microphone::STATE_STOPPING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFMicrophone::stop_() {
 | 
			
		||||
  ESP_LOGD(TAG, "Stopping microphone");
 | 
			
		||||
  audio_pipeline_stop(this->pipeline_);
 | 
			
		||||
  audio_pipeline_wait_for_stop(this->pipeline_);
 | 
			
		||||
  audio_pipeline_terminate(this->pipeline_);
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_unregister(this->pipeline_, this->i2s_stream_reader_);
 | 
			
		||||
  audio_pipeline_unregister(this->pipeline_, this->filter_);
 | 
			
		||||
  audio_pipeline_unregister(this->pipeline_, this->raw_read_);
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_deinit(this->pipeline_);
 | 
			
		||||
  audio_element_deinit(this->i2s_stream_reader_);
 | 
			
		||||
  audio_element_deinit(this->filter_);
 | 
			
		||||
  audio_element_deinit(this->raw_read_);
 | 
			
		||||
 | 
			
		||||
  this->parent_->unlock();
 | 
			
		||||
  this->state_ = microphone::STATE_STOPPED;
 | 
			
		||||
  ESP_LOGD(TAG, "Microphone stopped");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t ESPADFMicrophone::read(int16_t *buf, size_t len) {
 | 
			
		||||
  int bytes_read = raw_stream_read(this->raw_read_, (char *) buf, len);
 | 
			
		||||
 | 
			
		||||
  if (bytes_read == ESP_FAIL) {
 | 
			
		||||
    ESP_LOGW(TAG, "Error reading from I2S microphone");
 | 
			
		||||
    this->status_set_warning();
 | 
			
		||||
    return ESP_FAIL;
 | 
			
		||||
  }
 | 
			
		||||
  this->status_clear_warning();
 | 
			
		||||
 | 
			
		||||
  return bytes_read;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFMicrophone::read_() {
 | 
			
		||||
  std::vector<int16_t> samples;
 | 
			
		||||
  samples.resize(BUFFER_SIZE);
 | 
			
		||||
  this->read(samples.data(), samples.size());
 | 
			
		||||
 | 
			
		||||
  this->data_callbacks_.call(samples);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFMicrophone::loop() {
 | 
			
		||||
  switch (this->state_) {
 | 
			
		||||
    case microphone::STATE_STOPPED:
 | 
			
		||||
      break;
 | 
			
		||||
    case microphone::STATE_STARTING:
 | 
			
		||||
      this->start_();
 | 
			
		||||
      break;
 | 
			
		||||
    case microphone::STATE_RUNNING:
 | 
			
		||||
      if (this->data_callbacks_.size() > 0) {
 | 
			
		||||
        this->read_();
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case microphone::STATE_STOPPING:
 | 
			
		||||
      this->stop_();
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace esp_adf
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif  // USE_ESP32
 | 
			
		||||
@@ -1,37 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP32
 | 
			
		||||
 | 
			
		||||
#include "../esp_adf.h"
 | 
			
		||||
 | 
			
		||||
#include "esphome/components/microphone/microphone.h"
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
 | 
			
		||||
#include <audio_element.h>
 | 
			
		||||
#include <audio_pipeline.h>
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace esp_adf {
 | 
			
		||||
 | 
			
		||||
class ESPADFMicrophone : public ESPADFPipeline, public microphone::Microphone, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  void start() override;
 | 
			
		||||
  void stop() override;
 | 
			
		||||
 | 
			
		||||
  void loop() override;
 | 
			
		||||
 | 
			
		||||
  size_t read(int16_t *buf, size_t len) override;
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void start_();
 | 
			
		||||
  void stop_();
 | 
			
		||||
  void read_();
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_handle_t pipeline_;
 | 
			
		||||
  audio_element_handle_t i2s_stream_reader_, filter_, raw_read_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace esp_adf
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif  // USE_ESP32
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import speaker
 | 
			
		||||
from esphome.const import CONF_ID
 | 
			
		||||
 | 
			
		||||
from .. import CONF_ESP_ADF_ID, ESPADF, ESPADFPipeline, esp_adf_ns
 | 
			
		||||
 | 
			
		||||
AUTO_LOAD = ["esp_adf"]
 | 
			
		||||
DEPENDENCIES = ["esp32"]
 | 
			
		||||
 | 
			
		||||
ESPADFSpeaker = esp_adf_ns.class_(
 | 
			
		||||
    "ESPADFSpeaker", ESPADFPipeline, speaker.Speaker, cg.Component
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = cv.All(
 | 
			
		||||
    cv.Schema(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(ESPADFSpeaker),
 | 
			
		||||
            cv.GenerateID(CONF_ESP_ADF_ID): cv.use_id(ESPADF),
 | 
			
		||||
        }
 | 
			
		||||
    ).extend(cv.COMPONENT_SCHEMA),
 | 
			
		||||
    cv.only_with_esp_idf,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
			
		||||
    await cg.register_component(var, config)
 | 
			
		||||
    await cg.register_parented(var, config[CONF_ESP_ADF_ID])
 | 
			
		||||
 | 
			
		||||
    await speaker.register_speaker(var, config)
 | 
			
		||||
@@ -1,272 +0,0 @@
 | 
			
		||||
#include "esp_adf_speaker.h"
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP32
 | 
			
		||||
 | 
			
		||||
#include <driver/i2s.h>
 | 
			
		||||
 | 
			
		||||
#include "esphome/core/application.h"
 | 
			
		||||
#include "esphome/core/hal.h"
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
 | 
			
		||||
#include <audio_hal.h>
 | 
			
		||||
#include <filter_resample.h>
 | 
			
		||||
#include <i2s_stream.h>
 | 
			
		||||
#include <raw_stream.h>
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace esp_adf {
 | 
			
		||||
 | 
			
		||||
static const size_t BUFFER_COUNT = 50;
 | 
			
		||||
 | 
			
		||||
static const char *const TAG = "esp_adf.speaker";
 | 
			
		||||
 | 
			
		||||
void ESPADFSpeaker::setup() {
 | 
			
		||||
  ESP_LOGCONFIG(TAG, "Setting up ESP ADF Speaker...");
 | 
			
		||||
 | 
			
		||||
  this->buffer_queue_ = xQueueCreate(BUFFER_COUNT, sizeof(DataEvent));
 | 
			
		||||
  this->event_queue_ = xQueueCreate(20, sizeof(TaskEvent));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFSpeaker::start() { this->state_ = speaker::STATE_STARTING; }
 | 
			
		||||
void ESPADFSpeaker::start_() {
 | 
			
		||||
  if (!this->parent_->try_lock()) {
 | 
			
		||||
    return;  // Waiting for another i2s component to return lock
 | 
			
		||||
  }
 | 
			
		||||
  this->state_ = speaker::STATE_RUNNING;
 | 
			
		||||
 | 
			
		||||
  xTaskCreate(ESPADFSpeaker::player_task, "speaker_task", 8192, (void *) this, 0, &this->player_task_handle_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFSpeaker::player_task(void *params) {
 | 
			
		||||
  ESPADFSpeaker *this_speaker = (ESPADFSpeaker *) params;
 | 
			
		||||
 | 
			
		||||
  TaskEvent event;
 | 
			
		||||
  event.type = TaskEventType::STARTING;
 | 
			
		||||
  xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY);
 | 
			
		||||
 | 
			
		||||
  i2s_driver_config_t i2s_config = {
 | 
			
		||||
      .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_TX),
 | 
			
		||||
      .sample_rate = 16000,
 | 
			
		||||
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
 | 
			
		||||
      .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
 | 
			
		||||
      .communication_format = I2S_COMM_FORMAT_STAND_I2S,
 | 
			
		||||
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_IRAM,
 | 
			
		||||
      .dma_buf_count = 8,
 | 
			
		||||
      .dma_buf_len = 1024,
 | 
			
		||||
      .use_apll = false,
 | 
			
		||||
      .tx_desc_auto_clear = true,
 | 
			
		||||
      .fixed_mclk = 0,
 | 
			
		||||
      .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
 | 
			
		||||
      .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_cfg_t pipeline_cfg = {
 | 
			
		||||
      .rb_size = 8 * 1024,
 | 
			
		||||
  };
 | 
			
		||||
  audio_pipeline_handle_t pipeline = audio_pipeline_init(&pipeline_cfg);
 | 
			
		||||
 | 
			
		||||
  i2s_stream_cfg_t i2s_cfg = {
 | 
			
		||||
      .type = AUDIO_STREAM_WRITER,
 | 
			
		||||
      .i2s_config = i2s_config,
 | 
			
		||||
      .i2s_port = I2S_NUM_0,
 | 
			
		||||
      .use_alc = false,
 | 
			
		||||
      .volume = 0,
 | 
			
		||||
      .out_rb_size = I2S_STREAM_RINGBUFFER_SIZE,
 | 
			
		||||
      .task_stack = I2S_STREAM_TASK_STACK,
 | 
			
		||||
      .task_core = I2S_STREAM_TASK_CORE,
 | 
			
		||||
      .task_prio = I2S_STREAM_TASK_PRIO,
 | 
			
		||||
      .stack_in_ext = false,
 | 
			
		||||
      .multi_out_num = 0,
 | 
			
		||||
      .uninstall_drv = true,
 | 
			
		||||
      .need_expand = false,
 | 
			
		||||
      .expand_src_bits = I2S_BITS_PER_SAMPLE_16BIT,
 | 
			
		||||
  };
 | 
			
		||||
  audio_element_handle_t i2s_stream_writer = i2s_stream_init(&i2s_cfg);
 | 
			
		||||
 | 
			
		||||
  rsp_filter_cfg_t rsp_cfg = {
 | 
			
		||||
      .src_rate = 16000,
 | 
			
		||||
      .src_ch = 1,
 | 
			
		||||
      .dest_rate = 16000,
 | 
			
		||||
      .dest_bits = 16,
 | 
			
		||||
      .dest_ch = 2,
 | 
			
		||||
      .src_bits = 16,
 | 
			
		||||
      .mode = RESAMPLE_DECODE_MODE,
 | 
			
		||||
      .max_indata_bytes = RSP_FILTER_BUFFER_BYTE,
 | 
			
		||||
      .out_len_bytes = RSP_FILTER_BUFFER_BYTE,
 | 
			
		||||
      .type = ESP_RESAMPLE_TYPE_AUTO,
 | 
			
		||||
      .complexity = 2,
 | 
			
		||||
      .down_ch_idx = 0,
 | 
			
		||||
      .prefer_flag = ESP_RSP_PREFER_TYPE_SPEED,
 | 
			
		||||
      .out_rb_size = RSP_FILTER_RINGBUFFER_SIZE,
 | 
			
		||||
      .task_stack = RSP_FILTER_TASK_STACK,
 | 
			
		||||
      .task_core = RSP_FILTER_TASK_CORE,
 | 
			
		||||
      .task_prio = RSP_FILTER_TASK_PRIO,
 | 
			
		||||
      .stack_in_ext = true,
 | 
			
		||||
  };
 | 
			
		||||
  audio_element_handle_t filter = rsp_filter_init(&rsp_cfg);
 | 
			
		||||
 | 
			
		||||
  raw_stream_cfg_t raw_cfg = {
 | 
			
		||||
      .type = AUDIO_STREAM_WRITER,
 | 
			
		||||
      .out_rb_size = 8 * 1024,
 | 
			
		||||
  };
 | 
			
		||||
  audio_element_handle_t raw_write = raw_stream_init(&raw_cfg);
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_register(pipeline, raw_write, "raw");
 | 
			
		||||
  audio_pipeline_register(pipeline, filter, "filter");
 | 
			
		||||
  audio_pipeline_register(pipeline, i2s_stream_writer, "i2s");
 | 
			
		||||
 | 
			
		||||
  const char *link_tag[3] = {
 | 
			
		||||
      "raw",
 | 
			
		||||
      // "filter",
 | 
			
		||||
      "i2s",
 | 
			
		||||
  };
 | 
			
		||||
  audio_pipeline_link(pipeline, &link_tag[0], 2);
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_run(pipeline);
 | 
			
		||||
 | 
			
		||||
  DataEvent data_event;
 | 
			
		||||
 | 
			
		||||
  event.type = TaskEventType::STARTED;
 | 
			
		||||
  xQueueSend(this_speaker->event_queue_, &event, 0);
 | 
			
		||||
 | 
			
		||||
  uint32_t last_received = millis();
 | 
			
		||||
 | 
			
		||||
  while (true) {
 | 
			
		||||
    if (xQueueReceive(this_speaker->buffer_queue_, &data_event, 0) != pdTRUE) {
 | 
			
		||||
      if (millis() - last_received > 100) {
 | 
			
		||||
        // No audio for 100ms, stop
 | 
			
		||||
        break;
 | 
			
		||||
      } else {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (data_event.stop) {
 | 
			
		||||
      // Stop signal from main thread
 | 
			
		||||
      while (xQueueReceive(this_speaker->buffer_queue_, &data_event, 0) == pdTRUE) {
 | 
			
		||||
        // Flush queue
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t remaining = data_event.len;
 | 
			
		||||
    size_t current = 0;
 | 
			
		||||
    if (remaining > 0)
 | 
			
		||||
      last_received = millis();
 | 
			
		||||
 | 
			
		||||
    while (remaining > 0) {
 | 
			
		||||
      int bytes_written = raw_stream_write(raw_write, (char *) data_event.data + current, remaining);
 | 
			
		||||
      if (bytes_written == ESP_FAIL) {
 | 
			
		||||
        event = {.type = TaskEventType::WARNING, .err = ESP_FAIL};
 | 
			
		||||
        xQueueSend(this_speaker->event_queue_, &event, 0);
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      remaining -= bytes_written;
 | 
			
		||||
      current += bytes_written;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    event.type = TaskEventType::PLAYING;
 | 
			
		||||
    xQueueSend(this_speaker->event_queue_, &event, 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_stop(pipeline);
 | 
			
		||||
  audio_pipeline_wait_for_stop(pipeline);
 | 
			
		||||
  audio_pipeline_terminate(pipeline);
 | 
			
		||||
 | 
			
		||||
  event.type = TaskEventType::STOPPING;
 | 
			
		||||
  xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY);
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_unregister(pipeline, i2s_stream_writer);
 | 
			
		||||
  audio_pipeline_unregister(pipeline, filter);
 | 
			
		||||
  audio_pipeline_unregister(pipeline, raw_write);
 | 
			
		||||
 | 
			
		||||
  audio_pipeline_deinit(pipeline);
 | 
			
		||||
  audio_element_deinit(i2s_stream_writer);
 | 
			
		||||
  audio_element_deinit(filter);
 | 
			
		||||
  audio_element_deinit(raw_write);
 | 
			
		||||
 | 
			
		||||
  event.type = TaskEventType::STOPPED;
 | 
			
		||||
  xQueueSend(this_speaker->event_queue_, &event, portMAX_DELAY);
 | 
			
		||||
 | 
			
		||||
  while (true) {
 | 
			
		||||
    delay(10);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFSpeaker::stop() {
 | 
			
		||||
  if (this->state_ == speaker::STATE_STOPPED)
 | 
			
		||||
    return;
 | 
			
		||||
  if (this->state_ == speaker::STATE_STARTING) {
 | 
			
		||||
    this->state_ = speaker::STATE_STOPPED;
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  this->state_ = speaker::STATE_STOPPING;
 | 
			
		||||
  DataEvent data;
 | 
			
		||||
  data.stop = true;
 | 
			
		||||
  xQueueSendToFront(this->buffer_queue_, &data, portMAX_DELAY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFSpeaker::watch_() {
 | 
			
		||||
  TaskEvent event;
 | 
			
		||||
  if (xQueueReceive(this->event_queue_, &event, 0) == pdTRUE) {
 | 
			
		||||
    switch (event.type) {
 | 
			
		||||
      case TaskEventType::STARTING:
 | 
			
		||||
      case TaskEventType::STARTED:
 | 
			
		||||
      case TaskEventType::STOPPING:
 | 
			
		||||
        break;
 | 
			
		||||
      case TaskEventType::PLAYING:
 | 
			
		||||
        this->status_clear_warning();
 | 
			
		||||
        break;
 | 
			
		||||
      case TaskEventType::STOPPED:
 | 
			
		||||
        this->parent_->unlock();
 | 
			
		||||
        this->state_ = speaker::STATE_STOPPED;
 | 
			
		||||
        vTaskDelete(this->player_task_handle_);
 | 
			
		||||
        this->player_task_handle_ = nullptr;
 | 
			
		||||
        break;
 | 
			
		||||
      case TaskEventType::WARNING:
 | 
			
		||||
        ESP_LOGW(TAG, "Error writing to pipeline: %s", esp_err_to_name(event.err));
 | 
			
		||||
        this->status_set_warning();
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ESPADFSpeaker::loop() {
 | 
			
		||||
  switch (this->state_) {
 | 
			
		||||
    case speaker::STATE_STARTING:
 | 
			
		||||
      this->start_();
 | 
			
		||||
      break;
 | 
			
		||||
    case speaker::STATE_RUNNING:
 | 
			
		||||
      this->watch_();
 | 
			
		||||
      break;
 | 
			
		||||
    case speaker::STATE_STOPPING:
 | 
			
		||||
    case speaker::STATE_STOPPED:
 | 
			
		||||
      break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t ESPADFSpeaker::play(const uint8_t *data, size_t length) {
 | 
			
		||||
  if (this->state_ != speaker::STATE_RUNNING && this->state_ != speaker::STATE_STARTING) {
 | 
			
		||||
    this->start();
 | 
			
		||||
  }
 | 
			
		||||
  size_t remaining = length;
 | 
			
		||||
  size_t index = 0;
 | 
			
		||||
  while (remaining > 0) {
 | 
			
		||||
    DataEvent event;
 | 
			
		||||
    event.stop = false;
 | 
			
		||||
    size_t to_send_length = std::min(remaining, BUFFER_SIZE);
 | 
			
		||||
    event.len = to_send_length;
 | 
			
		||||
    memcpy(event.data, data + index, to_send_length);
 | 
			
		||||
    if (xQueueSend(this->buffer_queue_, &event, 0) != pdTRUE) {
 | 
			
		||||
      return index;  // Queue full
 | 
			
		||||
    }
 | 
			
		||||
    remaining -= to_send_length;
 | 
			
		||||
    index += to_send_length;
 | 
			
		||||
  }
 | 
			
		||||
  return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace esp_adf
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif  // USE_ESP32
 | 
			
		||||
@@ -1,68 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP32
 | 
			
		||||
 | 
			
		||||
#include "../esp_adf.h"
 | 
			
		||||
 | 
			
		||||
#include <freertos/FreeRTOS.h>
 | 
			
		||||
#include <freertos/queue.h>
 | 
			
		||||
 | 
			
		||||
#include "esphome/components/speaker/speaker.h"
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/core/helpers.h"
 | 
			
		||||
 | 
			
		||||
#include <audio_element.h>
 | 
			
		||||
#include <audio_pipeline.h>
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace esp_adf {
 | 
			
		||||
 | 
			
		||||
static const size_t BUFFER_SIZE = 1024;
 | 
			
		||||
 | 
			
		||||
enum class TaskEventType : uint8_t {
 | 
			
		||||
  STARTING = 0,
 | 
			
		||||
  STARTED,
 | 
			
		||||
  PLAYING,
 | 
			
		||||
  STOPPING,
 | 
			
		||||
  STOPPED,
 | 
			
		||||
  WARNING = 255,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct TaskEvent {
 | 
			
		||||
  TaskEventType type;
 | 
			
		||||
  esp_err_t err;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct DataEvent {
 | 
			
		||||
  bool stop;
 | 
			
		||||
  size_t len;
 | 
			
		||||
  uint8_t data[BUFFER_SIZE];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ESPADFSpeaker : public ESPADFPipeline, public speaker::Speaker, public Component {
 | 
			
		||||
 public:
 | 
			
		||||
  float get_setup_priority() const override { return esphome::setup_priority::LATE; }
 | 
			
		||||
 | 
			
		||||
  void setup() override;
 | 
			
		||||
  void loop() override;
 | 
			
		||||
 | 
			
		||||
  void start() override;
 | 
			
		||||
  void stop() override;
 | 
			
		||||
 | 
			
		||||
  size_t play(const uint8_t *data, size_t length) override;
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void start_();
 | 
			
		||||
  void watch_();
 | 
			
		||||
 | 
			
		||||
  static void player_task(void *params);
 | 
			
		||||
 | 
			
		||||
  TaskHandle_t player_task_handle_{nullptr};
 | 
			
		||||
  QueueHandle_t buffer_queue_;
 | 
			
		||||
  QueueHandle_t event_queue_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace esp_adf
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 | 
			
		||||
#endif  // USE_ESP32
 | 
			
		||||
@@ -89,7 +89,7 @@ SUPPORTED_SWING_MODES_OPTIONS = {
 | 
			
		||||
 | 
			
		||||
SUPPORTED_CLIMATE_MODES_OPTIONS = {
 | 
			
		||||
    "OFF": ClimateMode.CLIMATE_MODE_OFF,  # always available
 | 
			
		||||
    "HEAT_COOL": ClimateMode.CLIMATE_MODE_HEAT_COOL,  # always available
 | 
			
		||||
    "AUTO": ClimateMode.CLIMATE_MODE_AUTO,  # always available
 | 
			
		||||
    "COOL": ClimateMode.CLIMATE_MODE_COOL,
 | 
			
		||||
    "HEAT": ClimateMode.CLIMATE_MODE_HEAT,
 | 
			
		||||
    "DRY": ClimateMode.CLIMATE_MODE_DRY,
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,7 @@ HaierClimateBase::HaierClimateBase()
 | 
			
		||||
  this->traits_ = climate::ClimateTraits();
 | 
			
		||||
  this->traits_.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL, climate::CLIMATE_MODE_HEAT,
 | 
			
		||||
                                     climate::CLIMATE_MODE_FAN_ONLY, climate::CLIMATE_MODE_DRY,
 | 
			
		||||
                                     climate::CLIMATE_MODE_HEAT_COOL});
 | 
			
		||||
                                     climate::CLIMATE_MODE_AUTO});
 | 
			
		||||
  this->traits_.set_supported_fan_modes(
 | 
			
		||||
      {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH});
 | 
			
		||||
  this->traits_.set_supported_swing_modes({climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_BOTH,
 | 
			
		||||
@@ -171,8 +171,8 @@ void HaierClimateBase::set_answer_timeout(uint32_t timeout) {
 | 
			
		||||
 | 
			
		||||
void HaierClimateBase::set_supported_modes(const std::set<climate::ClimateMode> &modes) {
 | 
			
		||||
  this->traits_.set_supported_modes(modes);
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF);        // Always available
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_HEAT_COOL);  // Always available
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_OFF);   // Always available
 | 
			
		||||
  this->traits_.add_supported_mode(climate::CLIMATE_MODE_AUTO);  // Always available
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HaierClimateBase::set_supported_presets(const std::set<climate::ClimatePreset> &presets) {
 | 
			
		||||
 
 | 
			
		||||
@@ -458,7 +458,7 @@ haier_protocol::HaierMessage HonClimate::get_control_message() {
 | 
			
		||||
        case CLIMATE_MODE_OFF:
 | 
			
		||||
          out_data->ac_power = 0;
 | 
			
		||||
          break;
 | 
			
		||||
        case CLIMATE_MODE_HEAT_COOL:
 | 
			
		||||
        case CLIMATE_MODE_AUTO:
 | 
			
		||||
          out_data->ac_power = 1;
 | 
			
		||||
          out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::AUTO;
 | 
			
		||||
          out_data->fan_mode = this->other_modes_fan_speed_;
 | 
			
		||||
@@ -758,7 +758,7 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t *
 | 
			
		||||
          this->mode = CLIMATE_MODE_FAN_ONLY;
 | 
			
		||||
          break;
 | 
			
		||||
        case (uint8_t) hon_protocol::ConditioningMode::AUTO:
 | 
			
		||||
          this->mode = CLIMATE_MODE_HEAT_COOL;
 | 
			
		||||
          this->mode = CLIMATE_MODE_AUTO;
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -270,7 +270,7 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() {
 | 
			
		||||
          out_data->ac_power = 0;
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case CLIMATE_MODE_HEAT_COOL:
 | 
			
		||||
        case CLIMATE_MODE_AUTO:
 | 
			
		||||
          out_data->ac_power = 1;
 | 
			
		||||
          out_data->ac_mode = (uint8_t) smartair2_protocol::ConditioningMode::AUTO;
 | 
			
		||||
          out_data->fan_mode = this->other_modes_fan_speed_;
 | 
			
		||||
@@ -487,7 +487,7 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin
 | 
			
		||||
          this->mode = CLIMATE_MODE_FAN_ONLY;
 | 
			
		||||
          break;
 | 
			
		||||
        case (uint8_t) smartair2_protocol::ConditioningMode::AUTO:
 | 
			
		||||
          this->mode = CLIMATE_MODE_HEAT_COOL;
 | 
			
		||||
          this->mode = CLIMATE_MODE_AUTO;
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,6 @@ PROTOCOLS = {
 | 
			
		||||
    "greeya": Protocol.PROTOCOL_GREEYAA,
 | 
			
		||||
    "greeyan": Protocol.PROTOCOL_GREEYAN,
 | 
			
		||||
    "greeyac": Protocol.PROTOCOL_GREEYAC,
 | 
			
		||||
    "greeyt": Protocol.PROTOCOL_GREEYT,
 | 
			
		||||
    "hisense_aud": Protocol.PROTOCOL_HISENSE_AUD,
 | 
			
		||||
    "hitachi": Protocol.PROTOCOL_HITACHI,
 | 
			
		||||
    "hyundai": Protocol.PROTOCOL_HYUNDAI,
 | 
			
		||||
@@ -116,7 +115,7 @@ def to_code(config):
 | 
			
		||||
    cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE]))
 | 
			
		||||
    cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE]))
 | 
			
		||||
 | 
			
		||||
    cg.add_library("tonia/HeatpumpIR", "1.0.23")
 | 
			
		||||
    cg.add_library("tonia/HeatpumpIR", "1.0.20")
 | 
			
		||||
 | 
			
		||||
    if CORE.is_esp8266 or CORE.is_esp32:
 | 
			
		||||
        cg.add_library("crankyoldgit/IRremoteESP8266", "2.7.12")
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,6 @@ const std::map<Protocol, std::function<HeatpumpIR *()>> PROTOCOL_CONSTRUCTOR_MAP
 | 
			
		||||
    {PROTOCOL_GREEYAA, []() { return new GreeYAAHeatpumpIR(); }},                            // NOLINT
 | 
			
		||||
    {PROTOCOL_GREEYAN, []() { return new GreeYANHeatpumpIR(); }},                            // NOLINT
 | 
			
		||||
    {PROTOCOL_GREEYAC, []() { return new GreeYACHeatpumpIR(); }},                            // NOLINT
 | 
			
		||||
    {PROTOCOL_GREEYT, []() { return new GreeYTHeatpumpIR(); }},                              // NOLINT
 | 
			
		||||
    {PROTOCOL_HISENSE_AUD, []() { return new HisenseHeatpumpIR(); }},                        // NOLINT
 | 
			
		||||
    {PROTOCOL_HITACHI, []() { return new HitachiHeatpumpIR(); }},                            // NOLINT
 | 
			
		||||
    {PROTOCOL_HYUNDAI, []() { return new HyundaiHeatpumpIR(); }},                            // NOLINT
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,6 @@ enum Protocol {
 | 
			
		||||
  PROTOCOL_GREEYAA,
 | 
			
		||||
  PROTOCOL_GREEYAN,
 | 
			
		||||
  PROTOCOL_GREEYAC,
 | 
			
		||||
  PROTOCOL_GREEYT,
 | 
			
		||||
  PROTOCOL_HISENSE_AUD,
 | 
			
		||||
  PROTOCOL_HITACHI,
 | 
			
		||||
  PROTOCOL_HYUNDAI,
 | 
			
		||||
 
 | 
			
		||||
@@ -23,13 +23,13 @@ CONFIG_SCHEMA = (
 | 
			
		||||
    cv.Schema(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(HTU21DComponent),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
            cv.Required(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                unit_of_measurement=UNIT_CELSIUS,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_TEMPERATURE,
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
            cv.Required(CONF_HUMIDITY): sensor.sensor_schema(
 | 
			
		||||
                unit_of_measurement=UNIT_PERCENT,
 | 
			
		||||
                accuracy_decimals=1,
 | 
			
		||||
                device_class=DEVICE_CLASS_HUMIDITY,
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ from esphome.const import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ["i2c"]
 | 
			
		||||
CODEOWNERS = ["@mreditor97"]
 | 
			
		||||
CODEOWNERS = ["@MrEditor97"]
 | 
			
		||||
 | 
			
		||||
ina260_ns = cg.esphome_ns.namespace("ina260")
 | 
			
		||||
INA260Component = ina260_ns.class_(
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,6 @@ from esphome.components.esp32.const import (
 | 
			
		||||
    VARIANT_ESP32S2,
 | 
			
		||||
    VARIANT_ESP32C3,
 | 
			
		||||
    VARIANT_ESP32S3,
 | 
			
		||||
    VARIANT_ESP32C2,
 | 
			
		||||
    VARIANT_ESP32C6,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CODEOWNERS = ["@esphome/core"]
 | 
			
		||||
@@ -76,8 +74,6 @@ UART_SELECTION_ESP32 = {
 | 
			
		||||
    VARIANT_ESP32S2: [UART0, UART1, USB_CDC],
 | 
			
		||||
    VARIANT_ESP32S3: [UART0, UART1, USB_CDC, USB_SERIAL_JTAG],
 | 
			
		||||
    VARIANT_ESP32C3: [UART0, UART1, USB_SERIAL_JTAG],
 | 
			
		||||
    VARIANT_ESP32C2: [UART0, UART1],
 | 
			
		||||
    VARIANT_ESP32C6: [UART0, UART1, USB_CDC, USB_SERIAL_JTAG],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UART_SELECTION_ESP8266 = [UART0, UART0_SWAP, UART1]
 | 
			
		||||
 
 | 
			
		||||
@@ -120,7 +120,7 @@ void HOT Logger::log_message_(int level, const char *tag, int offset) {
 | 
			
		||||
    if (
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32S2)
 | 
			
		||||
        uart_ == UART_SELECTION_USB_CDC
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6)
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32C3)
 | 
			
		||||
        uart_ == UART_SELECTION_USB_SERIAL_JTAG
 | 
			
		||||
#elif defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
        uart_ == UART_SELECTION_USB_CDC || uart_ == UART_SELECTION_USB_SERIAL_JTAG
 | 
			
		||||
@@ -191,8 +191,8 @@ void Logger::pre_setup() {
 | 
			
		||||
        Serial1.setDebugOutput(ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE);
 | 
			
		||||
#endif
 | 
			
		||||
        break;
 | 
			
		||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
 | 
			
		||||
    !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && \
 | 
			
		||||
    !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
      case UART_SELECTION_UART2:
 | 
			
		||||
        this->hw_serial_ = &Serial2;
 | 
			
		||||
        Serial2.begin(this->baud_rate_);
 | 
			
		||||
@@ -215,8 +215,7 @@ void Logger::pre_setup() {
 | 
			
		||||
      case UART_SELECTION_UART1:
 | 
			
		||||
        uart_num_ = UART_NUM_1;
 | 
			
		||||
        break;
 | 
			
		||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
 | 
			
		||||
    !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
      case UART_SELECTION_UART2:
 | 
			
		||||
        uart_num_ = UART_NUM_2;
 | 
			
		||||
        break;
 | 
			
		||||
@@ -226,11 +225,11 @@ void Logger::pre_setup() {
 | 
			
		||||
        uart_num_ = -1;
 | 
			
		||||
        break;
 | 
			
		||||
#endif  // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
      case UART_SELECTION_USB_SERIAL_JTAG:
 | 
			
		||||
        uart_num_ = -1;
 | 
			
		||||
        break;
 | 
			
		||||
#endif  // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32S3
 | 
			
		||||
#endif  // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3
 | 
			
		||||
    }
 | 
			
		||||
    if (uart_num_ >= 0) {
 | 
			
		||||
      uart_config_t uart_config{};
 | 
			
		||||
@@ -279,8 +278,7 @@ const char *const LOG_LEVELS[] = {"NONE", "ERROR", "WARN", "INFO", "CONFIG", "DE
 | 
			
		||||
#ifdef USE_ESP32
 | 
			
		||||
const char *const UART_SELECTIONS[] = {
 | 
			
		||||
    "UART0",           "UART1",
 | 
			
		||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
 | 
			
		||||
    !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
    "UART2",
 | 
			
		||||
#endif  // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3
 | 
			
		||||
#if defined(USE_ESP_IDF)
 | 
			
		||||
 
 | 
			
		||||
@@ -34,15 +34,14 @@ enum UARTSelection {
 | 
			
		||||
  UART_SELECTION_UART0 = 0,
 | 
			
		||||
  UART_SELECTION_UART1,
 | 
			
		||||
#if defined(USE_ESP32)
 | 
			
		||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
 | 
			
		||||
    !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
  UART_SELECTION_UART2,
 | 
			
		||||
#endif  // !USE_ESP32_VARIANT_ESP32C3 && !USE_ESP32_VARIANT_ESP32S2 && !USE_ESP32_VARIANT_ESP32S3
 | 
			
		||||
#ifdef USE_ESP_IDF
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
  UART_SELECTION_USB_CDC,
 | 
			
		||||
#endif  // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
  UART_SELECTION_USB_SERIAL_JTAG,
 | 
			
		||||
#endif  // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32S3
 | 
			
		||||
#endif  // USE_ESP_IDF
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ CONF_HOT_JUNCTION = "hot_junction"
 | 
			
		||||
CONF_COLD_JUNCTION = "cold_junction"
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ["i2c"]
 | 
			
		||||
CODEOWNERS = ["@mreditor97"]
 | 
			
		||||
CODEOWNERS = ["@MrEditor97"]
 | 
			
		||||
 | 
			
		||||
mcp9600_ns = cg.esphome_ns.namespace("mcp9600")
 | 
			
		||||
MCP9600Component = mcp9600_ns.class_(
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
CODEOWNERS = ["@SeByDocKy"]
 | 
			
		||||
@@ -1,115 +0,0 @@
 | 
			
		||||
#include "pmwcs3.h"
 | 
			
		||||
#include "esphome/core/hal.h"
 | 
			
		||||
#include "esphome/core/log.h"
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace pmwcs3 {
 | 
			
		||||
 | 
			
		||||
static const uint8_t PMWCS3_I2C_ADDRESS = 0x63;
 | 
			
		||||
static const uint8_t PMWCS3_REG_READ_START = 0x01;
 | 
			
		||||
static const uint8_t PMWCS3_REG_READ_E25 = 0x02;
 | 
			
		||||
static const uint8_t PMWCS3_REG_READ_EC = 0x03;
 | 
			
		||||
static const uint8_t PMWCS3_REG_READ_TEMP = 0x04;
 | 
			
		||||
static const uint8_t PMWCS3_REG_READ_VWC = 0x05;
 | 
			
		||||
static const uint8_t PMWCS3_REG_CALIBRATE_AIR = 0x06;
 | 
			
		||||
static const uint8_t PMWCS3_REG_CALIBRATE_WATER = 0x07;
 | 
			
		||||
static const uint8_t PMWCS3_SET_I2C_ADDRESS = 0x08;
 | 
			
		||||
static const uint8_t PMWCS3_REG_GET_DATA = 0x09;
 | 
			
		||||
static const uint8_t PMWCS3_REG_CALIBRATE_EC = 0x10;
 | 
			
		||||
static const uint8_t PMWCS3_REG_CAP = 0x0A;
 | 
			
		||||
static const uint8_t PMWCS3_REG_RES = 0x0B;
 | 
			
		||||
static const uint8_t PMWCS3_REG_RC = 0x0C;
 | 
			
		||||
static const uint8_t PMWCS3_REG_RT = 0x0D;
 | 
			
		||||
 | 
			
		||||
static const char *const TAG = "pmwcs3";
 | 
			
		||||
 | 
			
		||||
void PMWCS3Component::new_i2c_address(uint8_t address) {
 | 
			
		||||
  if (!this->write_byte(PMWCS3_SET_I2C_ADDRESS, address)) {
 | 
			
		||||
    this->status_set_warning();
 | 
			
		||||
    ESP_LOGW(TAG, "couldn't write the new I2C address %d", address);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  this->set_i2c_address(address);  // Allows device to continue working until new firmware is written with new address.
 | 
			
		||||
  ESP_LOGVV(TAG, "changed I2C address to %d", address);
 | 
			
		||||
  this->status_clear_warning();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PMWCS3Component::air_calibration() {
 | 
			
		||||
  if (!this->write_bytes(PMWCS3_REG_CALIBRATE_AIR, nullptr, 0)) {
 | 
			
		||||
    this->status_set_warning();
 | 
			
		||||
    ESP_LOGW(TAG, "couldn't start air calibration");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  ESP_LOGW(TAG, "Start air calibration during the next 300s");
 | 
			
		||||
}
 | 
			
		||||
void PMWCS3Component::water_calibration() {
 | 
			
		||||
  if (!this->write_bytes(PMWCS3_REG_CALIBRATE_WATER, nullptr, 0)) {
 | 
			
		||||
    this->status_set_warning();
 | 
			
		||||
    ESP_LOGW(TAG, "couldn't start water calibration");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  ESP_LOGW(TAG, "Start water calibration during the next 300s");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PMWCS3Component::setup() { ESP_LOGCONFIG(TAG, "Setting up PMWCS3..."); }
 | 
			
		||||
 | 
			
		||||
void PMWCS3Component::update() { this->read_data_(); }
 | 
			
		||||
 | 
			
		||||
float PMWCS3Component::get_setup_priority() const { return setup_priority::DATA; }
 | 
			
		||||
 | 
			
		||||
void PMWCS3Component::dump_config() {
 | 
			
		||||
  ESP_LOGCONFIG(TAG, "PMWCS3");
 | 
			
		||||
  LOG_I2C_DEVICE(this);
 | 
			
		||||
  if (this->is_failed()) {
 | 
			
		||||
    ESP_LOGE(TAG, "Communication with PMWCS3 failed!");
 | 
			
		||||
  }
 | 
			
		||||
  ESP_LOGI(TAG, "%s", this->is_failed() ? "FAILED" : "OK");
 | 
			
		||||
 | 
			
		||||
  LOG_UPDATE_INTERVAL(this);
 | 
			
		||||
  LOG_SENSOR("  ", "e25", this->e25_sensor_);
 | 
			
		||||
  LOG_SENSOR("  ", "ec", this->ec_sensor_);
 | 
			
		||||
  LOG_SENSOR("  ", "temperature", this->temperature_sensor_);
 | 
			
		||||
  LOG_SENSOR("  ", "vwc", this->vwc_sensor_);
 | 
			
		||||
}
 | 
			
		||||
void PMWCS3Component::read_data_() {
 | 
			
		||||
  uint8_t data[8];
 | 
			
		||||
  float e25, ec, temperature, vwc;
 | 
			
		||||
 | 
			
		||||
  /////// Super important !!!! first activate reading PMWCS3_REG_READ_START (if not, return always the same values) ////
 | 
			
		||||
 | 
			
		||||
  if (!this->write_bytes(PMWCS3_REG_READ_START, nullptr, 0)) {
 | 
			
		||||
    this->status_set_warning();
 | 
			
		||||
    ESP_LOGVV(TAG, "Failed to write into REG_READ_START register !!!");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  // NOLINT  delay(100);
 | 
			
		||||
 | 
			
		||||
  if (!this->read_bytes(PMWCS3_REG_GET_DATA, (uint8_t *) &data, 8)) {
 | 
			
		||||
    ESP_LOGVV(TAG, "Error reading PMWCS3_REG_GET_DATA registers");
 | 
			
		||||
    this->mark_failed();
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (this->e25_sensor_ != nullptr) {
 | 
			
		||||
    e25 = ((data[1] << 8) | data[0]) / 100.0;
 | 
			
		||||
    this->e25_sensor_->publish_state(e25);
 | 
			
		||||
    ESP_LOGVV(TAG, "e25: data[0]=%d, data[1]=%d, result=%f", data[0], data[1], e25);
 | 
			
		||||
  }
 | 
			
		||||
  if (this->ec_sensor_ != nullptr) {
 | 
			
		||||
    ec = ((data[3] << 8) | data[2]) / 10.0;
 | 
			
		||||
    this->ec_sensor_->publish_state(ec);
 | 
			
		||||
    ESP_LOGVV(TAG, "ec: data[2]=%d, data[3]=%d, result=%f", data[2], data[3], ec);
 | 
			
		||||
  }
 | 
			
		||||
  if (this->temperature_sensor_ != nullptr) {
 | 
			
		||||
    temperature = ((data[5] << 8) | data[4]) / 100.0;
 | 
			
		||||
    this->temperature_sensor_->publish_state(temperature);
 | 
			
		||||
    ESP_LOGVV(TAG, "temp: data[4]=%d, data[5]=%d, result=%f", data[4], data[5], temperature);
 | 
			
		||||
  }
 | 
			
		||||
  if (this->vwc_sensor_ != nullptr) {
 | 
			
		||||
    vwc = ((data[7] << 8) | data[6]) / 10.0;
 | 
			
		||||
    this->vwc_sensor_->publish_state(vwc);
 | 
			
		||||
    ESP_LOGVV(TAG, "vwc: data[6]=%d, data[7]=%d, result=%f", data[6], data[7], vwc);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace pmwcs3
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
@@ -1,70 +0,0 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include "esphome/core/automation.h"
 | 
			
		||||
#include "esphome/core/component.h"
 | 
			
		||||
#include "esphome/components/sensor/sensor.h"
 | 
			
		||||
#include "esphome/components/i2c/i2c.h"
 | 
			
		||||
 | 
			
		||||
// ref:
 | 
			
		||||
// https://github.com/tinovi/i2cArduino/blob/master/i2cArduino.h
 | 
			
		||||
 | 
			
		||||
namespace esphome {
 | 
			
		||||
namespace pmwcs3 {
 | 
			
		||||
 | 
			
		||||
class PMWCS3Component : public PollingComponent, public i2c::I2CDevice {
 | 
			
		||||
 public:
 | 
			
		||||
  void setup() override;
 | 
			
		||||
  void update() override;
 | 
			
		||||
  void dump_config() override;
 | 
			
		||||
  float get_setup_priority() const override;
 | 
			
		||||
 | 
			
		||||
  void set_e25_sensor(sensor::Sensor *e25_sensor) { e25_sensor_ = e25_sensor; }
 | 
			
		||||
  void set_ec_sensor(sensor::Sensor *ec_sensor) { ec_sensor_ = ec_sensor; }
 | 
			
		||||
  void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
 | 
			
		||||
  void set_vwc_sensor(sensor::Sensor *vwc_sensor) { vwc_sensor_ = vwc_sensor; }
 | 
			
		||||
 | 
			
		||||
  void new_i2c_address(uint8_t newaddress);
 | 
			
		||||
  void air_calibration();
 | 
			
		||||
  void water_calibration();
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  void read_data_();
 | 
			
		||||
 | 
			
		||||
  sensor::Sensor *e25_sensor_{nullptr};
 | 
			
		||||
  sensor::Sensor *ec_sensor_{nullptr};
 | 
			
		||||
  sensor::Sensor *temperature_sensor_{nullptr};
 | 
			
		||||
  sensor::Sensor *vwc_sensor_{nullptr};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename... Ts> class PMWCS3AirCalibrationAction : public Action<Ts...> {
 | 
			
		||||
 public:
 | 
			
		||||
  PMWCS3AirCalibrationAction(PMWCS3Component *parent) : parent_(parent) {}
 | 
			
		||||
 | 
			
		||||
  void play(Ts... x) override { this->parent_->air_calibration(); }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  PMWCS3Component *parent_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename... Ts> class PMWCS3WaterCalibrationAction : public Action<Ts...> {
 | 
			
		||||
 public:
 | 
			
		||||
  PMWCS3WaterCalibrationAction(PMWCS3Component *parent) : parent_(parent) {}
 | 
			
		||||
 | 
			
		||||
  void play(Ts... x) override { this->parent_->water_calibration(); }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  PMWCS3Component *parent_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename... Ts> class PMWCS3NewI2cAddressAction : public Action<Ts...> {
 | 
			
		||||
 public:
 | 
			
		||||
  PMWCS3NewI2cAddressAction(PMWCS3Component *parent) : parent_(parent) {}
 | 
			
		||||
  TEMPLATABLE_VALUE(int, new_address)
 | 
			
		||||
 | 
			
		||||
  void play(Ts... x) override { this->parent_->new_i2c_address(this->new_address_.value(x...)); }
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  PMWCS3Component *parent_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace pmwcs3
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
@@ -1,140 +0,0 @@
 | 
			
		||||
import esphome.codegen as cg
 | 
			
		||||
from esphome import automation
 | 
			
		||||
import esphome.config_validation as cv
 | 
			
		||||
from esphome.components import i2c, sensor
 | 
			
		||||
from esphome.const import (
 | 
			
		||||
    CONF_ID,
 | 
			
		||||
    CONF_ADDRESS,
 | 
			
		||||
    CONF_TEMPERATURE,
 | 
			
		||||
    CONF_EC,
 | 
			
		||||
    STATE_CLASS_MEASUREMENT,
 | 
			
		||||
    ICON_THERMOMETER,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CODEOWNERS = ["@SeByDocKy"]
 | 
			
		||||
DEPENDENCIES = ["i2c"]
 | 
			
		||||
 | 
			
		||||
CONF_E25 = "e25"
 | 
			
		||||
CONF_VWC = "vwc"
 | 
			
		||||
 | 
			
		||||
ICON_EPSILON = "mdi:epsilon"
 | 
			
		||||
ICON_SIGMA = "mdi:sigma-lower"
 | 
			
		||||
ICON_ALPHA = "mdi:alpha-h-circle-outline"
 | 
			
		||||
 | 
			
		||||
pmwcs3_ns = cg.esphome_ns.namespace("pmwcs3")
 | 
			
		||||
PMWCS3Component = pmwcs3_ns.class_(
 | 
			
		||||
    "PMWCS3Component", cg.PollingComponent, i2c.I2CDevice
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Actions
 | 
			
		||||
PMWCS3AirCalibrationAction = pmwcs3_ns.class_(
 | 
			
		||||
    "PMWCS3AirCalibrationAction", automation.Action
 | 
			
		||||
)
 | 
			
		||||
PMWCS3WaterCalibrationAction = pmwcs3_ns.class_(
 | 
			
		||||
    "PMWCS3WaterCalibrationAction", automation.Action
 | 
			
		||||
)
 | 
			
		||||
PMWCS3NewI2cAddressAction = pmwcs3_ns.class_(
 | 
			
		||||
    "PMWCS3NewI2cAddressAction", automation.Action
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = (
 | 
			
		||||
    cv.Schema(
 | 
			
		||||
        {
 | 
			
		||||
            cv.GenerateID(): cv.declare_id(PMWCS3Component),
 | 
			
		||||
            cv.Optional(CONF_E25): sensor.sensor_schema(
 | 
			
		||||
                icon=ICON_EPSILON,
 | 
			
		||||
                accuracy_decimals=3,
 | 
			
		||||
                unit_of_measurement="dS/m",
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_EC): sensor.sensor_schema(
 | 
			
		||||
                icon=ICON_SIGMA,
 | 
			
		||||
                accuracy_decimals=2,
 | 
			
		||||
                unit_of_measurement="mS/m",
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
 | 
			
		||||
                icon=ICON_THERMOMETER,
 | 
			
		||||
                accuracy_decimals=3,
 | 
			
		||||
                unit_of_measurement="°C",
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
            cv.Optional(CONF_VWC): sensor.sensor_schema(
 | 
			
		||||
                icon=ICON_ALPHA,
 | 
			
		||||
                accuracy_decimals=3,
 | 
			
		||||
                unit_of_measurement="cm3cm−3",
 | 
			
		||||
                state_class=STATE_CLASS_MEASUREMENT,
 | 
			
		||||
            ),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
    .extend(cv.polling_component_schema("60s"))
 | 
			
		||||
    .extend(i2c.i2c_device_schema(0x63))
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async def to_code(config):
 | 
			
		||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
			
		||||
    await cg.register_component(var, config)
 | 
			
		||||
    await i2c.register_i2c_device(var, config)
 | 
			
		||||
 | 
			
		||||
    if CONF_E25 in config:
 | 
			
		||||
        sens = await sensor.new_sensor(config[CONF_E25])
 | 
			
		||||
        cg.add(var.set_e25_sensor(sens))
 | 
			
		||||
 | 
			
		||||
    if CONF_EC in config:
 | 
			
		||||
        sens = await sensor.new_sensor(config[CONF_EC])
 | 
			
		||||
        cg.add(var.set_ec_sensor(sens))
 | 
			
		||||
 | 
			
		||||
    if CONF_TEMPERATURE in config:
 | 
			
		||||
        sens = await sensor.new_sensor(config[CONF_TEMPERATURE])
 | 
			
		||||
        cg.add(var.set_temperature_sensor(sens))
 | 
			
		||||
 | 
			
		||||
    if CONF_VWC in config:
 | 
			
		||||
        sens = await sensor.new_sensor(config[CONF_VWC])
 | 
			
		||||
        cg.add(var.set_vwc_sensor(sens))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Actions
 | 
			
		||||
PMWCS3_CALIBRATION_SCHEMA = cv.Schema(
 | 
			
		||||
    {
 | 
			
		||||
        cv.GenerateID(): cv.use_id(PMWCS3Component),
 | 
			
		||||
    }
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@automation.register_action(
 | 
			
		||||
    "pmwcs3.air_calibration",
 | 
			
		||||
    PMWCS3AirCalibrationAction,
 | 
			
		||||
    PMWCS3_CALIBRATION_SCHEMA,
 | 
			
		||||
)
 | 
			
		||||
@automation.register_action(
 | 
			
		||||
    "pmwcs3.water_calibration",
 | 
			
		||||
    PMWCS3WaterCalibrationAction,
 | 
			
		||||
    PMWCS3_CALIBRATION_SCHEMA,
 | 
			
		||||
)
 | 
			
		||||
async def pmwcs3_calibration_to_code(config, action_id, template_arg, args):
 | 
			
		||||
    parent = await cg.get_variable(config[CONF_ID])
 | 
			
		||||
    var = cg.new_Pvariable(action_id, template_arg, parent)
 | 
			
		||||
    return var
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PMWCS3_NEW_I2C_ADDRESS_SCHEMA = cv.maybe_simple_value(
 | 
			
		||||
    {
 | 
			
		||||
        cv.GenerateID(): cv.use_id(PMWCS3Component),
 | 
			
		||||
        cv.Required(CONF_ADDRESS): cv.templatable(cv.i2c_address),
 | 
			
		||||
    },
 | 
			
		||||
    key=CONF_ADDRESS,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@automation.register_action(
 | 
			
		||||
    "pmwcs3.new_i2c_address",
 | 
			
		||||
    PMWCS3NewI2cAddressAction,
 | 
			
		||||
    PMWCS3_NEW_I2C_ADDRESS_SCHEMA,
 | 
			
		||||
)
 | 
			
		||||
async def pmwcs3newi2caddress_to_code(config, action_id, template_arg, args):
 | 
			
		||||
    parent = await cg.get_variable(config[CONF_ID])
 | 
			
		||||
    var = cg.new_Pvariable(action_id, template_arg, parent)
 | 
			
		||||
    address = await cg.templatable(config[CONF_ADDRESS], args, int)
 | 
			
		||||
    cg.add(var.set_new_address(address))
 | 
			
		||||
    return var
 | 
			
		||||
@@ -96,7 +96,7 @@ std::string AEHAProtocol::format_data_(const std::vector<uint8_t> &data) {
 | 
			
		||||
 | 
			
		||||
void AEHAProtocol::dump(const AEHAData &data) {
 | 
			
		||||
  auto data_str = format_data_(data.data);
 | 
			
		||||
  ESP_LOGI(TAG, "Received AEHA: address=0x%04X, data=[%s]", data.address, data_str.c_str());
 | 
			
		||||
  ESP_LOGD(TAG, "Received AEHA: address=0x%04X, data=[%s]", data.address, data_str.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -96,10 +96,10 @@ optional<CanalSatData> CanalSatBaseProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
 | 
			
		||||
void CanalSatBaseProtocol::dump(const CanalSatData &data) {
 | 
			
		||||
  if (this->tag_ == CANALSATLD_TAG) {
 | 
			
		||||
    ESP_LOGI(this->tag_, "Received CanalSatLD: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device,
 | 
			
		||||
    ESP_LOGD(this->tag_, "Received CanalSatLD: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device,
 | 
			
		||||
             data.address, data.command, data.repeat);
 | 
			
		||||
  } else {
 | 
			
		||||
    ESP_LOGI(this->tag_, "Received CanalSat: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device,
 | 
			
		||||
    ESP_LOGD(this->tag_, "Received CanalSat: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device,
 | 
			
		||||
             data.address, data.command, data.repeat);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -101,11 +101,11 @@ optional<CoolixData> CoolixProtocol::decode(RemoteReceiveData data) {
 | 
			
		||||
 | 
			
		||||
void CoolixProtocol::dump(const CoolixData &data) {
 | 
			
		||||
  if (data.is_strict()) {
 | 
			
		||||
    ESP_LOGI(TAG, "Received Coolix: 0x%06X", data.first);
 | 
			
		||||
    ESP_LOGD(TAG, "Received Coolix: 0x%06X", data.first);
 | 
			
		||||
  } else if (data.has_second()) {
 | 
			
		||||
    ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06X, 0x%06X]", data.first, data.second);
 | 
			
		||||
    ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X, 0x%06X]", data.first, data.second);
 | 
			
		||||
  } else {
 | 
			
		||||
    ESP_LOGI(TAG, "Received unstrict Coolix: [0x%06X]", data.first);
 | 
			
		||||
    ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X]", data.first);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,7 @@ optional<DishData> DishProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DishProtocol::dump(const DishData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received Dish: address=0x%02X, command=0x%02X", data.address, data.command);
 | 
			
		||||
  ESP_LOGD(TAG, "Received Dish: address=0x%02X, command=0x%02X", data.address, data.command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -205,7 +205,7 @@ optional<DraytonData> DraytonProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void DraytonProtocol::dump(const DraytonData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received Drayton: address=0x%04X (0x%04x), channel=0x%03x command=0x%03X", data.address,
 | 
			
		||||
  ESP_LOGD(TAG, "Received Drayton: address=0x%04X (0x%04x), channel=0x%03x command=0x%03X", data.address,
 | 
			
		||||
           ((data.address << 1) & 0xffff), data.channel, data.command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ optional<JVCData> JVCProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  }
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void JVCProtocol::dump(const JVCData &data) { ESP_LOGI(TAG, "Received JVC: data=0x%04X", data.data); }
 | 
			
		||||
void JVCProtocol::dump(const JVCData &data) { ESP_LOGD(TAG, "Received JVC: data=0x%04X", data.data); }
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -51,7 +51,7 @@ optional<LGData> LGProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void LGProtocol::dump(const LGData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received LG: data=0x%08X, nbits=%d", data.data, data.nbits);
 | 
			
		||||
  ESP_LOGD(TAG, "Received LG: data=0x%08X, nbits=%d", data.data, data.nbits);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ optional<MagiQuestData> MagiQuestProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
void MagiQuestProtocol::dump(const MagiQuestData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received MagiQuest: wand_id=0x%08X, magnitude=0x%04X", data.wand_id, data.magnitude);
 | 
			
		||||
  ESP_LOGD(TAG, "Received MagiQuest: wand_id=0x%08X, magnitude=0x%04X", data.wand_id, data.magnitude);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ optional<MideaData> MideaProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MideaProtocol::dump(const MideaData &data) { ESP_LOGI(TAG, "Received Midea: %s", data.to_string().c_str()); }
 | 
			
		||||
void MideaProtocol::dump(const MideaData &data) { ESP_LOGD(TAG, "Received Midea: %s", data.to_string().c_str()); }
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
}  // namespace esphome
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ optional<NECData> NECProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
void NECProtocol::dump(const NECData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received NEC: address=0x%04X, command=0x%04X", data.address, data.command);
 | 
			
		||||
  ESP_LOGD(TAG, "Received NEC: address=0x%04X, command=0x%04X", data.address, data.command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -232,7 +232,7 @@ optional<NexaData> NexaProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NexaProtocol::dump(const NexaData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received NEXA: device=0x%04X group=%d state=%d channel=%d level=%d", data.device, data.group,
 | 
			
		||||
  ESP_LOGD(TAG, "Received NEXA: device=0x%04X group=%d state=%d channel=%d level=%d", data.device, data.group,
 | 
			
		||||
           data.state, data.channel, data.level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ optional<PanasonicData> PanasonicProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void PanasonicProtocol::dump(const PanasonicData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received Panasonic: address=0x%04X, command=0x%08X", data.address, data.command);
 | 
			
		||||
  ESP_LOGD(TAG, "Received Panasonic: address=0x%04X, command=0x%08X", data.address, data.command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -146,9 +146,9 @@ optional<PioneerData> PioneerProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
}
 | 
			
		||||
void PioneerProtocol::dump(const PioneerData &data) {
 | 
			
		||||
  if (data.rc_code_2 == 0) {
 | 
			
		||||
    ESP_LOGI(TAG, "Received Pioneer: rc_code_X=0x%04X", data.rc_code_1);
 | 
			
		||||
    ESP_LOGD(TAG, "Received Pioneer: rc_code_X=0x%04X", data.rc_code_1);
 | 
			
		||||
  } else {
 | 
			
		||||
    ESP_LOGI(TAG, "Received Pioneer: rc_code_1=0x%04X, rc_code_2=0x%04X", data.rc_code_1, data.rc_code_2);
 | 
			
		||||
    ESP_LOGD(TAG, "Received Pioneer: rc_code_1=0x%04X, rc_code_2=0x%04X", data.rc_code_1, data.rc_code_2);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -234,9 +234,9 @@ void ProntoProtocol::dump(const ProntoData &data) {
 | 
			
		||||
    first = data.data.substr(0, 229);
 | 
			
		||||
    rest = data.data.substr(230);
 | 
			
		||||
  }
 | 
			
		||||
  ESP_LOGI(TAG, "Received Pronto: data=%s", first.c_str());
 | 
			
		||||
  ESP_LOGD(TAG, "Received Pronto: data=%s", first.c_str());
 | 
			
		||||
  if (!rest.empty()) {
 | 
			
		||||
    ESP_LOGI(TAG, "%s", rest.c_str());
 | 
			
		||||
    ESP_LOGD(TAG, "%s", rest.c_str());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ bool RawDumper::dump(RemoteReceiveData src) {
 | 
			
		||||
    if (written < 0 || written >= int(remaining_length)) {
 | 
			
		||||
      // write failed, flush...
 | 
			
		||||
      buffer[buffer_offset] = '\0';
 | 
			
		||||
      ESP_LOGI(TAG, "%s", buffer);
 | 
			
		||||
      ESP_LOGD(TAG, "%s", buffer);
 | 
			
		||||
      buffer_offset = 0;
 | 
			
		||||
      written = sprintf(buffer, "  ");
 | 
			
		||||
      if (i + 1 < src.size()) {
 | 
			
		||||
@@ -38,7 +38,7 @@ bool RawDumper::dump(RemoteReceiveData src) {
 | 
			
		||||
    buffer_offset += written;
 | 
			
		||||
  }
 | 
			
		||||
  if (buffer_offset != 0) {
 | 
			
		||||
    ESP_LOGI(TAG, "%s", buffer);
 | 
			
		||||
    ESP_LOGD(TAG, "%s", buffer);
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,7 @@ optional<RC5Data> RC5Protocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void RC5Protocol::dump(const RC5Data &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received RC5: address=0x%02X, command=0x%02X", data.address, data.command);
 | 
			
		||||
  ESP_LOGD(TAG, "Received RC5: address=0x%02X, command=0x%02X", data.address, data.command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -173,7 +173,7 @@ optional<RC6Data> RC6Protocol::decode(RemoteReceiveData src) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RC6Protocol::dump(const RC6Data &data) {
 | 
			
		||||
  ESP_LOGI(RC6_TAG, "Received RC6: mode=0x%X, address=0x%02X, command=0x%02X, toggle=0x%X", data.mode, data.address,
 | 
			
		||||
  ESP_LOGD(RC6_TAG, "Received RC6: mode=0x%X, address=0x%02X, command=0x%02X, toggle=0x%X", data.mode, data.address,
 | 
			
		||||
           data.command, data.toggle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -258,7 +258,7 @@ bool RCSwitchDumper::dump(RemoteReceiveData src) {
 | 
			
		||||
        buffer[j] = (out_data & ((uint64_t) 1 << (out_nbits - j - 1))) ? '1' : '0';
 | 
			
		||||
 | 
			
		||||
      buffer[out_nbits] = '\0';
 | 
			
		||||
      ESP_LOGI(TAG, "Received RCSwitch Raw: protocol=%u data='%s'", i, buffer);
 | 
			
		||||
      ESP_LOGD(TAG, "Received RCSwitch Raw: protocol=%u data='%s'", i, buffer);
 | 
			
		||||
 | 
			
		||||
      // only send first decoded protocol
 | 
			
		||||
      return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -96,7 +96,7 @@ optional<Samsung36Data> Samsung36Protocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void Samsung36Protocol::dump(const Samsung36Data &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received Samsung36: address=0x%04X, command=0x%08X", data.address, data.command);
 | 
			
		||||
  ESP_LOGD(TAG, "Received Samsung36: address=0x%04X, command=0x%08X", data.address, data.command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ optional<SamsungData> SamsungProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void SamsungProtocol::dump(const SamsungData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received Samsung: data=0x%" PRIX64 ", nbits=%d", data.data, data.nbits);
 | 
			
		||||
  ESP_LOGD(TAG, "Received Samsung: data=0x%" PRIX64 ", nbits=%d", data.data, data.nbits);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ optional<SonyData> SonyProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
void SonyProtocol::dump(const SonyData &data) {
 | 
			
		||||
  ESP_LOGI(TAG, "Received Sony: data=0x%08X, nbits=%d", data.data, data.nbits);
 | 
			
		||||
  ESP_LOGD(TAG, "Received Sony: data=0x%08X, nbits=%d", data.data, data.nbits);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace remote_base
 | 
			
		||||
 
 | 
			
		||||
@@ -105,9 +105,9 @@ optional<ToshibaAcData> ToshibaAcProtocol::decode(RemoteReceiveData src) {
 | 
			
		||||
 | 
			
		||||
void ToshibaAcProtocol::dump(const ToshibaAcData &data) {
 | 
			
		||||
  if (data.rc_code_2 != 0) {
 | 
			
		||||
    ESP_LOGI(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64 ", rc_code_2=0x%" PRIX64, data.rc_code_1, data.rc_code_2);
 | 
			
		||||
    ESP_LOGD(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64 ", rc_code_2=0x%" PRIX64, data.rc_code_1, data.rc_code_2);
 | 
			
		||||
  } else {
 | 
			
		||||
    ESP_LOGI(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64, data.rc_code_1);
 | 
			
		||||
    ESP_LOGD(TAG, "Received Toshiba AC: rc_code_1=0x%" PRIX64, data.rc_code_1);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -100,14 +100,14 @@ bool check_sml_data(const bytes &buffer) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint16_t crc_received = (buffer.at(buffer.size() - 2) << 8) | buffer.at(buffer.size() - 1);
 | 
			
		||||
  uint16_t crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0x6e23, 0x8408, true, true);
 | 
			
		||||
  uint16_t crc_calculated = crc16(buffer.data(), buffer.size(), 0x6e23, 0x8408, true, true);
 | 
			
		||||
  crc_calculated = (crc_calculated >> 8) | (crc_calculated << 8);
 | 
			
		||||
  if (crc_received == crc_calculated) {
 | 
			
		||||
    ESP_LOGV(TAG, "Checksum verification successful with CRC16/X25.");
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  crc_calculated = crc16(buffer.data(), buffer.size() - 2, 0xed50, 0x8408);
 | 
			
		||||
  crc_calculated = crc16(buffer.data(), buffer.size(), 0xed50, 0x8408);
 | 
			
		||||
  if (crc_received == crc_calculated) {
 | 
			
		||||
    ESP_LOGV(TAG, "Checksum verification successful with CRC16/KERMIT.");
 | 
			
		||||
    return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -87,7 +87,25 @@ class BSDSocketImpl : public Socket {
 | 
			
		||||
  int listen(int backlog) override { return ::listen(fd_, backlog); }
 | 
			
		||||
  ssize_t read(void *buf, size_t len) override { return ::read(fd_, buf, len); }
 | 
			
		||||
  ssize_t readv(const struct iovec *iov, int iovcnt) override {
 | 
			
		||||
#if defined(USE_ESP32)
 | 
			
		||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 4
 | 
			
		||||
    // esp-idf v3 doesn't have readv, emulate it
 | 
			
		||||
    ssize_t ret = 0;
 | 
			
		||||
    for (int i = 0; i < iovcnt; i++) {
 | 
			
		||||
      ssize_t err = this->read(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len);
 | 
			
		||||
      if (err == -1) {
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
          // if we already read some don't return an error
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        return err;
 | 
			
		||||
      }
 | 
			
		||||
      ret += err;
 | 
			
		||||
      if (err != iov[i].iov_len)
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
#elif defined(USE_ESP32)
 | 
			
		||||
    // ESP-IDF v4 only has symbol lwip_readv
 | 
			
		||||
    return ::lwip_readv(fd_, iov, iovcnt);
 | 
			
		||||
#else
 | 
			
		||||
    return ::readv(fd_, iov, iovcnt);
 | 
			
		||||
@@ -96,7 +114,26 @@ class BSDSocketImpl : public Socket {
 | 
			
		||||
  ssize_t write(const void *buf, size_t len) override { return ::write(fd_, buf, len); }
 | 
			
		||||
  ssize_t send(void *buf, size_t len, int flags) { return ::send(fd_, buf, len, flags); }
 | 
			
		||||
  ssize_t writev(const struct iovec *iov, int iovcnt) override {
 | 
			
		||||
#if defined(USE_ESP32)
 | 
			
		||||
#if defined(USE_ESP32) && ESP_IDF_VERSION_MAJOR < 4
 | 
			
		||||
    // esp-idf v3 doesn't have writev, emulate it
 | 
			
		||||
    ssize_t ret = 0;
 | 
			
		||||
    for (int i = 0; i < iovcnt; i++) {
 | 
			
		||||
      ssize_t err =
 | 
			
		||||
          this->send(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len, i == iovcnt - 1 ? 0 : MSG_MORE);
 | 
			
		||||
      if (err == -1) {
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
          // if we already wrote some don't return an error
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        return err;
 | 
			
		||||
      }
 | 
			
		||||
      ret += err;
 | 
			
		||||
      if (err != iov[i].iov_len)
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return ret;
 | 
			
		||||
#elif defined(USE_ESP32)
 | 
			
		||||
    // ESP-IDF v4 only has symbol lwip_writev
 | 
			
		||||
    return ::lwip_writev(fd_, iov, iovcnt);
 | 
			
		||||
#else
 | 
			
		||||
    return ::writev(fd_, iov, iovcnt);
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,7 @@ SPI_DATA_RATE_OPTIONS = {
 | 
			
		||||
    40e6: SPIDataRate.DATA_RATE_40MHZ,
 | 
			
		||||
    20e6: SPIDataRate.DATA_RATE_20MHZ,
 | 
			
		||||
    10e6: SPIDataRate.DATA_RATE_10MHZ,
 | 
			
		||||
    8e6: SPIDataRate.DATA_RATE_8MHZ,
 | 
			
		||||
    5e6: SPIDataRate.DATA_RATE_5MHZ,
 | 
			
		||||
    4e6: SPIDataRate.DATA_RATE_4MHZ,
 | 
			
		||||
    2e6: SPIDataRate.DATA_RATE_2MHZ,
 | 
			
		||||
    1e6: SPIDataRate.DATA_RATE_1MHZ,
 | 
			
		||||
    2e5: SPIDataRate.DATA_RATE_200KHZ,
 | 
			
		||||
 
 | 
			
		||||
@@ -76,8 +76,7 @@ void SPIComponent::setup() {
 | 
			
		||||
    if (spi_bus_num == 0) {
 | 
			
		||||
      this->hw_spi_ = &SPI;
 | 
			
		||||
    } else {
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || \
 | 
			
		||||
    defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C6)
 | 
			
		||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
 | 
			
		||||
      this->hw_spi_ = new SPIClass(FSPI);  // NOLINT(cppcoreguidelines-owning-memory)
 | 
			
		||||
#else
 | 
			
		||||
      this->hw_spi_ = new SPIClass(HSPI);  // NOLINT(cppcoreguidelines-owning-memory)
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,6 @@ enum SPIDataRate : uint32_t {
 | 
			
		||||
  DATA_RATE_1MHZ = 1000000,
 | 
			
		||||
  DATA_RATE_2MHZ = 2000000,
 | 
			
		||||
  DATA_RATE_4MHZ = 4000000,
 | 
			
		||||
  DATA_RATE_5MHZ = 5000000,
 | 
			
		||||
  DATA_RATE_8MHZ = 8000000,
 | 
			
		||||
  DATA_RATE_10MHZ = 10000000,
 | 
			
		||||
  DATA_RATE_20MHZ = 20000000,
 | 
			
		||||
 
 | 
			
		||||
@@ -132,7 +132,7 @@ void SSD1306::setup() {
 | 
			
		||||
  this->command(SSD1306_COMMAND_DISPLAY_ALL_ON_RESUME);
 | 
			
		||||
 | 
			
		||||
  // Inverse display mode (0xA6, 0xA7)
 | 
			
		||||
  this->set_invert(this->invert_);
 | 
			
		||||
  this->command(SSD1306_COMMAND_NORMAL_DISPLAY | this->invert_);
 | 
			
		||||
 | 
			
		||||
  // Disable scrolling mode (0x2E)
 | 
			
		||||
  this->command(SSD1306_COMMAND_DEACTIVATE_SCROLL);
 | 
			
		||||
@@ -190,12 +190,6 @@ void SSD1306::update() {
 | 
			
		||||
  this->do_update_();
 | 
			
		||||
  this->display();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SSD1306::set_invert(bool invert) {
 | 
			
		||||
  this->invert_ = invert;
 | 
			
		||||
  // Inverse display mode (0xA6, 0xA7)
 | 
			
		||||
  this->command(SSD1306_COMMAND_NORMAL_DISPLAY | this->invert_);
 | 
			
		||||
}
 | 
			
		||||
void SSD1306::set_contrast(float contrast) {
 | 
			
		||||
  // validation
 | 
			
		||||
  this->contrast_ = clamp(contrast, 0.0F, 1.0F);
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,6 @@ class SSD1306 : public PollingComponent, public display::DisplayBuffer {
 | 
			
		||||
  void init_offset_x(uint8_t offset_x) { this->offset_x_ = offset_x; }
 | 
			
		||||
  void init_offset_y(uint8_t offset_y) { this->offset_y_ = offset_y; }
 | 
			
		||||
  void init_invert(bool invert) { this->invert_ = invert; }
 | 
			
		||||
  void set_invert(bool invert);
 | 
			
		||||
  bool is_on();
 | 
			
		||||
  void turn_on();
 | 
			
		||||
  void turn_off();
 | 
			
		||||
 
 | 
			
		||||
@@ -591,11 +591,11 @@ CONFIG_SCHEMA = cv.All(
 | 
			
		||||
            cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature,
 | 
			
		||||
            cv.Optional(
 | 
			
		||||
                CONF_SET_POINT_MINIMUM_DIFFERENTIAL, default=0.5
 | 
			
		||||
            ): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature_delta,
 | 
			
		||||
            ): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_COOL_DEADBAND, default=0.5): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_COOL_OVERRUN, default=0.5): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_HEAT_DEADBAND, default=0.5): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_HEAT_OVERRUN, default=0.5): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_MAX_COOLING_RUN_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_MAX_HEATING_RUN_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_MIN_COOLING_OFF_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
@@ -608,8 +608,8 @@ CONFIG_SCHEMA = cv.All(
 | 
			
		||||
            cv.Optional(CONF_MIN_HEATING_OFF_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_MIN_HEATING_RUN_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Required(CONF_MIN_IDLE_TIME): cv.positive_time_period_seconds,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature_delta,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_COOLING_DELTA): cv.temperature,
 | 
			
		||||
            cv.Optional(CONF_SUPPLEMENTAL_HEATING_DELTA): cv.temperature,
 | 
			
		||||
            cv.Optional(
 | 
			
		||||
                CONF_FAN_ONLY_ACTION_USES_FAN_MODE_TIMER, default=False
 | 
			
		||||
            ): cv.boolean,
 | 
			
		||||
 
 | 
			
		||||
@@ -324,7 +324,11 @@ class WiFiComponent : public Component {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef USE_ESP32_FRAMEWORK_ARDUINO
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
  void wifi_event_callback_(arduino_event_id_t event, arduino_event_info_t info);
 | 
			
		||||
#else
 | 
			
		||||
  void wifi_event_callback_(system_event_id_t event, system_event_info_t info);
 | 
			
		||||
#endif
 | 
			
		||||
  void wifi_scan_done_callback_();
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef USE_ESP_IDF
 | 
			
		||||
 
 | 
			
		||||
@@ -203,10 +203,12 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
 | 
			
		||||
  // Units: AP beacon intervals. Defaults to 3 if set to 0.
 | 
			
		||||
  conf.sta.listen_interval = 0;
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
  // Protected Management Frame
 | 
			
		||||
  // Device will prefer to connect in PMF mode if other device also advertises PMF capability.
 | 
			
		||||
  conf.sta.pmf_cfg.capable = true;
 | 
			
		||||
  conf.sta.pmf_cfg.required = false;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // note, we do our own filtering
 | 
			
		||||
  // The minimum rssi to accept in the fast scan mode
 | 
			
		||||
@@ -312,7 +314,11 @@ const char *get_auth_mode_str(uint8_t mode) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
using esphome_ip4_addr_t = esp_ip4_addr_t;
 | 
			
		||||
#else
 | 
			
		||||
using esphome_ip4_addr_t = ip4_addr_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
std::string format_ip4_addr(const esphome_ip4_addr_t &ip) {
 | 
			
		||||
  char buf[20];
 | 
			
		||||
@@ -398,6 +404,8 @@ const char *get_disconnect_reason_str(uint8_t reason) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_READY ARDUINO_EVENT_WIFI_READY
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_SCAN_DONE ARDUINO_EVENT_WIFI_SCAN_DONE
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_START ARDUINO_EVENT_WIFI_STA_START
 | 
			
		||||
@@ -418,6 +426,28 @@ const char *get_disconnect_reason_str(uint8_t reason) {
 | 
			
		||||
using esphome_wifi_event_id_t = arduino_event_id_t;
 | 
			
		||||
using esphome_wifi_event_info_t = arduino_event_info_t;
 | 
			
		||||
 | 
			
		||||
#else  // ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_READY SYSTEM_EVENT_WIFI_READY
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_SCAN_DONE SYSTEM_EVENT_SCAN_DONE
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_START SYSTEM_EVENT_STA_START
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_STOP SYSTEM_EVENT_STA_STOP
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_CONNECTED SYSTEM_EVENT_STA_CONNECTED
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED SYSTEM_EVENT_STA_DISCONNECTED
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE SYSTEM_EVENT_STA_AUTHMODE_CHANGE
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_GOT_IP SYSTEM_EVENT_STA_GOT_IP
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_STA_LOST_IP SYSTEM_EVENT_STA_LOST_IP
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_AP_START SYSTEM_EVENT_AP_START
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_AP_STOP SYSTEM_EVENT_AP_STOP
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED SYSTEM_EVENT_AP_STACONNECTED
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED SYSTEM_EVENT_AP_STADISCONNECTED
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_AP_STAIPASSIGNED SYSTEM_EVENT_AP_STAIPASSIGNED
 | 
			
		||||
#define ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED SYSTEM_EVENT_AP_PROBEREQRECVED
 | 
			
		||||
using esphome_wifi_event_id_t = system_event_id_t;
 | 
			
		||||
using esphome_wifi_event_info_t = system_event_info_t;
 | 
			
		||||
 | 
			
		||||
#endif  // !(ESP_IDF_VERSION_MAJOR >= 4)
 | 
			
		||||
 | 
			
		||||
void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_wifi_event_info_t info) {
 | 
			
		||||
  switch (event) {
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_READY: {
 | 
			
		||||
@@ -425,7 +455,11 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_SCAN_DONE: {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
      auto it = info.wifi_scan_done;
 | 
			
		||||
#else
 | 
			
		||||
      auto it = info.scan_done;
 | 
			
		||||
#endif
 | 
			
		||||
      ESP_LOGV(TAG, "Event: WiFi Scan Done status=%u number=%u scan_id=%u", it.status, it.number, it.scan_id);
 | 
			
		||||
 | 
			
		||||
      this->wifi_scan_done_callback_();
 | 
			
		||||
@@ -441,20 +475,28 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_STA_CONNECTED: {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
      auto it = info.wifi_sta_connected;
 | 
			
		||||
#else
 | 
			
		||||
      auto it = info.connected;
 | 
			
		||||
#endif
 | 
			
		||||
      char buf[33];
 | 
			
		||||
      memcpy(buf, it.ssid, it.ssid_len);
 | 
			
		||||
      buf[it.ssid_len] = '\0';
 | 
			
		||||
      ESP_LOGV(TAG, "Event: Connected ssid='%s' bssid=" LOG_SECRET("%s") " channel=%u, authmode=%s", buf,
 | 
			
		||||
               format_mac_addr(it.bssid).c_str(), it.channel, get_auth_mode_str(it.authmode));
 | 
			
		||||
#if LWIP_IPV6
 | 
			
		||||
      this->set_timeout(100, [] { WiFi.enableIpV6(); });
 | 
			
		||||
      WiFi.enableIpV6();
 | 
			
		||||
#endif /* LWIP_IPV6 */
 | 
			
		||||
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_STA_DISCONNECTED: {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
      auto it = info.wifi_sta_disconnected;
 | 
			
		||||
#else
 | 
			
		||||
      auto it = info.disconnected;
 | 
			
		||||
#endif
 | 
			
		||||
      char buf[33];
 | 
			
		||||
      memcpy(buf, it.ssid, it.ssid_len);
 | 
			
		||||
      buf[it.ssid_len] = '\0';
 | 
			
		||||
@@ -480,7 +522,11 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_STA_AUTHMODE_CHANGE: {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
      auto it = info.wifi_sta_authmode_change;
 | 
			
		||||
#else
 | 
			
		||||
      auto it = info.auth_change;
 | 
			
		||||
#endif
 | 
			
		||||
      ESP_LOGV(TAG, "Event: Authmode Change old=%s new=%s", get_auth_mode_str(it.old_mode),
 | 
			
		||||
               get_auth_mode_str(it.new_mode));
 | 
			
		||||
      // Mitigate CVE-2020-12638
 | 
			
		||||
@@ -524,14 +570,24 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_AP_STACONNECTED: {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
      auto it = info.wifi_sta_connected;
 | 
			
		||||
      auto &mac = it.bssid;
 | 
			
		||||
#else
 | 
			
		||||
      auto it = info.sta_connected;
 | 
			
		||||
      auto &mac = it.mac;
 | 
			
		||||
#endif
 | 
			
		||||
      ESP_LOGV(TAG, "Event: AP client connected MAC=%s", format_mac_addr(mac).c_str());
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_AP_STADISCONNECTED: {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
      auto it = info.wifi_sta_disconnected;
 | 
			
		||||
      auto &mac = it.bssid;
 | 
			
		||||
#else
 | 
			
		||||
      auto it = info.sta_disconnected;
 | 
			
		||||
      auto &mac = it.mac;
 | 
			
		||||
#endif
 | 
			
		||||
      ESP_LOGV(TAG, "Event: AP client disconnected MAC=%s", format_mac_addr(mac).c_str());
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -540,7 +596,11 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case ESPHOME_EVENT_ID_WIFI_AP_PROBEREQRECVED: {
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
      auto it = info.wifi_ap_probereqrecved;
 | 
			
		||||
#else
 | 
			
		||||
      auto it = info.ap_probereqrecved;
 | 
			
		||||
#endif
 | 
			
		||||
      ESP_LOGVV(TAG, "Event: AP receive Probe Request MAC=%s RSSI=%d", format_mac_addr(it.mac).c_str(), it.rssi);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
@@ -682,7 +742,10 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
 | 
			
		||||
    strncpy(reinterpret_cast<char *>(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.ssid));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
  // pairwise cipher of SoftAP, group cipher will be derived using this.
 | 
			
		||||
  conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf);
 | 
			
		||||
  if (err != ESP_OK) {
 | 
			
		||||
 
 | 
			
		||||
@@ -312,10 +312,12 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) {
 | 
			
		||||
  // Units: AP beacon intervals. Defaults to 3 if set to 0.
 | 
			
		||||
  conf.sta.listen_interval = 0;
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
  // Protected Management Frame
 | 
			
		||||
  // Device will prefer to connect in PMF mode if other device also advertises PMF capability.
 | 
			
		||||
  conf.sta.pmf_cfg.capable = true;
 | 
			
		||||
  conf.sta.pmf_cfg.required = false;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // note, we do our own filtering
 | 
			
		||||
  // The minimum rssi to accept in the fast scan mode
 | 
			
		||||
@@ -836,8 +838,10 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) {
 | 
			
		||||
    strncpy(reinterpret_cast<char *>(conf.ap.password), ap.get_password().c_str(), sizeof(conf.ap.password));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if ESP_IDF_VERSION_MAJOR >= 4
 | 
			
		||||
  // pairwise cipher of SoftAP, group cipher will be derived using this.
 | 
			
		||||
  conf.ap.pairwise_cipher = WIFI_CIPHER_TYPE_CCMP;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  esp_err_t err = esp_wifi_set_config(WIFI_IF_AP, &conf);
 | 
			
		||||
  if (err != ESP_OK) {
 | 
			
		||||
 
 | 
			
		||||
@@ -125,7 +125,6 @@ RESERVED_IDS = [
 | 
			
		||||
    "char16_t",
 | 
			
		||||
    "char32_t",
 | 
			
		||||
    "class",
 | 
			
		||||
    "clock",
 | 
			
		||||
    "compl",
 | 
			
		||||
    "concept",
 | 
			
		||||
    "const",
 | 
			
		||||
@@ -929,27 +928,6 @@ def temperature(value):
 | 
			
		||||
    raise err
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def temperature_delta(value):
 | 
			
		||||
    err = None
 | 
			
		||||
    try:
 | 
			
		||||
        return _temperature_c(value)
 | 
			
		||||
    except Invalid as orig_err:
 | 
			
		||||
        err = orig_err
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        return _temperature_k(value)
 | 
			
		||||
    except Invalid:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        fahrenheit = _temperature_f(value)
 | 
			
		||||
        return fahrenheit * (5 / 9)
 | 
			
		||||
    except Invalid:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    raise err
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
_color_temperature_mireds = float_with_unit("Color Temperature", r"(mireds|Mireds)")
 | 
			
		||||
_color_temperature_kelvin = float_with_unit("Color Temperature", r"(K|Kelvin)")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
"""Constants used by esphome."""
 | 
			
		||||
 | 
			
		||||
__version__ = "2023.9.0-dev"
 | 
			
		||||
__version__ = "2023.8.0b3"
 | 
			
		||||
 | 
			
		||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
 | 
			
		||||
VALID_SUBSTITUTIONS_CHARACTERS = (
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,6 @@
 | 
			
		||||
// IDF-specific feature flags
 | 
			
		||||
#ifdef USE_ESP_IDF
 | 
			
		||||
#define USE_MQTT_IDF_ENQUEUE
 | 
			
		||||
#define USE_ESP_ADF
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// ESP32-specific feature flags
 | 
			
		||||
 
 | 
			
		||||
@@ -868,6 +868,9 @@ class PingStatusThread(threading.Thread):
 | 
			
		||||
                entries = _list_dashboard_entries()
 | 
			
		||||
                queue = collections.deque()
 | 
			
		||||
                for entry in entries:
 | 
			
		||||
                    if entry.no_mdns is True:
 | 
			
		||||
                        continue
 | 
			
		||||
 | 
			
		||||
                    if entry.address is None:
 | 
			
		||||
                        PING_RESULT[entry.filename] = None
 | 
			
		||||
                        continue
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ lib_deps =
 | 
			
		||||
    glmnet/Dsmr@0.7                                       ; dsmr
 | 
			
		||||
    rweather/Crypto@0.4.0                                 ; dsmr
 | 
			
		||||
    dudanov/MideaUART@1.1.8                               ; midea
 | 
			
		||||
    tonia/HeatpumpIR@1.0.23                               ; heatpumpir
 | 
			
		||||
    tonia/HeatpumpIR@1.0.20                               ; heatpumpir
 | 
			
		||||
build_flags =
 | 
			
		||||
    ${common.build_flags}
 | 
			
		||||
    -DUSE_ARDUINO
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,12 @@ tornado==6.3.2
 | 
			
		||||
tzlocal==5.0.1    # from time
 | 
			
		||||
tzdata>=2021.1  # from time
 | 
			
		||||
pyserial==3.5
 | 
			
		||||
platformio==6.1.10  # When updating platformio, also update Dockerfile
 | 
			
		||||
platformio==6.1.9  # When updating platformio, also update Dockerfile
 | 
			
		||||
esptool==4.6.2
 | 
			
		||||
click==8.1.7
 | 
			
		||||
click==8.1.6
 | 
			
		||||
esphome-dashboard==20230711.0
 | 
			
		||||
aioesphomeapi==15.0.0
 | 
			
		||||
zeroconf==0.80.0
 | 
			
		||||
zeroconf==0.74.0
 | 
			
		||||
 | 
			
		||||
# esp-idf requires this, but doesn't bundle it by default
 | 
			
		||||
# https://github.com/espressif/esp-idf/blob/220590d599e134d7a5e7f1e683cc4550349ffbf8/requirements.txt#L24
 | 
			
		||||
 
 | 
			
		||||
@@ -348,16 +348,6 @@ mcp23s17:
 | 
			
		||||
    deviceaddress: 1
 | 
			
		||||
 | 
			
		||||
sensor:
 | 
			
		||||
  - platform: pmwcs3
 | 
			
		||||
    i2c_id: i2c_bus
 | 
			
		||||
    e25:
 | 
			
		||||
      name: pmwcs3_e25
 | 
			
		||||
    ec:
 | 
			
		||||
      name: pmwcs3_ec
 | 
			
		||||
    temperature:
 | 
			
		||||
      name: pmwcs3_temperature
 | 
			
		||||
    vwc:
 | 
			
		||||
      name: pmwcs3_vwc
 | 
			
		||||
  - platform: gcja5
 | 
			
		||||
    pm_1_0:
 | 
			
		||||
      name: "Particulate Matter <1.0µm Concentration"
 | 
			
		||||
@@ -2299,13 +2289,6 @@ climate:
 | 
			
		||||
    name: HeatpumpIR Climate
 | 
			
		||||
    min_temperature: 18
 | 
			
		||||
    max_temperature: 30
 | 
			
		||||
  - platform: heatpumpir
 | 
			
		||||
    protocol: greeyt
 | 
			
		||||
    horizontal_default: left
 | 
			
		||||
    vertical_default: up
 | 
			
		||||
    name: HeatpumpIR Climate
 | 
			
		||||
    min_temperature: 18
 | 
			
		||||
    max_temperature: 30
 | 
			
		||||
  - platform: midea_ir
 | 
			
		||||
    name: Midea IR
 | 
			
		||||
    use_fahrenheit: true
 | 
			
		||||
 
 | 
			
		||||
@@ -768,8 +768,3 @@ switch:
 | 
			
		||||
          characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC
 | 
			
		||||
          value: !lambda |-
 | 
			
		||||
            return {0x13, 0x37};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
esp32_ble_server:
 | 
			
		||||
  id: ble
 | 
			
		||||
  manufacturer_data: [0x72, 0x4, 0x00, 0x23]
 | 
			
		||||
 
 | 
			
		||||
@@ -957,7 +957,7 @@ climate:
 | 
			
		||||
      temperature_step: 1 °C
 | 
			
		||||
    supported_modes:
 | 
			
		||||
    - 'OFF'
 | 
			
		||||
    - HEAT_COOL
 | 
			
		||||
    - AUTO
 | 
			
		||||
    - COOL
 | 
			
		||||
    - HEAT
 | 
			
		||||
    - DRY
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user