mirror of
https://github.com/esphome/esphome.git
synced 2024-11-29 18:24:13 +01:00
commit
833affc1bf
13 changed files with 50 additions and 30 deletions
|
@ -1449,6 +1449,7 @@ message VoiceAssistantRequest {
|
||||||
string conversation_id = 2;
|
string conversation_id = 2;
|
||||||
uint32 flags = 3;
|
uint32 flags = 3;
|
||||||
VoiceAssistantAudioSettings audio_settings = 4;
|
VoiceAssistantAudioSettings audio_settings = 4;
|
||||||
|
string wake_word_phrase = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message VoiceAssistantResponse {
|
message VoiceAssistantResponse {
|
||||||
|
|
|
@ -6594,6 +6594,10 @@ bool VoiceAssistantRequest::decode_length(uint32_t field_id, ProtoLengthDelimite
|
||||||
this->audio_settings = value.as_message<VoiceAssistantAudioSettings>();
|
this->audio_settings = value.as_message<VoiceAssistantAudioSettings>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 5: {
|
||||||
|
this->wake_word_phrase = value.as_string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6603,6 +6607,7 @@ void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const {
|
||||||
buffer.encode_string(2, this->conversation_id);
|
buffer.encode_string(2, this->conversation_id);
|
||||||
buffer.encode_uint32(3, this->flags);
|
buffer.encode_uint32(3, this->flags);
|
||||||
buffer.encode_message<VoiceAssistantAudioSettings>(4, this->audio_settings);
|
buffer.encode_message<VoiceAssistantAudioSettings>(4, this->audio_settings);
|
||||||
|
buffer.encode_string(5, this->wake_word_phrase);
|
||||||
}
|
}
|
||||||
#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 {
|
||||||
|
@ -6624,6 +6629,10 @@ void VoiceAssistantRequest::dump_to(std::string &out) const {
|
||||||
out.append(" audio_settings: ");
|
out.append(" audio_settings: ");
|
||||||
this->audio_settings.dump_to(out);
|
this->audio_settings.dump_to(out);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" wake_word_phrase: ");
|
||||||
|
out.append("'").append(this->wake_word_phrase).append("'");
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1701,6 +1701,7 @@ class VoiceAssistantRequest : public ProtoMessage {
|
||||||
std::string conversation_id{};
|
std::string conversation_id{};
|
||||||
uint32_t flags{0};
|
uint32_t flags{0};
|
||||||
VoiceAssistantAudioSettings audio_settings{};
|
VoiceAssistantAudioSettings audio_settings{};
|
||||||
|
std::string wake_word_phrase{};
|
||||||
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;
|
||||||
|
|
|
@ -118,7 +118,7 @@ void CSE7766Component::parse_data_() {
|
||||||
uint32_t power_coeff = this->get_24_bit_uint_(14);
|
uint32_t power_coeff = this->get_24_bit_uint_(14);
|
||||||
uint32_t power_cycle = this->get_24_bit_uint_(17);
|
uint32_t power_cycle = this->get_24_bit_uint_(17);
|
||||||
uint8_t adj = this->raw_data_[20];
|
uint8_t adj = this->raw_data_[20];
|
||||||
uint32_t cf_pulses = (this->raw_data_[21] << 8) + this->raw_data_[22];
|
uint16_t cf_pulses = (this->raw_data_[21] << 8) + this->raw_data_[22];
|
||||||
|
|
||||||
bool have_power = adj & 0x10;
|
bool have_power = adj & 0x10;
|
||||||
bool have_current = adj & 0x20;
|
bool have_current = adj & 0x20;
|
||||||
|
@ -132,8 +132,19 @@ void CSE7766Component::parse_data_() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float energy = 0.0;
|
||||||
|
if (this->energy_sensor_ != nullptr) {
|
||||||
|
if (this->cf_pulses_last_ == 0 && !this->energy_sensor_->has_state()) {
|
||||||
|
this->cf_pulses_last_ = cf_pulses;
|
||||||
|
}
|
||||||
|
uint16_t cf_diff = cf_pulses - this->cf_pulses_last_;
|
||||||
|
this->cf_pulses_total_ += cf_diff;
|
||||||
|
this->cf_pulses_last_ = cf_pulses;
|
||||||
|
energy = this->cf_pulses_total_ * float(power_coeff) / 1000000.0f / 3600.0f;
|
||||||
|
this->energy_sensor_->publish_state(energy);
|
||||||
|
}
|
||||||
|
|
||||||
float power = 0.0f;
|
float power = 0.0f;
|
||||||
float energy = 0.0f;
|
|
||||||
if (power_cycle_exceeds_range) {
|
if (power_cycle_exceeds_range) {
|
||||||
// Datasheet: power cycle exceeding range means active power is 0
|
// Datasheet: power cycle exceeding range means active power is 0
|
||||||
if (this->power_sensor_ != nullptr) {
|
if (this->power_sensor_ != nullptr) {
|
||||||
|
@ -144,27 +155,6 @@ void CSE7766Component::parse_data_() {
|
||||||
if (this->power_sensor_ != nullptr) {
|
if (this->power_sensor_ != nullptr) {
|
||||||
this->power_sensor_->publish_state(power);
|
this->power_sensor_->publish_state(power);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add CF pulses to the total energy only if we have Power coefficient to multiply by
|
|
||||||
|
|
||||||
if (this->cf_pulses_last_ == 0) {
|
|
||||||
this->cf_pulses_last_ = cf_pulses;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t cf_diff;
|
|
||||||
if (cf_pulses < this->cf_pulses_last_) {
|
|
||||||
cf_diff = cf_pulses + (0x10000 - this->cf_pulses_last_);
|
|
||||||
} else {
|
|
||||||
cf_diff = cf_pulses - this->cf_pulses_last_;
|
|
||||||
}
|
|
||||||
this->cf_pulses_last_ = cf_pulses;
|
|
||||||
|
|
||||||
energy = cf_diff * float(power_coeff) / 1000000.0f / 3600.0f;
|
|
||||||
this->energy_total_ += energy;
|
|
||||||
if (this->energy_sensor_ != nullptr)
|
|
||||||
this->energy_sensor_->publish_state(this->energy_total_);
|
|
||||||
} else if ((this->energy_sensor_ != nullptr) && !this->energy_sensor_->has_state()) {
|
|
||||||
this->energy_sensor_->publish_state(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float current = 0.0f;
|
float current = 0.0f;
|
||||||
|
|
|
@ -30,8 +30,8 @@ class CSE7766Component : public Component, public uart::UARTDevice {
|
||||||
sensor::Sensor *current_sensor_{nullptr};
|
sensor::Sensor *current_sensor_{nullptr};
|
||||||
sensor::Sensor *power_sensor_{nullptr};
|
sensor::Sensor *power_sensor_{nullptr};
|
||||||
sensor::Sensor *energy_sensor_{nullptr};
|
sensor::Sensor *energy_sensor_{nullptr};
|
||||||
float energy_total_{0.0f};
|
uint32_t cf_pulses_total_{0};
|
||||||
uint32_t cf_pulses_last_{0};
|
uint16_t cf_pulses_last_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cse7766
|
} // namespace cse7766
|
||||||
|
|
|
@ -134,7 +134,7 @@ void MicroWakeWord::loop() {
|
||||||
this->set_state_(State::IDLE);
|
this->set_state_(State::IDLE);
|
||||||
if (this->detected_) {
|
if (this->detected_) {
|
||||||
this->detected_ = false;
|
this->detected_ = false;
|
||||||
this->wake_word_detected_trigger_->trigger("");
|
this->wake_word_detected_trigger_->trigger(this->wake_word_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -14,6 +14,8 @@ from esphome.const import (
|
||||||
|
|
||||||
from .. import speed_ns
|
from .. import speed_ns
|
||||||
|
|
||||||
|
AUTO_LOAD = ["output"]
|
||||||
|
|
||||||
SpeedFan = speed_ns.class_("SpeedFan", cg.Component, fan.Fan)
|
SpeedFan = speed_ns.class_("SpeedFan", cg.Component, fan.Fan)
|
||||||
|
|
||||||
CONFIG_SCHEMA = fan.FAN_SCHEMA.extend(
|
CONFIG_SCHEMA = fan.FAN_SCHEMA.extend(
|
||||||
|
|
|
@ -28,7 +28,7 @@ void TMP102Component::dump_config() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMP102Component::update() {
|
void TMP102Component::update() {
|
||||||
uint16_t raw_temperature;
|
int16_t raw_temperature;
|
||||||
if (this->write(&TMP102_REGISTER_TEMPERATURE, 1) != i2c::ERROR_OK) {
|
if (this->write(&TMP102_REGISTER_TEMPERATURE, 1) != i2c::ERROR_OK) {
|
||||||
this->status_set_warning();
|
this->status_set_warning();
|
||||||
return;
|
return;
|
||||||
|
@ -39,7 +39,6 @@ void TMP102Component::update() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
raw_temperature = i2c::i2ctohs(raw_temperature);
|
raw_temperature = i2c::i2ctohs(raw_temperature);
|
||||||
|
|
||||||
raw_temperature = raw_temperature >> 4;
|
raw_temperature = raw_temperature >> 4;
|
||||||
float temperature = raw_temperature * TMP102_CONVERSION_FACTOR;
|
float temperature = raw_temperature * TMP102_CONVERSION_FACTOR;
|
||||||
ESP_LOGD(TAG, "Got Temperature=%.1f°C", temperature);
|
ESP_LOGD(TAG, "Got Temperature=%.1f°C", temperature);
|
||||||
|
|
|
@ -42,6 +42,8 @@ CONF_AUTO_GAIN = "auto_gain"
|
||||||
CONF_NOISE_SUPPRESSION_LEVEL = "noise_suppression_level"
|
CONF_NOISE_SUPPRESSION_LEVEL = "noise_suppression_level"
|
||||||
CONF_VOLUME_MULTIPLIER = "volume_multiplier"
|
CONF_VOLUME_MULTIPLIER = "volume_multiplier"
|
||||||
|
|
||||||
|
CONF_WAKE_WORD = "wake_word"
|
||||||
|
|
||||||
|
|
||||||
voice_assistant_ns = cg.esphome_ns.namespace("voice_assistant")
|
voice_assistant_ns = cg.esphome_ns.namespace("voice_assistant")
|
||||||
VoiceAssistant = voice_assistant_ns.class_("VoiceAssistant", cg.Component)
|
VoiceAssistant = voice_assistant_ns.class_("VoiceAssistant", cg.Component)
|
||||||
|
@ -285,6 +287,7 @@ VOICE_ASSISTANT_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(VoiceAssis
|
||||||
VOICE_ASSISTANT_ACTION_SCHEMA.extend(
|
VOICE_ASSISTANT_ACTION_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_SILENCE_DETECTION, default=True): cv.boolean,
|
cv.Optional(CONF_SILENCE_DETECTION, default=True): cv.boolean,
|
||||||
|
cv.Optional(CONF_WAKE_WORD): cv.templatable(cv.string),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -293,6 +296,9 @@ async def voice_assistant_listen_to_code(config, action_id, template_arg, args):
|
||||||
await cg.register_parented(var, config[CONF_ID])
|
await cg.register_parented(var, config[CONF_ID])
|
||||||
if CONF_SILENCE_DETECTION in config:
|
if CONF_SILENCE_DETECTION in config:
|
||||||
cg.add(var.set_silence_detection(config[CONF_SILENCE_DETECTION]))
|
cg.add(var.set_silence_detection(config[CONF_SILENCE_DETECTION]))
|
||||||
|
if wake_word := config.get(CONF_WAKE_WORD):
|
||||||
|
templ = await cg.templatable(wake_word, args, cg.std_string)
|
||||||
|
cg.add(var.set_wake_word(templ))
|
||||||
return var
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -215,6 +215,8 @@ void VoiceAssistant::loop() {
|
||||||
msg.conversation_id = this->conversation_id_;
|
msg.conversation_id = this->conversation_id_;
|
||||||
msg.flags = flags;
|
msg.flags = flags;
|
||||||
msg.audio_settings = audio_settings;
|
msg.audio_settings = audio_settings;
|
||||||
|
msg.wake_word_phrase = this->wake_word_;
|
||||||
|
this->wake_word_ = "";
|
||||||
|
|
||||||
if (this->api_client_ == nullptr || !this->api_client_->send_voice_assistant_request(msg)) {
|
if (this->api_client_ == nullptr || !this->api_client_->send_voice_assistant_request(msg)) {
|
||||||
ESP_LOGW(TAG, "Could not request start");
|
ESP_LOGW(TAG, "Could not request start");
|
||||||
|
|
|
@ -124,6 +124,8 @@ class VoiceAssistant : public Component {
|
||||||
void client_subscription(api::APIConnection *client, bool subscribe);
|
void client_subscription(api::APIConnection *client, bool subscribe);
|
||||||
api::APIConnection *get_api_connection() const { return this->api_client_; }
|
api::APIConnection *get_api_connection() const { return this->api_client_; }
|
||||||
|
|
||||||
|
void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int read_microphone_();
|
int read_microphone_();
|
||||||
void set_state_(State state);
|
void set_state_(State state);
|
||||||
|
@ -175,6 +177,8 @@ class VoiceAssistant : public Component {
|
||||||
|
|
||||||
std::string conversation_id_{""};
|
std::string conversation_id_{""};
|
||||||
|
|
||||||
|
std::string wake_word_{""};
|
||||||
|
|
||||||
HighFrequencyLoopRequester high_freq_;
|
HighFrequencyLoopRequester high_freq_;
|
||||||
|
|
||||||
#ifdef USE_ESP_ADF
|
#ifdef USE_ESP_ADF
|
||||||
|
@ -200,8 +204,13 @@ class VoiceAssistant : public Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Ts> class StartAction : public Action<Ts...>, public Parented<VoiceAssistant> {
|
template<typename... Ts> class StartAction : public Action<Ts...>, public Parented<VoiceAssistant> {
|
||||||
|
TEMPLATABLE_VALUE(std::string, wake_word);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void play(Ts... x) override { this->parent_->request_start(false, this->silence_detection_); }
|
void play(Ts... x) override {
|
||||||
|
this->parent_->set_wake_word(this->wake_word_.value(x...));
|
||||||
|
this->parent_->request_start(false, this->silence_detection_);
|
||||||
|
}
|
||||||
|
|
||||||
void set_silence_detection(bool silence_detection) { this->silence_detection_ = silence_detection; }
|
void set_silence_detection(bool silence_detection) { this->silence_detection_ = silence_detection; }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""Constants used by esphome."""
|
"""Constants used by esphome."""
|
||||||
|
|
||||||
__version__ = "2024.2.1"
|
__version__ = "2024.2.2"
|
||||||
|
|
||||||
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||||
VALID_SUBSTITUTIONS_CHARACTERS = (
|
VALID_SUBSTITUTIONS_CHARACTERS = (
|
||||||
|
|
|
@ -820,6 +820,7 @@ class EditRequestHandler(BaseHandler):
|
||||||
None, self._read_file, filename, configuration
|
None, self._read_file, filename, configuration
|
||||||
)
|
)
|
||||||
if content is not None:
|
if content is not None:
|
||||||
|
self.set_header("Content-Type", "application/yaml")
|
||||||
self.write(content)
|
self.write(content)
|
||||||
|
|
||||||
def _read_file(self, filename: str, configuration: str) -> bytes | None:
|
def _read_file(self, filename: str, configuration: str) -> bytes | None:
|
||||||
|
|
Loading…
Reference in a new issue