基类
公共头文件:
#include "brookesia/service_helper/base.hpp"
概述
esp_brookesia::service::helper::Base<Derived> 是 Service Helper 体系的 CRTP 基类,为各具体 helper 提供统一的函数调用、事件订阅与 schema 校验能力。
特性
CRTP 契约约束:通过 DerivedMeta 要求派生类提供 FunctionId/EventId/get_name/get_*_schemas 等标准元信息。
统一函数调用:提供 call_function_sync 与 call_function_async,自动完成参数打包与返回值解析。
类型安全事件订阅:提供多种 subscribe_event 重载,支持按回调签名自动适配事件参数。
服务可用性检查:通过 is_available、get_function_schema、get_event_schema 快速判断和获取能力描述。
超时控制:同步调用支持在参数末尾附加 Timeout(ms),用于控制等待时长。
回调适配宏:提供 BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_*,简化服务函数注册时的参数转换样板代码。
使用方式
派生 helper 需定义函数/事件枚举和 schema,并继承 Base<Derived> 复用通用调用逻辑。
class MyHelper : public esp_brookesia::service::helper::Base<MyHelper> {
public:
enum class FunctionId { Ping };
enum class EventId { Ready };
static std::string_view get_name();
static std::vector<FunctionSchema> get_function_schemas();
static std::vector<EventSchema> get_event_schemas();
};
API 参考
Header File
Classes
-
template<typename Derived>
class Base Base class for all service helpers (CRTP)
Note: Concept check is removed from template parameter to allow CRTP pattern where Derived is incomplete. Type and method checks are performed when methods are actually used via static_assert or compiler errors.
- 模板参数
Derived – The derived class (must be a subclass of Base)
Public Functions
- template<typename EventIdType, typename Callable> inline requires (has_event_name_first_param_v< Callable > &&!has_event_items_second_param_v< Callable >) static EventRegistry
Subscribe to an event with automatic parameter extraction.
// Event with two schema parameters: (string name, double value) auto conn = subscribe_event(EventId::ValueChanged, [](const std::string &event_name, const std::string &name, double value) { std::cout << event_name << ": " << name << " = " << value << std::endl; }); // Event with no schema parameters, only event_name auto conn = subscribe_event(EventId::Ready, [](const std::string &event_name) { std::cout << event_name << " triggered!" << std::endl; }); // Using string_view for event_name auto conn = subscribe_event(EventId::StatusChanged, [](std::string_view event_name, bool status) { std::cout << event_name << ": " << (status ? "ON" : "OFF") << std::endl; });
备注
REQUIRED: First parameter must be
std::stringorstd::string_viewto receiveevent_name.备注
Second parameter must not be
EventItemMap; use the other overload for that case.备注
Remaining parameters are extracted from
EventItemMapbased on the event-schema order.备注
All non-
event_nameparameter types must satisfy theConvertibleToEventItemconcept.备注
Parameter types must match the actual
EventItemtypes in the map.- 模板参数
EventIdType – Type of the event identifier (enum)
Callable – Type of the callable object (lambda, function, std::function, etc.) Event identifier is passed as
event_id. Callable object is passed ascallback, with first parameter as event_name and remaining parameters matching the event schema order.
- 返回
EventRegistry::SignalConnection Connection object (scoped, automatically unsubscribes on destruction)
Public Static Functions
-
template<typename ReturnType>
static inline std::expected<ReturnType, std::string> process_function_result(const FunctionResult &result) Helper function to process function result and convert to expected return type.
- 参数
result – [in] Function result from service call
- 返回
std::expected containing ReturnType or error message
-
template<typename ReturnType = void, typename FunctionIdType, typename ...Args>
static inline std::expected<ReturnType, std::string> call_function_sync(FunctionIdType function_id, Args&&... args) Call a function synchronously with variadic arguments (timeout at end)
// No arguments with default timeout auto result = call_function_sync<int>(FunctionId::GetValue); // With arguments and default timeout auto result = call_function_sync<int>(FunctionId::Add, 1.0, 2.0); // With custom timeout at the end auto result = call_function_sync<int>(FunctionId::Add, 1.0, 2.0, Timeout(500));
备注
Arguments are packed into std::vector<FunctionValue> in the order provided
备注
Last argument can be Timeout(milliseconds) to specify custom timeout
备注
All non-Timeout arguments must satisfy
ConvertibleToFunctionValueconcept- 模板参数
ReturnType – Expected return type (default: void)
FunctionIdType – Type of the function identifier (enum)
Args – Types of function arguments (must be convertible to FunctionValue)
- 参数
function_id – Function identifier
args – Function arguments in order, last argument can be Timeout(ms)
- 返回
std::expected<ReturnType, std::string> Function result or error
-
template<typename FunctionIdType, typename ...Args>
static inline bool call_function_async(FunctionIdType function_id, Args&&... args) Call a function asynchronously with variadic arguments.
// No arguments call_function_async(FunctionId::GetValue); // With arguments call_function_async(FunctionId::Add, 1.0, 2.0); // With handler call_function_async(FunctionId::Add, 1.0, 2.0, [](FunctionResult &&result) { // Handle result });
备注
Arguments are packed into std::vector<FunctionValue> in the order provided
备注
All arguments (except optional FunctionResultHandler) must satisfy ConvertibleToFunctionValue concept
备注
This overload is not used when the first argument is FunctionParameterMap or boost::json::object
- 模板参数
FunctionIdType – Type of the function identifier (enum)
Args – Types of function arguments (must be convertible to FunctionValue, optionally with FunctionResultHandler at the end)
- 参数
function_id – Function identifier
args – Function arguments in order, optionally with FunctionResultHandler at the end
- 返回
true if the call was successfully submitted, false otherwise
-
template<typename EventIdType>
static inline EventRegistry::SignalConnection subscribe_event(EventIdType event_id, EventRegistry::SignalSlot slot) Subscribe to an event with a raw SignalSlot.
auto conn = subscribe_event(EventId::ValueChanged, [](const std::string &event_name, const EventItemMap &items) { // Handle event with raw items directly });
- 模板参数
EventIdType – Type of the event identifier (enum)
- 参数
event_id – Event identifier
slot – Signal slot function with signature: void(const std::string &event_name, const EventItemMap &event_items)
- 返回
EventRegistry::SignalConnection Connection object (scoped, automatically unsubscribes on destruction)
-
template<typename T>
static inline FunctionResult to_function_result(std::expected<T, std::string> &&result) Helper function to convert std::expected to FunctionResult.
- 模板参数
T – Return value type, can be void or any type convertible to FunctionValue
- 参数
result – [in] std::expected object
- 返回
FunctionResult Converted result
-
template<auto EventIdValue>
class EventMonitor Event monitor for monitoring and waiting for specific events.
// Create a monitor for WiFi GeneralEventHappened WifiHelper::EventMonitor<WifiHelper::EventId::GeneralEventHappened> monitor; monitor.start(); // ... trigger some action ... bool got_event = monitor.wait_for(std::vector<service::EventItem>{"Connected", false}, 5000); monitor.stop();
- 模板参数
EventIdValue – The specific EventId enum value to monitor
Public Functions
-
inline bool start()
Start monitoring for events.
- 返回
true if successfully started monitoring, false if already monitoring or failed
-
inline void stop()
Stop monitoring for events.
-
inline void clear()
Clear all received events.
-
inline bool wait_for(const ReceivedItmes &expected_items, uint32_t timeout_ms)
Wait for an event containing specific items.
- 参数
expected_items – The expected items to find
timeout_ms – Maximum time to wait in milliseconds
- 返回
true if matching items were received, false on timeout
-
inline bool wait_for_any(uint32_t timeout_ms)
Wait for any event to be received within a timeout period.
- 参数
timeout_ms – Maximum time to wait in milliseconds
- 返回
true if any event was received, false on timeout
-
inline size_t get_count() const
Get the number of received events.
-
inline bool has(const ReceivedItmes &expected_items) const
Check if specific items have been received.
- 参数
expected_items – The expected items to find
- 返回
true if matching items exists in received items
-
inline const std::vector<ReceivedItmes> &get_all() const
Get all received events (unfiltered)
- 返回
Copy of all received events
-
inline std::optional<ReceivedItmes> get_last() const
Get the last received event.
- 返回
std::optional containing the last received items, std::nullopt if no items were received
-
template<typename ...Args>
inline std::vector<std::tuple<Args...>> get_all() const Get received events filtered by item types and extracted as tuples.
// Get events where first item is string and second is bool auto events = monitor.get_all<std::string, bool>(); for (const auto& [str_val, bool_val] : events) { // use str_val and bool_val }
- 模板参数
Args – Expected types for each position in the event (bool, double, std::string, boost::json::object, boost::json::array, RawBuffer)
- 返回
Vector of tuples containing extracted values from matching events
-
template<typename ...Args>
inline std::optional<std::tuple<Args...>> get_last() const Get the last received event filtered by item types and extracted as tuple.
// Get last event where first item is string and second is bool auto last_event = monitor.get_last<std::string, bool>(); if (last_event.has_value()) { const auto &[event_str, is_unexpected] = last_event.value(); // Or use std::get<0>/std::get<1> const auto &event_str = std::get<0>(last_event.value()); bool is_unexpected = std::get<1>(last_event.value()); } // Get last event with single boost::json::array item auto last_scan = monitor.get_last<boost::json::array>(); if (last_scan.has_value()) { const auto &ap_infos_array = std::get<0>(last_scan.value()); }
- 模板参数
Args – Expected types for each position in the event (bool, double, std::string, boost::json::object, boost::json::array, RawBuffer)
- 返回
std::optional containing tuple of extracted values if the last event matches, std::nullopt if no events or type mismatch
-
inline bool is_running() const
Check if currently running.
- 返回
true if actively running
Macros
-
BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_0(Derived, function_id, func_call)
Create a zero-parameter function handler based on Derived and FunctionId.
- 参数
Derived – The derived class type
function_id – FunctionId enum value
func_call – Actual function call (e.g., function_get_volume())
-
BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_1(Derived, function_id, param_type, func_call)
Create a single-parameter function handler based on Derived and FunctionId.
- 参数
Derived – The derived class type
function_id – FunctionId enum value
param_type – Parameter C++ type (e.g., std::string, double)
func_call – Function call, use PARAM as parameter placeholder
-
BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_2(Derived, function_id, param1_type, param2_type, func_call)
Create a two-parameter function handler based on Derived and FunctionId.
Example: BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_2(MyService, MyService::FunctionId::Add, double, double, function_add(PARAM1, PARAM2))
- 参数
Derived – The derived class type
function_id – FunctionId enum value
param1_type – First parameter C++ type
param2_type – Second parameter C++ type
func_call – Function call, use PARAM1, PARAM2 as parameter placeholders
-
BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_3(Derived, function_id, param1_type, param2_type, param3_type, func_call)
Create a three-parameter function handler based on Derived and FunctionId.
Example: BROOKESIA_SERVICE_HELPER_FUNC_HANDLER_3(MyService, MyService::FunctionId::SetConfig, std::string, int, bool, function_set_config(PARAM1, PARAM2, PARAM3))
- 参数
Derived – The derived class type
function_id – FunctionId enum value
param1_type – First parameter C++ type
param2_type – Second parameter C++ type
param3_type – Third parameter C++ type
func_call – Function call, use PARAM1, PARAM2, PARAM3 as parameter placeholders