28#include <esp_heap_caps.h>
32#include <freertos/FreeRTOS.h>
33#include <freertos/semphr.h>
34#elif defined(USE_LIBRETINY)
43#define HOT __attribute__((hot))
44#define ESPDEPRECATED(msg, when) __attribute__((deprecated(msg)))
45#define ESPHOME_ALWAYS_INLINE __attribute__((always_inline))
46#define PACKED __attribute__((packed))
58using std::is_trivially_copyable;
59using std::make_unique;
60using std::enable_if_t;
62using std::is_invocable;
63#if __cpp_lib_bit_cast >= 201806
68 typename To,
typename From,
69 enable_if_t<
sizeof(To) ==
sizeof(From) && is_trivially_copyable<From>::value && is_trivially_copyable<To>::value,
73 memcpy(&dst, &src,
sizeof(To));
79inline float lerp(
float completion,
float start,
float end) =
delete;
83template<
typename T>
constexpr T
byteswap(T n) {
85 for (
size_t i = 0; i <
sizeof(T); i++)
86 reinterpret_cast<uint8_t *
>(&
m)[i] =
reinterpret_cast<uint8_t *
>(&n)[
sizeof(T) - 1 - i];
89template<>
constexpr uint8_t
byteswap(uint8_t n) {
return n; }
92template<>
inline uint16_t
byteswap(uint16_t n) {
return __builtin_bswap16(n); }
93template<>
inline uint32_t
byteswap(uint32_t n) {
return __builtin_bswap32(n); }
94template<>
inline uint64_t
byteswap(uint64_t n) {
return __builtin_bswap64(n); }
95template<>
inline int8_t
byteswap(int8_t n) {
return n; }
96template<>
inline int16_t
byteswap(int16_t n) {
return __builtin_bswap16(n); }
97template<>
inline int32_t
byteswap(int32_t n) {
return __builtin_bswap32(n); }
98template<>
inline int64_t
byteswap(int64_t n) {
return __builtin_bswap64(n); }
100template<>
constexpr uint16_t
byteswap(uint16_t n) {
return __builtin_bswap16(n); }
101template<>
constexpr uint32_t
byteswap(uint32_t n) {
return __builtin_bswap32(n); }
102template<>
constexpr uint64_t
byteswap(uint64_t n) {
return __builtin_bswap64(n); }
103template<>
constexpr int8_t
byteswap(int8_t n) {
return n; }
104template<>
constexpr int16_t
byteswap(int16_t n) {
return __builtin_bswap16(n); }
105template<>
constexpr int32_t
byteswap(int32_t n) {
return __builtin_bswap32(n); }
106template<>
constexpr int64_t
byteswap(int64_t n) {
return __builtin_bswap64(n); }
135 using iterator =
typename std::array<T, N>::iterator;
141 std::array<T, N> data_{};
148 data_[count_++] = value;
159 return data_[count_++];
162 size_t size()
const {
return count_; }
163 bool empty()
const {
return count_ == 0; }
191 void destroy_elements_() {
193 if constexpr (!std::is_trivially_destructible<T>::value) {
194 for (
size_t i = 0; i < size_; i++) {
202 if (data_ !=
nullptr) {
205 ::operator
delete(data_);
217 void assign_from_initializer_list_(std::initializer_list<T> init_list) {
218 init(init_list.size());
220 for (
const auto &item : init_list) {
221 new (data_ + idx) T(item);
224 size_ = init_list.size();
232 FixedVector(std::initializer_list<T> init_list) { assign_from_initializer_list_(init_list); }
246 operator std::vector<T>()
const {
return {data_, data_ + size_}; }
249 if (
this != &other) {
255 capacity_ = other.capacity_;
267 assign_from_initializer_list_(init_list);
281 data_ =
static_cast<T *
>(::operator
new(n *
sizeof(T)));
302 if (size_ < capacity_) {
304 new (&data_[size_]) T(value);
313 if (size_ < capacity_) {
315 new (&data_[size_]) T(std::move(value));
326 new (&data_[size_]) T(std::forward<Args>(args)...);
328 return data_[size_ - 1];
334 const T &
front()
const {
return data_[0]; }
338 T &
back() {
return data_[size_ - 1]; }
339 const T &
back()
const {
return data_[size_ - 1]; }
341 size_t size()
const {
return size_; }
342 bool empty()
const {
return size_ == 0; }
351 T &
at(
size_t i) {
return data_[i]; }
352 const T &
at(
size_t i)
const {
return data_[i]; }
356 T *
end() {
return data_ + size_; }
357 const T *
begin()
const {
return data_; }
358 const T *
end()
const {
return data_ + size_; }
367template<
typename T,
typename U> T
remap(U value, U min, U max, T min_out, T max_out) {
368 return (value - min) * (max_out - min_out) / (max - min) + min_out;
372uint8_t
crc8(
const uint8_t *data, uint8_t
len, uint8_t crc = 0x00, uint8_t poly = 0x8C,
bool msb_first =
false);
375uint16_t
crc16(
const uint8_t *data, uint16_t
len, uint16_t crc = 0xffff, uint16_t reverse_poly = 0xa001,
376 bool refin =
false,
bool refout =
false);
377uint16_t
crc16be(
const uint8_t *data, uint16_t
len, uint16_t crc = 0, uint16_t poly = 0x1021,
bool refin =
false,
378 bool refout =
false);
398 return (
static_cast<uint16_t
>(msb) << 8) | (
static_cast<uint16_t
>(lsb));
401constexpr uint32_t
encode_uint24(uint8_t byte1, uint8_t byte2, uint8_t byte3) {
402 return (
static_cast<uint32_t
>(byte1) << 16) | (
static_cast<uint32_t
>(byte2) << 8) | (
static_cast<uint32_t
>(byte3));
405constexpr uint32_t
encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4) {
406 return (
static_cast<uint32_t
>(byte1) << 24) | (
static_cast<uint32_t
>(byte2) << 16) |
407 (
static_cast<uint32_t
>(byte3) << 8) | (
static_cast<uint32_t
>(byte4));
411template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0>
constexpr T
encode_value(
const uint8_t *bytes) {
413 for (
size_t i = 0; i <
sizeof(T); i++) {
420template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0>
425template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0>
427 std::array<uint8_t,
sizeof(T)> ret{};
428 for (
size_t i =
sizeof(T); i > 0; i--) {
429 ret[i - 1] =
val & 0xFF;
437 x = ((
x & 0xAA) >> 1) | ((
x & 0x55) << 1);
438 x = ((
x & 0xCC) >> 2) | ((
x & 0x33) << 2);
439 x = ((
x & 0xF0) >> 4) | ((
x & 0x0F) << 4);
448 return (
reverse_bits(
static_cast<uint16_t
>(
x & 0xFFFF)) << 16) |
454#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
463#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
479bool str_startswith(
const std::string &str,
const std::string &start);
488std::string
str_until(
const char *str,
char ch);
490std::string
str_until(
const std::string &str,
char ch);
516std::
string make_name_with_suffix(const std::
string &name,
char sep, const
char *suffix_ptr,
size_t suffix_len);
526std::
string make_name_with_suffix(const
char *name,
size_t name_len,
char sep, const
char *suffix_ptr,
535template<typename T, enable_if_t<(std::is_integral<T>::value && std::is_unsigned<T>::value),
int> = 0>
538 unsigned long value = ::strtoul(str, &
end, 10);
539 if (
end == str || *
end !=
'\0' || value > std::numeric_limits<T>::max())
544template<
typename T, enable_if_t<(std::is_
integral<T>::value && std::is_
unsigned<T>::value),
int> = 0>
549template<
typename T, enable_if_t<(std::is_
integral<T>::value && std::is_
signed<T>::value),
int> = 0>
552 signed long value = ::strtol(str, &
end, 10);
553 if (
end == str || *
end !=
'\0' || value < std::numeric_limits<T>::min() || value > std::numeric_limits<T>::max())
558template<
typename T, enable_if_t<(std::is_
integral<T>::value && std::is_
signed<T>::value),
int> = 0>
563template<
typename T, enable_if_t<(std::is_same<T,
float>::value),
int> = 0> optional<T>
parse_number(
const char *str) {
565 float value = ::strtof(str, &
end);
566 if (
end == str || *
end !=
'\0' || value == HUGE_VALF)
571template<
typename T, enable_if_t<(std::is_same<T,
float>::value),
int> = 0>
587size_t parse_hex(
const char *str,
size_t len, uint8_t *data,
size_t count);
589inline bool parse_hex(
const char *str, uint8_t *data,
size_t count) {
590 return parse_hex(str, strlen(str), data, count) == 2 * count;
593inline bool parse_hex(
const std::string &str, uint8_t *data,
size_t count) {
594 return parse_hex(str.c_str(), str.length(), data, count) == 2 * count;
597inline bool parse_hex(
const char *str, std::vector<uint8_t> &data,
size_t count) {
599 return parse_hex(str, strlen(str), data.data(), count) == 2 * count;
602inline bool parse_hex(
const std::string &str, std::vector<uint8_t> &data,
size_t count) {
604 return parse_hex(str.c_str(), str.length(), data.data(), count) == 2 * count;
611template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0>
614 if (
len > 2 *
sizeof(T) ||
parse_hex(str,
len,
reinterpret_cast<uint8_t *
>(&
val),
sizeof(T)) == 0)
623template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0>
optional<T> parse_hex(
const std::string &str) {
636 for (
size_t i = 0; i < 6; i++) {
637 uint8_t
byte = mac[i];
641 output[i * 3 + 2] =
':';
648 for (
size_t i = 0; i < 6; i++) {
649 uint8_t
byte = mac[i];
661std::string
format_hex(
const std::vector<uint8_t> &data);
663template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0> std::string
format_hex(T
val) {
665 return format_hex(
reinterpret_cast<uint8_t *
>(&
val),
sizeof(T));
667template<std::
size_t N> std::string
format_hex(
const std::array<uint8_t, N> &data) {
696std::string
format_hex_pretty(
const uint8_t *data,
size_t length,
char separator =
'.',
bool show_length =
true);
718std::string
format_hex_pretty(
const uint16_t *data,
size_t length,
char separator =
'.',
bool show_length =
true);
741std::string
format_hex_pretty(
const std::vector<uint8_t> &data,
char separator =
'.',
bool show_length =
true);
763std::string
format_hex_pretty(
const std::vector<uint16_t> &data,
char separator =
'.',
bool show_length =
true);
785std::string
format_hex_pretty(
const std::string &data,
char separator =
'.',
bool show_length =
true);
810template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0>
819template<typename T, enable_if_t<std::is_unsigned<T>::value,
int> = 0> std::string
format_bin(T
val) {
821 return format_bin(
reinterpret_cast<uint8_t *
>(&
val),
sizeof(T));
842std::string
base64_encode(
const uint8_t *buf,
size_t buf_len);
845std::vector<uint8_t>
base64_decode(
const std::string &encoded_string);
846size_t base64_decode(std::string
const &encoded_string, uint8_t *buf,
size_t buf_len);
859void rgb_to_hsv(
float red,
float green,
float blue,
int &hue,
float &saturation,
float &value);
861void hsv_to_rgb(
int hue,
float saturation,
float value,
float &red,
float &green,
float &blue);
887 void add(std::function<
void(Ts...)> &&callback) { this->callbacks_.push_back(std::move(callback)); }
891 for (
auto &cb : this->callbacks_)
894 size_t size()
const {
return this->callbacks_.size(); }
967#if defined(USE_ESP32) || defined(USE_LIBRETINY)
968 SemaphoreHandle_t handle_;
1014#if defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_ZEPHYR)
1126 this->flags_ =
flags;
1133 size_t size = n * manual_size;
1137 ptr =
static_cast<T *
>(heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
1140 ptr =
static_cast<T *
>(heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
1144 ptr =
static_cast<T *
>(malloc(size));
1152 size_t size = n * manual_size;
1156 ptr =
static_cast<T *
>(heap_caps_realloc(p, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
1159 ptr =
static_cast<T *
>(heap_caps_realloc(p, size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
1163 ptr =
static_cast<T *
>(realloc(p, size));
1177 return ESP.getFreeHeap();
1178#elif defined(USE_ESP32)
1180 this->flags_ &
ALLOC_INTERNAL ? heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL) : 0;
1182 this->flags_ &
ALLOC_EXTERNAL ? heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM) : 0;
1183 return max_internal + max_external;
1184#elif defined(USE_RP2040)
1185 return ::rp2040.getFreeHeap();
1186#elif defined(USE_LIBRETINY)
1187 return lt_heap_get_free();
1198 return ESP.getMaxFreeBlockSize();
1199#elif defined(USE_ESP32)
1201 this->flags_ &
ALLOC_INTERNAL ? heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL) : 0;
1203 this->flags_ &
ALLOC_EXTERNAL ? heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM) : 0;
1204 return std::max(max_internal, max_external);
1220template<
typename T,
typename U>
1222 { a > b } -> std::convertible_to<bool>;
1223 { a < b } -> std::convertible_to<bool>;
1226template<std::totally_ordered T, comparable_with<T> U> T
clamp_at_least(T value, U min) {
1231template<std::totally_ordered T, comparable_with<T> U> T
clamp_at_most(T value, U max) {
1244template<typename T, enable_if_t<!std::is_pointer<T>::value,
int> = 0> T
id(T value) {
return value; }
1249template<typename T, enable_if_t<std::is_pointer<T *>::value,
int> = 0> T &
id(T *value) {
return *value; }
void operator()(Ts... args)
Call all callbacks in this manager.
std::vector< std::function< void(Ts...)> > callbacks_
void call(Ts... args)
Call all callbacks in this manager.
void add(std::function< void(Ts...)> &&callback)
Add a callback to the list.
Lightweight read-only view over a const array stored in RODATA (will typically be in flash memory) Av...
const constexpr T & operator[](size_t i) const
constexpr bool empty() const
constexpr ConstVector(const T *data, size_t size)
constexpr size_t size() const
Helper class to deduplicate items in a series of values.
bool next(T value)
Feeds the next item in the series to the deduplicator and returns false if this is a duplicate.
bool has_value() const
Returns true if this deduplicator has processed any items.
bool next_unknown()
Returns true if the deduplicator's value was previously known.
Fixed-capacity vector - allocates once at runtime, never reallocates This avoids std::vector template...
const T & at(size_t i) const
FixedVector(FixedVector &&other) noexcept
FixedVector(std::initializer_list< T > init_list)
Constructor from initializer list - allocates exact size needed This enables brace initialization: Fi...
FixedVector & operator=(std::initializer_list< T > init_list)
Assignment from initializer list - avoids temporary and move overhead This enables: FixedVector<int> ...
T & front()
Access first element (no bounds checking - matches std::vector behavior) Caller must ensure vector is...
const T & operator[](size_t i) const
T & operator[](size_t i)
Access element without bounds checking (matches std::vector behavior) Caller must ensure index is val...
T & back()
Access last element (no bounds checking - matches std::vector behavior) Caller must ensure vector is ...
FixedVector & operator=(const FixedVector &)=delete
FixedVector(const FixedVector &)=delete
void push_back(T &&value)
Add element by move without bounds checking Caller must ensure sufficient capacity was allocated via ...
T & emplace_back(Args &&...args)
Emplace element without bounds checking - constructs in-place with arguments Caller must ensure suffi...
FixedVector & operator=(FixedVector &&other) noexcept
T & at(size_t i)
Access element with bounds checking (matches std::vector behavior) Note: No exception thrown on out o...
void push_back(const T &value)
Add element without bounds checking Caller must ensure sufficient capacity was allocated via init() S...
Helper class to request loop() to be called as fast as possible.
void stop()
Stop running the loop continuously.
static bool is_high_frequency()
Check whether the loop is running continuously.
static uint8_t num_requests
void start()
Start running the loop continuously.
Helper class to disable interrupts.
Helper class that wraps a mutex with a RAII-style API.
Helper class to lock the lwIP TCPIP core when making lwIP API calls from non-TCPIP threads.
LwIPLock(const LwIPLock &)=delete
LwIPLock & operator=(const LwIPLock &)=delete
Mutex implementation, with API based on the unavailable std::mutex.
Mutex(const Mutex &)=delete
Mutex & operator=(const Mutex &)=delete
Helper class to easily give an object a parent of type T.
T * get_parent() const
Get the parent of this object.
void set_parent(T *parent)
Set the parent of this object.
An STL allocator that uses SPI or internal RAM.
RAMAllocator(uint8_t flags)
T * reallocate(T *p, size_t n, size_t manual_size)
size_t get_free_heap_size() const
Return the total heap space available via this allocator.
T * reallocate(T *p, size_t n)
void deallocate(T *p, size_t n)
size_t get_max_free_block_size() const
Return the maximum size block this allocator could allocate.
constexpr RAMAllocator(const RAMAllocator< U > &other)
T * allocate(size_t n, size_t manual_size)
Minimal static vector - saves memory by avoiding std::vector overhead.
const_reverse_iterator rend() const
reverse_iterator rbegin()
const T & operator[](size_t i) const
void push_back(const T &value)
const_reverse_iterator rbegin() const
std::reverse_iterator< const_iterator > const_reverse_iterator
typename std::array< T, N >::iterator iterator
typename std::array< T, N >::const_iterator const_iterator
std::reverse_iterator< iterator > reverse_iterator
const_iterator end() const
const_iterator begin() const
struct @65::@66 __attribute__
Functions to constrain the range of arithmetic values.
Providing packet encoding functions for exchanging data with a remote host.
T clamp_at_most(T value, U max)
bool random_bytes(uint8_t *data, size_t len)
Generate len number of random bytes.
float random_float()
Return a random float between 0 and 1.
float gamma_uncorrect(float value, float gamma)
Reverts gamma correction of gamma to value.
uint16_t crc16(const uint8_t *data, uint16_t len, uint16_t crc, uint16_t reverse_poly, bool refin, bool refout)
Calculate a CRC-16 checksum of data with size len.
std::string value_accuracy_to_string(float value, int8_t accuracy_decimals)
Create a string from a value and an accuracy in decimals.
constexpr T convert_big_endian(T val)
Convert a value between host byte order and big endian (most significant byte first) order.
char format_hex_pretty_char(uint8_t v)
Convert a nibble (0-15) to uppercase hex char (used for pretty printing) This always uses uppercase (...
float gamma_correct(float value, float gamma)
Applies gamma correction of gamma to value.
void format_mac_addr_upper(const uint8_t *mac, char *output)
Format MAC address as XX:XX:XX:XX:XX:XX (uppercase)
bool mac_address_is_valid(const uint8_t *mac)
Check if the MAC address is not all zeros or all ones.
void format_mac_addr_lower_no_sep(const uint8_t *mac, char *output)
Format MAC address as xxxxxxxxxxxxxx (lowercase, no separators)
void rgb_to_hsv(float red, float green, float blue, int &hue, float &saturation, float &value)
Convert red, green and blue (all 0-1) values to hue (0-360), saturation (0-1) and value (0-1).
std::string format_hex(const uint8_t *data, size_t length)
Format the byte array data of length len in lowercased hex.
std::string str_lower_case(const std::string &str)
Convert the string to lower case.
ParseOnOffState parse_on_off(const char *str, const char *on, const char *off)
Parse a string that contains either on, off or toggle.
constexpr size_t MAC_ADDRESS_PRETTY_BUFFER_SIZE
Buffer size for MAC address in colon-separated uppercase hex notation (17 chars + null terminator)
std::string format_bin(const uint8_t *data, size_t length)
Format the byte array data of length len in binary.
constexpr T convert_little_endian(T val)
Convert a value between host byte order and little endian (least significant byte first) order.
std::string str_sanitize(const std::string &str)
Sanitizes the input string by removing all characters but alphanumerics, dashes and underscores.
constexpr uint32_t encode_uint24(uint8_t byte1, uint8_t byte2, uint8_t byte3)
Encode a 24-bit value given three bytes in most to least significant byte order.
bool has_custom_mac_address()
Check if a custom MAC address is set (ESP32 & variants)
std::string value_accuracy_with_uom_to_string(float value, int8_t accuracy_decimals, StringRef unit_of_measurement)
Create a string from a value, an accuracy in decimals, and a unit of measurement.
size_t parse_hex(const char *str, size_t length, uint8_t *data, size_t count)
Parse bytes from a hex-encoded string into a byte array.
uint32_t fnv1_hash(const char *str)
Calculate a FNV-1 hash of str.
T clamp_at_least(T value, U min)
optional< T > parse_number(const char *str)
Parse an unsigned decimal number from a null-terminated string.
constexpr size_t MAC_ADDRESS_BUFFER_SIZE
Buffer size for MAC address in lowercase hex notation (12 hex chars + null terminator)
std::string get_mac_address_pretty()
Get the device MAC address as a string, in colon-separated uppercase hex notation.
std::string str_snprintf(const char *fmt, size_t len,...)
void set_mac_address(uint8_t *mac)
Set the MAC address to use from the provided byte array (6 bytes).
int8_t step_to_accuracy_decimals(float step)
Derive accuracy in decimals from an increment step.
uint32_t random_uint32()
Return a random 32-bit unsigned integer.
const char * get_mac_address_pretty_into_buffer(std::span< char, MAC_ADDRESS_PRETTY_BUFFER_SIZE > buf)
Get the device MAC address into the given buffer, in colon-separated uppercase hex notation.
void IRAM_ATTR HOT delay_microseconds_safe(uint32_t us)
Delay for the given amount of microseconds, possibly yielding to other processes during the wait.
std::string str_upper_case(const std::string &str)
Convert the string to upper case.
std::string format_hex_pretty(const uint8_t *data, size_t length, char separator, bool show_length)
Format a byte array in pretty-printed, human-readable hex format.
bool str_equals_case_insensitive(const std::string &a, const std::string &b)
Compare strings for equality in case-insensitive manner.
std::string str_until(const char *str, char ch)
Extract the part of the string until either the first occurrence of the specified character,...
std::string format_mac_address_pretty(const uint8_t *mac)
std::string base64_encode(const std::vector< uint8_t > &buf)
constexpr T encode_value(const uint8_t *bytes)
Encode a value from its constituent bytes (from most to least significant) in an array with length si...
void hsv_to_rgb(int hue, float saturation, float value, float &red, float &green, float &blue)
Convert hue (0-360), saturation (0-1) and value (0-1) to red, green and blue (all 0-1).
void get_mac_address_into_buffer(std::span< char, MAC_ADDRESS_BUFFER_SIZE > buf)
Get the device MAC address into the given buffer, in lowercase hex notation.
uint16_t crc16be(const uint8_t *data, uint16_t len, uint16_t crc, uint16_t poly, bool refin, bool refout)
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc, uint8_t poly, bool msb_first)
Calculate a CRC-8 checksum of data with size len.
constexpr float celsius_to_fahrenheit(float value)
Convert degrees Celsius to degrees Fahrenheit.
std::string str_sprintf(const char *fmt,...)
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
void get_mac_address_raw(uint8_t *mac)
Get the device MAC address as raw bytes, written into the provided byte array (6 bytes).
bool str_startswith(const std::string &str, const std::string &start)
Check whether a string starts with a value.
char format_hex_char(uint8_t v)
Convert a nibble (0-15) to lowercase hex char.
constexpr std::array< uint8_t, sizeof(T)> decode_value(T val)
Decode a value into its constituent bytes (from most to least significant).
std::string get_mac_address()
Get the device MAC address as a string, in lowercase hex notation.
To bit_cast(const From &src)
Convert data between types, without aliasing issues or undefined behaviour.
constexpr float fahrenheit_to_celsius(float value)
Convert degrees Fahrenheit to degrees Celsius.
uint8_t reverse_bits(uint8_t x)
Reverse the order of 8 bits.
std::string str_snake_case(const std::string &str)
Convert the string to snake case (lowercase with underscores).
float lerp(float completion, float start, float end)=delete
T remap(U value, U min, U max, T min_out, T max_out)
Remap value from the range (min, max) to (min_out, max_out).
bool str_endswith(const std::string &str, const std::string &end)
Check whether a string ends with a value.
size_t base64_decode(const std::string &encoded_string, uint8_t *buf, size_t buf_len)
ParseOnOffState
Return values for parse_on_off().
std::string make_name_with_suffix(const char *name, size_t name_len, char sep, const char *suffix_ptr, size_t suffix_len)
Optimized string concatenation: name + separator + suffix (const char* overload) Uses a fixed stack b...
std::string str_truncate(const std::string &str, size_t length)
Truncate a string to a specific length.