mirror of
https://github.com/esphome/esphome.git
synced 2026-09-19 02:58:38 +00:00
86 lines
2.7 KiB
C++
86 lines
2.7 KiB
C++
#include "improv_base.h"
|
|
|
|
#include <cstring>
|
|
#include "esphome/components/network/util.h"
|
|
#include "esphome/core/application.h"
|
|
#include "esphome/core/defines.h"
|
|
#include "esphome/core/log.h"
|
|
|
|
namespace esphome::improv_base {
|
|
|
|
#ifdef USE_IMPROV_NEXT_URL
|
|
static const char *const TAG = "improv_base";
|
|
|
|
static constexpr const char DEVICE_NAME_PLACEHOLDER[] = "{{device_name}}";
|
|
static constexpr size_t DEVICE_NAME_PLACEHOLDER_LEN = sizeof(DEVICE_NAME_PLACEHOLDER) - 1;
|
|
static constexpr const char IP_ADDRESS_PLACEHOLDER[] = "{{ip_address}}";
|
|
static constexpr size_t IP_ADDRESS_PLACEHOLDER_LEN = sizeof(IP_ADDRESS_PLACEHOLDER) - 1;
|
|
|
|
/// Copy src to dest, returning pointer past last written char. Stops at end or if src is null.
|
|
static char *copy_to_buffer(char *dest, const char *end, const char *src) {
|
|
if (src == nullptr) {
|
|
return dest;
|
|
}
|
|
while (*src != '\0' && dest < end) {
|
|
*dest++ = *src++;
|
|
}
|
|
return dest;
|
|
}
|
|
|
|
size_t ImprovBase::get_formatted_next_url_(char *buffer, size_t buffer_size) {
|
|
if (this->next_url_ == nullptr || buffer_size == 0) {
|
|
if (buffer_size > 0) {
|
|
buffer[0] = '\0';
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Get IP address once for replacement
|
|
const char *ip_str = nullptr;
|
|
char ip_buffer[network::IP_ADDRESS_BUFFER_SIZE];
|
|
for (auto &ip : network::get_ip_addresses()) {
|
|
if (ip.is_ip4()) {
|
|
ip.str_to(ip_buffer);
|
|
ip_str = ip_buffer;
|
|
break;
|
|
}
|
|
}
|
|
|
|
const char *device_name = App.get_name().c_str();
|
|
char *out = buffer;
|
|
const char *end = buffer + buffer_size - 1;
|
|
|
|
// Note: {{esphome_version}} is replaced at code generation time in Python
|
|
for (const char *p = this->next_url_; *p != '\0' && out < end;) {
|
|
if (strncmp(p, DEVICE_NAME_PLACEHOLDER, DEVICE_NAME_PLACEHOLDER_LEN) == 0) {
|
|
out = copy_to_buffer(out, end, device_name);
|
|
p += DEVICE_NAME_PLACEHOLDER_LEN;
|
|
} else if (ip_str != nullptr && strncmp(p, IP_ADDRESS_PLACEHOLDER, IP_ADDRESS_PLACEHOLDER_LEN) == 0) {
|
|
out = copy_to_buffer(out, end, ip_str);
|
|
p += IP_ADDRESS_PLACEHOLDER_LEN;
|
|
} else {
|
|
*out++ = *p++;
|
|
}
|
|
}
|
|
*out = '\0';
|
|
return out - buffer;
|
|
}
|
|
|
|
void ImprovBase::add_next_url_(improv::RpcResponseBuilder &builder, size_t max_len) {
|
|
// The builder rejects strings above 254 bytes, so anything longer than this
|
|
// buffer could never be sent anyway
|
|
char url_buffer[256];
|
|
size_t len = this->get_formatted_next_url_(url_buffer, sizeof(url_buffer));
|
|
if (len == 0) {
|
|
return;
|
|
}
|
|
// max_len is the transport's budget for this entry; skipping an over-long URL
|
|
// here keeps the rest of the response sendable instead of oversizing the frame
|
|
if (len > max_len || !builder.add_string(url_buffer, len)) {
|
|
ESP_LOGW(TAG, "Next URL too long; skipping");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} // namespace esphome::improv_base
|