#pragma once #include #include #include #include "esphome/core/component.h" #include "esphome/components/esp32_ble_server/ble_server.h" namespace esphome { namespace fastcon { class FastconController : public Component { public: FastconController() = default; void setup() override; void loop() override; void queueCommand(uint32_t light_id_, const std::vector &data); std::vector get_advertisement(uint32_t light_id_, bool is_on, float brightness, float red, float green, float blue); void clear_queue(); bool is_queue_empty() const { std::lock_guard lock(queue_mutex_); return queue_.empty(); } size_t get_queue_size() const { std::lock_guard lock(queue_mutex_); return queue_.size(); } void set_max_queue_size(size_t size) { max_queue_size_ = size; } void set_mesh_key(std::array key) { mesh_key_ = key; } void set_adv_interval_min(uint16_t val) { adv_interval_min_ = val; } void set_adv_interval_max(uint16_t val) { adv_interval_max_ = val; if (adv_interval_max_ < adv_interval_min_) { adv_interval_max_ = adv_interval_min_; } } void set_adv_duration(uint16_t val) { adv_duration_ = val; } void set_adv_gap(uint16_t val) { adv_gap_ = val; } protected: struct Command { std::vector data; uint32_t timestamp; uint8_t retries{0}; static constexpr uint8_t MAX_RETRIES = 3; }; std::queue queue_; mutable std::mutex queue_mutex_; size_t max_queue_size_{100}; enum class AdvertiseState { IDLE, ADVERTISING, GAP }; AdvertiseState adv_state_{AdvertiseState::IDLE}; uint32_t state_start_time_{0}; // Protocol implementation std::vector generate_command(uint8_t n, uint32_t light_id_, const std::vector &data, bool forward = true); std::vector single_control(uint32_t addr, const std::vector &data); std::array mesh_key_{}; uint16_t adv_interval_min_{0x20}; uint16_t adv_interval_max_{0x40}; uint16_t adv_duration_{50}; uint16_t adv_gap_{10}; static const uint16_t MANUFACTURER_DATA_ID = 0xfff0; }; } // namespace fastcon } // namespace esphome