Review components files
This commit is contained in:
24
components/nspanel_ha_blueprint/ha_components.cpp
Normal file
24
components/nspanel_ha_blueprint/ha_components.cpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
21
components/nspanel_ha_blueprint/hardware.cpp
Normal file
21
components/nspanel_ha_blueprint/hardware.cpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
47
components/nspanel_ha_blueprint/nextion_components.cpp
Normal file
47
components/nspanel_ha_blueprint/nextion_components.cpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
26
components/nspanel_ha_blueprint/pages.cpp
Normal file
26
components/nspanel_ha_blueprint/pages.cpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
49
components/nspanel_ha_blueprint/text.cpp
Normal file
49
components/nspanel_ha_blueprint/text.cpp
Normal 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
|
||||
@@ -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.
|
||||
* Determines if a character is part of a numeric string. This includes digits,
|
||||
* a period (.), a minus sign (-), or a comma (,).
|
||||
*
|
||||
* @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.
|
||||
* @param c The character to check.
|
||||
* @return True if the character is part of a number; false otherwise.
|
||||
*/
|
||||
std::string adjustDecimalSeparator(const std::string& input, char decimalSeparator) {
|
||||
// Immediately return the original string if the desired decimal separator is "."
|
||||
if (decimalSeparator == '.') {
|
||||
return input;
|
||||
}
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -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 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
|
||||
|
||||
20
components/nspanel_ha_blueprint/versioning.cpp
Normal file
20
components/nspanel_ha_blueprint/versioning.cpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
28
components/nspanel_ha_blueprint_upload_tft/upload_tft.cpp
Normal file
28
components/nspanel_ha_blueprint_upload_tft/upload_tft.cpp
Normal 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
|
||||
@@ -1,4 +1,5 @@
|
||||
// upload_tft.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#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.
|
||||
*
|
||||
* @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.
|
||||
* @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.
|
||||
* 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
|
||||
* 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.
|
||||
* @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) {
|
||||
|
||||
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;
|
||||
}
|
||||
std::string getNSPanelText(int displayMode, int charset);
|
||||
|
||||
} // namespace nspanel_ha_blueprint_upload_tft
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user