#pragma once #include #include #include #include #include #include #include "gateway_cache.hpp" #include "esp_err.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" namespace gateway { class DaliDomainService; struct DaliRawFrame; class GatewayRuntime; struct GatewayControllerConfig { uint32_t task_stack_size{6144}; UBaseType_t task_priority{5}; int color_temperature_min{2000}; int color_temperature_max{6500}; bool setup_supported{true}; bool ble_supported{false}; bool wifi_supported{true}; bool ip_router_supported{true}; bool internal_scene_supported{true}; bool internal_group_supported{true}; }; struct GatewayChannelSnapshot { uint8_t channel_index{0}; uint8_t gateway_id{0}; std::string name; std::string phy; uint8_t scene_mask_low{0}; uint8_t scene_mask_high{0}; uint8_t group_mask_low{0}; uint8_t group_mask_high{0}; bool allocating{false}; int last_alloc_addr{0}; }; struct GatewayControllerSnapshot { bool setup_mode{false}; bool wireless_setup_mode{false}; bool ble_enabled{false}; bool wifi_enabled{false}; bool ip_router_enabled{false}; bool internal_scene_supported{false}; bool internal_group_supported{false}; std::vector channels; }; class GatewayController { public: using NotificationSink = std::function& frame)>; using BleStateSink = std::function; using WifiStateSink = std::function; using GatewayNameSink = std::function; GatewayController(GatewayRuntime& runtime, DaliDomainService& dali_domain, GatewayCache& cache, GatewayControllerConfig config = {}); ~GatewayController(); esp_err_t start(); bool enqueueCommandFrame(const std::vector& frame); void addNotificationSink(NotificationSink sink); void addBleStateSink(BleStateSink sink); void addWifiStateSink(WifiStateSink sink); void addGatewayNameSink(GatewayNameSink sink); bool setupMode() const; bool wirelessSetupMode() const; void setWirelessSetupMode(bool enabled); bool bleEnabled() const; bool wifiEnabled() const; bool ipRouterEnabled() const; GatewayControllerSnapshot snapshot(); private: static void TaskEntry(void* arg); void taskLoop(); void dispatchCommand(const std::vector& command); bool hasGateway(uint8_t gateway_id) const; std::vector gatewayIds() const; std::string gatewayName(uint8_t gateway_id) const; void refreshRuntimeGatewayNames(); void publishPayload(uint8_t gateway_id, const std::vector& payload); void publishFrame(const std::vector& frame); void handleDaliRawFrame(const DaliRawFrame& frame); uint8_t resolveInternalGroupRawAddress(uint8_t gateway_id, uint8_t raw_addr); static uint8_t normalizeGroupTargetType(uint8_t target_type); static uint8_t normalizeGroupTargetValue(uint8_t target_type, uint8_t target_value); static uint8_t internalGroupRawTargetAddress(uint8_t target_type, uint8_t target_value, uint8_t raw_addr); static int internalGroupDecTargetAddress(uint8_t target_type, uint8_t target_value); static int shortAddressFromRaw(uint8_t raw_addr); static int reverseInRange(int value, int min_value, int max_value); bool setSceneEnabled(uint8_t gateway_id, uint8_t scene_id, bool enabled); bool setSceneDetail(uint8_t gateway_id, uint8_t scene_id, uint8_t brightness, uint8_t color_mode, uint8_t data1, uint8_t data2, uint8_t data3); bool setSceneName(uint8_t gateway_id, uint8_t scene_id, std::string_view name); bool deleteScene(uint8_t gateway_id, uint8_t scene_id); std::pair sceneMask(uint8_t gateway_id); bool executeScene(uint8_t gateway_id, int short_address, uint8_t scene_id); bool setGroupEnabled(uint8_t gateway_id, uint8_t group_id, bool enabled); bool setGroupDetail(uint8_t gateway_id, uint8_t group_id, uint8_t target_type, uint8_t target_value); bool setGroupName(uint8_t gateway_id, uint8_t group_id, std::string_view name); bool deleteGroup(uint8_t gateway_id, uint8_t group_id); std::pair groupMask(uint8_t gateway_id); bool executeGroup(uint8_t gateway_id, uint8_t group_id); void handleGatewayNameCommand(uint8_t gateway_id, const std::vector& command); void handleGatewayIdentityCommand(uint8_t gateway_id, uint8_t op); void handleAllocationCommand(uint8_t gateway_id, const std::vector& command); void handleInternalSceneCommand(uint8_t gateway_id, const std::vector& command); void handleInternalGroupCommand(uint8_t gateway_id, const std::vector& command); GatewayRuntime& runtime_; DaliDomainService& dali_domain_; GatewayCache& cache_; GatewayControllerConfig config_; TaskHandle_t task_handle_{nullptr}; std::vector notification_sinks_; std::vector ble_state_sinks_; std::vector wifi_state_sinks_; std::vector gateway_name_sinks_; bool setup_mode_{false}; bool wireless_setup_mode_{false}; bool ble_enabled_{false}; bool wifi_enabled_{false}; bool ip_router_enabled_{true}; }; } // namespace gateway