mirror of
https://github.com/esphome/esphome.git
synced 2024-11-24 07:58:09 +01:00
Merge branch 'dev' into optolink
This commit is contained in:
commit
28236c9db4
34 changed files with 410 additions and 128 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -130,3 +130,5 @@ sdkconfig.*
|
||||||
!sdkconfig.defaults
|
!sdkconfig.defaults
|
||||||
|
|
||||||
.tests/
|
.tests/
|
||||||
|
|
||||||
|
/components
|
||||||
|
|
|
@ -22,16 +22,22 @@ RUN \
|
||||||
python3=3.9.2-3 \
|
python3=3.9.2-3 \
|
||||||
python3-pip=20.3.4-4+deb11u1 \
|
python3-pip=20.3.4-4+deb11u1 \
|
||||||
python3-setuptools=52.0.0-4 \
|
python3-setuptools=52.0.0-4 \
|
||||||
python3-pil=8.1.2+dfsg-0.3+deb11u1 \
|
|
||||||
python3-cryptography=3.3.2-1 \
|
python3-cryptography=3.3.2-1 \
|
||||||
python3-venv=3.9.2-3 \
|
python3-venv=3.9.2-3 \
|
||||||
iputils-ping=3:20210202-1 \
|
iputils-ping=3:20210202-1 \
|
||||||
git=1:2.30.2-1+deb11u2 \
|
git=1:2.30.2-1+deb11u2 \
|
||||||
curl=7.74.0-1.3+deb11u7 \
|
curl=7.74.0-1.3+deb11u7 \
|
||||||
openssh-client=1:8.4p1-5+deb11u1 \
|
openssh-client=1:8.4p1-5+deb11u1 \
|
||||||
libcairo2=1.16.0-5 \
|
python3-cffi=1.14.5-1; \
|
||||||
python3-cffi=1.14.5-1 \
|
if [ "$TARGETARCH$TARGETVARIANT" = "armv7" ]; then \
|
||||||
&& rm -rf \
|
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 \
|
||||||
|
libcairo2=1.16.0-5; \
|
||||||
|
fi; \
|
||||||
|
rm -rf \
|
||||||
/tmp/* \
|
/tmp/* \
|
||||||
/var/{cache,log}/* \
|
/var/{cache,log}/* \
|
||||||
/var/lib/apt/lists/*
|
/var/lib/apt/lists/*
|
||||||
|
|
|
@ -365,10 +365,16 @@ def command_wizard(args):
|
||||||
|
|
||||||
|
|
||||||
def command_config(args, config):
|
def command_config(args, config):
|
||||||
_LOGGER.info("Configuration is valid!")
|
|
||||||
if not CORE.verbose:
|
if not CORE.verbose:
|
||||||
config = strip_default_ids(config)
|
config = strip_default_ids(config)
|
||||||
safe_print(yaml_util.dump(config, args.show_secrets))
|
output = yaml_util.dump(config, args.show_secrets)
|
||||||
|
# add the console decoration so the front-end can hide the secrets
|
||||||
|
if not args.show_secrets:
|
||||||
|
output = re.sub(
|
||||||
|
r"(password|key|psk|ssid)\:\s(.*)", r"\1: \\033[5m\2\\033[6m", output
|
||||||
|
)
|
||||||
|
safe_print(output)
|
||||||
|
_LOGGER.info("Configuration is valid!")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1420,6 +1420,7 @@ message VoiceAssistantRequest {
|
||||||
|
|
||||||
bool start = 1;
|
bool start = 1;
|
||||||
string conversation_id = 2;
|
string conversation_id = 2;
|
||||||
|
bool use_vad = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message VoiceAssistantResponse {
|
message VoiceAssistantResponse {
|
||||||
|
|
|
@ -907,12 +907,13 @@ BluetoothConnectionsFreeResponse APIConnection::subscribe_bluetooth_connections_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_VOICE_ASSISTANT
|
#ifdef USE_VOICE_ASSISTANT
|
||||||
bool APIConnection::request_voice_assistant(bool start, const std::string &conversation_id) {
|
bool APIConnection::request_voice_assistant(bool start, const std::string &conversation_id, bool use_vad) {
|
||||||
if (!this->voice_assistant_subscription_)
|
if (!this->voice_assistant_subscription_)
|
||||||
return false;
|
return false;
|
||||||
VoiceAssistantRequest msg;
|
VoiceAssistantRequest msg;
|
||||||
msg.start = start;
|
msg.start = start;
|
||||||
msg.conversation_id = conversation_id;
|
msg.conversation_id = conversation_id;
|
||||||
|
msg.use_vad = use_vad;
|
||||||
return this->send_voice_assistant_request(msg);
|
return this->send_voice_assistant_request(msg);
|
||||||
}
|
}
|
||||||
void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &msg) {
|
void APIConnection::on_voice_assistant_response(const VoiceAssistantResponse &msg) {
|
||||||
|
|
|
@ -124,7 +124,7 @@ class APIConnection : public APIServerConnection {
|
||||||
void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override {
|
void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override {
|
||||||
this->voice_assistant_subscription_ = msg.subscribe;
|
this->voice_assistant_subscription_ = msg.subscribe;
|
||||||
}
|
}
|
||||||
bool request_voice_assistant(bool start, const std::string &conversation_id);
|
bool request_voice_assistant(bool start, const std::string &conversation_id, bool use_vad);
|
||||||
void on_voice_assistant_response(const VoiceAssistantResponse &msg) override;
|
void on_voice_assistant_response(const VoiceAssistantResponse &msg) override;
|
||||||
void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override;
|
void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6348,6 +6348,10 @@ bool VoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarInt value)
|
||||||
this->start = value.as_bool();
|
this->start = value.as_bool();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 3: {
|
||||||
|
this->use_vad = value.as_bool();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6365,6 +6369,7 @@ bool VoiceAssistantRequest::decode_length(uint32_t field_id, ProtoLengthDelimite
|
||||||
void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const {
|
void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const {
|
||||||
buffer.encode_bool(1, this->start);
|
buffer.encode_bool(1, this->start);
|
||||||
buffer.encode_string(2, this->conversation_id);
|
buffer.encode_string(2, this->conversation_id);
|
||||||
|
buffer.encode_bool(3, this->use_vad);
|
||||||
}
|
}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void VoiceAssistantRequest::dump_to(std::string &out) const {
|
void VoiceAssistantRequest::dump_to(std::string &out) const {
|
||||||
|
@ -6377,6 +6382,10 @@ void VoiceAssistantRequest::dump_to(std::string &out) const {
|
||||||
out.append(" conversation_id: ");
|
out.append(" conversation_id: ");
|
||||||
out.append("'").append(this->conversation_id).append("'");
|
out.append("'").append(this->conversation_id).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" use_vad: ");
|
||||||
|
out.append(YESNO(this->use_vad));
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1655,6 +1655,7 @@ class VoiceAssistantRequest : public ProtoMessage {
|
||||||
public:
|
public:
|
||||||
bool start{false};
|
bool start{false};
|
||||||
std::string conversation_id{};
|
std::string conversation_id{};
|
||||||
|
bool use_vad{false};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
|
|
|
@ -323,16 +323,16 @@ void APIServer::on_shutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_VOICE_ASSISTANT
|
#ifdef USE_VOICE_ASSISTANT
|
||||||
bool APIServer::start_voice_assistant(const std::string &conversation_id) {
|
bool APIServer::start_voice_assistant(const std::string &conversation_id, bool use_vad) {
|
||||||
for (auto &c : this->clients_) {
|
for (auto &c : this->clients_) {
|
||||||
if (c->request_voice_assistant(true, conversation_id))
|
if (c->request_voice_assistant(true, conversation_id, use_vad))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void APIServer::stop_voice_assistant() {
|
void APIServer::stop_voice_assistant() {
|
||||||
for (auto &c : this->clients_) {
|
for (auto &c : this->clients_) {
|
||||||
if (c->request_voice_assistant(false, ""))
|
if (c->request_voice_assistant(false, "", false))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ class APIServer : public Component, public Controller {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_VOICE_ASSISTANT
|
#ifdef USE_VOICE_ASSISTANT
|
||||||
bool start_voice_assistant(const std::string &conversation_id);
|
bool start_voice_assistant(const std::string &conversation_id, bool use_vad);
|
||||||
void stop_voice_assistant();
|
void stop_voice_assistant();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ bool CoolixClimate::on_coolix(climate::Climate *parent, remote_base::RemoteRecei
|
||||||
if (!decoded.has_value())
|
if (!decoded.has_value())
|
||||||
return false;
|
return false;
|
||||||
// Decoded remote state y 3 bytes long code.
|
// Decoded remote state y 3 bytes long code.
|
||||||
uint32_t remote_state = *decoded;
|
uint32_t remote_state = (*decoded).second;
|
||||||
ESP_LOGV(TAG, "Decoded 0x%06X", remote_state);
|
ESP_LOGV(TAG, "Decoded 0x%06X", remote_state);
|
||||||
if ((remote_state & 0xFF0000) != 0xB20000)
|
if ((remote_state & 0xFF0000) != 0xB20000)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -51,7 +51,7 @@ bool E131AddressableLightEffect::process_(int universe, const E131Packet &packet
|
||||||
if (universe < first_universe_ || universe > get_last_universe())
|
if (universe < first_universe_ || universe > get_last_universe())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int output_offset = (universe - first_universe_) * get_lights_per_universe();
|
int32_t output_offset = (universe - first_universe_) * get_lights_per_universe();
|
||||||
// limit amount of lights per universe and received
|
// limit amount of lights per universe and received
|
||||||
int output_end =
|
int output_end =
|
||||||
std::min(it->size(), std::min(output_offset + get_lights_per_universe(), output_offset + packet.count - 1));
|
std::min(it->size(), std::min(output_offset + get_lights_per_universe(), output_offset + packet.count - 1));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Union
|
from typing import Union, Optional
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -42,6 +42,7 @@ from .const import ( # noqa
|
||||||
KEY_REFRESH,
|
KEY_REFRESH,
|
||||||
KEY_REPO,
|
KEY_REPO,
|
||||||
KEY_SDKCONFIG_OPTIONS,
|
KEY_SDKCONFIG_OPTIONS,
|
||||||
|
KEY_SUBMODULES,
|
||||||
KEY_VARIANT,
|
KEY_VARIANT,
|
||||||
VARIANT_ESP32C3,
|
VARIANT_ESP32C3,
|
||||||
VARIANT_FRIENDLY,
|
VARIANT_FRIENDLY,
|
||||||
|
@ -120,17 +121,28 @@ def add_idf_sdkconfig_option(name: str, value: SdkconfigValueType):
|
||||||
|
|
||||||
|
|
||||||
def add_idf_component(
|
def add_idf_component(
|
||||||
name: str, repo: str, ref: str = None, path: str = None, refresh: TimePeriod = None
|
*,
|
||||||
|
name: str,
|
||||||
|
repo: str,
|
||||||
|
ref: str = None,
|
||||||
|
path: str = None,
|
||||||
|
refresh: TimePeriod = None,
|
||||||
|
components: Optional[list[str]] = None,
|
||||||
|
submodules: Optional[list[str]] = None,
|
||||||
):
|
):
|
||||||
"""Add an esp-idf component to the project."""
|
"""Add an esp-idf component to the project."""
|
||||||
if not CORE.using_esp_idf:
|
if not CORE.using_esp_idf:
|
||||||
raise ValueError("Not an esp-idf project")
|
raise ValueError("Not an esp-idf project")
|
||||||
|
if components is None:
|
||||||
|
components = []
|
||||||
if name not in CORE.data[KEY_ESP32][KEY_COMPONENTS]:
|
if name not in CORE.data[KEY_ESP32][KEY_COMPONENTS]:
|
||||||
CORE.data[KEY_ESP32][KEY_COMPONENTS][name] = {
|
CORE.data[KEY_ESP32][KEY_COMPONENTS][name] = {
|
||||||
KEY_REPO: repo,
|
KEY_REPO: repo,
|
||||||
KEY_REF: ref,
|
KEY_REF: ref,
|
||||||
KEY_PATH: path,
|
KEY_PATH: path,
|
||||||
KEY_REFRESH: refresh,
|
KEY_REFRESH: refresh,
|
||||||
|
KEY_COMPONENTS: components,
|
||||||
|
KEY_SUBMODULES: submodules,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,23 +175,23 @@ RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(2, 0, 5)
|
||||||
# The platformio/espressif32 version to use for arduino frameworks
|
# The platformio/espressif32 version to use for arduino frameworks
|
||||||
# - https://github.com/platformio/platform-espressif32/releases
|
# - https://github.com/platformio/platform-espressif32/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
||||||
ARDUINO_PLATFORM_VERSION = cv.Version(5, 3, 0)
|
ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0)
|
||||||
|
|
||||||
# The default/recommended esp-idf framework version
|
# The default/recommended esp-idf framework version
|
||||||
# - https://github.com/espressif/esp-idf/releases
|
# - https://github.com/espressif/esp-idf/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
|
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
|
||||||
RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 4)
|
RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 5)
|
||||||
# The platformio/espressif32 version to use for esp-idf frameworks
|
# The platformio/espressif32 version to use for esp-idf frameworks
|
||||||
# - https://github.com/platformio/platform-espressif32/releases
|
# - https://github.com/platformio/platform-espressif32/releases
|
||||||
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
||||||
ESP_IDF_PLATFORM_VERSION = cv.Version(5, 3, 0)
|
ESP_IDF_PLATFORM_VERSION = cv.Version(5, 4, 0)
|
||||||
|
|
||||||
|
|
||||||
def _arduino_check_versions(value):
|
def _arduino_check_versions(value):
|
||||||
value = value.copy()
|
value = value.copy()
|
||||||
lookups = {
|
lookups = {
|
||||||
"dev": (cv.Version(2, 1, 0), "https://github.com/espressif/arduino-esp32.git"),
|
"dev": (cv.Version(2, 1, 0), "https://github.com/espressif/arduino-esp32.git"),
|
||||||
"latest": (cv.Version(2, 0, 7), None),
|
"latest": (cv.Version(2, 0, 9), None),
|
||||||
"recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
|
"recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +226,7 @@ def _esp_idf_check_versions(value):
|
||||||
value = value.copy()
|
value = value.copy()
|
||||||
lookups = {
|
lookups = {
|
||||||
"dev": (cv.Version(5, 1, 0), "https://github.com/espressif/esp-idf.git"),
|
"dev": (cv.Version(5, 1, 0), "https://github.com/espressif/esp-idf.git"),
|
||||||
"latest": (cv.Version(5, 0, 1), None),
|
"latest": (cv.Version(5, 1, 0), None),
|
||||||
"recommended": (RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION, None),
|
"recommended": (RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,17 +548,38 @@ def copy_files():
|
||||||
ref=component[KEY_REF],
|
ref=component[KEY_REF],
|
||||||
refresh=component[KEY_REFRESH],
|
refresh=component[KEY_REFRESH],
|
||||||
domain="idf_components",
|
domain="idf_components",
|
||||||
|
submodules=component[KEY_SUBMODULES],
|
||||||
)
|
)
|
||||||
mkdir_p(CORE.relative_build_path("components"))
|
mkdir_p(CORE.relative_build_path("components"))
|
||||||
component_dir = repo_dir
|
component_dir = repo_dir
|
||||||
if component[KEY_PATH] is not None:
|
if component[KEY_PATH] is not None:
|
||||||
component_dir = component_dir / component[KEY_PATH]
|
component_dir = component_dir / component[KEY_PATH]
|
||||||
|
|
||||||
|
if component[KEY_COMPONENTS] == ["*"]:
|
||||||
|
shutil.copytree(
|
||||||
|
component_dir,
|
||||||
|
CORE.relative_build_path("components"),
|
||||||
|
dirs_exist_ok=True,
|
||||||
|
ignore=shutil.ignore_patterns(".git*"),
|
||||||
|
symlinks=True,
|
||||||
|
ignore_dangling_symlinks=True,
|
||||||
|
)
|
||||||
|
elif len(component[KEY_COMPONENTS]) > 0:
|
||||||
|
for comp in component[KEY_COMPONENTS]:
|
||||||
|
shutil.copytree(
|
||||||
|
component_dir / comp,
|
||||||
|
CORE.relative_build_path(f"components/{comp}"),
|
||||||
|
dirs_exist_ok=True,
|
||||||
|
ignore=shutil.ignore_patterns(".git*"),
|
||||||
|
symlinks=True,
|
||||||
|
ignore_dangling_symlinks=True,
|
||||||
|
)
|
||||||
|
else:
|
||||||
shutil.copytree(
|
shutil.copytree(
|
||||||
component_dir,
|
component_dir,
|
||||||
CORE.relative_build_path(f"components/{name}"),
|
CORE.relative_build_path(f"components/{name}"),
|
||||||
dirs_exist_ok=True,
|
dirs_exist_ok=True,
|
||||||
ignore=shutil.ignore_patterns(".git", ".github"),
|
ignore=shutil.ignore_patterns(".git*"),
|
||||||
symlinks=True,
|
symlinks=True,
|
||||||
ignore_dangling_symlinks=True,
|
ignore_dangling_symlinks=True,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1201,6 +1201,10 @@ BOARDS = {
|
||||||
"name": "BPI-Bit",
|
"name": "BPI-Bit",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
},
|
},
|
||||||
|
"bpi_leaf_s3": {
|
||||||
|
"name": "BPI-Leaf-S3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
"briki_abc_esp32": {
|
"briki_abc_esp32": {
|
||||||
"name": "Briki ABC (MBC-WB) - ESP32",
|
"name": "Briki ABC (MBC-WB) - ESP32",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
|
@ -1217,6 +1221,10 @@ BOARDS = {
|
||||||
"name": "Connaxio's Espoir",
|
"name": "Connaxio's Espoir",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
},
|
},
|
||||||
|
"cytron_maker_feather_aiot_s3": {
|
||||||
|
"name": "Cytron Maker Feather AIoT S3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
"d-duino-32": {
|
"d-duino-32": {
|
||||||
"name": "D-duino-32",
|
"name": "D-duino-32",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
|
@ -1225,6 +1233,10 @@ BOARDS = {
|
||||||
"name": "Deneyap Kart 1A",
|
"name": "Deneyap Kart 1A",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
},
|
},
|
||||||
|
"deneyapkart1Av2": {
|
||||||
|
"name": "Deneyap Kart 1A v2",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
"deneyapkartg": {
|
"deneyapkartg": {
|
||||||
"name": "Deneyap Kart G",
|
"name": "Deneyap Kart G",
|
||||||
"variant": VARIANT_ESP32C3,
|
"variant": VARIANT_ESP32C3,
|
||||||
|
@ -1237,6 +1249,10 @@ BOARDS = {
|
||||||
"name": "Deneyap Mini",
|
"name": "Deneyap Mini",
|
||||||
"variant": VARIANT_ESP32S2,
|
"variant": VARIANT_ESP32S2,
|
||||||
},
|
},
|
||||||
|
"deneyapminiv2": {
|
||||||
|
"name": "Deneyap Mini v2",
|
||||||
|
"variant": VARIANT_ESP32S2,
|
||||||
|
},
|
||||||
"denky32": {
|
"denky32": {
|
||||||
"name": "Denky32 (WROOM32)",
|
"name": "Denky32 (WROOM32)",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
|
@ -1265,6 +1281,10 @@ BOARDS = {
|
||||||
"name": "Espressif ESP32-C3-DevKitM-1",
|
"name": "Espressif ESP32-C3-DevKitM-1",
|
||||||
"variant": VARIANT_ESP32C3,
|
"variant": VARIANT_ESP32C3,
|
||||||
},
|
},
|
||||||
|
"esp32-c3-m1i-kit": {
|
||||||
|
"name": "Ai-Thinker ESP-C3-M1-I-Kit",
|
||||||
|
"variant": VARIANT_ESP32C3,
|
||||||
|
},
|
||||||
"esp32cam": {
|
"esp32cam": {
|
||||||
"name": "AI Thinker ESP32-CAM",
|
"name": "AI Thinker ESP32-CAM",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
|
@ -1329,6 +1349,10 @@ BOARDS = {
|
||||||
"name": "Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)",
|
"name": "Espressif ESP32-S3-DevKitC-1-N8 (8 MB QD, No PSRAM)",
|
||||||
"variant": VARIANT_ESP32S3,
|
"variant": VARIANT_ESP32S3,
|
||||||
},
|
},
|
||||||
|
"esp32-s3-korvo-2": {
|
||||||
|
"name": "Espressif ESP32-S3-Korvo-2",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
"esp32thing": {
|
"esp32thing": {
|
||||||
"name": "SparkFun ESP32 Thing",
|
"name": "SparkFun ESP32 Thing",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
|
@ -1637,6 +1661,10 @@ BOARDS = {
|
||||||
"name": "Noduino Quantum",
|
"name": "Noduino Quantum",
|
||||||
"variant": VARIANT_ESP32,
|
"variant": VARIANT_ESP32,
|
||||||
},
|
},
|
||||||
|
"redpill_esp32s3": {
|
||||||
|
"name": "Munich Labs RedPill ESP32-S3",
|
||||||
|
"variant": VARIANT_ESP32S3,
|
||||||
|
},
|
||||||
"seeed_xiao_esp32c3": {
|
"seeed_xiao_esp32c3": {
|
||||||
"name": "Seeed Studio XIAO ESP32C3",
|
"name": "Seeed Studio XIAO ESP32C3",
|
||||||
"variant": VARIANT_ESP32C3,
|
"variant": VARIANT_ESP32C3,
|
||||||
|
|
|
@ -9,6 +9,7 @@ KEY_REPO = "repo"
|
||||||
KEY_REF = "ref"
|
KEY_REF = "ref"
|
||||||
KEY_REFRESH = "refresh"
|
KEY_REFRESH = "refresh"
|
||||||
KEY_PATH = "path"
|
KEY_PATH = "path"
|
||||||
|
KEY_SUBMODULES = "submodules"
|
||||||
|
|
||||||
VARIANT_ESP32 = "ESP32"
|
VARIANT_ESP32 = "ESP32"
|
||||||
VARIANT_ESP32S2 = "ESP32S2"
|
VARIANT_ESP32S2 = "ESP32S2"
|
||||||
|
|
|
@ -112,7 +112,6 @@ CONFIG_SCHEMA = cv.All(
|
||||||
|
|
||||||
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema(
|
||||||
"ld2410",
|
"ld2410",
|
||||||
baud_rate=256000,
|
|
||||||
require_tx=True,
|
require_tx=True,
|
||||||
require_rx=True,
|
require_rx=True,
|
||||||
parity="NONE",
|
parity="NONE",
|
||||||
|
|
|
@ -86,10 +86,10 @@ async def to_code(config):
|
||||||
5, 0, 0
|
5, 0, 0
|
||||||
):
|
):
|
||||||
add_idf_component(
|
add_idf_component(
|
||||||
"mdns",
|
name="mdns",
|
||||||
"https://github.com/espressif/esp-protocols.git",
|
repo="https://github.com/espressif/esp-protocols.git",
|
||||||
"mdns-v1.0.9",
|
ref="mdns-v1.0.9",
|
||||||
"components/mdns",
|
path="components/mdns",
|
||||||
)
|
)
|
||||||
|
|
||||||
if config[CONF_DISABLED]:
|
if config[CONF_DISABLED]:
|
||||||
|
|
|
@ -28,6 +28,7 @@ from esphome.const import (
|
||||||
DEVICE_CLASS_DATA_RATE,
|
DEVICE_CLASS_DATA_RATE,
|
||||||
DEVICE_CLASS_DATA_SIZE,
|
DEVICE_CLASS_DATA_SIZE,
|
||||||
DEVICE_CLASS_DISTANCE,
|
DEVICE_CLASS_DISTANCE,
|
||||||
|
DEVICE_CLASS_DURATION,
|
||||||
DEVICE_CLASS_EMPTY,
|
DEVICE_CLASS_EMPTY,
|
||||||
DEVICE_CLASS_ENERGY,
|
DEVICE_CLASS_ENERGY,
|
||||||
DEVICE_CLASS_ENERGY_STORAGE,
|
DEVICE_CLASS_ENERGY_STORAGE,
|
||||||
|
@ -42,6 +43,7 @@ from esphome.const import (
|
||||||
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
||||||
DEVICE_CLASS_NITROUS_OXIDE,
|
DEVICE_CLASS_NITROUS_OXIDE,
|
||||||
DEVICE_CLASS_OZONE,
|
DEVICE_CLASS_OZONE,
|
||||||
|
DEVICE_CLASS_PH,
|
||||||
DEVICE_CLASS_PM1,
|
DEVICE_CLASS_PM1,
|
||||||
DEVICE_CLASS_PM10,
|
DEVICE_CLASS_PM10,
|
||||||
DEVICE_CLASS_PM25,
|
DEVICE_CLASS_PM25,
|
||||||
|
@ -81,6 +83,7 @@ DEVICE_CLASSES = [
|
||||||
DEVICE_CLASS_DATA_RATE,
|
DEVICE_CLASS_DATA_RATE,
|
||||||
DEVICE_CLASS_DATA_SIZE,
|
DEVICE_CLASS_DATA_SIZE,
|
||||||
DEVICE_CLASS_DISTANCE,
|
DEVICE_CLASS_DISTANCE,
|
||||||
|
DEVICE_CLASS_DURATION,
|
||||||
DEVICE_CLASS_EMPTY,
|
DEVICE_CLASS_EMPTY,
|
||||||
DEVICE_CLASS_ENERGY,
|
DEVICE_CLASS_ENERGY,
|
||||||
DEVICE_CLASS_ENERGY_STORAGE,
|
DEVICE_CLASS_ENERGY_STORAGE,
|
||||||
|
@ -95,6 +98,7 @@ DEVICE_CLASSES = [
|
||||||
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
||||||
DEVICE_CLASS_NITROUS_OXIDE,
|
DEVICE_CLASS_NITROUS_OXIDE,
|
||||||
DEVICE_CLASS_OZONE,
|
DEVICE_CLASS_OZONE,
|
||||||
|
DEVICE_CLASS_PH,
|
||||||
DEVICE_CLASS_PM1,
|
DEVICE_CLASS_PM1,
|
||||||
DEVICE_CLASS_PM10,
|
DEVICE_CLASS_PM10,
|
||||||
DEVICE_CLASS_PM25,
|
DEVICE_CLASS_PM25,
|
||||||
|
|
|
@ -17,6 +17,7 @@ from esphome.const import (
|
||||||
CONF_PROTOCOL,
|
CONF_PROTOCOL,
|
||||||
CONF_GROUP,
|
CONF_GROUP,
|
||||||
CONF_DEVICE,
|
CONF_DEVICE,
|
||||||
|
CONF_SECOND,
|
||||||
CONF_STATE,
|
CONF_STATE,
|
||||||
CONF_CHANNEL,
|
CONF_CHANNEL,
|
||||||
CONF_FAMILY,
|
CONF_FAMILY,
|
||||||
|
@ -39,6 +40,7 @@ AUTO_LOAD = ["binary_sensor"]
|
||||||
|
|
||||||
CONF_RECEIVER_ID = "receiver_id"
|
CONF_RECEIVER_ID = "receiver_id"
|
||||||
CONF_TRANSMITTER_ID = "transmitter_id"
|
CONF_TRANSMITTER_ID = "transmitter_id"
|
||||||
|
CONF_FIRST = "first"
|
||||||
|
|
||||||
ns = remote_base_ns = cg.esphome_ns.namespace("remote_base")
|
ns = remote_base_ns = cg.esphome_ns.namespace("remote_base")
|
||||||
RemoteProtocol = ns.class_("RemoteProtocol")
|
RemoteProtocol = ns.class_("RemoteProtocol")
|
||||||
|
@ -349,19 +351,48 @@ async def canalsatld_action(var, config, args):
|
||||||
CoolixAction,
|
CoolixAction,
|
||||||
CoolixDumper,
|
CoolixDumper,
|
||||||
) = declare_protocol("Coolix")
|
) = declare_protocol("Coolix")
|
||||||
COOLIX_SCHEMA = cv.Schema({cv.Required(CONF_DATA): cv.hex_uint32_t})
|
|
||||||
|
|
||||||
|
|
||||||
@register_binary_sensor("coolix", CoolixBinarySensor, COOLIX_SCHEMA)
|
COOLIX_BASE_SCHEMA = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_FIRST): cv.hex_int_range(0, 16777215),
|
||||||
|
cv.Optional(CONF_SECOND, default=0): cv.hex_int_range(0, 16777215),
|
||||||
|
cv.Optional(CONF_DATA): cv.invalid(
|
||||||
|
"'data' option has been removed in ESPHome 2023.8. "
|
||||||
|
"Use the 'first' and 'second' options instead."
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
COOLIX_SENSOR_SCHEMA = cv.Any(cv.hex_int_range(0, 16777215), COOLIX_BASE_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
|
@register_binary_sensor("coolix", CoolixBinarySensor, COOLIX_SENSOR_SCHEMA)
|
||||||
def coolix_binary_sensor(var, config):
|
def coolix_binary_sensor(var, config):
|
||||||
|
if isinstance(config, dict):
|
||||||
cg.add(
|
cg.add(
|
||||||
var.set_data(
|
var.set_data(
|
||||||
cg.StructInitializer(
|
cg.StructInitializer(
|
||||||
CoolixData,
|
CoolixData,
|
||||||
("data", config[CONF_DATA]),
|
("first", config[CONF_FIRST]),
|
||||||
|
("second", config[CONF_SECOND]),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
cg.add(
|
||||||
|
var.set_data(
|
||||||
|
cg.StructInitializer(CoolixData, ("first", 0), ("second", config))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register_action("coolix", CoolixAction, COOLIX_BASE_SCHEMA)
|
||||||
|
async def coolix_action(var, config, args):
|
||||||
|
template_ = await cg.templatable(config[CONF_FIRST], args, cg.uint32)
|
||||||
|
cg.add(var.set_first(template_))
|
||||||
|
template_ = await cg.templatable(config[CONF_SECOND], args, cg.uint32)
|
||||||
|
cg.add(var.set_second(template_))
|
||||||
|
|
||||||
|
|
||||||
@register_trigger("coolix", CoolixTrigger, CoolixData)
|
@register_trigger("coolix", CoolixTrigger, CoolixData)
|
||||||
|
@ -374,12 +405,6 @@ def coolix_dumper(var, config):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@register_action("coolix", CoolixAction, COOLIX_SCHEMA)
|
|
||||||
async def coolix_action(var, config, args):
|
|
||||||
template_ = await cg.templatable(config[CONF_DATA], args, cg.uint32)
|
|
||||||
cg.add(var.set_data(template_))
|
|
||||||
|
|
||||||
|
|
||||||
# Dish
|
# Dish
|
||||||
DishData, DishBinarySensor, DishTrigger, DishAction, DishDumper = declare_protocol(
|
DishData, DishBinarySensor, DishTrigger, DishAction, DishDumper = declare_protocol(
|
||||||
"Dish"
|
"Dish"
|
||||||
|
|
|
@ -15,11 +15,21 @@ static const int32_t BIT_ZERO_SPACE_US = 1 * TICK_US;
|
||||||
static const int32_t FOOTER_MARK_US = 1 * TICK_US;
|
static const int32_t FOOTER_MARK_US = 1 * TICK_US;
|
||||||
static const int32_t FOOTER_SPACE_US = 10 * TICK_US;
|
static const int32_t FOOTER_SPACE_US = 10 * TICK_US;
|
||||||
|
|
||||||
static void encode_data(RemoteTransmitData *dst, const CoolixData &src) {
|
bool CoolixData::operator==(const CoolixData &other) const {
|
||||||
|
if (this->first == 0)
|
||||||
|
return this->second == other.first || this->second == other.second;
|
||||||
|
if (other.first == 0)
|
||||||
|
return other.second == this->first || other.second == this->second;
|
||||||
|
return this->first == other.first && this->second == other.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void encode_frame(RemoteTransmitData *dst, const uint32_t &src) {
|
||||||
|
// Append header
|
||||||
|
dst->item(HEADER_MARK_US, HEADER_SPACE_US);
|
||||||
// Break data into bytes, starting at the Most Significant
|
// Break data into bytes, starting at the Most Significant
|
||||||
// Byte. Each byte then being sent normal, then followed inverted.
|
// Byte. Each byte then being sent normal, then followed inverted.
|
||||||
for (unsigned shift = 16;; shift -= 8) {
|
for (unsigned shift = 16;; shift -= 8) {
|
||||||
// Grab a bytes worth of data.
|
// Grab a bytes worth of data
|
||||||
const uint8_t byte = src >> shift;
|
const uint8_t byte = src >> shift;
|
||||||
// Normal
|
// Normal
|
||||||
for (uint8_t mask = 1 << 7; mask; mask >>= 1)
|
for (uint8_t mask = 1 << 7; mask; mask >>= 1)
|
||||||
|
@ -27,27 +37,33 @@ static void encode_data(RemoteTransmitData *dst, const CoolixData &src) {
|
||||||
// Inverted
|
// Inverted
|
||||||
for (uint8_t mask = 1 << 7; mask; mask >>= 1)
|
for (uint8_t mask = 1 << 7; mask; mask >>= 1)
|
||||||
dst->item(BIT_MARK_US, (byte & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US);
|
dst->item(BIT_MARK_US, (byte & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US);
|
||||||
// Data end
|
// End of frame
|
||||||
if (shift == 0)
|
if (shift == 0) {
|
||||||
|
// Append footer
|
||||||
|
dst->mark(FOOTER_MARK_US);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CoolixProtocol::encode(RemoteTransmitData *dst, const CoolixData &data) {
|
void CoolixProtocol::encode(RemoteTransmitData *dst, const CoolixData &data) {
|
||||||
dst->set_carrier_frequency(38000);
|
dst->set_carrier_frequency(38000);
|
||||||
dst->reserve(2 + 2 * 48 + 2 + 2 + 2 * 48 + 1);
|
dst->reserve(100 + 100 * data.has_second());
|
||||||
dst->item(HEADER_MARK_US, HEADER_SPACE_US);
|
encode_frame(dst, data.first);
|
||||||
encode_data(dst, data);
|
if (data.has_second()) {
|
||||||
dst->item(FOOTER_MARK_US, FOOTER_SPACE_US);
|
dst->space(FOOTER_SPACE_US);
|
||||||
dst->item(HEADER_MARK_US, HEADER_SPACE_US);
|
encode_frame(dst, data.second);
|
||||||
encode_data(dst, data);
|
}
|
||||||
dst->mark(FOOTER_MARK_US);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decode_data(RemoteReceiveData &src, CoolixData &dst) {
|
static bool decode_frame(RemoteReceiveData &src, uint32_t &dst) {
|
||||||
|
// Checking for header
|
||||||
|
if (!src.expect_item(HEADER_MARK_US, HEADER_SPACE_US))
|
||||||
|
return false;
|
||||||
|
// Reading data
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
for (unsigned n = 3;; data <<= 8) {
|
for (unsigned n = 3;; data <<= 8) {
|
||||||
// Read byte
|
// Reading byte
|
||||||
for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
|
for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
|
||||||
if (!src.expect_mark(BIT_MARK_US))
|
if (!src.expect_mark(BIT_MARK_US))
|
||||||
return false;
|
return false;
|
||||||
|
@ -57,13 +73,16 @@ static bool decode_data(RemoteReceiveData &src, CoolixData &dst) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for inverse byte
|
// Checking for inverted byte
|
||||||
for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
|
for (uint32_t mask = 1 << 7; mask; mask >>= 1) {
|
||||||
if (!src.expect_item(BIT_MARK_US, (data & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US))
|
if (!src.expect_item(BIT_MARK_US, (data & mask) ? BIT_ZERO_SPACE_US : BIT_ONE_SPACE_US))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Checking the end of reading
|
// End of frame
|
||||||
if (--n == 0) {
|
if (--n == 0) {
|
||||||
|
// Checking for footer
|
||||||
|
if (!src.expect_mark(FOOTER_MARK_US))
|
||||||
|
return false;
|
||||||
dst = data;
|
dst = data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -71,15 +90,24 @@ static bool decode_data(RemoteReceiveData &src, CoolixData &dst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<CoolixData> CoolixProtocol::decode(RemoteReceiveData data) {
|
optional<CoolixData> CoolixProtocol::decode(RemoteReceiveData data) {
|
||||||
CoolixData first, second;
|
CoolixData result;
|
||||||
if (data.expect_item(HEADER_MARK_US, HEADER_SPACE_US) && decode_data(data, first) &&
|
const auto size = data.size();
|
||||||
data.expect_item(FOOTER_MARK_US, FOOTER_SPACE_US) && data.expect_item(HEADER_MARK_US, HEADER_SPACE_US) &&
|
if ((size != 200 && size != 100) || !decode_frame(data, result.first))
|
||||||
decode_data(data, second) && data.expect_mark(FOOTER_MARK_US) && first == second)
|
|
||||||
return first;
|
|
||||||
return {};
|
return {};
|
||||||
|
if (size == 100 || !data.expect_space(FOOTER_SPACE_US) || !decode_frame(data, result.second))
|
||||||
|
result.second = 0;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoolixProtocol::dump(const CoolixData &data) { ESP_LOGD(TAG, "Received Coolix: 0x%06X", data); }
|
void CoolixProtocol::dump(const CoolixData &data) {
|
||||||
|
if (data.is_strict()) {
|
||||||
|
ESP_LOGD(TAG, "Received Coolix: 0x%06X", data.first);
|
||||||
|
} else if (data.has_second()) {
|
||||||
|
ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X, 0x%06X]", data.first, data.second);
|
||||||
|
} else {
|
||||||
|
ESP_LOGD(TAG, "Received unstrict Coolix: [0x%06X]", data.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace remote_base
|
} // namespace remote_base
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -7,7 +7,16 @@
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace remote_base {
|
namespace remote_base {
|
||||||
|
|
||||||
using CoolixData = uint32_t;
|
struct CoolixData {
|
||||||
|
CoolixData() {}
|
||||||
|
CoolixData(uint32_t a) : first(a), second(a) {}
|
||||||
|
CoolixData(uint32_t a, uint32_t b) : first(a), second(b) {}
|
||||||
|
bool operator==(const CoolixData &other) const;
|
||||||
|
bool is_strict() const { return this->first == this->second; }
|
||||||
|
bool has_second() const { return this->second != 0; }
|
||||||
|
uint32_t first;
|
||||||
|
uint32_t second;
|
||||||
|
};
|
||||||
|
|
||||||
class CoolixProtocol : public RemoteProtocol<CoolixData> {
|
class CoolixProtocol : public RemoteProtocol<CoolixData> {
|
||||||
public:
|
public:
|
||||||
|
@ -19,10 +28,10 @@ class CoolixProtocol : public RemoteProtocol<CoolixData> {
|
||||||
DECLARE_REMOTE_PROTOCOL(Coolix)
|
DECLARE_REMOTE_PROTOCOL(Coolix)
|
||||||
|
|
||||||
template<typename... Ts> class CoolixAction : public RemoteTransmitterActionBase<Ts...> {
|
template<typename... Ts> class CoolixAction : public RemoteTransmitterActionBase<Ts...> {
|
||||||
TEMPLATABLE_VALUE(CoolixData, data)
|
TEMPLATABLE_VALUE(uint32_t, first)
|
||||||
|
TEMPLATABLE_VALUE(uint32_t, second)
|
||||||
void encode(RemoteTransmitData *dst, Ts... x) override {
|
void encode(RemoteTransmitData *dst, Ts... x) override {
|
||||||
CoolixData data = this->data_.value(x...);
|
CoolixProtocol().encode(dst, {this->first_.value(x...), this->second_.value(x...)});
|
||||||
CoolixProtocol().encode(dst, data);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ from esphome.const import (
|
||||||
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
||||||
DEVICE_CLASS_NITROUS_OXIDE,
|
DEVICE_CLASS_NITROUS_OXIDE,
|
||||||
DEVICE_CLASS_OZONE,
|
DEVICE_CLASS_OZONE,
|
||||||
|
DEVICE_CLASS_PH,
|
||||||
DEVICE_CLASS_PM1,
|
DEVICE_CLASS_PM1,
|
||||||
DEVICE_CLASS_PM10,
|
DEVICE_CLASS_PM10,
|
||||||
DEVICE_CLASS_PM25,
|
DEVICE_CLASS_PM25,
|
||||||
|
@ -114,6 +115,7 @@ DEVICE_CLASSES = [
|
||||||
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
DEVICE_CLASS_NITROGEN_MONOXIDE,
|
||||||
DEVICE_CLASS_NITROUS_OXIDE,
|
DEVICE_CLASS_NITROUS_OXIDE,
|
||||||
DEVICE_CLASS_OZONE,
|
DEVICE_CLASS_OZONE,
|
||||||
|
DEVICE_CLASS_PH,
|
||||||
DEVICE_CLASS_PM1,
|
DEVICE_CLASS_PM1,
|
||||||
DEVICE_CLASS_PM10,
|
DEVICE_CLASS_PM10,
|
||||||
DEVICE_CLASS_PM25,
|
DEVICE_CLASS_PM25,
|
||||||
|
|
57
esphome/components/sigma_delta_output/sigma_delta_output.cpp
Normal file
57
esphome/components/sigma_delta_output/sigma_delta_output.cpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#include "sigma_delta_output.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace sigma_delta_output {
|
||||||
|
|
||||||
|
static const char *const TAG = "output.sigma_delta";
|
||||||
|
|
||||||
|
void SigmaDeltaOutput::setup() {
|
||||||
|
if (this->pin_)
|
||||||
|
this->pin_->setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SigmaDeltaOutput::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "Sigma Delta Output:");
|
||||||
|
LOG_PIN(" Pin: ", this->pin_);
|
||||||
|
if (this->state_change_trigger_) {
|
||||||
|
ESP_LOGCONFIG(TAG, " State change automation configured");
|
||||||
|
}
|
||||||
|
if (this->turn_on_trigger_) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Turn on automation configured");
|
||||||
|
}
|
||||||
|
if (this->turn_off_trigger_) {
|
||||||
|
ESP_LOGCONFIG(TAG, " Turn off automation configured");
|
||||||
|
}
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
LOG_FLOAT_OUTPUT(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SigmaDeltaOutput::update() {
|
||||||
|
this->accum_ += this->state_;
|
||||||
|
const bool next_value = this->accum_ > 0;
|
||||||
|
|
||||||
|
if (next_value) {
|
||||||
|
this->accum_ -= 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_value != this->value_) {
|
||||||
|
this->value_ = next_value;
|
||||||
|
if (this->pin_) {
|
||||||
|
this->pin_->digital_write(next_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->state_change_trigger_) {
|
||||||
|
this->state_change_trigger_->trigger(next_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_value && this->turn_on_trigger_) {
|
||||||
|
this->turn_on_trigger_->trigger();
|
||||||
|
} else if (!next_value && this->turn_off_trigger_) {
|
||||||
|
this->turn_off_trigger_->trigger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sigma_delta_output
|
||||||
|
} // namespace esphome
|
|
@ -1,9 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "esphome/core/automation.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
#include "esphome/components/output/float_output.h"
|
#include "esphome/components/output/float_output.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace sigma_delta_output {
|
namespace sigma_delta_output {
|
||||||
|
|
||||||
class SigmaDeltaOutput : public PollingComponent, public output::FloatOutput {
|
class SigmaDeltaOutput : public PollingComponent, public output::FloatOutput {
|
||||||
public:
|
public:
|
||||||
Trigger<> *get_turn_on_trigger() {
|
Trigger<> *get_turn_on_trigger() {
|
||||||
|
@ -25,31 +28,9 @@ class SigmaDeltaOutput : public PollingComponent, public output::FloatOutput {
|
||||||
|
|
||||||
void set_pin(GPIOPin *pin) { this->pin_ = pin; };
|
void set_pin(GPIOPin *pin) { this->pin_ = pin; };
|
||||||
void write_state(float state) override { this->state_ = state; }
|
void write_state(float state) override { this->state_ = state; }
|
||||||
void update() override {
|
void setup() override;
|
||||||
this->accum_ += this->state_;
|
void dump_config() override;
|
||||||
const bool next_value = this->accum_ > 0;
|
void update() override;
|
||||||
|
|
||||||
if (next_value) {
|
|
||||||
this->accum_ -= 1.;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_value != this->value_) {
|
|
||||||
this->value_ = next_value;
|
|
||||||
if (this->pin_) {
|
|
||||||
this->pin_->digital_write(next_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->state_change_trigger_) {
|
|
||||||
this->state_change_trigger_->trigger(next_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_value && this->turn_on_trigger_) {
|
|
||||||
this->turn_on_trigger_->trigger();
|
|
||||||
} else if (!next_value && this->turn_off_trigger_) {
|
|
||||||
this->turn_off_trigger_->trigger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GPIOPin *pin_{nullptr};
|
GPIOPin *pin_{nullptr};
|
||||||
|
|
|
@ -130,7 +130,7 @@ void VoiceAssistant::start(struct sockaddr_storage *addr, uint16_t port) {
|
||||||
|
|
||||||
void VoiceAssistant::request_start(bool continuous) {
|
void VoiceAssistant::request_start(bool continuous) {
|
||||||
ESP_LOGD(TAG, "Requesting start...");
|
ESP_LOGD(TAG, "Requesting start...");
|
||||||
if (!api::global_api_server->start_voice_assistant(this->conversation_id_)) {
|
if (!api::global_api_server->start_voice_assistant(this->conversation_id_, this->silence_detection_)) {
|
||||||
ESP_LOGW(TAG, "Could not request start.");
|
ESP_LOGW(TAG, "Could not request start.");
|
||||||
this->error_trigger_->trigger("not-connected", "Could not request start.");
|
this->error_trigger_->trigger("not-connected", "Could not request start.");
|
||||||
this->continuous_ = false;
|
this->continuous_ = false;
|
||||||
|
|
|
@ -25,10 +25,9 @@ namespace voice_assistant {
|
||||||
|
|
||||||
// Version 1: Initial version
|
// Version 1: Initial version
|
||||||
// Version 2: Adds raw speaker support
|
// Version 2: Adds raw speaker support
|
||||||
// Version 3: Adds continuous support
|
// Version 3: Unused/skip
|
||||||
static const uint32_t INITIAL_VERSION = 1;
|
static const uint32_t INITIAL_VERSION = 1;
|
||||||
static const uint32_t SPEAKER_SUPPORT = 2;
|
static const uint32_t SPEAKER_SUPPORT = 2;
|
||||||
static const uint32_t SILENCE_DETECTION_SUPPORT = 3;
|
|
||||||
|
|
||||||
class VoiceAssistant : public Component {
|
class VoiceAssistant : public Component {
|
||||||
public:
|
public:
|
||||||
|
@ -48,9 +47,6 @@ class VoiceAssistant : public Component {
|
||||||
uint32_t get_version() const {
|
uint32_t get_version() const {
|
||||||
#ifdef USE_SPEAKER
|
#ifdef USE_SPEAKER
|
||||||
if (this->speaker_ != nullptr) {
|
if (this->speaker_ != nullptr) {
|
||||||
if (this->silence_detection_) {
|
|
||||||
return SILENCE_DETECTION_SUPPORT;
|
|
||||||
}
|
|
||||||
return SPEAKER_SUPPORT;
|
return SPEAKER_SUPPORT;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -988,6 +988,7 @@ DEVICE_CLASS_OCCUPANCY = "occupancy"
|
||||||
DEVICE_CLASS_OPENING = "opening"
|
DEVICE_CLASS_OPENING = "opening"
|
||||||
DEVICE_CLASS_OUTLET = "outlet"
|
DEVICE_CLASS_OUTLET = "outlet"
|
||||||
DEVICE_CLASS_OZONE = "ozone"
|
DEVICE_CLASS_OZONE = "ozone"
|
||||||
|
DEVICE_CLASS_PH = "ph"
|
||||||
DEVICE_CLASS_PLUG = "plug"
|
DEVICE_CLASS_PLUG = "plug"
|
||||||
DEVICE_CLASS_PM1 = "pm1"
|
DEVICE_CLASS_PM1 = "pm1"
|
||||||
DEVICE_CLASS_PM10 = "pm10"
|
DEVICE_CLASS_PM10 = "pm10"
|
||||||
|
|
|
@ -475,6 +475,7 @@ template<typename... Ts> class CallbackManager<void(Ts...)> {
|
||||||
for (auto &cb : this->callbacks_)
|
for (auto &cb : this->callbacks_)
|
||||||
cb(args...);
|
cb(args...);
|
||||||
}
|
}
|
||||||
|
size_t size() const { return this->callbacks_.size(); }
|
||||||
|
|
||||||
/// Call all callbacks in this manager.
|
/// Call all callbacks in this manager.
|
||||||
void operator()(Ts... args) { call(args...); }
|
void operator()(Ts... args) { call(args...); }
|
||||||
|
|
|
@ -25,6 +25,7 @@ import tornado.ioloop
|
||||||
import tornado.iostream
|
import tornado.iostream
|
||||||
import tornado.netutil
|
import tornado.netutil
|
||||||
import tornado.process
|
import tornado.process
|
||||||
|
import tornado.queues
|
||||||
import tornado.web
|
import tornado.web
|
||||||
import tornado.websocket
|
import tornado.websocket
|
||||||
import yaml
|
import yaml
|
||||||
|
@ -92,6 +93,10 @@ class DashboardSettings:
|
||||||
def using_auth(self):
|
def using_auth(self):
|
||||||
return self.using_password or self.using_ha_addon_auth
|
return self.using_password or self.using_ha_addon_auth
|
||||||
|
|
||||||
|
@property
|
||||||
|
def streamer_mode(self):
|
||||||
|
return get_bool_env("ESPHOME_STREAMER_MODE")
|
||||||
|
|
||||||
def check_password(self, username, password):
|
def check_password(self, username, password):
|
||||||
if not self.using_auth:
|
if not self.using_auth:
|
||||||
return True
|
return True
|
||||||
|
@ -130,7 +135,7 @@ def template_args():
|
||||||
"docs_link": docs_link,
|
"docs_link": docs_link,
|
||||||
"get_static_file_url": get_static_file_url,
|
"get_static_file_url": get_static_file_url,
|
||||||
"relative_url": settings.relative_url,
|
"relative_url": settings.relative_url,
|
||||||
"streamer_mode": get_bool_env("ESPHOME_STREAMER_MODE"),
|
"streamer_mode": settings.streamer_mode,
|
||||||
"config_dir": settings.config_dir,
|
"config_dir": settings.config_dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +207,11 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
||||||
def __init__(self, application, request, **kwargs):
|
def __init__(self, application, request, **kwargs):
|
||||||
super().__init__(application, request, **kwargs)
|
super().__init__(application, request, **kwargs)
|
||||||
self._proc = None
|
self._proc = None
|
||||||
|
self._queue = None
|
||||||
self._is_closed = False
|
self._is_closed = False
|
||||||
|
# Windows doesn't support non-blocking pipes,
|
||||||
|
# use Popen() with a reading thread instead
|
||||||
|
self._use_popen = os.name == "nt"
|
||||||
|
|
||||||
@authenticated
|
@authenticated
|
||||||
def on_message(self, message):
|
def on_message(self, message):
|
||||||
|
@ -224,6 +233,20 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
||||||
return
|
return
|
||||||
command = self.build_command(json_message)
|
command = self.build_command(json_message)
|
||||||
_LOGGER.info("Running command '%s'", " ".join(shlex_quote(x) for x in command))
|
_LOGGER.info("Running command '%s'", " ".join(shlex_quote(x) for x in command))
|
||||||
|
|
||||||
|
if self._use_popen:
|
||||||
|
self._queue = tornado.queues.Queue()
|
||||||
|
# pylint: disable=consider-using-with
|
||||||
|
self._proc = subprocess.Popen(
|
||||||
|
command,
|
||||||
|
stdin=subprocess.PIPE,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
)
|
||||||
|
stdout_thread = threading.Thread(target=self._stdout_thread)
|
||||||
|
stdout_thread.daemon = True
|
||||||
|
stdout_thread.start()
|
||||||
|
else:
|
||||||
self._proc = tornado.process.Subprocess(
|
self._proc = tornado.process.Subprocess(
|
||||||
command,
|
command,
|
||||||
stdout=tornado.process.Subprocess.STREAM,
|
stdout=tornado.process.Subprocess.STREAM,
|
||||||
|
@ -231,6 +254,7 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
||||||
stdin=tornado.process.Subprocess.STREAM,
|
stdin=tornado.process.Subprocess.STREAM,
|
||||||
)
|
)
|
||||||
self._proc.set_exit_callback(self._proc_on_exit)
|
self._proc.set_exit_callback(self._proc_on_exit)
|
||||||
|
|
||||||
tornado.ioloop.IOLoop.current().spawn_callback(self._redirect_stdout)
|
tornado.ioloop.IOLoop.current().spawn_callback(self._redirect_stdout)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -252,6 +276,12 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
if self._use_popen:
|
||||||
|
data = yield self._queue.get()
|
||||||
|
if data is None:
|
||||||
|
self._proc_on_exit(self._proc.poll())
|
||||||
|
break
|
||||||
|
else:
|
||||||
data = yield self._proc.stdout.read_until_regex(reg)
|
data = yield self._proc.stdout.read_until_regex(reg)
|
||||||
except tornado.iostream.StreamClosedError:
|
except tornado.iostream.StreamClosedError:
|
||||||
break
|
break
|
||||||
|
@ -260,6 +290,19 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
||||||
_LOGGER.debug("> stdout: %s", data)
|
_LOGGER.debug("> stdout: %s", data)
|
||||||
self.write_message({"event": "line", "data": data})
|
self.write_message({"event": "line", "data": data})
|
||||||
|
|
||||||
|
def _stdout_thread(self):
|
||||||
|
if not self._use_popen:
|
||||||
|
return
|
||||||
|
while True:
|
||||||
|
data = self._proc.stdout.readline()
|
||||||
|
if data:
|
||||||
|
data = data.replace(b"\r", b"")
|
||||||
|
self._queue.put_nowait(data)
|
||||||
|
if self._proc.poll() is not None:
|
||||||
|
break
|
||||||
|
self._proc.wait(1.0)
|
||||||
|
self._queue.put_nowait(None)
|
||||||
|
|
||||||
def _proc_on_exit(self, returncode):
|
def _proc_on_exit(self, returncode):
|
||||||
if not self._is_closed:
|
if not self._is_closed:
|
||||||
# Check if the proc was not forcibly closed
|
# Check if the proc was not forcibly closed
|
||||||
|
@ -270,6 +313,9 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler):
|
||||||
# Check if proc exists (if 'start' has been run)
|
# Check if proc exists (if 'start' has been run)
|
||||||
if self.is_process_active:
|
if self.is_process_active:
|
||||||
_LOGGER.debug("Terminating process")
|
_LOGGER.debug("Terminating process")
|
||||||
|
if self._use_popen:
|
||||||
|
self._proc.terminate()
|
||||||
|
else:
|
||||||
self._proc.proc.terminate()
|
self._proc.proc.terminate()
|
||||||
# Shutdown proc on WS close
|
# Shutdown proc on WS close
|
||||||
self._is_closed = True
|
self._is_closed = True
|
||||||
|
@ -354,7 +400,10 @@ class EsphomeCompileHandler(EsphomeCommandWebSocket):
|
||||||
class EsphomeValidateHandler(EsphomeCommandWebSocket):
|
class EsphomeValidateHandler(EsphomeCommandWebSocket):
|
||||||
def build_command(self, json_message):
|
def build_command(self, json_message):
|
||||||
config_file = settings.rel_path(json_message["configuration"])
|
config_file = settings.rel_path(json_message["configuration"])
|
||||||
return ["esphome", "--dashboard", "config", config_file]
|
command = ["esphome", "--dashboard", "config", config_file]
|
||||||
|
if not settings.streamer_mode:
|
||||||
|
command.append("--show-secrets")
|
||||||
|
return command
|
||||||
|
|
||||||
|
|
||||||
class EsphomeCleanMqttHandler(EsphomeCommandWebSocket):
|
class EsphomeCleanMqttHandler(EsphomeCommandWebSocket):
|
||||||
|
@ -1105,7 +1154,7 @@ class JsonConfigRequestHandler(BaseHandler):
|
||||||
self.send_error(404)
|
self.send_error(404)
|
||||||
return
|
return
|
||||||
|
|
||||||
args = ["esphome", "config", settings.rel_path(configuration), "--show-secrets"]
|
args = ["esphome", "config", filename, "--show-secrets"]
|
||||||
|
|
||||||
rc, stdout, _ = run_system_command(*args)
|
rc, stdout, _ = run_system_command(*args)
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def run_git_command(cmd, cwd=None) -> str:
|
def run_git_command(cmd, cwd=None) -> str:
|
||||||
|
_LOGGER.debug("Running git command: %s", " ".join(cmd))
|
||||||
try:
|
try:
|
||||||
ret = subprocess.run(cmd, cwd=cwd, capture_output=True, check=False)
|
ret = subprocess.run(cmd, cwd=cwd, capture_output=True, check=False)
|
||||||
except FileNotFoundError as err:
|
except FileNotFoundError as err:
|
||||||
|
@ -48,6 +49,7 @@ def clone_or_update(
|
||||||
domain: str,
|
domain: str,
|
||||||
username: str = None,
|
username: str = None,
|
||||||
password: str = None,
|
password: str = None,
|
||||||
|
submodules: Optional[list[str]] = None,
|
||||||
) -> tuple[Path, Optional[Callable[[], None]]]:
|
) -> tuple[Path, Optional[Callable[[], None]]]:
|
||||||
key = f"{url}@{ref}"
|
key = f"{url}@{ref}"
|
||||||
|
|
||||||
|
@ -74,6 +76,14 @@ def clone_or_update(
|
||||||
run_git_command(["git", "fetch", "--", "origin", ref], str(repo_dir))
|
run_git_command(["git", "fetch", "--", "origin", ref], str(repo_dir))
|
||||||
run_git_command(["git", "reset", "--hard", "FETCH_HEAD"], str(repo_dir))
|
run_git_command(["git", "reset", "--hard", "FETCH_HEAD"], str(repo_dir))
|
||||||
|
|
||||||
|
if submodules is not None:
|
||||||
|
_LOGGER.info(
|
||||||
|
"Initialising submodules (%s) for %s", ", ".join(submodules), key
|
||||||
|
)
|
||||||
|
run_git_command(
|
||||||
|
["git", "submodule", "update", "--init"] + submodules, str(repo_dir)
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Check refresh needed
|
# Check refresh needed
|
||||||
file_timestamp = Path(repo_dir / ".git" / "FETCH_HEAD")
|
file_timestamp = Path(repo_dir / ".git" / "FETCH_HEAD")
|
||||||
|
@ -97,6 +107,14 @@ def clone_or_update(
|
||||||
# Hard reset to FETCH_HEAD (short-lived git ref corresponding to most recent fetch)
|
# Hard reset to FETCH_HEAD (short-lived git ref corresponding to most recent fetch)
|
||||||
run_git_command(["git", "reset", "--hard", "FETCH_HEAD"], str(repo_dir))
|
run_git_command(["git", "reset", "--hard", "FETCH_HEAD"], str(repo_dir))
|
||||||
|
|
||||||
|
if submodules is not None:
|
||||||
|
_LOGGER.info(
|
||||||
|
"Updating submodules (%s) for %s", ", ".join(submodules), key
|
||||||
|
)
|
||||||
|
run_git_command(
|
||||||
|
["git", "submodule", "update", "--init"] + submodules, str(repo_dir)
|
||||||
|
)
|
||||||
|
|
||||||
def revert():
|
def revert():
|
||||||
_LOGGER.info("Reverting changes to %s -> %s", key, old_sha)
|
_LOGGER.info("Reverting changes to %s -> %s", key, old_sha)
|
||||||
run_git_command(["git", "reset", "--hard", old_sha], str(repo_dir))
|
run_git_command(["git", "reset", "--hard", old_sha], str(repo_dir))
|
||||||
|
|
|
@ -71,6 +71,8 @@ def setup_log(
|
||||||
) -> None:
|
) -> None:
|
||||||
import colorama
|
import colorama
|
||||||
|
|
||||||
|
colorama.init()
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
log_level = logging.DEBUG
|
log_level = logging.DEBUG
|
||||||
CORE.verbose = True
|
CORE.verbose = True
|
||||||
|
@ -82,7 +84,6 @@ def setup_log(
|
||||||
|
|
||||||
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
||||||
|
|
||||||
colorama.init()
|
|
||||||
logging.getLogger().handlers[0].setFormatter(
|
logging.getLogger().handlers[0].setFormatter(
|
||||||
ESPHomeLogFormatter(include_timestamp=include_timestamp)
|
ESPHomeLogFormatter(include_timestamp=include_timestamp)
|
||||||
)
|
)
|
||||||
|
|
|
@ -105,7 +105,7 @@ extra_scripts = post:esphome/components/esp8266/post_build.py.script
|
||||||
; This are common settings for the ESP32 (all variants) using Arduino.
|
; This are common settings for the ESP32 (all variants) using Arduino.
|
||||||
[common:esp32-arduino]
|
[common:esp32-arduino]
|
||||||
extends = common:arduino
|
extends = common:arduino
|
||||||
platform = platformio/espressif32@5.3.0
|
platform = platformio/espressif32@5.4.0
|
||||||
platform_packages =
|
platform_packages =
|
||||||
platformio/framework-arduinoespressif32@~3.20005.0
|
platformio/framework-arduinoespressif32@~3.20005.0
|
||||||
|
|
||||||
|
@ -134,9 +134,9 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script
|
||||||
; This are common settings for the ESP32 (all variants) using IDF.
|
; This are common settings for the ESP32 (all variants) using IDF.
|
||||||
[common:esp32-idf]
|
[common:esp32-idf]
|
||||||
extends = common:idf
|
extends = common:idf
|
||||||
platform = platformio/espressif32@5.3.0
|
platform = platformio/espressif32@5.4.0
|
||||||
platform_packages =
|
platform_packages =
|
||||||
platformio/framework-espidf@~3.40404.0
|
platformio/framework-espidf@~3.40405.0
|
||||||
|
|
||||||
framework = espidf
|
framework = espidf
|
||||||
lib_deps =
|
lib_deps =
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
voluptuous==0.13.1
|
voluptuous==0.13.1
|
||||||
PyYAML==6.0
|
PyYAML==6.0.1
|
||||||
paho-mqtt==1.6.1
|
paho-mqtt==1.6.1
|
||||||
colorama==0.4.6
|
colorama==0.4.6
|
||||||
tornado==6.3.2
|
tornado==6.3.2
|
||||||
|
@ -8,7 +8,7 @@ tzdata>=2021.1 # from time
|
||||||
pyserial==3.5
|
pyserial==3.5
|
||||||
platformio==6.1.7 # When updating platformio, also update Dockerfile
|
platformio==6.1.7 # When updating platformio, also update Dockerfile
|
||||||
esptool==4.6.2
|
esptool==4.6.2
|
||||||
click==8.1.3
|
click==8.1.5
|
||||||
esphome-dashboard==20230711.0
|
esphome-dashboard==20230711.0
|
||||||
aioesphomeapi==15.0.0
|
aioesphomeapi==15.0.0
|
||||||
zeroconf==0.69.0
|
zeroconf==0.69.0
|
||||||
|
|
|
@ -1609,6 +1609,18 @@ binary_sensor:
|
||||||
-2267,
|
-2267,
|
||||||
1709,
|
1709,
|
||||||
]
|
]
|
||||||
|
- platform: remote_receiver
|
||||||
|
name: Coolix Test 1
|
||||||
|
coolix: 0xB21F98
|
||||||
|
- platform: remote_receiver
|
||||||
|
name: Coolix Test 2
|
||||||
|
coolix:
|
||||||
|
first: 0xB2E003
|
||||||
|
- platform: remote_receiver
|
||||||
|
name: Coolix Test 3
|
||||||
|
coolix:
|
||||||
|
first: 0xB2E003
|
||||||
|
second: 0xB21F98
|
||||||
- platform: as3935
|
- platform: as3935
|
||||||
name: Storm Alert
|
name: Storm Alert
|
||||||
- platform: analog_threshold
|
- platform: analog_threshold
|
||||||
|
@ -2283,7 +2295,15 @@ switch:
|
||||||
- platform: template
|
- platform: template
|
||||||
name: MIDEA_RAW
|
name: MIDEA_RAW
|
||||||
turn_on_action:
|
turn_on_action:
|
||||||
remote_transmitter.transmit_midea:
|
- remote_transmitter.transmit_coolix:
|
||||||
|
first: 0xB21F98
|
||||||
|
- remote_transmitter.transmit_coolix:
|
||||||
|
first: 0xB21F98
|
||||||
|
second: 0xB21F98
|
||||||
|
- remote_transmitter.transmit_coolix:
|
||||||
|
first: !lambda "return 0xB21F98;"
|
||||||
|
second: !lambda "return 0xB21F98;"
|
||||||
|
- remote_transmitter.transmit_midea:
|
||||||
code: [0xA2, 0x08, 0xFF, 0xFF, 0xFF]
|
code: [0xA2, 0x08, 0xFF, 0xFF, 0xFF]
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
name: "MCP23S08 Pin #0"
|
name: "MCP23S08 Pin #0"
|
||||||
|
@ -2868,6 +2888,9 @@ tm1651:
|
||||||
remote_receiver:
|
remote_receiver:
|
||||||
pin: GPIO32
|
pin: GPIO32
|
||||||
dump: all
|
dump: all
|
||||||
|
on_coolix:
|
||||||
|
then:
|
||||||
|
delay: !lambda "return x.first + x.second;"
|
||||||
|
|
||||||
status_led:
|
status_led:
|
||||||
pin: GPIO2
|
pin: GPIO2
|
||||||
|
|
Loading…
Reference in a new issue