#pragma once #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; }; 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; 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; 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 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