mirror of
https://github.com/esphome/esphome.git
synced 2025-11-05 17:41:49 +00:00
Compare commits
15 Commits
2023.10.0b
...
2023.10.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b973238323 | ||
|
|
582b8383d2 | ||
|
|
e1c9418aee | ||
|
|
2aa787f5f0 | ||
|
|
2189a40a39 | ||
|
|
51688d4078 | ||
|
|
cc4c0e3e0b | ||
|
|
1a44c6487e | ||
|
|
5e7ce610a0 | ||
|
|
1f02096edb | ||
|
|
fd7d3c4332 | ||
|
|
61cf566560 | ||
|
|
97d624114d | ||
|
|
52e8a2e9e4 | ||
|
|
261c271d60 |
@@ -1459,6 +1459,8 @@ enum VoiceAssistantEvent {
|
|||||||
VOICE_ASSISTANT_WAKE_WORD_END = 10;
|
VOICE_ASSISTANT_WAKE_WORD_END = 10;
|
||||||
VOICE_ASSISTANT_STT_VAD_START = 11;
|
VOICE_ASSISTANT_STT_VAD_START = 11;
|
||||||
VOICE_ASSISTANT_STT_VAD_END = 12;
|
VOICE_ASSISTANT_STT_VAD_END = 12;
|
||||||
|
VOICE_ASSISTANT_TTS_STREAM_START = 98;
|
||||||
|
VOICE_ASSISTANT_TTS_STREAM_END = 99;
|
||||||
}
|
}
|
||||||
|
|
||||||
message VoiceAssistantEventData {
|
message VoiceAssistantEventData {
|
||||||
|
|||||||
@@ -452,6 +452,10 @@ template<> const char *proto_enum_to_string<enums::VoiceAssistantEvent>(enums::V
|
|||||||
return "VOICE_ASSISTANT_STT_VAD_START";
|
return "VOICE_ASSISTANT_STT_VAD_START";
|
||||||
case enums::VOICE_ASSISTANT_STT_VAD_END:
|
case enums::VOICE_ASSISTANT_STT_VAD_END:
|
||||||
return "VOICE_ASSISTANT_STT_VAD_END";
|
return "VOICE_ASSISTANT_STT_VAD_END";
|
||||||
|
case enums::VOICE_ASSISTANT_TTS_STREAM_START:
|
||||||
|
return "VOICE_ASSISTANT_TTS_STREAM_START";
|
||||||
|
case enums::VOICE_ASSISTANT_TTS_STREAM_END:
|
||||||
|
return "VOICE_ASSISTANT_TTS_STREAM_END";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,8 @@ enum VoiceAssistantEvent : uint32_t {
|
|||||||
VOICE_ASSISTANT_WAKE_WORD_END = 10,
|
VOICE_ASSISTANT_WAKE_WORD_END = 10,
|
||||||
VOICE_ASSISTANT_STT_VAD_START = 11,
|
VOICE_ASSISTANT_STT_VAD_START = 11,
|
||||||
VOICE_ASSISTANT_STT_VAD_END = 12,
|
VOICE_ASSISTANT_STT_VAD_END = 12,
|
||||||
|
VOICE_ASSISTANT_TTS_STREAM_START = 98,
|
||||||
|
VOICE_ASSISTANT_TTS_STREAM_END = 99,
|
||||||
};
|
};
|
||||||
enum AlarmControlPanelState : uint32_t {
|
enum AlarmControlPanelState : uint32_t {
|
||||||
ALARM_STATE_DISARMED = 0,
|
ALARM_STATE_DISARMED = 0,
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include "ble_uuid.h"
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
#include "ble_uuid.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
@@ -16,8 +16,8 @@ BLEAdvertising::BLEAdvertising() {
|
|||||||
this->advertising_data_.set_scan_rsp = false;
|
this->advertising_data_.set_scan_rsp = false;
|
||||||
this->advertising_data_.include_name = true;
|
this->advertising_data_.include_name = true;
|
||||||
this->advertising_data_.include_txpower = true;
|
this->advertising_data_.include_txpower = true;
|
||||||
this->advertising_data_.min_interval = 0x20;
|
this->advertising_data_.min_interval = 0;
|
||||||
this->advertising_data_.max_interval = 0x40;
|
this->advertising_data_.max_interval = 0;
|
||||||
this->advertising_data_.appearance = 0x00;
|
this->advertising_data_.appearance = 0x00;
|
||||||
this->advertising_data_.manufacturer_len = 0;
|
this->advertising_data_.manufacturer_len = 0;
|
||||||
this->advertising_data_.p_manufacturer_data = nullptr;
|
this->advertising_data_.p_manufacturer_data = nullptr;
|
||||||
@@ -42,6 +42,17 @@ void BLEAdvertising::remove_service_uuid(ESPBTUUID uuid) {
|
|||||||
this->advertising_uuids_.end());
|
this->advertising_uuids_.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BLEAdvertising::set_service_data(const std::vector<uint8_t> &data) {
|
||||||
|
delete[] this->advertising_data_.p_service_data;
|
||||||
|
this->advertising_data_.p_service_data = nullptr;
|
||||||
|
this->advertising_data_.service_data_len = data.size();
|
||||||
|
if (!data.empty()) {
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
|
||||||
|
this->advertising_data_.p_service_data = new uint8_t[data.size()];
|
||||||
|
memcpy(this->advertising_data_.p_service_data, data.data(), data.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BLEAdvertising::set_manufacturer_data(const std::vector<uint8_t> &data) {
|
void BLEAdvertising::set_manufacturer_data(const std::vector<uint8_t> &data) {
|
||||||
delete[] this->advertising_data_.p_manufacturer_data;
|
delete[] this->advertising_data_.p_manufacturer_data;
|
||||||
this->advertising_data_.p_manufacturer_data = nullptr;
|
this->advertising_data_.p_manufacturer_data = nullptr;
|
||||||
@@ -85,8 +96,6 @@ void BLEAdvertising::start() {
|
|||||||
this->scan_response_data_.set_scan_rsp = true;
|
this->scan_response_data_.set_scan_rsp = true;
|
||||||
this->scan_response_data_.include_name = true;
|
this->scan_response_data_.include_name = true;
|
||||||
this->scan_response_data_.include_txpower = 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_.manufacturer_len = 0;
|
||||||
this->scan_response_data_.appearance = 0;
|
this->scan_response_data_.appearance = 0;
|
||||||
this->scan_response_data_.flag = 0;
|
this->scan_response_data_.flag = 0;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class BLEAdvertising {
|
|||||||
void set_scan_response(bool scan_response) { this->scan_response_ = scan_response; }
|
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_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(const std::vector<uint8_t> &data);
|
||||||
|
void set_service_data(const std::vector<uint8_t> &data);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ void ESP32ImprovComponent::loop() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case improv::STATE_AUTHORIZED: {
|
case improv::STATE_AUTHORIZED: {
|
||||||
|
#ifdef USE_BINARY_SENSOR
|
||||||
if (this->authorizer_ != nullptr) {
|
if (this->authorizer_ != nullptr) {
|
||||||
if (now - this->authorized_start_ > this->authorized_duration_) {
|
if (now - this->authorized_start_ > this->authorized_duration_) {
|
||||||
ESP_LOGD(TAG, "Authorization timeout");
|
ESP_LOGD(TAG, "Authorization timeout");
|
||||||
@@ -114,6 +115,7 @@ void ESP32ImprovComponent::loop() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!this->check_identify_()) {
|
if (!this->check_identify_()) {
|
||||||
this->set_status_indicator_state_((now % 1000) < 500);
|
this->set_status_indicator_state_((now % 1000) < 500);
|
||||||
}
|
}
|
||||||
@@ -187,6 +189,25 @@ void ESP32ImprovComponent::set_state_(improv::State state) {
|
|||||||
if (state != improv::STATE_STOPPED)
|
if (state != improv::STATE_STOPPED)
|
||||||
this->status_->notify();
|
this->status_->notify();
|
||||||
}
|
}
|
||||||
|
std::vector<uint8_t> service_data(8, 0);
|
||||||
|
service_data[0] = 0x77; // PR
|
||||||
|
service_data[1] = 0x46; // IM
|
||||||
|
service_data[2] = static_cast<uint8_t>(state);
|
||||||
|
|
||||||
|
uint8_t capabilities = 0x00;
|
||||||
|
#ifdef USE_OUTPUT
|
||||||
|
if (this->status_indicator_ != nullptr)
|
||||||
|
capabilities |= improv::CAPABILITY_IDENTIFY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
service_data[3] = capabilities;
|
||||||
|
service_data[4] = 0x00; // Reserved
|
||||||
|
service_data[5] = 0x00; // Reserved
|
||||||
|
service_data[6] = 0x00; // Reserved
|
||||||
|
service_data[7] = 0x00; // Reserved
|
||||||
|
|
||||||
|
esp32_ble::global_ble->get_advertising()->set_service_data(service_data);
|
||||||
|
esp32_ble::global_ble->get_advertising()->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESP32ImprovComponent::set_error_(improv::Error error) {
|
void ESP32ImprovComponent::set_error_(improv::Error error) {
|
||||||
@@ -290,8 +311,10 @@ void ESP32ImprovComponent::process_incoming_data_() {
|
|||||||
void ESP32ImprovComponent::on_wifi_connect_timeout_() {
|
void ESP32ImprovComponent::on_wifi_connect_timeout_() {
|
||||||
this->set_error_(improv::ERROR_UNABLE_TO_CONNECT);
|
this->set_error_(improv::ERROR_UNABLE_TO_CONNECT);
|
||||||
this->set_state_(improv::STATE_AUTHORIZED);
|
this->set_state_(improv::STATE_AUTHORIZED);
|
||||||
|
#ifdef USE_BINARY_SENSOR
|
||||||
if (this->authorizer_ != nullptr)
|
if (this->authorizer_ != nullptr)
|
||||||
this->authorized_start_ = millis();
|
this->authorized_start_ = millis();
|
||||||
|
#endif
|
||||||
ESP_LOGW(TAG, "Timed out trying to connect to given WiFi network");
|
ESP_LOGW(TAG, "Timed out trying to connect to given WiFi network");
|
||||||
wifi::global_wifi_component->clear_sta();
|
wifi::global_wifi_component->clear_sta();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ from esphome.const import (
|
|||||||
CONF_CHANNEL,
|
CONF_CHANNEL,
|
||||||
CONF_SPEED,
|
CONF_SPEED,
|
||||||
CONF_DIRECTION,
|
CONF_DIRECTION,
|
||||||
|
CONF_ADDRESS,
|
||||||
)
|
)
|
||||||
|
|
||||||
DEPENDENCIES = ["i2c"]
|
DEPENDENCIES = ["i2c"]
|
||||||
|
|
||||||
CODEOWNERS = ["@max246"]
|
CODEOWNERS = ["@max246"]
|
||||||
|
|
||||||
|
MULTI_CONF = True
|
||||||
|
|
||||||
grove_tb6612fng_ns = cg.esphome_ns.namespace("grove_tb6612fng")
|
grove_tb6612fng_ns = cg.esphome_ns.namespace("grove_tb6612fng")
|
||||||
GROVE_TB6612FNG = grove_tb6612fng_ns.class_(
|
GROVE_TB6612FNG = grove_tb6612fng_ns.class_(
|
||||||
"GroveMotorDriveTB6612FNG", cg.Component, i2c.I2CDevice
|
"GroveMotorDriveTB6612FNG", cg.Component, i2c.I2CDevice
|
||||||
@@ -33,6 +36,9 @@ GROVETB6612FNGMotorStandbyAction = grove_tb6612fng_ns.class_(
|
|||||||
GROVETB6612FNGMotorNoStandbyAction = grove_tb6612fng_ns.class_(
|
GROVETB6612FNGMotorNoStandbyAction = grove_tb6612fng_ns.class_(
|
||||||
"GROVETB6612FNGMotorNoStandbyAction", automation.Action
|
"GROVETB6612FNGMotorNoStandbyAction", automation.Action
|
||||||
)
|
)
|
||||||
|
GROVETB6612FNGMotorChangeAddressAction = grove_tb6612fng_ns.class_(
|
||||||
|
"GROVETB6612FNGMotorChangeAddressAction", automation.Action
|
||||||
|
)
|
||||||
|
|
||||||
DIRECTION_TYPE = {
|
DIRECTION_TYPE = {
|
||||||
"FORWARD": 1,
|
"FORWARD": 1,
|
||||||
@@ -150,3 +156,22 @@ async def grove_tb6612fng_no_standby_to_code(config, action_id, template_arg, ar
|
|||||||
await cg.register_parented(var, config[CONF_ID])
|
await cg.register_parented(var, config[CONF_ID])
|
||||||
|
|
||||||
return var
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
@automation.register_action(
|
||||||
|
"grove_tb6612fng.change_address",
|
||||||
|
GROVETB6612FNGMotorChangeAddressAction,
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_ID): cv.use_id(GROVE_TB6612FNG),
|
||||||
|
cv.Required(CONF_ADDRESS): cv.i2c_address,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
async def grove_tb6612fng_change_address_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
await cg.register_parented(var, config[CONF_ID])
|
||||||
|
|
||||||
|
template_channel = await cg.templatable(config[CONF_ADDRESS], args, int)
|
||||||
|
cg.add(var.set_address(template_channel))
|
||||||
|
return var
|
||||||
|
|||||||
@@ -84,8 +84,7 @@ class GroveMotorDriveTB6612FNG : public Component, public i2c::I2CDevice {
|
|||||||
*************************************************************/
|
*************************************************************/
|
||||||
void set_i2c_addr(uint8_t addr);
|
void set_i2c_addr(uint8_t addr);
|
||||||
|
|
||||||
/*************************************************************
|
/***********************************change_address
|
||||||
Description
|
|
||||||
Drive a motor.
|
Drive a motor.
|
||||||
Parameter
|
Parameter
|
||||||
chl: MOTOR_CHA or MOTOR_CHB
|
chl: MOTOR_CHA or MOTOR_CHB
|
||||||
@@ -204,5 +203,13 @@ class GROVETB6612FNGMotorNoStandbyAction : public Action<Ts...>, public Parented
|
|||||||
void play(Ts... x) override { this->parent_->not_standby(); }
|
void play(Ts... x) override { this->parent_->not_standby(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename... Ts>
|
||||||
|
class GROVETB6612FNGMotorChangeAddressAction : public Action<Ts...>, public Parented<GroveMotorDriveTB6612FNG> {
|
||||||
|
public:
|
||||||
|
TEMPLATABLE_VALUE(uint8_t, address)
|
||||||
|
|
||||||
|
void play(Ts... x) override { this->parent_->set_i2c_addr(this->address_.value(x...)); }
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace grove_tb6612fng
|
} // namespace grove_tb6612fng
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ void I2SAudioMicrophone::setup() {
|
|||||||
void I2SAudioMicrophone::start() {
|
void I2SAudioMicrophone::start() {
|
||||||
if (this->is_failed())
|
if (this->is_failed())
|
||||||
return;
|
return;
|
||||||
|
if (this->state_ == microphone::STATE_RUNNING)
|
||||||
|
return; // Already running
|
||||||
this->state_ = microphone::STATE_STARTING;
|
this->state_ = microphone::STATE_STARTING;
|
||||||
}
|
}
|
||||||
void I2SAudioMicrophone::start_() {
|
void I2SAudioMicrophone::start_() {
|
||||||
|
|||||||
@@ -158,8 +158,13 @@ void I2SAudioSpeaker::watch_() {
|
|||||||
if (xQueueReceive(this->event_queue_, &event, 0) == pdTRUE) {
|
if (xQueueReceive(this->event_queue_, &event, 0) == pdTRUE) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case TaskEventType::STARTING:
|
case TaskEventType::STARTING:
|
||||||
|
ESP_LOGD(TAG, "Starting I2S Audio Speaker");
|
||||||
|
break;
|
||||||
case TaskEventType::STARTED:
|
case TaskEventType::STARTED:
|
||||||
|
ESP_LOGD(TAG, "Started I2S Audio Speaker");
|
||||||
|
break;
|
||||||
case TaskEventType::STOPPING:
|
case TaskEventType::STOPPING:
|
||||||
|
ESP_LOGD(TAG, "Stopping I2S Audio Speaker");
|
||||||
break;
|
break;
|
||||||
case TaskEventType::PLAYING:
|
case TaskEventType::PLAYING:
|
||||||
this->status_clear_warning();
|
this->status_clear_warning();
|
||||||
@@ -170,6 +175,7 @@ void I2SAudioSpeaker::watch_() {
|
|||||||
this->player_task_handle_ = nullptr;
|
this->player_task_handle_ = nullptr;
|
||||||
this->parent_->unlock();
|
this->parent_->unlock();
|
||||||
xQueueReset(this->buffer_queue_);
|
xQueueReset(this->buffer_queue_);
|
||||||
|
ESP_LOGD(TAG, "Stopped I2S Audio Speaker");
|
||||||
break;
|
break;
|
||||||
case TaskEventType::WARNING:
|
case TaskEventType::WARNING:
|
||||||
ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(event.err));
|
ESP_LOGW(TAG, "Error writing to I2S: %s", esp_err_to_name(event.err));
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ async def component_to_code(config):
|
|||||||
# setup board config
|
# setup board config
|
||||||
cg.add_platformio_option("board", config[CONF_BOARD])
|
cg.add_platformio_option("board", config[CONF_BOARD])
|
||||||
cg.add_build_flag("-DUSE_LIBRETINY")
|
cg.add_build_flag("-DUSE_LIBRETINY")
|
||||||
cg.add_build_flag(f"-DUSE_{config[CONF_COMPONENT_ID]}")
|
cg.add_build_flag(f"-DUSE_{config[CONF_COMPONENT_ID].upper()}")
|
||||||
cg.add_build_flag(f"-DUSE_LIBRETINY_VARIANT_{config[CONF_FAMILY]}")
|
cg.add_build_flag(f"-DUSE_LIBRETINY_VARIANT_{config[CONF_FAMILY]}")
|
||||||
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
|
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
|
||||||
cg.add_define("ESPHOME_VARIANT", FAMILY_FRIENDLY[config[CONF_FAMILY]])
|
cg.add_define("ESPHOME_VARIANT", FAMILY_FRIENDLY[config[CONF_FAMILY]])
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ struct IPAddress {
|
|||||||
bool is_ip6() { return IP_IS_V6(&ip_addr_); }
|
bool is_ip6() { return IP_IS_V6(&ip_addr_); }
|
||||||
std::string str() const { return ipaddr_ntoa(&ip_addr_); }
|
std::string str() const { return ipaddr_ntoa(&ip_addr_); }
|
||||||
bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); }
|
bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); }
|
||||||
bool operator!=(const IPAddress &other) const { return !(&ip_addr_ == &other.ip_addr_); }
|
bool operator!=(const IPAddress &other) const { return !ip_addr_cmp(&ip_addr_, &other.ip_addr_); }
|
||||||
IPAddress &operator+=(uint8_t increase) {
|
IPAddress &operator+=(uint8_t increase) {
|
||||||
if (IP_IS_V4(&ip_addr_)) {
|
if (IP_IS_V4(&ip_addr_)) {
|
||||||
#if LWIP_IPV6
|
#if LWIP_IPV6
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#ifdef USE_ARDUINO
|
|
||||||
|
|
||||||
#include "prometheus_handler.h"
|
#include "prometheus_handler.h"
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
|
|
||||||
@@ -89,7 +87,7 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor
|
|||||||
stream->print(obj->get_unit_of_measurement().c_str());
|
stream->print(obj->get_unit_of_measurement().c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(value_accuracy_to_string(obj->state, obj->get_accuracy_decimals()).c_str());
|
stream->print(value_accuracy_to_string(obj->state, obj->get_accuracy_decimals()).c_str());
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
} else {
|
} else {
|
||||||
// Invalid state
|
// Invalid state
|
||||||
stream->print(F("esphome_sensor_failed{id=\""));
|
stream->print(F("esphome_sensor_failed{id=\""));
|
||||||
@@ -124,7 +122,7 @@ void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_s
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->state);
|
stream->print(obj->state);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
} else {
|
} else {
|
||||||
// Invalid state
|
// Invalid state
|
||||||
stream->print(F("esphome_binary_sensor_failed{id=\""));
|
stream->print(F("esphome_binary_sensor_failed{id=\""));
|
||||||
@@ -158,7 +156,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) {
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->state);
|
stream->print(obj->state);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
// Speed if available
|
// Speed if available
|
||||||
if (obj->get_traits().supports_speed()) {
|
if (obj->get_traits().supports_speed()) {
|
||||||
stream->print(F("esphome_fan_speed{id=\""));
|
stream->print(F("esphome_fan_speed{id=\""));
|
||||||
@@ -167,7 +165,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) {
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->speed);
|
stream->print(obj->speed);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
}
|
}
|
||||||
// Oscillation if available
|
// Oscillation if available
|
||||||
if (obj->get_traits().supports_oscillation()) {
|
if (obj->get_traits().supports_oscillation()) {
|
||||||
@@ -177,7 +175,7 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj) {
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->oscillating);
|
stream->print(obj->oscillating);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -281,7 +279,7 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->position);
|
stream->print(obj->position);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
if (obj->get_traits().get_supports_tilt()) {
|
if (obj->get_traits().get_supports_tilt()) {
|
||||||
stream->print(F("esphome_cover_tilt{id=\""));
|
stream->print(F("esphome_cover_tilt{id=\""));
|
||||||
stream->print(relabel_id_(obj).c_str());
|
stream->print(relabel_id_(obj).c_str());
|
||||||
@@ -289,7 +287,7 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->tilt);
|
stream->print(obj->tilt);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Invalid state
|
// Invalid state
|
||||||
@@ -322,7 +320,7 @@ void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->state);
|
stream->print(obj->state);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -346,11 +344,9 @@ void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj)
|
|||||||
stream->print(relabel_name_(obj).c_str());
|
stream->print(relabel_name_(obj).c_str());
|
||||||
stream->print(F("\"} "));
|
stream->print(F("\"} "));
|
||||||
stream->print(obj->state);
|
stream->print(obj->state);
|
||||||
stream->print('\n');
|
stream->print(F("\n"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace prometheus
|
} // namespace prometheus
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ARDUINO
|
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef USE_ARDUINO
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "esphome/core/entity_base.h"
|
|
||||||
#include "esphome/components/web_server_base/web_server_base.h"
|
#include "esphome/components/web_server_base/web_server_base.h"
|
||||||
#include "esphome/core/controller.h"
|
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/controller.h"
|
||||||
|
#include "esphome/core/entity_base.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace prometheus {
|
namespace prometheus {
|
||||||
@@ -119,5 +117,3 @@ class PrometheusHandler : public AsyncWebHandler, public Component {
|
|||||||
|
|
||||||
} // namespace prometheus
|
} // namespace prometheus
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ARDUINO
|
|
||||||
|
|||||||
@@ -88,11 +88,6 @@ uint64_t bytes_to_uint(const bytes &buffer) {
|
|||||||
for (auto const value : buffer) {
|
for (auto const value : buffer) {
|
||||||
val = (val << 8) + value;
|
val = (val << 8) + value;
|
||||||
}
|
}
|
||||||
// Some smart meters send 24 bit signed integers. Sign extend to 64 bit if the
|
|
||||||
// 24 bit value is negative.
|
|
||||||
if (buffer.size() == 3 && buffer[0] & 0x80) {
|
|
||||||
val |= 0xFFFFFFFFFF000000;
|
|
||||||
}
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,19 +95,15 @@ int64_t bytes_to_int(const bytes &buffer) {
|
|||||||
uint64_t tmp = bytes_to_uint(buffer);
|
uint64_t tmp = bytes_to_uint(buffer);
|
||||||
int64_t val;
|
int64_t val;
|
||||||
|
|
||||||
switch (buffer.size()) {
|
// sign extension for abbreviations of leading ones (e.g. 3 byte transmissions, see 6.2.2 of SML protocol definition)
|
||||||
case 1: // int8
|
// see https://stackoverflow.com/questions/42534749/signed-extension-from-24-bit-to-32-bit-in-c
|
||||||
val = (int8_t) tmp;
|
if (buffer.size() < 8) {
|
||||||
break;
|
const int bits = buffer.size() * 8;
|
||||||
case 2: // int16
|
const uint64_t m = 1u << (bits - 1);
|
||||||
val = (int16_t) tmp;
|
tmp = (tmp ^ m) - m;
|
||||||
break;
|
|
||||||
case 4: // int32
|
|
||||||
val = (int32_t) tmp;
|
|
||||||
break;
|
|
||||||
default: // int64
|
|
||||||
val = (int64_t) tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val = (int64_t) tmp;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -281,11 +281,15 @@ void VoiceAssistant::loop() {
|
|||||||
memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written);
|
memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written);
|
||||||
this->speaker_buffer_size_ -= written;
|
this->speaker_buffer_size_ -= written;
|
||||||
this->speaker_buffer_index_ -= written;
|
this->speaker_buffer_index_ -= written;
|
||||||
this->set_timeout("speaker-timeout", 1000, [this]() { this->speaker_->stop(); });
|
this->set_timeout("speaker-timeout", 2000, [this]() { this->speaker_->stop(); });
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGW(TAG, "Speaker buffer full.");
|
ESP_LOGW(TAG, "Speaker buffer full.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this->wait_for_stream_end_) {
|
||||||
|
this->cancel_timeout("playing");
|
||||||
|
break; // We dont want to timeout here as the STREAM_END event will take care of that.
|
||||||
|
}
|
||||||
playing = this->speaker_->is_running();
|
playing = this->speaker_->is_running();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -295,28 +299,77 @@ void VoiceAssistant::loop() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (playing) {
|
if (playing) {
|
||||||
this->set_timeout("playing", 100, [this]() {
|
this->set_timeout("playing", 2000, [this]() {
|
||||||
this->cancel_timeout("speaker-timeout");
|
this->cancel_timeout("speaker-timeout");
|
||||||
this->set_state_(State::IDLE, State::IDLE);
|
this->set_state_(State::IDLE, State::IDLE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case State::RESPONSE_FINISHED: {
|
||||||
|
#ifdef USE_SPEAKER
|
||||||
|
if (this->speaker_ != nullptr) {
|
||||||
|
this->speaker_->stop();
|
||||||
|
this->cancel_timeout("speaker-timeout");
|
||||||
|
this->cancel_timeout("playing");
|
||||||
|
this->speaker_buffer_size_ = 0;
|
||||||
|
this->speaker_buffer_index_ = 0;
|
||||||
|
memset(this->speaker_buffer_, 0, SPEAKER_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
this->wait_for_stream_end_ = false;
|
||||||
|
this->set_state_(State::IDLE, State::IDLE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const LogString *voice_assistant_state_to_string(State state) {
|
||||||
|
switch (state) {
|
||||||
|
case State::IDLE:
|
||||||
|
return LOG_STR("IDLE");
|
||||||
|
case State::START_MICROPHONE:
|
||||||
|
return LOG_STR("START_MICROPHONE");
|
||||||
|
case State::STARTING_MICROPHONE:
|
||||||
|
return LOG_STR("STARTING_MICROPHONE");
|
||||||
|
case State::WAIT_FOR_VAD:
|
||||||
|
return LOG_STR("WAIT_FOR_VAD");
|
||||||
|
case State::WAITING_FOR_VAD:
|
||||||
|
return LOG_STR("WAITING_FOR_VAD");
|
||||||
|
case State::START_PIPELINE:
|
||||||
|
return LOG_STR("START_PIPELINE");
|
||||||
|
case State::STARTING_PIPELINE:
|
||||||
|
return LOG_STR("STARTING_PIPELINE");
|
||||||
|
case State::STREAMING_MICROPHONE:
|
||||||
|
return LOG_STR("STREAMING_MICROPHONE");
|
||||||
|
case State::STOP_MICROPHONE:
|
||||||
|
return LOG_STR("STOP_MICROPHONE");
|
||||||
|
case State::STOPPING_MICROPHONE:
|
||||||
|
return LOG_STR("STOPPING_MICROPHONE");
|
||||||
|
case State::AWAITING_RESPONSE:
|
||||||
|
return LOG_STR("AWAITING_RESPONSE");
|
||||||
|
case State::STREAMING_RESPONSE:
|
||||||
|
return LOG_STR("STREAMING_RESPONSE");
|
||||||
|
case State::RESPONSE_FINISHED:
|
||||||
|
return LOG_STR("RESPONSE_FINISHED");
|
||||||
|
default:
|
||||||
|
return LOG_STR("UNKNOWN");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void VoiceAssistant::set_state_(State state) {
|
void VoiceAssistant::set_state_(State state) {
|
||||||
State old_state = this->state_;
|
State old_state = this->state_;
|
||||||
this->state_ = state;
|
this->state_ = state;
|
||||||
ESP_LOGD(TAG, "State changed from %d to %d", static_cast<uint8_t>(old_state), static_cast<uint8_t>(state));
|
ESP_LOGD(TAG, "State changed from %s to %s", LOG_STR_ARG(voice_assistant_state_to_string(old_state)),
|
||||||
|
LOG_STR_ARG(voice_assistant_state_to_string(state)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceAssistant::set_state_(State state, State desired_state) {
|
void VoiceAssistant::set_state_(State state, State desired_state) {
|
||||||
this->set_state_(state);
|
this->set_state_(state);
|
||||||
this->desired_state_ = desired_state;
|
this->desired_state_ = desired_state;
|
||||||
ESP_LOGD(TAG, "Desired state set to %d", static_cast<uint8_t>(desired_state));
|
ESP_LOGD(TAG, "Desired state set to %s", LOG_STR_ARG(voice_assistant_state_to_string(desired_state)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceAssistant::failed_to_start() {
|
void VoiceAssistant::failed_to_start() {
|
||||||
@@ -400,6 +453,7 @@ void VoiceAssistant::request_stop() {
|
|||||||
break;
|
break;
|
||||||
case State::AWAITING_RESPONSE:
|
case State::AWAITING_RESPONSE:
|
||||||
case State::STREAMING_RESPONSE:
|
case State::STREAMING_RESPONSE:
|
||||||
|
case State::RESPONSE_FINISHED:
|
||||||
break; // Let the incoming audio stream finish then it will go to idle.
|
break; // Let the incoming audio stream finish then it will go to idle.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -531,6 +585,14 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|||||||
this->error_trigger_->trigger(code, message);
|
this->error_trigger_->trigger(code, message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: {
|
||||||
|
this->wait_for_stream_end_ = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: {
|
||||||
|
this->set_state_(State::RESPONSE_FINISHED, State::IDLE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ESP_LOGD(TAG, "Unhandled event type: %d", msg.event_type);
|
ESP_LOGD(TAG, "Unhandled event type: %d", msg.event_type);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ enum class State {
|
|||||||
STOPPING_MICROPHONE,
|
STOPPING_MICROPHONE,
|
||||||
AWAITING_RESPONSE,
|
AWAITING_RESPONSE,
|
||||||
STREAMING_RESPONSE,
|
STREAMING_RESPONSE,
|
||||||
|
RESPONSE_FINISHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class VoiceAssistant : public Component {
|
class VoiceAssistant : public Component {
|
||||||
@@ -132,10 +133,10 @@ class VoiceAssistant : public Component {
|
|||||||
uint8_t *speaker_buffer_;
|
uint8_t *speaker_buffer_;
|
||||||
size_t speaker_buffer_index_{0};
|
size_t speaker_buffer_index_{0};
|
||||||
size_t speaker_buffer_size_{0};
|
size_t speaker_buffer_size_{0};
|
||||||
|
bool wait_for_stream_end_{false};
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_MEDIA_PLAYER
|
#ifdef USE_MEDIA_PLAYER
|
||||||
media_player::MediaPlayer *media_player_{nullptr};
|
media_player::MediaPlayer *media_player_{nullptr};
|
||||||
bool playing_tts_{false};
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool local_output_{false};
|
bool local_output_{false};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2023.10.0b2"
|
__version__ = "2023.10.0"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||||
|
|||||||
Reference in New Issue
Block a user