mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	| @@ -267,6 +267,9 @@ def angle(value): | |||||||
|     return int(cv.float_range(0.0, 360.0)(cv.angle(value)) * 10) |     return int(cv.float_range(0.0, 360.0)(cv.angle(value)) * 10) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | lv_angle = LValidator(angle, uint32) | ||||||
|  |  | ||||||
|  |  | ||||||
| @schema_extractor("one_of") | @schema_extractor("one_of") | ||||||
| def size_validator(value): | def size_validator(value): | ||||||
|     """A size in one axis - one of "size_content", a number (pixels) or a percentage""" |     """A size in one axis - one of "size_content", a number (pixels) or a percentage""" | ||||||
| @@ -403,6 +406,7 @@ class TextValidator(LValidator): | |||||||
| lv_text = TextValidator() | lv_text = TextValidator() | ||||||
| lv_float = LValidator(cv.float_, cg.float_) | lv_float = LValidator(cv.float_, cg.float_) | ||||||
| lv_int = LValidator(cv.int_, cg.int_) | lv_int = LValidator(cv.int_, cg.int_) | ||||||
|  | lv_positive_int = LValidator(cv.positive_int, cg.int_) | ||||||
| lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255)) | lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255)) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -91,7 +91,7 @@ STYLE_PROPS = { | |||||||
|     "arc_opa": lvalid.opacity, |     "arc_opa": lvalid.opacity, | ||||||
|     "arc_color": lvalid.lv_color, |     "arc_color": lvalid.lv_color, | ||||||
|     "arc_rounded": lvalid.lv_bool, |     "arc_rounded": lvalid.lv_bool, | ||||||
|     "arc_width": cv.positive_int, |     "arc_width": lvalid.lv_positive_int, | ||||||
|     "anim_time": lvalid.lv_milliseconds, |     "anim_time": lvalid.lv_milliseconds, | ||||||
|     "bg_color": lvalid.lv_color, |     "bg_color": lvalid.lv_color, | ||||||
|     "bg_grad": lv_gradient, |     "bg_grad": lv_gradient, | ||||||
| @@ -111,7 +111,7 @@ STYLE_PROPS = { | |||||||
|     "border_side": df.LvConstant( |     "border_side": df.LvConstant( | ||||||
|         "LV_BORDER_SIDE_", "NONE", "TOP", "BOTTOM", "LEFT", "RIGHT", "INTERNAL" |         "LV_BORDER_SIDE_", "NONE", "TOP", "BOTTOM", "LEFT", "RIGHT", "INTERNAL" | ||||||
|     ).several_of, |     ).several_of, | ||||||
|     "border_width": cv.positive_int, |     "border_width": lvalid.lv_positive_int, | ||||||
|     "clip_corner": lvalid.lv_bool, |     "clip_corner": lvalid.lv_bool, | ||||||
|     "color_filter_opa": lvalid.opacity, |     "color_filter_opa": lvalid.opacity, | ||||||
|     "height": lvalid.size, |     "height": lvalid.size, | ||||||
| @@ -134,11 +134,11 @@ STYLE_PROPS = { | |||||||
|     "pad_right": lvalid.pixels, |     "pad_right": lvalid.pixels, | ||||||
|     "pad_top": lvalid.pixels, |     "pad_top": lvalid.pixels, | ||||||
|     "shadow_color": lvalid.lv_color, |     "shadow_color": lvalid.lv_color, | ||||||
|     "shadow_ofs_x": cv.int_, |     "shadow_ofs_x": lvalid.lv_int, | ||||||
|     "shadow_ofs_y": cv.int_, |     "shadow_ofs_y": lvalid.lv_int, | ||||||
|     "shadow_opa": lvalid.opacity, |     "shadow_opa": lvalid.opacity, | ||||||
|     "shadow_spread": cv.int_, |     "shadow_spread": lvalid.lv_int, | ||||||
|     "shadow_width": cv.positive_int, |     "shadow_width": lvalid.lv_positive_int, | ||||||
|     "text_align": df.LvConstant( |     "text_align": df.LvConstant( | ||||||
|         "LV_TEXT_ALIGN_", "LEFT", "CENTER", "RIGHT", "AUTO" |         "LV_TEXT_ALIGN_", "LEFT", "CENTER", "RIGHT", "AUTO" | ||||||
|     ).one_of, |     ).one_of, | ||||||
| @@ -150,7 +150,7 @@ STYLE_PROPS = { | |||||||
|     "text_letter_space": cv.positive_int, |     "text_letter_space": cv.positive_int, | ||||||
|     "text_line_space": cv.positive_int, |     "text_line_space": cv.positive_int, | ||||||
|     "text_opa": lvalid.opacity, |     "text_opa": lvalid.opacity, | ||||||
|     "transform_angle": lvalid.angle, |     "transform_angle": lvalid.lv_angle, | ||||||
|     "transform_height": lvalid.pixels_or_percent, |     "transform_height": lvalid.pixels_or_percent, | ||||||
|     "transform_pivot_x": lvalid.pixels_or_percent, |     "transform_pivot_x": lvalid.pixels_or_percent, | ||||||
|     "transform_pivot_y": lvalid.pixels_or_percent, |     "transform_pivot_y": lvalid.pixels_or_percent, | ||||||
|   | |||||||
| @@ -433,16 +433,18 @@ void VoiceAssistant::loop() { | |||||||
|  |  | ||||||
| #ifdef USE_SPEAKER | #ifdef USE_SPEAKER | ||||||
| void VoiceAssistant::write_speaker_() { | void VoiceAssistant::write_speaker_() { | ||||||
|   if (this->speaker_buffer_size_ > 0) { |   if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) { | ||||||
|     size_t write_chunk = std::min<size_t>(this->speaker_buffer_size_, 4 * 1024); |     if (this->speaker_buffer_size_ > 0) { | ||||||
|     size_t written = this->speaker_->play(this->speaker_buffer_, write_chunk); |       size_t write_chunk = std::min<size_t>(this->speaker_buffer_size_, 4 * 1024); | ||||||
|     if (written > 0) { |       size_t written = this->speaker_->play(this->speaker_buffer_, write_chunk); | ||||||
|       memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); |       if (written > 0) { | ||||||
|       this->speaker_buffer_size_ -= written; |         memmove(this->speaker_buffer_, this->speaker_buffer_ + written, this->speaker_buffer_size_ - written); | ||||||
|       this->speaker_buffer_index_ -= written; |         this->speaker_buffer_size_ -= written; | ||||||
|       this->set_timeout("speaker-timeout", 5000, [this]() { this->speaker_->stop(); }); |         this->speaker_buffer_index_ -= written; | ||||||
|     } else { |         this->set_timeout("speaker-timeout", 5000, [this]() { this->speaker_->stop(); }); | ||||||
|       ESP_LOGV(TAG, "Speaker buffer full, trying again next loop"); |       } else { | ||||||
|  |         ESP_LOGV(TAG, "Speaker buffer full, trying again next loop"); | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -772,16 +774,20 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { | |||||||
|     } |     } | ||||||
|     case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { |     case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { | ||||||
| #ifdef USE_SPEAKER | #ifdef USE_SPEAKER | ||||||
|       this->wait_for_stream_end_ = true; |       if (this->speaker_ != nullptr) { | ||||||
|       ESP_LOGD(TAG, "TTS stream start"); |         this->wait_for_stream_end_ = true; | ||||||
|       this->defer([this] { this->tts_stream_start_trigger_->trigger(); }); |         ESP_LOGD(TAG, "TTS stream start"); | ||||||
|  |         this->defer([this] { this->tts_stream_start_trigger_->trigger(); }); | ||||||
|  |       } | ||||||
| #endif | #endif | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: { |     case api::enums::VOICE_ASSISTANT_TTS_STREAM_END: { | ||||||
| #ifdef USE_SPEAKER | #ifdef USE_SPEAKER | ||||||
|       this->stream_ended_ = true; |       if (this->speaker_ != nullptr) { | ||||||
|       ESP_LOGD(TAG, "TTS stream end"); |         this->stream_ended_ = true; | ||||||
|  |         ESP_LOGD(TAG, "TTS stream end"); | ||||||
|  |       } | ||||||
| #endif | #endif | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
| @@ -802,14 +808,16 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { | |||||||
|  |  | ||||||
| void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { | void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { | ||||||
| #ifdef USE_SPEAKER  // We should never get to this function if there is no speaker anyway | #ifdef USE_SPEAKER  // We should never get to this function if there is no speaker anyway | ||||||
|   if (this->speaker_buffer_index_ + msg.data.length() < SPEAKER_BUFFER_SIZE) { |   if ((this->speaker_ != nullptr) && (this->speaker_buffer_ != nullptr)) { | ||||||
|     memcpy(this->speaker_buffer_ + this->speaker_buffer_index_, msg.data.data(), msg.data.length()); |     if (this->speaker_buffer_index_ + msg.data.length() < SPEAKER_BUFFER_SIZE) { | ||||||
|     this->speaker_buffer_index_ += msg.data.length(); |       memcpy(this->speaker_buffer_ + this->speaker_buffer_index_, msg.data.data(), msg.data.length()); | ||||||
|     this->speaker_buffer_size_ += msg.data.length(); |       this->speaker_buffer_index_ += msg.data.length(); | ||||||
|     this->speaker_bytes_received_ += msg.data.length(); |       this->speaker_buffer_size_ += msg.data.length(); | ||||||
|     ESP_LOGV(TAG, "Received audio: %u bytes from API", msg.data.length()); |       this->speaker_bytes_received_ += msg.data.length(); | ||||||
|   } else { |       ESP_LOGV(TAG, "Received audio: %u bytes from API", msg.data.length()); | ||||||
|     ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); |     } else { | ||||||
|  |       ESP_LOGE(TAG, "Cannot receive audio, buffer is full"); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|   | |||||||
| @@ -250,7 +250,7 @@ class VoiceAssistant : public Component { | |||||||
| #ifdef USE_SPEAKER | #ifdef USE_SPEAKER | ||||||
|   void write_speaker_(); |   void write_speaker_(); | ||||||
|   speaker::Speaker *speaker_{nullptr}; |   speaker::Speaker *speaker_{nullptr}; | ||||||
|   uint8_t *speaker_buffer_; |   uint8_t *speaker_buffer_{nullptr}; | ||||||
|   size_t speaker_buffer_index_{0}; |   size_t speaker_buffer_index_{0}; | ||||||
|   size_t speaker_buffer_size_{0}; |   size_t speaker_buffer_size_{0}; | ||||||
|   size_t speaker_bytes_received_{0}; |   size_t speaker_bytes_received_{0}; | ||||||
| @@ -282,8 +282,8 @@ class VoiceAssistant : public Component { | |||||||
|   float volume_multiplier_; |   float volume_multiplier_; | ||||||
|   uint32_t conversation_timeout_; |   uint32_t conversation_timeout_; | ||||||
|  |  | ||||||
|   uint8_t *send_buffer_; |   uint8_t *send_buffer_{nullptr}; | ||||||
|   int16_t *input_buffer_; |   int16_t *input_buffer_{nullptr}; | ||||||
|  |  | ||||||
|   bool continuous_{false}; |   bool continuous_{false}; | ||||||
|   bool silence_detection_; |   bool silence_detection_; | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| """Constants used by esphome.""" | """Constants used by esphome.""" | ||||||
|  |  | ||||||
| __version__ = "2024.10.1" | __version__ = "2024.10.2" | ||||||
|  |  | ||||||
| ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ||||||
| VALID_SUBSTITUTIONS_CHARACTERS = ( | VALID_SUBSTITUTIONS_CHARACTERS = ( | ||||||
|   | |||||||
| @@ -209,6 +209,12 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None): | |||||||
|     elif CONF_MQTT in config: |     elif CONF_MQTT in config: | ||||||
|         conf = config[CONF_MQTT] |         conf = config[CONF_MQTT] | ||||||
|         if CONF_LOG_TOPIC in conf: |         if CONF_LOG_TOPIC in conf: | ||||||
|  |             if config[CONF_MQTT][CONF_LOG_TOPIC] is None: | ||||||
|  |                 _LOGGER.error("MQTT log topic set to null, can't start MQTT logs") | ||||||
|  |                 return 1 | ||||||
|  |             if CONF_TOPIC not in config[CONF_MQTT][CONF_LOG_TOPIC]: | ||||||
|  |                 _LOGGER.error("MQTT log topic not available, can't start MQTT logs") | ||||||
|  |                 return 1 | ||||||
|             topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC] |             topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC] | ||||||
|         elif CONF_TOPIC_PREFIX in config[CONF_MQTT]: |         elif CONF_TOPIC_PREFIX in config[CONF_MQTT]: | ||||||
|             topic = f"{config[CONF_MQTT][CONF_TOPIC_PREFIX]}/debug" |             topic = f"{config[CONF_MQTT][CONF_TOPIC_PREFIX]}/debug" | ||||||
|   | |||||||
| @@ -299,6 +299,13 @@ lvgl: | |||||||
|             id: button_button |             id: button_button | ||||||
|             width: 20% |             width: 20% | ||||||
|             height: 10% |             height: 10% | ||||||
|  |             transform_angle: !lambda return 180*100; | ||||||
|  |             arc_width: !lambda return 4; | ||||||
|  |             border_width: !lambda return 6; | ||||||
|  |             shadow_ofs_x: !lambda return 6; | ||||||
|  |             shadow_ofs_y: !lambda return 6; | ||||||
|  |             shadow_spread: !lambda return 6; | ||||||
|  |             shadow_width: !lambda return 6; | ||||||
|             pressed: |             pressed: | ||||||
|               bg_color: light_blue |               bg_color: light_blue | ||||||
|             checkable: true |             checkable: true | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user