mirror of https://github.com/esphome/esphome.git
Merge branch 'dev' into dev
This commit is contained in:
commit
54ce1e5080
|
@ -54,7 +54,12 @@ from esphome.components.esp32 import add_idf_sdkconfig_option
|
|||
|
||||
DEPENDENCIES = ["network"]
|
||||
|
||||
AUTO_LOAD = ["json"]
|
||||
|
||||
def AUTO_LOAD():
|
||||
if CORE.is_esp8266 or CORE.is_libretiny:
|
||||
return ["async_tcp", "json"]
|
||||
return ["json"]
|
||||
|
||||
|
||||
CONF_IDF_SEND_ASYNC = "idf_send_async"
|
||||
CONF_SKIP_CERT_CN_CHECK = "skip_cert_cn_check"
|
||||
|
|
|
@ -976,6 +976,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
* @return Whether the send was successful.
|
||||
*/
|
||||
bool send_command(const char *command);
|
||||
|
||||
/**
|
||||
* Manually send a raw formatted command to the display.
|
||||
* @param format The printf-style command format, like "vis %s,0"
|
||||
|
@ -989,7 +990,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
* Set the tft file URL. https seems problematic with arduino..
|
||||
*/
|
||||
void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Uploads the TFT file to the Nextion display.
|
||||
|
@ -1013,6 +1013,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
*/
|
||||
bool upload_tft(uint32_t baud_rate = 0, bool exit_reparse = true);
|
||||
|
||||
#endif
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
/**
|
||||
|
@ -1134,6 +1136,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
void all_components_send_state_(bool force_update = false);
|
||||
uint64_t comok_sent_ = 0;
|
||||
bool remove_from_q_(bool report_empty = true);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Sends commands ignoring of the Nextion has been setup.
|
||||
|
@ -1175,20 +1178,16 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
void check_pending_waveform_();
|
||||
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
uint32_t content_length_ = 0;
|
||||
int tft_size_ = 0;
|
||||
uint32_t original_baud_rate_ = 0;
|
||||
bool upload_first_chunk_sent_ = false;
|
||||
|
||||
std::string tft_url_;
|
||||
uint8_t *transfer_buffer_{nullptr};
|
||||
size_t transfer_buffer_size_;
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
WiFiClient *wifi_client_{nullptr};
|
||||
BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr};
|
||||
WiFiClient *get_wifi_client_();
|
||||
#endif
|
||||
std::string tft_url_;
|
||||
uint32_t content_length_ = 0;
|
||||
int tft_size_ = 0;
|
||||
uint32_t original_baud_rate_ = 0;
|
||||
bool upload_first_chunk_sent_ = false;
|
||||
|
||||
#ifdef ARDUINO
|
||||
/**
|
||||
|
@ -1198,18 +1197,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
* @param int range_start Position of next byte to transfer.
|
||||
* @return position of last byte transferred, -1 for failure.
|
||||
*/
|
||||
int upload_by_chunks_(HTTPClient *http, int range_start);
|
||||
int upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start);
|
||||
|
||||
bool upload_with_range_(uint32_t range_start, uint32_t range_end);
|
||||
|
||||
/**
|
||||
* start update tft file to nextion.
|
||||
*
|
||||
* @param const uint8_t *file_buf
|
||||
* @param size_t buf_size
|
||||
* @return true if success, false for failure.
|
||||
*/
|
||||
bool upload_from_buffer_(const uint8_t *file_buf, size_t buf_size);
|
||||
/**
|
||||
* Ends the upload process, restart Nextion and, if successful,
|
||||
* restarts ESP
|
||||
|
@ -1217,6 +1206,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
* @return bool True: Transfer completed successfuly, False: Transfer failed.
|
||||
*/
|
||||
bool upload_end_(bool successful);
|
||||
|
||||
#elif defined(USE_ESP_IDF)
|
||||
/**
|
||||
* will request 4096 bytes chunks from the web server
|
||||
|
@ -1226,6 +1216,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
* @return position of last byte transferred, -1 for failure.
|
||||
*/
|
||||
int upload_range(const std::string &url, int range_start);
|
||||
|
||||
/**
|
||||
* Ends the upload process, restart Nextion and, if successful,
|
||||
* restarts ESP
|
||||
|
@ -1233,7 +1224,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
|||
* @return bool True: Transfer completed successfuly, False: Transfer failed.
|
||||
*/
|
||||
bool upload_end(bool successful);
|
||||
#endif // ARDUINO vs ESP-IDF
|
||||
#endif // ARDUINO vs USE_ESP_IDF
|
||||
/**
|
||||
* Returns the ESP Free Heap memory. This is framework independent.
|
||||
* @return Free Heap in bytes.
|
||||
*/
|
||||
uint32_t get_free_heap_();
|
||||
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include "nextion.h"
|
||||
|
||||
#ifdef ARDUINO
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
#ifdef ARDUINO
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/network/util.h"
|
||||
#include <cinttypes>
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#include <esp_heap_caps.h>
|
||||
|
@ -20,124 +21,132 @@ static const char *const TAG = "nextion.upload.arduino";
|
|||
// Followed guide
|
||||
// https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2
|
||||
|
||||
int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
|
||||
int range_end = 0;
|
||||
inline uint32_t Nextion::get_free_heap_() {
|
||||
#if defined(USE_ESP32)
|
||||
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
#elif defined(USE_ESP8266)
|
||||
return EspClass::getFreeHeap();
|
||||
#endif // USE_ESP32 vs USE_ESP8266
|
||||
}
|
||||
|
||||
if (range_start == 0 && this->transfer_buffer_size_ > 16384) { // Start small at the first run in case of a big skip
|
||||
range_end = 16384 - 1;
|
||||
} else {
|
||||
range_end = range_start + this->transfer_buffer_size_ - 1;
|
||||
int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) {
|
||||
uint32_t range_size = this->tft_size_ - range_start;
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1;
|
||||
ESP_LOGD(TAG, "Range start: %" PRIu32, range_start);
|
||||
if (range_size <= 0 or range_end <= range_start) {
|
||||
ESP_LOGD(TAG, "Range end: %" PRIu32, range_end);
|
||||
ESP_LOGD(TAG, "Range size: %" PRIu32, range_size);
|
||||
ESP_LOGE(TAG, "Invalid range");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (range_end > this->tft_size_)
|
||||
range_end = this->tft_size_;
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0)
|
||||
http->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
#elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http->setFollowRedirects(true);
|
||||
#endif
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http->setRedirectLimit(3);
|
||||
#endif
|
||||
#endif // USE_ESP8266
|
||||
|
||||
char range_header[64];
|
||||
sprintf(range_header, "bytes=%d-%d", range_start, range_end);
|
||||
|
||||
ESP_LOGD(TAG, "Requesting range: %s", range_header);
|
||||
|
||||
int tries = 1;
|
||||
int code = 0;
|
||||
bool begin_status = false;
|
||||
while (tries <= 5) {
|
||||
#ifdef USE_ESP32
|
||||
begin_status = http->begin(this->tft_url_.c_str());
|
||||
#endif
|
||||
#ifdef USE_ESP8266
|
||||
begin_status = http->begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||
#endif
|
||||
|
||||
++tries;
|
||||
if (!begin_status) {
|
||||
ESP_LOGD(TAG, "upload_by_chunks_: connection failed");
|
||||
delay(500); // NOLINT
|
||||
continue;
|
||||
}
|
||||
|
||||
http->addHeader("Range", range_header);
|
||||
|
||||
code = http->GET();
|
||||
if (code == 200 || code == 206) {
|
||||
break;
|
||||
}
|
||||
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s, retries(%d/5)", this->tft_url_.c_str(),
|
||||
HTTPClient::errorToString(code).c_str(), tries);
|
||||
http->end();
|
||||
App.feed_wdt();
|
||||
delay(500); // NOLINT
|
||||
char range_header[32];
|
||||
sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end);
|
||||
ESP_LOGV(TAG, "Requesting range: %s", range_header);
|
||||
http_client.addHeader("Range", range_header);
|
||||
int code = http_client.GET();
|
||||
if (code != HTTP_CODE_OK and code != HTTP_CODE_PARTIAL_CONTENT) {
|
||||
ESP_LOGW(TAG, "HTTP Request failed; Error: %s", HTTPClient::errorToString(code).c_str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tries > 5) {
|
||||
// Allocate the buffer dynamically
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
uint8_t *buffer = allocator.allocate(4096);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "Failed to allocate upload buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string recv_string;
|
||||
size_t size = 0;
|
||||
int fetched = 0;
|
||||
int range = range_end - range_start;
|
||||
|
||||
while (fetched < range) {
|
||||
size = http->getStreamPtr()->available();
|
||||
if (!size) {
|
||||
App.feed_wdt();
|
||||
delay(0);
|
||||
continue;
|
||||
}
|
||||
int c = http->getStreamPtr()->readBytes(
|
||||
&this->transfer_buffer_[fetched], ((size > this->transfer_buffer_size_) ? this->transfer_buffer_size_ : size));
|
||||
fetched += c;
|
||||
}
|
||||
http->end();
|
||||
ESP_LOGN(TAG, "Fetched %d of %d bytes", fetched, this->content_length_);
|
||||
|
||||
// upload fetched segments to the display in 4KB chunks
|
||||
int write_len;
|
||||
for (int i = 0; i < range; i += 4096) {
|
||||
while (true) {
|
||||
App.feed_wdt();
|
||||
write_len = this->content_length_ < 4096 ? this->content_length_ : 4096;
|
||||
this->write_array(&this->transfer_buffer_[i], write_len);
|
||||
this->content_length_ -= write_len;
|
||||
ESP_LOGD(TAG, "Uploaded %0.2f %%; %d bytes remaining",
|
||||
100.0 * (this->tft_size_ - this->content_length_) / this->tft_size_, this->content_length_);
|
||||
|
||||
if (!this->upload_first_chunk_sent_) {
|
||||
this->upload_first_chunk_sent_ = true;
|
||||
delay(500); // NOLINT
|
||||
}
|
||||
|
||||
this->recv_ret_string_(recv_string, 4096, true);
|
||||
if (recv_string[0] != 0x05) { // 0x05 == "ok"
|
||||
ESP_LOGD(TAG, "recv_string [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
}
|
||||
|
||||
// handle partial upload request
|
||||
if (recv_string[0] == 0x08 && recv_string.size() == 5) {
|
||||
uint32_t result = 0;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
|
||||
}
|
||||
if (result > 0) {
|
||||
ESP_LOGD(TAG, "Nextion reported new range %d", result);
|
||||
this->content_length_ = this->tft_size_ - result;
|
||||
return result;
|
||||
const uint16_t buffer_size =
|
||||
this->content_length_ < 4096 ? this->content_length_ : 4096; // Limits buffer to the remaining data
|
||||
ESP_LOGV(TAG, "Fetching %" PRIu16 " bytes from HTTP", buffer_size);
|
||||
uint16_t read_len = 0;
|
||||
int partial_read_len = 0;
|
||||
const uint32_t start_time = millis();
|
||||
while (read_len < buffer_size && millis() - start_time < 5000) {
|
||||
if (http_client.getStreamPtr()->available() > 0) {
|
||||
partial_read_len =
|
||||
http_client.getStreamPtr()->readBytes(reinterpret_cast<char *>(buffer) + read_len, buffer_size - read_len);
|
||||
read_len += partial_read_len;
|
||||
if (partial_read_len > 0) {
|
||||
App.feed_wdt();
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
recv_string.clear();
|
||||
if (read_len != buffer_size) {
|
||||
// Did not receive the full package within the timeout period
|
||||
ESP_LOGE(TAG, "Failed to read full package, received only %" PRIu16 " of %" PRIu16 " bytes", read_len,
|
||||
buffer_size);
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return -1;
|
||||
}
|
||||
ESP_LOGV(TAG, "%d bytes fetched, writing it to UART", read_len);
|
||||
if (read_len > 0) {
|
||||
recv_string.clear();
|
||||
this->write_array(buffer, buffer_size);
|
||||
App.feed_wdt();
|
||||
this->recv_ret_string_(recv_string, upload_first_chunk_sent_ ? 500 : 5000, true);
|
||||
this->content_length_ -= read_len;
|
||||
const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_;
|
||||
#if defined(USE_ESP32) && defined(USE_PSRAM)
|
||||
ESP_LOGD(
|
||||
TAG,
|
||||
"Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " (DRAM) + %" PRIu32 " (PSRAM) bytes",
|
||||
upload_percentage, this->content_length_, static_cast<uint32_t>(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)),
|
||||
static_cast<uint32_t>(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)));
|
||||
#else
|
||||
ESP_LOGD(TAG, "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " bytes", upload_percentage,
|
||||
this->content_length_, this->get_free_heap_());
|
||||
#endif
|
||||
upload_first_chunk_sent_ = true;
|
||||
if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request
|
||||
ESP_LOGD(TAG, "recv_string [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
uint32_t result = 0;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
|
||||
}
|
||||
if (result > 0) {
|
||||
ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result);
|
||||
this->content_length_ = this->tft_size_ - result;
|
||||
range_start = result;
|
||||
} else {
|
||||
range_start = range_end + 1;
|
||||
}
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return range_end + 1;
|
||||
} else if (recv_string[0] != 0x05 and recv_string[0] != 0x08) { // 0x05 == "ok"
|
||||
ESP_LOGE(TAG, "Invalid response from Nextion: [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
recv_string.clear();
|
||||
} else if (read_len == 0) {
|
||||
ESP_LOGV(TAG, "End of HTTP response reached");
|
||||
break; // Exit the loop if there is no more data to read
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %d", read_len);
|
||||
break; // Exit the loop on error
|
||||
}
|
||||
}
|
||||
|
||||
range_start = range_end + 1;
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return range_end + 1;
|
||||
}
|
||||
|
||||
|
@ -147,12 +156,12 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
|||
ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str());
|
||||
|
||||
if (this->is_updating_) {
|
||||
ESP_LOGD(TAG, "Currently updating");
|
||||
ESP_LOGW(TAG, "Currently uploading");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!network::is_connected()) {
|
||||
ESP_LOGD(TAG, "network is not connected");
|
||||
ESP_LOGE(TAG, "Network is not connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -175,43 +184,42 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
|||
}
|
||||
ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate);
|
||||
|
||||
HTTPClient http;
|
||||
http.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
|
||||
// Define the configuration for the HTTP client
|
||||
ESP_LOGV(TAG, "Initializing HTTP client");
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
HTTPClient http_client;
|
||||
http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
|
||||
|
||||
bool begin_status = false;
|
||||
#ifdef USE_ESP32
|
||||
begin_status = http.begin(this->tft_url_.c_str());
|
||||
begin_status = http_client.begin(this->tft_url_.c_str());
|
||||
#endif
|
||||
#ifdef USE_ESP8266
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0)
|
||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
http_client.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
#elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http.setFollowRedirects(true);
|
||||
http_client.setFollowRedirects(true);
|
||||
#endif
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http.setRedirectLimit(3);
|
||||
http_client.setRedirectLimit(3);
|
||||
#endif
|
||||
begin_status = http.begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||
#endif
|
||||
|
||||
begin_status = http_client.begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||
#endif // USE_ESP8266
|
||||
if (!begin_status) {
|
||||
this->is_updating_ = false;
|
||||
ESP_LOGD(TAG, "Connection failed");
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
allocator.deallocate(this->transfer_buffer_, this->transfer_buffer_size_);
|
||||
return false;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Connected");
|
||||
}
|
||||
|
||||
http.addHeader("Range", "bytes=0-255");
|
||||
http_client.addHeader("Range", "bytes=0-255");
|
||||
const char *header_names[] = {"Content-Range"};
|
||||
http.collectHeaders(header_names, 1);
|
||||
http_client.collectHeaders(header_names, 1);
|
||||
ESP_LOGD(TAG, "Requesting URL: %s", this->tft_url_.c_str());
|
||||
|
||||
http.setReuse(true);
|
||||
http_client.setReuse(true);
|
||||
// try up to 5 times. DNS sometimes needs a second try or so
|
||||
int tries = 1;
|
||||
int code = http.GET();
|
||||
int code = http_client.GET();
|
||||
delay(100); // NOLINT
|
||||
|
||||
App.feed_wdt();
|
||||
|
@ -221,34 +229,41 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
|||
|
||||
delay(250); // NOLINT
|
||||
App.feed_wdt();
|
||||
code = http.GET();
|
||||
code = http_client.GET();
|
||||
++tries;
|
||||
}
|
||||
|
||||
if ((code != 200 && code != 206) || tries > 5) {
|
||||
if (code != 200 and code != 206) {
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
|
||||
String content_range_string = http.header("Content-Range");
|
||||
String content_range_string = http_client.header("Content-Range");
|
||||
content_range_string.remove(0, 12);
|
||||
this->content_length_ = content_range_string.toInt();
|
||||
this->tft_size_ = content_length_;
|
||||
http.end();
|
||||
this->tft_size_ = content_range_string.toInt();
|
||||
|
||||
if (this->content_length_ < 4096) {
|
||||
ESP_LOGE(TAG, "Failed to get file size");
|
||||
ESP_LOGD(TAG, "TFT file size: %zu bytes", this->tft_size_);
|
||||
if (this->tft_size_ < 4096) {
|
||||
ESP_LOGE(TAG, "File size check failed.");
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "File size check passed. Proceeding...");
|
||||
}
|
||||
this->content_length_ = this->tft_size_;
|
||||
|
||||
ESP_LOGD(TAG, "Updating Nextion %s...", this->device_model_.c_str());
|
||||
// The Nextion will ignore the update command if it is sleeping
|
||||
ESP_LOGD(TAG, "Uploading Nextion");
|
||||
|
||||
// The Nextion will ignore the upload command if it is sleeping
|
||||
ESP_LOGV(TAG, "Wake-up Nextion");
|
||||
this->ignore_is_setup_ = true;
|
||||
this->send_command_("sleep=0");
|
||||
this->set_backlight_brightness(1.0);
|
||||
this->send_command_("dim=100");
|
||||
delay(250); // NOLINT
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
|
||||
App.feed_wdt();
|
||||
|
||||
char command[128];
|
||||
// Tells the Nextion the content length of the tft file and baud rate it will be sent at
|
||||
// Once the Nextion accepts the command it will wait until the file is successfully uploaded
|
||||
|
@ -256,11 +271,12 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
|||
sprintf(command, "whmi-wris %d,%d,1", this->content_length_, baud_rate);
|
||||
|
||||
// Clear serial receive buffer
|
||||
uint8_t d;
|
||||
while (this->available()) {
|
||||
this->read_byte(&d);
|
||||
};
|
||||
ESP_LOGV(TAG, "Clear serial receive buffer");
|
||||
this->reset_(false);
|
||||
delay(250); // NOLINT
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
|
||||
ESP_LOGV(TAG, "Send upload instruction: %s", command);
|
||||
this->send_command_(command);
|
||||
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
|
@ -272,84 +288,60 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
|||
App.feed_wdt();
|
||||
|
||||
std::string response;
|
||||
ESP_LOGD(TAG, "Waiting for upgrade response");
|
||||
this->recv_ret_string_(response, 2000, true); // This can take some time to return
|
||||
ESP_LOGV(TAG, "Waiting for upgrade response");
|
||||
this->recv_ret_string_(response, 5000, true); // This can take some time to return
|
||||
|
||||
// The Nextion display will, if it's ready to accept data, send a 0x05 byte.
|
||||
ESP_LOGD(TAG, "Upgrade response is [%s] - %zu bytes",
|
||||
ESP_LOGD(TAG, "Upgrade response is [%s] - %zu byte(s)",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(response.data()), response.size()).c_str(),
|
||||
response.length());
|
||||
|
||||
for (size_t i = 0; i < response.length(); i++) {
|
||||
ESP_LOGD(TAG, "Available %d : 0x%02X", i, response[i]);
|
||||
}
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
|
||||
if (response.find(0x05) != std::string::npos) {
|
||||
ESP_LOGD(TAG, "preparation for tft update done");
|
||||
ESP_LOGV(TAG, "Preparation for TFT upload done");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "preparation for tft update failed %d \"%s\"", response[0], response.c_str());
|
||||
ESP_LOGE(TAG, "Preparation for TFT upload failed %d \"%s\"", response[0], response.c_str());
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
|
||||
// Nextion wants 4096 bytes at a time. Make chunk_size a multiple of 4096
|
||||
#ifdef USE_ESP32
|
||||
uint32_t chunk_size = 8192;
|
||||
if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0) {
|
||||
chunk_size = this->content_length_;
|
||||
} else {
|
||||
if (ESP.getFreeHeap() > 81920) { // Ensure some FreeHeap to other things and limit chunk size
|
||||
chunk_size = ESP.getFreeHeap() - 65536;
|
||||
chunk_size = int(chunk_size / 4096) * 4096;
|
||||
chunk_size = chunk_size > 65536 ? 65536 : chunk_size;
|
||||
} else if (ESP.getFreeHeap() < 32768) {
|
||||
chunk_size = 4096;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
uint32_t chunk_size = ESP.getFreeHeap() < 16384 ? 4096 : 8192;
|
||||
#endif
|
||||
ESP_LOGD(TAG, "Uploading TFT to Nextion:");
|
||||
ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str());
|
||||
ESP_LOGD(TAG, " File size: %d bytes", this->content_length_);
|
||||
ESP_LOGD(TAG, " Free heap: %" PRIu32, this->get_free_heap_());
|
||||
|
||||
if (this->transfer_buffer_ == nullptr) {
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
ESP_LOGD(TAG, "Allocating buffer size %d, Heap size is %u", chunk_size, ESP.getFreeHeap());
|
||||
this->transfer_buffer_ = allocator.allocate(chunk_size);
|
||||
if (this->transfer_buffer_ == nullptr) { // Try a smaller size
|
||||
ESP_LOGD(TAG, "Could not allocate buffer size: %d trying 4096 instead", chunk_size);
|
||||
chunk_size = 4096;
|
||||
ESP_LOGD(TAG, "Allocating %d buffer", chunk_size);
|
||||
this->transfer_buffer_ = allocator.allocate(chunk_size);
|
||||
// Proceed with the content download as before
|
||||
|
||||
if (!this->transfer_buffer_)
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
ESP_LOGV(TAG, "Starting transfer by chunks loop");
|
||||
|
||||
this->transfer_buffer_size_ = chunk_size;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d using %zu chunksize, Heap Size %d",
|
||||
this->tft_url_.c_str(), this->content_length_, this->transfer_buffer_size_, ESP.getFreeHeap());
|
||||
|
||||
int result = 0;
|
||||
uint32_t position = 0;
|
||||
while (this->content_length_ > 0) {
|
||||
result = this->upload_by_chunks_(&http, result);
|
||||
if (result < 0) {
|
||||
ESP_LOGD(TAG, "Error updating Nextion!");
|
||||
int upload_result = upload_by_chunks_(http_client, position);
|
||||
if (upload_result < 0) {
|
||||
ESP_LOGE(TAG, "Error uploading TFT to Nextion!");
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
App.feed_wdt();
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
ESP_LOGD(TAG, "Heap Size %d, Bytes left %d", ESP.getFreeHeap(), this->content_length_);
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32 ", Bytes left: %" PRIu32, this->get_free_heap_(), this->content_length_);
|
||||
}
|
||||
ESP_LOGD(TAG, "Successfully updated Nextion!");
|
||||
|
||||
return this->upload_end_(true);
|
||||
ESP_LOGD(TAG, "Successfully uploaded TFT to Nextion!");
|
||||
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return upload_end_(true);
|
||||
}
|
||||
|
||||
bool Nextion::upload_end_(bool successful) {
|
||||
ESP_LOGD(TAG, "Nextion TFT upload finished: %s", YESNO(successful));
|
||||
this->is_updating_ = false;
|
||||
this->ignore_is_setup_ = false;
|
||||
|
||||
uint32_t baud_rate = this->parent_->get_baud_rate();
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
|
@ -358,12 +350,12 @@ bool Nextion::upload_end_(bool successful) {
|
|||
this->parent_->load_settings();
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Restarting Nextion");
|
||||
this->soft_reset();
|
||||
if (successful) {
|
||||
ESP_LOGD(TAG, "Restarting ESPHome");
|
||||
delay(1500); // NOLINT
|
||||
ESP_LOGD(TAG, "Restarting esphome");
|
||||
ESP.restart(); // NOLINT(readability-static-accessed-through-instance)
|
||||
arch_restart();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Nextion TFT upload failed");
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
@ -386,9 +378,10 @@ WiFiClient *Nextion::get_wifi_client_() {
|
|||
}
|
||||
return this->wifi_client_;
|
||||
}
|
||||
#endif
|
||||
#endif // USE_ESP8266
|
||||
|
||||
} // namespace nextion
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
#endif // ARDUINO
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
|
|
|
@ -0,0 +1,428 @@
|
|||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
time:
|
||||
- platform: sntp
|
||||
|
||||
mqtt:
|
||||
broker: "192.168.178.84"
|
||||
port: 1883
|
||||
username: debug
|
||||
password: debug
|
||||
client_id: someclient
|
||||
use_abbreviations: false
|
||||
discovery: true
|
||||
discovery_retain: false
|
||||
discovery_prefix: discovery
|
||||
discovery_unique_id_generator: legacy
|
||||
topic_prefix: helloworld
|
||||
log_topic:
|
||||
topic: helloworld/hi
|
||||
level: INFO
|
||||
birth_message:
|
||||
will_message:
|
||||
shutdown_message:
|
||||
topic: topic/to/send/to
|
||||
payload: hi
|
||||
qos: 2
|
||||
retain: true
|
||||
keepalive: 60s
|
||||
reboot_timeout: 60s
|
||||
on_message:
|
||||
- topic: my/custom/topic
|
||||
qos: 0
|
||||
then:
|
||||
- lambda: >-
|
||||
ESP_LOGD("main", "Got message %s", x.c_str());
|
||||
- topic: bedroom/ota_mode
|
||||
then:
|
||||
- logger.log: Got bedroom/ota_mode
|
||||
- topic: livingroom/ota_mode
|
||||
then:
|
||||
- logger.log: Got livingroom/ota_mode
|
||||
on_json_message:
|
||||
topic: the/topic
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
- wifi.connected:
|
||||
- mqtt.connected:
|
||||
then:
|
||||
- logger.log: on_json_message
|
||||
on_connect:
|
||||
- mqtt.publish:
|
||||
topic: some/topic
|
||||
payload: Hello
|
||||
on_disconnect:
|
||||
- mqtt.publish:
|
||||
topic: some/topic
|
||||
payload: Good-bye
|
||||
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
id: some_binary_sensor
|
||||
name: Garage Door Open
|
||||
state_topic: some/topic/binary_sensor
|
||||
qos: 2
|
||||
lambda: |-
|
||||
if (id(template_sens).state > 30) {
|
||||
// Garage Door is open.
|
||||
return true;
|
||||
} else {
|
||||
// Garage Door is closed.
|
||||
return false;
|
||||
}
|
||||
on_state:
|
||||
- mqtt.publish:
|
||||
topic: some/topic/binary_sensor
|
||||
payload: Hello
|
||||
qos: 2
|
||||
retain: true
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: "Template Button"
|
||||
state_topic: some/topic/button
|
||||
qos: 2
|
||||
on_press:
|
||||
- mqtt.publish:
|
||||
topic: some/topic/button
|
||||
payload: Hello
|
||||
qos: 2
|
||||
retain: true
|
||||
|
||||
climate:
|
||||
- platform: thermostat
|
||||
name: Test Thermostat
|
||||
sensor: template_sens
|
||||
humidity_sensor: template_sens
|
||||
action_state_topic: some/topicaction_state
|
||||
current_temperature_state_topic: some/topiccurrent_temperature_state
|
||||
current_humidity_state_topic: some/topiccurrent_humidity_state
|
||||
fan_mode_state_topic: some/topicfan_mode_state
|
||||
fan_mode_command_topic: some/topicfan_mode_command
|
||||
mode_state_topic: some/topicmode_state
|
||||
mode_command_topic: some/topicmode_command
|
||||
preset_state_topic: some/topicpreset_state
|
||||
preset_command_topic: some/topicpreset_command
|
||||
swing_mode_state_topic: some/topicswing_mode_state
|
||||
swing_mode_command_topic: some/topicswing_mode_command
|
||||
target_temperature_state_topic: some/topictarget_temperature_state
|
||||
target_temperature_command_topic: some/topictarget_temperature_command
|
||||
target_temperature_high_state_topic: some/topictarget_temperature_high_state
|
||||
target_temperature_high_command_topic: some/topictarget_temperature_high_command
|
||||
target_temperature_low_state_topic: some/topictarget_temperature_low_state
|
||||
target_temperature_low_command_topic: some/topictarget_temperature_low_command
|
||||
target_humidity_state_topic: some/topictarget_humidity_state
|
||||
target_humidity_command_topic: some/topictarget_humidity_command
|
||||
preset:
|
||||
- name: Default Preset
|
||||
default_target_temperature_low: 18°C
|
||||
default_target_temperature_high: 24°C
|
||||
- name: Away
|
||||
default_target_temperature_low: 16°C
|
||||
default_target_temperature_high: 20°C
|
||||
idle_action:
|
||||
- logger.log: idle_action
|
||||
cool_action:
|
||||
- logger.log: cool_action
|
||||
supplemental_cooling_action:
|
||||
- logger.log: supplemental_cooling_action
|
||||
heat_action:
|
||||
- logger.log: heat_action
|
||||
supplemental_heating_action:
|
||||
- logger.log: supplemental_heating_action
|
||||
dry_action:
|
||||
- logger.log: dry_action
|
||||
fan_only_action:
|
||||
- logger.log: fan_only_action
|
||||
auto_mode:
|
||||
- logger.log: auto_mode
|
||||
off_mode:
|
||||
- logger.log: off_mode
|
||||
heat_mode:
|
||||
- logger.log: heat_mode
|
||||
cool_mode:
|
||||
- logger.log: cool_mode
|
||||
dry_mode:
|
||||
- logger.log: dry_mode
|
||||
fan_only_mode:
|
||||
- logger.log: fan_only_mode
|
||||
fan_mode_auto_action:
|
||||
- logger.log: fan_mode_auto_action
|
||||
fan_mode_on_action:
|
||||
- logger.log: fan_mode_on_action
|
||||
fan_mode_off_action:
|
||||
- logger.log: fan_mode_off_action
|
||||
fan_mode_low_action:
|
||||
- logger.log: fan_mode_low_action
|
||||
fan_mode_medium_action:
|
||||
- logger.log: fan_mode_medium_action
|
||||
fan_mode_high_action:
|
||||
- logger.log: fan_mode_high_action
|
||||
fan_mode_middle_action:
|
||||
- logger.log: fan_mode_middle_action
|
||||
fan_mode_focus_action:
|
||||
- logger.log: fan_mode_focus_action
|
||||
fan_mode_diffuse_action:
|
||||
- logger.log: fan_mode_diffuse_action
|
||||
fan_mode_quiet_action:
|
||||
- logger.log: fan_mode_quiet_action
|
||||
swing_off_action:
|
||||
- logger.log: swing_off_action
|
||||
swing_horizontal_action:
|
||||
- logger.log: swing_horizontal_action
|
||||
swing_vertical_action:
|
||||
- logger.log: swing_vertical_action
|
||||
swing_both_action:
|
||||
- logger.log: swing_both_action
|
||||
startup_delay: true
|
||||
supplemental_cooling_delta: 2.0
|
||||
cool_deadband: 0.5
|
||||
cool_overrun: 0.5
|
||||
min_cooling_off_time: 300s
|
||||
min_cooling_run_time: 300s
|
||||
max_cooling_run_time: 600s
|
||||
supplemental_heating_delta: 2.0
|
||||
heat_deadband: 0.5
|
||||
heat_overrun: 0.5
|
||||
min_heating_off_time: 300s
|
||||
min_heating_run_time: 300s
|
||||
max_heating_run_time: 600s
|
||||
min_fanning_off_time: 30s
|
||||
min_fanning_run_time: 30s
|
||||
min_fan_mode_switching_time: 15s
|
||||
min_idle_time: 30s
|
||||
set_point_minimum_differential: 0.5
|
||||
fan_only_action_uses_fan_mode_timer: true
|
||||
fan_only_cooling: true
|
||||
fan_with_cooling: true
|
||||
fan_with_heating: true
|
||||
|
||||
cover:
|
||||
- platform: template
|
||||
name: Template Cover
|
||||
state_topic: some/topic/cover
|
||||
qos: 2
|
||||
lambda: |-
|
||||
if (id(some_binary_sensor).state) {
|
||||
return COVER_OPEN;
|
||||
} else {
|
||||
return COVER_CLOSED;
|
||||
}
|
||||
open_action:
|
||||
- logger.log: open_action
|
||||
close_action:
|
||||
- logger.log: close_action
|
||||
stop_action:
|
||||
- logger.log: stop_action
|
||||
optimistic: true
|
||||
|
||||
datetime:
|
||||
- platform: template
|
||||
name: Date
|
||||
id: test_date
|
||||
type: date
|
||||
state_topic: some/topic/date
|
||||
qos: 2
|
||||
set_action:
|
||||
- logger.log: "set_value"
|
||||
on_value:
|
||||
- logger.log:
|
||||
format: "Date: %04d-%02d-%02d"
|
||||
args:
|
||||
- x.year
|
||||
- x.month
|
||||
- x.day_of_month
|
||||
- platform: template
|
||||
name: Time
|
||||
id: test_time
|
||||
type: time
|
||||
state_topic: some/topic/time
|
||||
qos: 2
|
||||
set_action:
|
||||
- logger.log: "set_value"
|
||||
on_value:
|
||||
- logger.log:
|
||||
format: "Time: %02d:%02d:%02d"
|
||||
args:
|
||||
- x.hour
|
||||
- x.minute
|
||||
- x.second
|
||||
- platform: template
|
||||
name: DateTime
|
||||
id: test_datetime
|
||||
type: datetime
|
||||
state_topic: some/topic/datetime
|
||||
qos: 2
|
||||
set_action:
|
||||
- logger.log: set_value
|
||||
on_value:
|
||||
- logger.log:
|
||||
format: "DateTime: %04d-%02d-%02d %02d:%02d:%02d"
|
||||
args:
|
||||
- x.year
|
||||
- x.month
|
||||
- x.day_of_month
|
||||
- x.hour
|
||||
- x.minute
|
||||
- x.second
|
||||
|
||||
event:
|
||||
- platform: template
|
||||
name: Template Event
|
||||
state_topic: some/topic/event
|
||||
qos: 2
|
||||
event_types:
|
||||
- "custom_event_1"
|
||||
- "custom_event_2"
|
||||
|
||||
fan:
|
||||
- platform: template
|
||||
name: Template Fan
|
||||
state_topic: some/topic/fan
|
||||
qos: 2
|
||||
on_state:
|
||||
- logger.log: on_state
|
||||
on_speed_set:
|
||||
- logger.log: on_speed_set
|
||||
|
||||
light:
|
||||
- platform: binary
|
||||
name: Desk Lamp
|
||||
output: light_output
|
||||
state_topic: some/topic/light
|
||||
qos: 2
|
||||
|
||||
output:
|
||||
- id: light_output
|
||||
platform: gpio
|
||||
pin: 0
|
||||
|
||||
lock:
|
||||
- platform: template
|
||||
name: "Template Lock"
|
||||
state_topic: some/topic/lock
|
||||
qos: 2
|
||||
lambda: |-
|
||||
if (id(some_binary_sensor).state) {
|
||||
return LOCK_STATE_LOCKED;
|
||||
} else {
|
||||
return LOCK_STATE_UNLOCKED;
|
||||
}
|
||||
lock_action:
|
||||
- logger.log: lock_action
|
||||
unlock_action:
|
||||
- logger.log: unlock_action
|
||||
open_action:
|
||||
- logger.log: open_action
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
name: "Template number"
|
||||
state_topic: some/topic/number
|
||||
qos: 2
|
||||
optimistic: true
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
step: 1
|
||||
|
||||
select:
|
||||
- platform: template
|
||||
name: "Template select"
|
||||
state_topic: some/topic/select
|
||||
qos: 2
|
||||
optimistic: true
|
||||
options:
|
||||
- one
|
||||
- two
|
||||
- three
|
||||
initial_option: two
|
||||
|
||||
sensor:
|
||||
- platform: template
|
||||
name: Template Sensor
|
||||
id: template_sens
|
||||
lambda: |-
|
||||
if (id(some_binary_sensor).state) {
|
||||
return 42.0;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
update_interval: 60s
|
||||
on_value:
|
||||
- mqtt.publish:
|
||||
topic: some/topic/sensor
|
||||
payload: Hello
|
||||
qos: 2
|
||||
retain: true
|
||||
- platform: mqtt_subscribe
|
||||
name: MQTT Subscribe Sensor
|
||||
topic: mqtt/topic
|
||||
id: the_sensor
|
||||
qos: 2
|
||||
on_value:
|
||||
- mqtt.publish_json:
|
||||
topic: the/topic
|
||||
payload: |-
|
||||
root["key"] = id(template_sens).state;
|
||||
root["greeting"] = "Hello World";
|
||||
|
||||
switch:
|
||||
- platform: template
|
||||
name: Template Switch
|
||||
state_topic: some/topic/switch
|
||||
qos: 2
|
||||
lambda: |-
|
||||
if (id(some_binary_sensor).state) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
turn_on_action:
|
||||
- logger.log: turn_on_action
|
||||
turn_off_action:
|
||||
- logger.log: turn_off_action
|
||||
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: Template Text Sensor
|
||||
id: tts_text
|
||||
state_topic: some/topic/text_sensor
|
||||
qos: 2
|
||||
- platform: mqtt_subscribe
|
||||
name: MQTT Subscribe Text
|
||||
topic: some/topic/text_sensor
|
||||
qos: 2
|
||||
on_value:
|
||||
- text_sensor.template.publish:
|
||||
id: tts_text
|
||||
state: Hello World
|
||||
- text_sensor.template.publish:
|
||||
id: tts_text
|
||||
state: |-
|
||||
return "Hello World2";
|
||||
|
||||
text:
|
||||
- platform: template
|
||||
name: Template Text
|
||||
optimistic: true
|
||||
min_length: 0
|
||||
max_length: 100
|
||||
mode: text
|
||||
state_topic: some/topic/text
|
||||
qos: 2
|
||||
|
||||
valve:
|
||||
- platform: template
|
||||
name: Template Valve
|
||||
state_topic: some/topic/valve
|
||||
qos: 2
|
||||
optimistic: true
|
||||
lambda: |-
|
||||
if (id(some_binary_sensor).state) {
|
||||
return VALVE_OPEN;
|
||||
} else {
|
||||
return VALVE_CLOSED;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
packages:
|
||||
common: !include common.yaml
|
|
@ -1,16 +1,2 @@
|
|||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
mqtt:
|
||||
broker: test.mosquitto.org
|
||||
port: 1883
|
||||
discovery: true
|
||||
discovery_prefix: homeassistant
|
||||
idf_send_async: false
|
||||
log_topic:
|
||||
on_message:
|
||||
topic: testing/sensor/testing_sensor/state
|
||||
qos: 0
|
||||
then:
|
||||
- logger.log: Mqtt Test
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
|
|
|
@ -1,15 +1,2 @@
|
|||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
mqtt:
|
||||
broker: test.mosquitto.org
|
||||
port: 1883
|
||||
discovery: true
|
||||
discovery_prefix: homeassistant
|
||||
log_topic:
|
||||
on_message:
|
||||
topic: testing/sensor/testing_sensor/state
|
||||
qos: 0
|
||||
then:
|
||||
- logger.log: Mqtt Test
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
|
|
|
@ -1,16 +1,2 @@
|
|||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
mqtt:
|
||||
broker: test.mosquitto.org
|
||||
port: 1883
|
||||
discovery: true
|
||||
discovery_prefix: homeassistant
|
||||
idf_send_async: false
|
||||
log_topic:
|
||||
on_message:
|
||||
topic: testing/sensor/testing_sensor/state
|
||||
qos: 0
|
||||
then:
|
||||
- logger.log: Mqtt Test
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
|
|
|
@ -1,15 +1,2 @@
|
|||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
mqtt:
|
||||
broker: test.mosquitto.org
|
||||
port: 1883
|
||||
discovery: true
|
||||
discovery_prefix: homeassistant
|
||||
log_topic:
|
||||
on_message:
|
||||
topic: testing/sensor/testing_sensor/state
|
||||
qos: 0
|
||||
then:
|
||||
- logger.log: Mqtt Test
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
|
|
|
@ -1,15 +1,2 @@
|
|||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
|
||||
mqtt:
|
||||
broker: test.mosquitto.org
|
||||
port: 1883
|
||||
discovery: true
|
||||
discovery_prefix: homeassistant
|
||||
log_topic:
|
||||
on_message:
|
||||
topic: testing/sensor/testing_sensor/state
|
||||
qos: 0
|
||||
then:
|
||||
- logger.log: Mqtt Test
|
||||
packages:
|
||||
common: !include common.yaml
|
||||
|
|
Loading…
Reference in New Issue