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 // ha_components.h
#pragma once #pragma once
#include <string> #include <string>
// Defines structures and functions related to Home Assistant entities within the nspanel_ha_blueprint namespace.
namespace nspanel_ha_blueprint { namespace nspanel_ha_blueprint {
// Represents a Home Assistant entity with a domain and an identifier.
struct HomeAssistantEntity { struct HomeAssistantEntity {
std::string domain; std::string domain; // The domain part of the entity, like "light" or "switch".
std::string id; 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. * 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. * @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. * @return A HomeAssistantEntity struct containing the extracted domain and the unique ID.
*/ */
HomeAssistantEntity extractHomeAssistantEntity(const std::string& entity_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;
}
} // namespace nspanel_ha_blueprint } // 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 // hardware.h
#pragma once #pragma once
#include <cstdint> #include <cstdint>
// Namespace for nspanel_ha_blueprint, encapsulating definitions related to hardware settings.
namespace nspanel_ha_blueprint { namespace nspanel_ha_blueprint {
/** /**
* @enum ButtonsSettings * @enum ButtonSettings
* Represents the settings for hardware buttons as individual bits within a uint8_t value. * Represents the settings for hardware buttons using individual bits within a uint8_t value.
* Each enum value corresponds to a specific bit position that represents a distinct setting * This allows efficient storage and manipulation of settings for multiple buttons in a compact form.
* for the buttons. This allows for efficient storage and manipulation of multiple buttons
* settings within a single byte.
* *
* Bits are allocated as follows: * The bit allocations are as follows:
* - Bit 0: Left button - Enabled. * - Bit 0: Left button enabled.
* - Bit 1: Left button - Current state (0 for `off` or 1 for `on`) * - Bit 1: Left button state (0 for `off`, 1 for `on`).
* - Bits 2-3: Reserved for future use. * - Bits 2-3: Reserved for future use.
* - Bit 4: Right button - Enabled. * - Bit 4: Right button enabled.
* - Bit 5: Right button - Current state (0 for `off` or 1 for `on`) * - Bit 5: Right button state (0 for `off`, 1 for `on`).
* - Bits 6-7: Reserved for future use. * - Bits 6-7: Reserved for future use.
* *
* Usage involves bitwise operations to set, clear, and check these settings within a * These settings facilitate easy manipulation of button states and configurations through bitwise operations.
* uint8_t variable. This approach enables compact representation and easy manipulation
* of relay settings.
*/ */
enum ButtonSettings { enum ButtonSettings {
ButtonLeft_Enabled = 1 << 0, ///< Bit 0: Enables left button visualization on screen. ButtonLeft_Enabled = 1 << 0, ///< Enables left button visualization on screen.
ButtonLeft_State = 1 << 1, ///< Bit 1: Current state of left button. ButtonLeft_State = 1 << 1, ///< Indicates current state of the left button.
// Bits 2 and 3 are reserved for future expansion. // Bits 2 and 3 are reserved for future expansion.
ButtonRight_Enabled = 1 << 4, ///< Bit 4: Enables right button visualization on screen. ButtonRight_Enabled = 1 << 4, ///< Enables right button visualization on screen.
ButtonRight_State = 1 << 5, ///< Bit 5: Current state of right button. ButtonRight_State = 1 << 5, ///< Indicates current state of the right button.
// Bits 6 and 7 are reserved for future expansion. // Bits 6 and 7 are reserved for future expansion.
}; };
/** /**
* @enum RelaySettings * @enum RelaySettings
* Represents the settings for relays as individual bits within a uint8_t value. Each * Represents the settings for relays using individual bits within a uint8_t value.
* enum value corresponds to a specific bit position that represents a distinct setting * This approach allows for the efficient storage and manipulation of settings for multiple
* for the relays. This allows for efficient storage and manipulation of multiple relay * relays in a single byte, enabling compact representation and ease of setting manipulation.
* settings within a single byte.
* *
* Bits are allocated as follows: * The bit allocations are as follows:
* - Bit 0: Relay 1 - Local control enabled. * - Bit 0: Relay 1 local control enabled.
* - Bit 1: Relay 1 - Fallback mode enabled. * - Bit 1: Relay 1 fallback mode enabled.
* - Bits 2-3: Reserved for future use. * - Bits 2-3: Reserved for future use.
* - Bit 4: Relay 2 - Local control enabled. * - Bit 4: Relay 2 local control enabled.
* - Bit 5: Relay 2 - Fallback mode enabled. * - Bit 5: Relay 2 fallback mode enabled.
* - Bits 6-7: Reserved for future use. * - Bits 6-7: Reserved for future use.
* *
* Usage involves bitwise operations to set, clear, and check these settings within a * These settings support flexible relay configuration and state management through bitwise operations.
* uint8_t variable. This approach enables compact representation and easy manipulation
* of relay settings.
*/ */
enum RelaySettings { enum RelaySettings {
Relay1_Local = 1 << 0, ///< Bit 0: Enables local control for Relay 1. Relay1_Local = 1 << 0, ///< Enables local control for Relay 1.
Relay1_Fallback = 1 << 1, ///< Bit 1: Enables fallback mode for Relay 1. Relay1_Fallback = 1 << 1, ///< Enables fallback mode for Relay 1.
// Bits 2 and 3 are reserved for future expansion. // Bits 2 and 3 are reserved for future expansion.
Relay2_Local = 1 << 4, ///< Bit 4: Enables local control for Relay 2. Relay2_Local = 1 << 4, ///< Enables local control for Relay 2.
Relay2_Fallback = 1 << 5, ///< Bit 5: Enables fallback mode for Relay 2. Relay2_Fallback = 1 << 5, ///< Enables fallback mode for Relay 2.
// Bits 6 and 7 are reserved for future expansion. // 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> template<typename SettingsEnum>
void update_bitwise_setting(uint8_t& settings, bool condition, SettingsEnum flag) { void update_bitwise_setting(uint8_t& settings, bool condition, SettingsEnum flag);
if (condition) {
settings |= flag; // Set bit
} else {
settings &= ~flag; // Clear bit
}
}
} // namespace nspanel_ha_blueprint } // 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 // nextion_components.h
#pragma once #pragma once
#include <array>
#include <cstdint>
#include <string> #include <string>
#include <vector> #include <vector>
#include <cstdint>
namespace nspanel_ha_blueprint { namespace nspanel_ha_blueprint {
struct NextionComponent { struct NextionComponent {
char page[15]; // 14 characters + null terminator char page[15]; // 14 characters + null terminator, representing the Nextion display page
char component_id[15]; // 14 characters + null terminator char component_id[15]; // 14 characters + null terminator, representing the component ID within the page
bool is_current_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. * Extracts the page name and component ID from a given input string.
* If the input string omits the page, uses defaultPage. * If the input string omits the page, a default page name is used.
* Special case: "alarm_control_panel" is shortened to "alarm". * 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 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. * @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, the component ID, and a flag for current page status. * @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 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;
}
/** /**
* Converts an RGB color represented as a vector of integers to the 16-bit 5-6-5 format supported by Nextion displays. * 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]. * @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 * @return The color encoded in 16-bit 5-6-5 format, or UINT16_MAX if the input vector does not contain exactly three elements.
* does not contain at least three elements.
*/ */
template <typename Container> template <typename Container>
inline uint16_t rgbTo565(const Container& rgb) { 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);
}
} // namespace nspanel_ha_blueprint } // 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 // pages.h
#pragma once #pragma once
#include <array> #include <array>
#include <cstring>
#include <cstdint> #include <cstdint>
#include <utility>
#include <string> #include <string>
#include <initializer_list> #include <initializer_list>
@@ -12,7 +11,7 @@ namespace nspanel_ha_blueprint {
/** /**
* @file pages.h * @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 // 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 * @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. * 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) { 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
}
/** /**
* Checks if a given string is present within a list of strings. * 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 * @param strToSearch The string to search for within the list.
* within a variably sized list of strings. It iterates through each string in the provided * @param list An initializer list of strings to search within.
* list, comparing it against the target string for an exact match. This utility is particularly * @return `true` if the target string is found within the list, `false` otherwise.
* 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
* }
* ```
*/ */
bool isStringInList(const std::string& strToSearch, std::initializer_list<std::string> list) { 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 } // 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 // text.h
#pragma once #pragma once
#include <algorithm>
#include <cctype>
#include <cstring>
#include <string> #include <string>
namespace nspanel_ha_blueprint { namespace nspanel_ha_blueprint {
/** /**
* Copies the contents of a std::string to a fixed-size char array, ensuring * 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 * null termination. The destination array size is automatically deduced.
* automatically deduces the size of the destination char array at compile time, * Designed for fixed-size char arrays only.
* minimizing the risk of buffer overflow. It's designed for use with fixed-size
* char arrays only, not pointers or dynamically allocated memory.
* *
* Template Parameter: * @param dest A reference to the destination char array.
* N - The size of the destination char array. This value is deduced automatically * @param src The source std::string to copy.
* 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.
*/ */
template <unsigned int N> template <unsigned int N>
void copyStringToCharArray(char (&dest)[N], const std::string& src) { 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 == ',';
}
/** /**
* Adjusts the decimal separator in a numeric string to a specified character. * Determines if a character is part of a numeric string. This includes digits,
* This function identifies and modifies the decimal separator of a number within a string, * a period (.), a minus sign (-), or a comma (,).
* 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 c The character to check.
* @param decimalSeparator The character to use as the decimal separator. * @return True if the character is part of a number; false otherwise.
* @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) { bool isNumberChar(char c);
// Immediately return the original string if the desired decimal separator is "."
if (decimalSeparator == '.') {
return input;
}
// Find the end of the numeric part of the string /**
size_t numericEnd = 0; * Adjusts the decimal separator in a numeric string to the specified character.
for (; numericEnd < input.size() && isNumberChar(input[numericEnd]); ++numericEnd); * 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.
// Extract the numeric part and the suffix (if any) *
std::string numericPart = input.substr(0, numericEnd); * @param input The string containing a numeric value followed by text.
std::string suffix = input.substr(numericEnd); * @param decimalSeparator The character to use as the decimal separator.
* @return A string with the adjusted decimal separator if valid; otherwise, the original string.
// Attempt to convert the numeric part to a double */
char* end; std::string adjustDecimalSeparator(const std::string& input, char decimalSeparator);
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;
}
}
} // namespace nspanel_ha_blueprint } // namespace nspanel_ha_blueprint

View File

@@ -1,13 +1,12 @@
// utilities.cpp // utilities.cpp
#include "utilities.h" #include "utilities.h"
#include <cstdint> #include <cstdlib> // For malloc/free
#include <cstring>
#ifdef USE_ESP_IDF #ifdef USE_ESP_IDF
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#elif defined(USE_ARDUINO) #elif defined(USE_ARDUINO)
#include "esp32-hal-psram.h" #include "esp32-hal-psram.h"
#endif // ESP-IDF vs ARDUINO #endif
namespace nspanel_ha_blueprint { namespace nspanel_ha_blueprint {
@@ -19,11 +18,12 @@ namespace nspanel_ha_blueprint {
UtilitiesGroups = static_cast<UtilitiesGroupValues*>(heap_caps_malloc(8 * sizeof(UtilitiesGroupValues), MALLOC_CAP_SPIRAM)); UtilitiesGroups = static_cast<UtilitiesGroupValues*>(heap_caps_malloc(8 * sizeof(UtilitiesGroupValues), MALLOC_CAP_SPIRAM));
#elif defined(USE_ARDUINO) #elif defined(USE_ARDUINO)
UtilitiesGroups = static_cast<UtilitiesGroupValues*>(ps_malloc(8 * sizeof(UtilitiesGroupValues))); 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) 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] = { const UtilitiesGroupValues initialUtilitiesGroups[8] = {
{"grid", "\0", "\0", 0}, {"grid", "\0", "\0", 0},
{"group01", "\0", "\0", 0}, {"group01", "\0", "\0", 0},

View File

@@ -1,20 +1,44 @@
// utilities.h // utilities.h
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <cstring> // For std::strcpy
#include <string>
namespace nspanel_ha_blueprint { namespace nspanel_ha_blueprint {
struct UtilitiesGroupValues { struct UtilitiesGroupValues {
char group_id[8]; // 7 characters + null terminator char group_id[8]; // 7 characters + null terminator
char value1[11]; // 10 characters + null terminator char value1[11]; // 10 characters + null terminator
char value2[11]; // 11 characters + null terminator char value2[11]; // 10 characters + null terminator
int8_t direction; int8_t direction;
}; };
extern UtilitiesGroupValues UtilitiesGroups[8]; extern UtilitiesGroupValues *UtilitiesGroups;
void resetUtilitiesGroups(); void resetUtilitiesGroups();
void cleanupUtilitiesGroups();
uint8_t findUtilitiesGroupIndex(const char* group_id); 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 } // 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 // versioning.h
#pragma once #pragma once
#include <cstdio> // For sscanf
namespace nspanel_ha_blueprint { namespace nspanel_ha_blueprint {
/** /**
* Compares two version strings by major and minor version numbers. * Compares two version strings by major and minor version numbers, assuming the version
* Assumes version strings are in the format "major.minor". * 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 version1 The first version string to compare, in "major.minor" format.
* @param version2 Second version string to compare. * @param version2 The second version string to compare, in "major.minor" format.
* @return true if the major and minor versions are equal, false otherwise. * @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) { 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);
}
} // namespace nspanel_ha_blueprint } // 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 // upload_tft.h
#pragma once #pragma once
#include <string> #include <string>
@@ -8,74 +9,22 @@ namespace nspanel_ha_blueprint_upload_tft {
/** /**
* Constructs the TFT file URL based on branch, model, default URL, and base URL. * 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 branch The branch version input, potentially containing keywords like "beta" or "dev".
* @param model The model of the device, used to determine the specific TFT file name. * @param model The device model, determining the specific TFT file name.
* @param defaultUrl The default URL to use if no specific file is associated with the model. * @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 construct the full URL. * @param baseUrl The base URL, to which branch and file names are appended to create the full URL.
* @return The fully constructed URL as a string. * @return A string representing the fully constructed URL.
*/ */
std::string construct_tft_url(const std::string& branch, const std::string& model, std::string construct_tft_url(const std::string& branch, const std::string& model,
const std::string& defaultUrl, const std::string& baseUrl) { 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
}
/** /**
* @brief Generates a descriptive text for the NSPanel based on the given display mode and charset. * Generates a descriptive text for the NSPanel based on display mode and charset.
* *
* This function maps numeric codes for the display mode and charset to a human-readable * @param displayMode Numeric code for the NSPanel's display mode: 1 for "EU", 2 for "US", 3 for "US Landscape".
* description of an NSPanel configuration. It supports different geographic regions and language * @param charset Numeric code for the character set: 1 for "International (original)", 2 for "CJK languages".
* character sets. If the inputs do not match any predefined configuration, the function returns * @return A string describing the NSPanel configuration, or an empty string if inputs don't match any configuration.
* 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) { 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;
}
} // namespace nspanel_ha_blueprint_upload_tft } // namespace nspanel_ha_blueprint_upload_tft

View File

@@ -176,7 +176,7 @@ time:
then: then:
- lambda: |- - lambda: |-
ESP_LOGD("time.on_time_sync", "System clock synchronized"); 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(); refresh_datetime->execute();
json: # Can be replaced by web_server json: # Can be replaced by web_server