#pragma once #include #include #include #include #include #include #include #include #include #include #include "esp_err.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/task.h" class Dali; class DaliComm; namespace gateway { struct DaliTransportHooks { std::function send; std::function(size_t len, uint32_t timeout_ms)> read; std::function(const uint8_t* data, size_t len)> transact; std::function delay; }; struct DaliHardwareBusConfig { uint8_t channel_index{0}; uint8_t gateway_id{0}; uint8_t bus_id{0}; uint8_t tx_pin{0}; uint8_t rx_pin{0}; uint32_t baudrate{1200}; std::string name{"gateway"}; }; struct DaliSerialBusConfig { uint8_t channel_index{0}; uint8_t gateway_id{0}; int uart_port{1}; int tx_pin{0}; int rx_pin{1}; uint32_t baudrate{9600}; size_t rx_buffer_size{256}; size_t tx_buffer_size{256}; uint32_t query_timeout_ms{500}; std::string name{"gateway"}; }; struct DaliChannelConfig { uint8_t channel_index{0}; uint8_t gateway_id{0}; std::string name{"gateway"}; }; enum class DaliPhyKind { kCustom, kNativeHardware, kSerialUart, }; struct DaliChannelInfo { uint8_t channel_index{0}; uint8_t gateway_id{0}; DaliPhyKind phy_kind{DaliPhyKind::kCustom}; std::string name; }; struct DaliRawFrame { uint8_t channel_index{0}; uint8_t gateway_id{0}; DaliPhyKind phy_kind{DaliPhyKind::kCustom}; std::vector data; }; enum class DaliDt8SceneColorMode { kDisabled, kColorTemperature, kRgb, }; struct DaliDomainSnapshot { uint8_t gateway_id{0}; int address{0}; std::string kind; std::map bools; std::map ints; std::map numbers; std::map> int_arrays; std::map> number_arrays; }; struct DaliAddressSettingsSnapshot { std::optional power_on_level; std::optional system_failure_level; std::optional min_level; std::optional max_level; std::optional fade_time; std::optional fade_rate; bool anyKnown() const { return power_on_level.has_value() || system_failure_level.has_value() || min_level.has_value() || max_level.has_value() || fade_time.has_value() || fade_rate.has_value(); } }; class DaliDomainService { public: DaliDomainService(); ~DaliDomainService(); bool bindTransport(const DaliChannelConfig& config, DaliTransportHooks hooks); esp_err_t bindHardwareBus(const DaliHardwareBusConfig& config); esp_err_t bindSerialBus(const DaliSerialBusConfig& config); bool isBound() const; bool isHardwareBound(uint8_t gateway_id) const; const char* implementationName() const; size_t channelCount() const; std::vector channelInfo() const; void addRawFrameSink(std::function sink); bool resetBus(uint8_t gateway_id) const; bool writeBridgeFrame(uint8_t gateway_id, const uint8_t* data, size_t len) const; std::vector transactBridgeFrame(uint8_t gateway_id, const uint8_t* data, size_t len) const; bool sendRaw(uint8_t gateway_id, uint8_t raw_addr, uint8_t command) const; bool sendExtRaw(uint8_t gateway_id, uint8_t raw_addr, uint8_t command) const; std::optional queryRaw(uint8_t gateway_id, uint8_t raw_addr, uint8_t command) const; std::optional discoverDeviceTypes( uint8_t gateway_id, int short_address, const std::vector& fallback_types = {}, int max_next_types = 16) const; std::optional dt4Snapshot(uint8_t gateway_id, int short_address) const; std::optional dt5Snapshot(uint8_t gateway_id, int short_address) const; std::optional dt6Snapshot(uint8_t gateway_id, int short_address) const; std::optional dt8SceneColorReport(uint8_t gateway_id, int short_address, int scene) const; std::optional dt8PowerOnLevelColorReport(uint8_t gateway_id, int short_address) const; std::optional dt8SystemFailureLevelColorReport(uint8_t gateway_id, int short_address) const; bool storeDt8SceneSnapshot(uint8_t gateway_id, int short_address, int scene, int brightness, DaliDt8SceneColorMode color_mode = DaliDt8SceneColorMode::kDisabled, int color_temperature = 0, int red = 0, int green = 0, int blue = 0) const; bool storeDt8PowerOnLevelSnapshot(uint8_t gateway_id, int short_address, int level) const; bool storeDt8SystemFailureLevelSnapshot(uint8_t gateway_id, int short_address, int level) const; bool setBright(uint8_t gateway_id, int short_address, int brightness) const; bool setColTempRaw(uint8_t gateway_id, int short_address, int mirek) const; bool setColTemp(uint8_t gateway_id, int short_address, int kelvin) const; bool setColourRaw(uint8_t gateway_id, int raw_addr, int x, int y) const; bool setColourRGB(uint8_t gateway_id, int short_address, int r, int g, int b) const; bool on(uint8_t gateway_id, int short_address) const; bool off(uint8_t gateway_id, int short_address) const; bool off(int short_address) const; std::optional queryGroupMask(uint8_t gateway_id, int short_address) const; std::optional querySceneLevel(uint8_t gateway_id, int short_address, int scene) const; std::optional queryAddressSettings(uint8_t gateway_id, int short_address) const; bool applyGroupMask(uint8_t gateway_id, int short_address, uint16_t group_mask) const; bool applySceneLevel(uint8_t gateway_id, int short_address, int scene, std::optional level) const; bool applyAddressSettings(uint8_t gateway_id, int short_address, const DaliAddressSettingsSnapshot& settings) const; bool updateChannelName(uint8_t gateway_id, std::string_view name); bool allocateAllAddr(uint8_t gateway_id, int start_address = 0) const; void stopAllocAddr(uint8_t gateway_id) const; bool resetAndAllocAddr(uint8_t gateway_id, int start_address = 0, bool remove_addr_first = false, bool close_light = false) const; bool isAllocAddr(uint8_t gateway_id) const; int lastAllocAddr(uint8_t gateway_id) const; private: struct DaliChannel; DaliChannel* findChannelByGateway(uint8_t gateway_id); const DaliChannel* findChannelByGateway(uint8_t gateway_id) const; DaliChannel* findChannelByIndex(uint8_t channel_index); const DaliChannel* findChannelByHardwareBus(uint8_t bus_id) const; bool hasSerialPort(int uart_port) const; esp_err_t startSerialRxTask(DaliChannel& channel); static void SerialRxTaskEntry(void* arg); void serialRxTaskLoop(DaliChannel* channel); esp_err_t startRawFrameTask(); static void RawFrameTaskEntry(void* arg); void rawFrameTaskLoop(); void notifyRawFrameSinks(const DaliRawFrame& frame); std::vector> channels_; std::vector> raw_frame_sinks_; SemaphoreHandle_t raw_frame_sink_lock_{nullptr}; TaskHandle_t raw_frame_task_handle_{nullptr}; }; } // namespace gateway