Review components files

This commit is contained in:
Edward Firmo
2024-04-08 23:47:16 +02:00
parent 88cca0d1bf
commit 10e0a47b6f
18 changed files with 385 additions and 369 deletions

View File

@@ -0,0 +1,24 @@
// ha_components.cpp
#include "ha_components.h"
namespace nspanel_ha_blueprint {
// Function Definition
HomeAssistantEntity extractHomeAssistantEntity(const std::string& entity_id) {
size_t dotPos = entity_id.find(".");
HomeAssistantEntity result;
if (dotPos != std::string::npos) {
// Extract domain and id from the entity_id string
result.domain = entity_id.substr(0, dotPos);
result.id = entity_id.substr(dotPos + 1);
} else {
// No dot found, the entire entity_id is considered as id.
result.domain = "invalid";
result.id = entity_id;
}
return result;
}
} // namespace nspanel_ha_blueprint

View File

@@ -1,36 +1,36 @@
// ha_components.h
#pragma once
#include <string>
// Defines structures and functions related to Home Assistant entities within the nspanel_ha_blueprint namespace.
namespace nspanel_ha_blueprint {
// Represents a Home Assistant entity with a domain and an identifier.
struct HomeAssistantEntity {
std::string domain;
std::string id;
std::string domain; // The domain part of the entity, like "light" or "switch".
std::string id; // The unique identifier of the entity within its domain.
};
/**
* Extracts the domain name and unique ID from a given Home Assistant entity string.
* Handles a special case where "alarm_control_panel" should be shortened to "alarm".
*
* This function parses a Home Assistant entity string to extract and separate the domain
* and ID components of the entity. If the string does not contain a valid entity format
* (i.e., "domain.id"), the function will mark the domain as "invalid" and treat the entire
* string as the ID. It also handles a special case where "alarm_control_panel" should be
* shortened to "alarm", though the implementation of this feature needs to be added in the
* function's definition in the corresponding .cpp file.
*
* Usage example:
* auto entity = extractHomeAssistantEntity("light.kitchen");
* // entity.domain would be "light"
* // entity.id would be "kitchen"
*
* @param entity_id The input string containing either the combined domain and unique ID or just the unique ID.
* @return A HomeAssistantEntity struct containing the extracted domain and the unique ID.
*/
HomeAssistantEntity extractHomeAssistantEntity(const std::string& entity_id) {
size_t dotPos = entity_id.find(".");
HomeAssistantEntity result;
if (dotPos != std::string::npos) {
// Extract domain and id from the entity_id string
result.domain = entity_id.substr(0, dotPos);
result.id = entity_id.substr(dotPos + 1);
} else {
// No dot found, the entire entity_id is considered as id.
result.domain = "invalid";
result.id = entity_id;
}
return result;
}
HomeAssistantEntity extractHomeAssistantEntity(const std::string& entity_id);
} // namespace nspanel_ha_blueprint

View File

@@ -0,0 +1,21 @@
// hardware.cpp
#include "hardware.h"
namespace nspanel_ha_blueprint {
template<typename SettingsEnum>
void update_bitwise_setting(uint8_t& settings, bool condition, SettingsEnum flag) {
if (condition) {
settings |= flag; // Set bit
} else {
settings &= ~flag; // Clear bit
}
}
// Explicit template instantiation
// Note: You need to explicitly instantiate templates for all enums used as SettingsEnum
template void update_bitwise_setting<ButtonSettings>(uint8_t& settings, bool condition, ButtonSettings flag);
template void update_bitwise_setting<RelaySettings>(uint8_t& settings, bool condition, RelaySettings flag);
} // namespace nspanel_ha_blueprint

View File

@@ -1,73 +1,73 @@
// hardware.h
#pragma once
#include <cstdint>
// Namespace for nspanel_ha_blueprint, encapsulating definitions related to hardware settings.
namespace nspanel_ha_blueprint {
/**
* @enum ButtonsSettings
* Represents the settings for hardware buttons as individual bits within a uint8_t value.
* Each enum value corresponds to a specific bit position that represents a distinct setting
* for the buttons. This allows for efficient storage and manipulation of multiple buttons
* settings within a single byte.
* @enum ButtonSettings
* Represents the settings for hardware buttons using individual bits within a uint8_t value.
* This allows efficient storage and manipulation of settings for multiple buttons in a compact form.
*
* Bits are allocated as follows:
* - Bit 0: Left button - Enabled.
* - Bit 1: Left button - Current state (0 for `off` or 1 for `on`)
* The bit allocations are as follows:
* - Bit 0: Left button enabled.
* - Bit 1: Left button state (0 for `off`, 1 for `on`).
* - Bits 2-3: Reserved for future use.
* - Bit 4: Right button - Enabled.
* - Bit 5: Right button - Current state (0 for `off` or 1 for `on`)
* - Bit 4: Right button enabled.
* - Bit 5: Right button state (0 for `off`, 1 for `on`).
* - Bits 6-7: Reserved for future use.
*
* Usage involves bitwise operations to set, clear, and check these settings within a
* uint8_t variable. This approach enables compact representation and easy manipulation
* of relay settings.
* These settings facilitate easy manipulation of button states and configurations through bitwise operations.
*/
enum ButtonSettings {
ButtonLeft_Enabled = 1 << 0, ///< Bit 0: Enables left button visualization on screen.
ButtonLeft_State = 1 << 1, ///< Bit 1: Current state of left button.
ButtonLeft_Enabled = 1 << 0, ///< Enables left button visualization on screen.
ButtonLeft_State = 1 << 1, ///< Indicates current state of the left button.
// Bits 2 and 3 are reserved for future expansion.
ButtonRight_Enabled = 1 << 4, ///< Bit 4: Enables right button visualization on screen.
ButtonRight_State = 1 << 5, ///< Bit 5: Current state of right button.
ButtonRight_Enabled = 1 << 4, ///< Enables right button visualization on screen.
ButtonRight_State = 1 << 5, ///< Indicates current state of the right button.
// Bits 6 and 7 are reserved for future expansion.
};
/**
* @enum RelaySettings
* Represents the settings for relays as individual bits within a uint8_t value. Each
* enum value corresponds to a specific bit position that represents a distinct setting
* for the relays. This allows for efficient storage and manipulation of multiple relay
* settings within a single byte.
* Represents the settings for relays using individual bits within a uint8_t value.
* This approach allows for the efficient storage and manipulation of settings for multiple
* relays in a single byte, enabling compact representation and ease of setting manipulation.
*
* Bits are allocated as follows:
* - Bit 0: Relay 1 - Local control enabled.
* - Bit 1: Relay 1 - Fallback mode enabled.
* The bit allocations are as follows:
* - Bit 0: Relay 1 local control enabled.
* - Bit 1: Relay 1 fallback mode enabled.
* - Bits 2-3: Reserved for future use.
* - Bit 4: Relay 2 - Local control enabled.
* - Bit 5: Relay 2 - Fallback mode enabled.
* - Bit 4: Relay 2 local control enabled.
* - Bit 5: Relay 2 fallback mode enabled.
* - Bits 6-7: Reserved for future use.
*
* Usage involves bitwise operations to set, clear, and check these settings within a
* uint8_t variable. This approach enables compact representation and easy manipulation
* of relay settings.
* These settings support flexible relay configuration and state management through bitwise operations.
*/
enum RelaySettings {
Relay1_Local = 1 << 0, ///< Bit 0: Enables local control for Relay 1.
Relay1_Fallback = 1 << 1, ///< Bit 1: Enables fallback mode for Relay 1.
Relay1_Local = 1 << 0, ///< Enables local control for Relay 1.
Relay1_Fallback = 1 << 1, ///< Enables fallback mode for Relay 1.
// Bits 2 and 3 are reserved for future expansion.
Relay2_Local = 1 << 4, ///< Bit 4: Enables local control for Relay 2.
Relay2_Fallback = 1 << 5, ///< Bit 5: Enables fallback mode for Relay 2.
Relay2_Local = 1 << 4, ///< Enables local control for Relay 2.
Relay2_Fallback = 1 << 5, ///< Enables fallback mode for Relay 2.
// Bits 6 and 7 are reserved for future expansion.
};
/**
* Updates a settings byte according to a specified condition and flag.
*
* This function template applies a bitwise operation to modify the settings byte based on
* the provided condition and flag. If the condition is true, the bit corresponding to the flag
* is set; otherwise, it's cleared. This method enables dynamic and conditional settings updates.
*
* @param settings Reference to the settings byte to be modified.
* @param condition Boolean condition determining how the settings byte is modified.
* @param flag The specific bit flag (from ButtonSettings or RelaySettings) to modify.
*/
template<typename SettingsEnum>
void update_bitwise_setting(uint8_t& settings, bool condition, SettingsEnum flag) {
if (condition) {
settings |= flag; // Set bit
} else {
settings &= ~flag; // Clear bit
}
}
void update_bitwise_setting(uint8_t& settings, bool condition, SettingsEnum flag);
} // namespace nspanel_ha_blueprint

View File

@@ -0,0 +1,47 @@
// nextion_components.cpp
#include "nextion_components.h"
#include <algorithm>
#include <cstring>
namespace nspanel_ha_blueprint {
NextionComponent extractNextionComponent(const std::string& input, const std::string& defaultPage) {
NextionComponent result{};
size_t dotPos = input.find(".");
if (dotPos != std::string::npos) {
// Handling special case and standard extraction
strncpy(result.page, input.substr(0, std::min<size_t>(dotPos, 14)).c_str(), 14);
result.page[14] = '\0'; // Ensure null termination
strncpy(result.component_id, input.substr(dotPos + 1, 14).c_str(), 14);
result.component_id[14] = '\0'; // Ensure null termination
result.is_current_page = false;
} else {
// Default page case
strncpy(result.page, defaultPage.c_str(), 14);
result.page[14] = '\0'; // Ensure null termination
strncpy(result.component_id, input.c_str(), 14);
result.component_id[14] = '\0'; // Ensure null termination
result.is_current_page = true;
}
if (strcmp(result.page, defaultPage.c_str()) == 0) {
result.is_current_page = true;
}
return result;
}
template <typename Container>
uint16_t rgbTo565(const Container& rgb) {
if (rgb.size() != 3) {
return UINT16_MAX;
}
return ((rgb[0] & 0xF8) << 8) | ((rgb[1] & 0xFC) << 3) | (rgb[2] >> 3);
}
// Template instantiation for std::vector<int>
template uint16_t rgbTo565<std::vector<int>>(const std::vector<int>& rgb);
} // namespace nspanel_ha_blueprint

View File

@@ -1,86 +1,37 @@
// nextion_components.h
#pragma once
#include <array>
#include <cstdint>
#include <string>
#include <vector>
#include <cstdint>
namespace nspanel_ha_blueprint {
struct NextionComponent {
char page[15]; // 14 characters + null terminator
char component_id[15]; // 14 characters + null terminator
bool is_current_page;
char page[15]; // 14 characters + null terminator, representing the Nextion display page
char component_id[15]; // 14 characters + null terminator, representing the component ID within the page
bool is_current_page; // Flag indicating whether the component is on the current page
};
/**
* Extracts the page name and component ID from a given input string.
* If the input string omits the page, uses defaultPage.
* Special case: "alarm_control_panel" is shortened to "alarm".
* If the input string omits the page, a default page name is used.
* Handles a special case for "alarm_control_panel" by shortening it to "alarm".
*
* @param input The input string containing the component ID, optionally prefixed by the page name and a dot.
* @param defaultPage The default page name to use if the input string does not specify a page, limited to 14 characters.
* @return A NextionComponent struct with the extracted or default page name, the component ID, and a flag for current page status.
* @param defaultPage The default page name to use if the input string does not specify a page.
* @return A NextionComponent struct with the extracted or default page name, component ID, and current page status.
*/
NextionComponent extractNextionComponent(const std::string& input, const std::string& defaultPage) {
NextionComponent result{};
size_t dotPos = input.find(".");
if (dotPos != std::string::npos) {
if (input.compare(0, 20, "alarm_control_panel.") == 0) {
strncpy(result.page, "alarm", sizeof(result.page) - 1);
result.page[sizeof(result.page) - 1] = '\0';
} else {
// Copy up to the dot or 14 characters, whichever is smaller
size_t lengthToCopy = std::min(dotPos, static_cast<size_t>(14));
strncpy(result.page, input.c_str(), lengthToCopy);
result.page[lengthToCopy] = '\0'; // Ensure null termination
}
// Extract and copy component_id
const char* componentStart = input.c_str() + dotPos + 1;
strncpy(result.component_id, componentStart, std::min(input.length() - dotPos - 1, static_cast<size_t>(14)));
result.component_id[14] = '\0'; // Ensure null termination
result.is_current_page = false;
} else {
// No dot found, use defaultPage and assume it's the current page
strncpy(result.page, defaultPage.c_str(), 14);
result.page[14] = '\0'; // Ensure null termination
// Input is the component_id
strncpy(result.component_id, input.c_str(), std::min(input.length(), static_cast<size_t>(14)));
result.component_id[14] = '\0'; // Ensure null termination
result.is_current_page = true;
}
// Additional check to see if the current page matches defaultPage
if (strncmp(result.page, defaultPage.c_str(), 14) == 0) {
result.is_current_page = true;
}
return result;
}
NextionComponent extractNextionComponent(const std::string& input, const std::string& defaultPage);
/**
* Converts an RGB color represented as a vector of integers to the 16-bit 5-6-5 format supported by Nextion displays.
*
* This function takes a vector containing three integer values representing
* the red, green, and blue components of an RGB color, each in the range 0-255.
* It then converts these values into a single uint16_t value in 5-6-5 format,
* commonly used for color displays. The conversion process masks and shifts
* the components to fit into the 5 bits for red, 6 bits for green, and 5 bits for blue.
*
*
* @param rgb A vector of integers with exactly three elements: [red, green, blue].
* @return The color encoded in 16-bit 5-6-5 format, or UINT16_MAX if the input vector
* does not contain at least three elements.
* @return The color encoded in 16-bit 5-6-5 format, or UINT16_MAX if the input vector does not contain exactly three elements.
*/
template <typename Container>
inline uint16_t rgbTo565(const Container& rgb) {
if (rgb.size() != 3) {
return UINT16_MAX; // Use UINT16_MAX as an error indicator
}
return ((rgb[0] & 0xF8) << 8) | ((rgb[1] & 0xFC) << 3) | (rgb[2] >> 3);
}
uint16_t rgbTo565(const Container& rgb);
} // namespace nspanel_ha_blueprint

View File

@@ -0,0 +1,26 @@
// pages.cpp
#include "pages.h"
#include <cstring>
namespace nspanel_ha_blueprint {
uint8_t get_page_id(const std::string& page_name) {
for (uint8_t i = 0; i < page_names.size(); ++i) {
if (strcmp(page_names[i], page_name.c_str()) == 0) {
return i;
}
}
return UINT8_MAX;
}
bool isStringInList(const std::string& strToSearch, std::initializer_list<std::string> list) {
for (const auto& str : list) {
if (strToSearch == str) {
return true;
}
}
return false;
}
} // namespace nspanel_ha_blueprint

View File

@@ -1,10 +1,9 @@
// pages.h
#pragma once
#include <array>
#include <cstring>
#include <cstdint>
#include <utility>
#include <string>
#include <initializer_list>
@@ -12,7 +11,7 @@ namespace nspanel_ha_blueprint {
/**
* @file pages.h
* Defines constants and functions related to page names for "NSPanel HA Blueprint" project.
* Defines constants and functions related to page names for the NSPanel HA Blueprint project.
*/
// Constants
@@ -59,51 +58,15 @@ namespace nspanel_ha_blueprint {
* @return The index of the page_name in the page_names array. If the page_name
* is not found, returns UINT8_MAX as an indicator that no matching page was found.
*/
inline uint8_t get_page_id(const std::string& page_name) {
for (uint8_t i = 0; i < page_names.size(); ++i) {
if (strcmp(page_names[i], page_name.c_str()) == 0) {
return i; // Return the index if found
}
}
return UINT8_MAX; // Return UINT8_MAX if not found
}
uint8_t get_page_id(const std::string& page_name);
/**
* Checks if a given string is present within a list of strings.
*
* This function provides a convenient way to search for the presence of a specific string
* within a variably sized list of strings. It iterates through each string in the provided
* list, comparing it against the target string for an exact match. This utility is particularly
* useful for validating if a certain value matches any item from a predefined set of allowed
* values.
*
* @param strToSearch The string to search for within the list. This is the target string
* that the function will attempt to find an exact match for within the
* provided list of strings.
* @param list An initializer list of strings to search within. This list contains the strings
* against which the target string will be compared. The list is flexible in size,
* allowing for a variable number of strings to be specified.
*
* @return Returns `true` if the target string is found within the list, indicating an exact
* match was encountered. Returns `false` if the target string is not present in the
* list, indicating no matches were found.
*
* Usage Example:
* ```cpp
* std::string page = "alarm";
* bool isPresent = isStringInList(page, {"alarm", "climate", "cover", "fan", "light", "media_player", "confirm", "keyb_num"});
* if (!isPresent) {
* // The string 'page' was not found in the list
* }
* ```
* @param strToSearch The string to search for within the list.
* @param list An initializer list of strings to search within.
* @return `true` if the target string is found within the list, `false` otherwise.
*/
bool isStringInList(const std::string& strToSearch, std::initializer_list<std::string> list) {
for (const auto& str : list) {
if (strToSearch == str) {
return true;
}
}
return false;
}
bool isStringInList(const std::string& strToSearch, std::initializer_list<std::string> list);
} // namespace nspanel_ha_blueprint

View File

@@ -1,20 +0,0 @@
// subscriptions.h
#pragma once
#include <vector>
#include <string>
#include <optional>
namespace nspanel_ha_blueprint {
struct Subscription {
std::string component_id;
std::string entity_id;
int subscription_id;
};
std::vector<Subscription> subscriptions;
std::string subs_component_id;
std::string subs_entity_id;
} // namespace nspanel_ha_blueprint

View File

@@ -0,0 +1,49 @@
// text.cpp
#include "text.h"
#include <algorithm>
#include <cctype>
#include <cstring>
namespace nspanel_ha_blueprint {
template <unsigned int N>
void copyStringToCharArray(char (&dest)[N], const std::string& src) {
size_t length = std::min(src.size(), static_cast<size_t>(N - 1));
std::strncpy(dest, src.c_str(), length);
dest[length] = '\0';
}
// Explicit template instantiation might be needed depending on usage
// template void copyStringToCharArray<YOUR_SIZE_HERE>(char (&)[YOUR_SIZE_HERE], const std::string&);
bool isNumberChar(char c) {
return std::isdigit(static_cast<unsigned char>(c)) || c == '.' || c == '-' || c == ',';
}
std::string adjustDecimalSeparator(const std::string& input, char decimalSeparator) {
if (decimalSeparator == '.') {
return input;
}
size_t numericEnd = 0;
for (; numericEnd < input.size() && isNumberChar(input[numericEnd]); ++numericEnd);
std::string numericPart = input.substr(0, numericEnd);
std::string suffix = input.substr(numericEnd);
char* end;
double val = strtod(numericPart.c_str(), &end);
if (end != numericPart.c_str() && *end == '\0') {
size_t decimalPointPos = numericPart.find('.');
if (decimalPointPos != std::string::npos) {
numericPart[decimalPointPos] = decimalSeparator;
}
return numericPart + suffix;
} else {
return input;
}
}
} // namespace nspanel_ha_blueprint

View File

@@ -1,100 +1,40 @@
// text.h
#pragma once
#include <algorithm>
#include <cctype>
#include <cstring>
#include <string>
namespace nspanel_ha_blueprint {
/**
* Copies the contents of a std::string to a fixed-size char array, ensuring
* null termination of the string within the array. This function template
* automatically deduces the size of the destination char array at compile time,
* minimizing the risk of buffer overflow. It's designed for use with fixed-size
* char arrays only, not pointers or dynamically allocated memory.
* null termination. The destination array size is automatically deduced.
* Designed for fixed-size char arrays only.
*
* Template Parameter:
* N - The size of the destination char array. This value is deduced automatically
* and must be greater than 0.
*
* Parameters:
* dest - A reference to the destination char array where the string should be copied.
* The array must have a size that can accommodate the source string plus a
* null terminator. If the source string is longer than the destination array,
* it will be truncated.
* src - The source std::string to copy. This string's contents are copied into the
* destination array up to the array's capacity minus one, to leave space for
* the null terminator.
*
* Usage Example:
* char destination[11];
* std::string source = "Hello";
* nspanel_ha_blueprint::copyStringToCharArray(destination, source);
*
* Note: The destination array is always null-terminated, even if the source string
* is truncated to fit into the array.
* @param dest A reference to the destination char array.
* @param src The source std::string to copy.
*/
template <unsigned int N>
void copyStringToCharArray(char (&dest)[N], const std::string& src) {
// Ensure we do not exceed the buffer size, leaving space for the null terminator
size_t length = std::min(src.size(), N - 1);
// Copy the string data into the destination buffer
std::strncpy(dest, src.c_str(), length);
// Explicitly null-terminate the destination buffer
dest[length] = '\0';
}
// Helper function to determine if a character is part of a number
bool isNumberChar(char c) {
return std::isdigit(c) || c == '.' || c == '-' || c == ',';
}
void copyStringToCharArray(char (&dest)[N], const std::string& src);
/**
* Adjusts the decimal separator in a numeric string to a specified character.
* This function identifies and modifies the decimal separator of a number within a string,
* ensuring that only the first occurrence is replaced if it is a valid number followed by
* any non-numeric characters (e.g., units of measurement). If the input string does not
* start with a valid number, it is returned unchanged.
*
* @param input The string potentially containing a numeric value followed by text.
* @param decimalSeparator The character to use as the decimal separator.
* @return A string with the decimal separator adjusted if the input is a valid number,
* otherwise the original input string.
*/
std::string adjustDecimalSeparator(const std::string& input, char decimalSeparator) {
// Immediately return the original string if the desired decimal separator is "."
if (decimalSeparator == '.') {
return input;
}
* Determines if a character is part of a numeric string. This includes digits,
* a period (.), a minus sign (-), or a comma (,).
*
* @param c The character to check.
* @return True if the character is part of a number; false otherwise.
*/
bool isNumberChar(char c);
// Find the end of the numeric part of the string
size_t numericEnd = 0;
for (; numericEnd < input.size() && isNumberChar(input[numericEnd]); ++numericEnd);
// Extract the numeric part and the suffix (if any)
std::string numericPart = input.substr(0, numericEnd);
std::string suffix = input.substr(numericEnd);
// Attempt to convert the numeric part to a double
char* end;
double val = strtod(numericPart.c_str(), &end);
// Check if conversion was successful (end points to a null terminator if so)
if (end != numericPart.c_str() && *end == '\0') {
// Find and replace only the first occurrence of '.' with the specified decimalSeparator
size_t decimalPointPos = numericPart.find('.');
if (decimalPointPos != std::string::npos) {
numericPart[decimalPointPos] = decimalSeparator;
}
return numericPart + suffix;
} else {
// If the input is not a number, return it as is
return input;
}
}
/**
* Adjusts the decimal separator in a numeric string to the specified character.
* Only the first occurrence is replaced if it's a valid number followed by text.
* Returns the original string if it doesn't start with a valid number.
*
* @param input The string containing a numeric value followed by text.
* @param decimalSeparator The character to use as the decimal separator.
* @return A string with the adjusted decimal separator if valid; otherwise, the original string.
*/
std::string adjustDecimalSeparator(const std::string& input, char decimalSeparator);
} // namespace nspanel_ha_blueprint

View File

@@ -1,13 +1,12 @@
// utilities.cpp
#include "utilities.h"
#include <cstdint>
#include <cstring>
#include <cstdlib> // For malloc/free
#ifdef USE_ESP_IDF
#include "esp_heap_caps.h"
#elif defined(USE_ARDUINO)
#include "esp32-hal-psram.h"
#endif // ESP-IDF vs ARDUINO
#endif
namespace nspanel_ha_blueprint {
@@ -19,20 +18,21 @@ namespace nspanel_ha_blueprint {
UtilitiesGroups = static_cast<UtilitiesGroupValues*>(heap_caps_malloc(8 * sizeof(UtilitiesGroupValues), MALLOC_CAP_SPIRAM));
#elif defined(USE_ARDUINO)
UtilitiesGroups = static_cast<UtilitiesGroupValues*>(ps_malloc(8 * sizeof(UtilitiesGroupValues)));
#endif // ESP-IDF vs ARDUINO
#endif
if (!UtilitiesGroups) UtilitiesGroups = new UtilitiesGroupValues[8]; // Fallback to internal SRAM if PSRAM is not available or not supported
if (!UtilitiesGroups) return; // Fail nicely if no memory is available
if (!UtilitiesGroups) return; // Fail nicely if no memory is available
// Initialize UtilitiesGroups with default values
const UtilitiesGroupValues initialUtilitiesGroups[8] = {
{ "grid", "\0", "\0", 0 },
{ "group01", "\0", "\0", 0 },
{ "group02", "\0", "\0", 0 },
{ "group03", "\0", "\0", 0 },
{ "group04", "\0", "\0", 0 },
{ "group05", "\0", "\0", 0 },
{ "group06", "\0", "\0", 0 },
{ "home", "\0", "\0", 0 }
{"grid", "\0", "\0", 0},
{"group01", "\0", "\0", 0},
{"group02", "\0", "\0", 0},
{"group03", "\0", "\0", 0},
{"group04", "\0", "\0", 0},
{"group05", "\0", "\0", 0},
{"group06", "\0", "\0", 0},
{"home", "\0", "\0", 0}
};
for (size_t i = 0; i < 8; ++i) {
@@ -45,7 +45,7 @@ namespace nspanel_ha_blueprint {
void cleanupUtilitiesGroups() {
if (UtilitiesGroups != nullptr) {
free(UtilitiesGroups); // Compatible with both heap_caps_malloc and ps_malloc
free(UtilitiesGroups); // Compatible with both heap_caps_malloc and ps_malloc
UtilitiesGroups = nullptr; // Prevent dangling pointers
}
}

View File

@@ -1,20 +1,44 @@
// utilities.h
#pragma once
#include <cstdint>
#include <cstring> // For std::strcpy
#include <string>
namespace nspanel_ha_blueprint {
struct UtilitiesGroupValues {
char group_id[8]; // 7 characters + null terminator
char value1[11]; // 10 characters + null terminator
char value2[11]; // 11 characters + null terminator
char value1[11]; // 10 characters + null terminator
char value2[11]; // 10 characters + null terminator
int8_t direction;
};
extern UtilitiesGroupValues UtilitiesGroups[8];
extern UtilitiesGroupValues *UtilitiesGroups;
void resetUtilitiesGroups();
void cleanupUtilitiesGroups();
uint8_t findUtilitiesGroupIndex(const char* group_id);
/**
* Copies the contents of a std::string to a fixed-size char array, ensuring
* null termination. The destination array size is automatically deduced.
* Designed for fixed-size char arrays only.
*
* @param dest A reference to the destination char array.
* @param src The source std::string to copy.
*/
template <unsigned int N>
void copyStringToCharArray(char (&dest)[N], const std::string& src) {
// Ensure we do not exceed the buffer size, leaving space for the null terminator
size_t length = std::min(src.size(), N - 1);
// Copy the string data into the destination buffer
std::strncpy(dest, src.c_str(), length);
// Explicitly null-terminate the destination buffer
dest[length] = '\0';
}
} // namespace nspanel_ha_blueprint

View File

@@ -0,0 +1,20 @@
// versioning.cpp
#include "versioning.h"
#include <cstdio> // For sscanf
namespace nspanel_ha_blueprint {
bool compare_versions(const char* version1, const char* version2) {
int major1 = 0, minor1 = 0;
int major2 = 0, minor2 = 0;
// Parse the version strings into major and minor numbers
sscanf(version1, "%d.%d", &major1, &minor1);
sscanf(version2, "%d.%d", &major2, &minor2);
// Compare the parsed major and minor numbers
return (major1 == major2) && (minor1 == minor2);
}
} // namespace nspanel_ha_blueprint

View File

@@ -1,25 +1,19 @@
// versioning.h
#pragma once
#include <cstdio> // For sscanf
namespace nspanel_ha_blueprint {
/**
* Compares two version strings by major and minor version numbers.
* Assumes version strings are in the format "major.minor".
* Compares two version strings by major and minor version numbers, assuming the version
* strings are formatted as "major.minor". This function parses both version strings and
* compares their major and minor components.
*
* @param version1 First version string to compare.
* @param version2 Second version string to compare.
* @return true if the major and minor versions are equal, false otherwise.
* @param version1 The first version string to compare, in "major.minor" format.
* @param version2 The second version string to compare, in "major.minor" format.
* @return True if both the major and minor versions of version1 and version2 are equal,
* false otherwise.
*/
inline bool compare_versions(const char* version1, const char* version2) {
int major1 = 0, minor1 = 0;
int major2 = 0, minor2 = 0;
sscanf(version1, "%d.%d", &major1, &minor1);
sscanf(version2, "%d.%d", &major2, &minor2);
return (major1 == major2) && (minor1 == minor2);
}
bool compare_versions(const char* version1, const char* version2);
} // namespace nspanel_ha_blueprint

View File

@@ -0,0 +1,28 @@
// upload_tft.cpp
#include "upload_tft.h"
namespace nspanel_ha_blueprint_upload_tft {
std::string construct_tft_url(const std::string& branch, const std::string& model,
const std::string& defaultUrl, const std::string& baseUrl) {
std::string relative_branch = branch.find("b") != std::string::npos ? "beta" : branch.find("d") != std::string::npos ? "dev" : branch;
std::string file_name;
if (model == "NSPanel Blank") file_name = "nspanel_blank.tft";
else if (model == "NSPanel EU") file_name = "nspanel_eu.tft";
else if (model == "NSPanel US") file_name = "nspanel_us.tft";
else if (model == "NSPanel US Landscape") file_name = "nspanel_us_land.tft";
else if (model == "NSPanel EU (CJK languages)") file_name = "nspanel_CJK_eu.tft";
else if (model == "NSPanel US (CJK languages)") file_name = "nspanel_CJK_us.tft";
else if (model == "NSPanel US Landscape (CJK languages)") file_name = "nspanel_CJK_us_land.tft";
return file_name.empty() ? defaultUrl : baseUrl + relative_branch + "/hmi/" + file_name;
}
std::string getNSPanelText(int displayMode, int charset) {
if (displayMode < 1 || displayMode > 3 || charset < 1 || charset > 2) return "";
std::string text = (displayMode == 1) ? "NSPanel EU" : (displayMode == 2) ? "NSPanel US" : "NSPanel US Landscape";
if (charset == 2) text += " (CJK languages)";
return text;
}
} // namespace nspanel_ha_blueprint_upload_tft

View File

@@ -1,4 +1,5 @@
// upload_tft.h
#pragma once
#include <string>
@@ -6,76 +7,24 @@
namespace nspanel_ha_blueprint_upload_tft {
/**
* Constructs the TFT file URL based on branch, model, default URL, and base URL.
*
* @param branchInput The input branch version, which might contain special keywords like "beta" or "dev".
* @param model The model of the device, used to determine the specific TFT file name.
* @param defaultUrl The default URL to use if no specific file is associated with the model.
* @param baseUrl The base URL to which branch and file names are appended to construct the full URL.
* @return The fully constructed URL as a string.
*/
* Constructs the TFT file URL based on branch, model, default URL, and base URL.
*
* @param branch The branch version input, potentially containing keywords like "beta" or "dev".
* @param model The device model, determining the specific TFT file name.
* @param defaultUrl The fallback URL if no specific file is associated with the model.
* @param baseUrl The base URL, to which branch and file names are appended to create the full URL.
* @return A string representing the fully constructed URL.
*/
std::string construct_tft_url(const std::string& branch, const std::string& model,
const std::string& defaultUrl, const std::string& baseUrl) {
// Determine the branch based on the input
std::string relative_branch = branch;
if (branch.find("b") != std::string::npos) relative_branch = "beta";
else if (branch.find("d") != std::string::npos) relative_branch = "dev";
// Mapping model to the corresponding TFT file name
std::string file_name;
if (model == "NSPanel Blank") file_name = "nspanel_blank.tft";
else if (model == "NSPanel EU") file_name = "nspanel_eu.tft";
else if (model == "NSPanel US") file_name = "nspanel_us.tft";
else if (model == "NSPanel US Landscape") file_name = "nspanel_us_land.tft";
else if (model == "NSPanel EU (CJK languages)") file_name = "nspanel_CJK_eu.tft";
else if (model == "NSPanel US (CJK languages)") file_name = "nspanel_CJK_us.tft";
else if (model == "NSPanel US Landscape (CJK languages)") file_name = "nspanel_CJK_us_land.tft";
// Construct the URL based on the determined file name
std::string url;
if (file_name.empty()) {
url = defaultUrl; // Use the default URL if no specific file name is matched
} else {
url = baseUrl + relative_branch + "/hmi/" + file_name; // Construct the full URL
}
return url; // Return the constructed URL
}
const std::string& defaultUrl, const std::string& baseUrl);
/**
* @brief Generates a descriptive text for the NSPanel based on the given display mode and charset.
*
* This function maps numeric codes for the display mode and charset to a human-readable
* description of an NSPanel configuration. It supports different geographic regions and language
* character sets. If the inputs do not match any predefined configuration, the function returns
* an empty string, allowing for easy detection of unexpected or invalid inputs.
*
* @param displayMode An integer representing the display mode of the NSPanel:
* 1 for "EU", 2 for "US", and 3 for "US Landscape".
* @param charset An integer indicating the character set used:
* 1 for "International (original)" and 2 for "CJK languages".
* @return std::string A string describing the NSPanel configuration based on the inputs.
* Returns an empty string if the inputs do not match any known configuration.
*/
std::string getNSPanelText(int displayMode, int charset) {
if (displayMode < 1 or displayMode > 3 or charset < 1 or charset > 2) return "";
std::string text;
// Determine the base text based on the display mode
switch(displayMode) {
case 1: text = "NSPanel EU"; break;
case 2: text = "NSPanel US"; break;
case 3: text = "NSPanel US Landscape"; break;
default: return ""; // Return an empty string for unmatched display modes
}
// Append the charset text if necessary
if (charset == 2) {
text += " (CJK languages)";
}
return text;
}
* Generates a descriptive text for the NSPanel based on display mode and charset.
*
* @param displayMode Numeric code for the NSPanel's display mode: 1 for "EU", 2 for "US", 3 for "US Landscape".
* @param charset Numeric code for the character set: 1 for "International (original)", 2 for "CJK languages".
* @return A string describing the NSPanel configuration, or an empty string if inputs don't match any configuration.
*/
std::string getNSPanelText(int displayMode, int charset);
} // namespace nspanel_ha_blueprint_upload_tft

View File

@@ -176,7 +176,7 @@ time:
then:
- lambda: |-
ESP_LOGD("time.on_time_sync", "System clock synchronized");
ESP_LOGD("time.on_time_sync", "Timezone: %s", get_timezone().c_str());
ESP_LOGD("time.on_time_sync", "Timezone: %s", time_provider->get_timezone().c_str());
refresh_datetime->execute();
json: # Can be replaced by web_server