#pragma once #include #include #include #include #include "esp_err.h" /** * @brief UDP client for sending commands and receiving responses * * Implements non-blocking UDP communication with configurable timeouts. * Socket remains open for the lifetime of the instance. */ class UDPClient { public: UDPClient(); ~UDPClient(); /** * @brief Initialize UDP socket * @return ESP_OK on success, error code otherwise */ esp_err_t init(); /** * @brief Configure remote endpoint * @param ip Remote IP address (e.g., "192.168.50.201") * @param port Remote port number (e.g., 4211) * @return ESP_OK on success, ESP_ERR_INVALID_ARG if IP is invalid */ esp_err_t configure(const std::string& ip, uint16_t port); /** * @brief Send command to remote endpoint * @param command Command string to send (e.g., "TOGGLE", "STATUS", "MUTE", "UNMUTE") * @return ESP_OK on success, ESP_FAIL if not configured or send failed */ esp_err_t send_command(const std::string& command); /** * @brief Receive response from remote endpoint (non-blocking) * @param response Output string for received data * @param timeout_ms Timeout in milliseconds (0 = no wait, -1 = wait forever) * @return ESP_OK on success, ESP_ERR_TIMEOUT on timeout, ESP_FAIL on error */ esp_err_t receive_response(std::string& response, int timeout_ms = 1000); /** * @brief Check if client is configured with valid endpoint * @return true if IP and port are configured */ bool is_configured() const { return configured_; } /** * @brief Get current remote IP */ std::string get_ip() const { return remote_ip_; } /** * @brief Get current remote port */ uint16_t get_port() const { return remote_port_; } /** * @brief Close socket and reset configuration */ void close(); private: int sock_fd_; // Socket file descriptor struct sockaddr_in remote_addr_; // Remote endpoint address std::string remote_ip_; // Remote IP address uint16_t remote_port_; // Remote port number bool configured_; // Whether endpoint is configured bool initialized_; // Whether socket is initialized /** * @brief Set socket to non-blocking mode * @return ESP_OK on success */ esp_err_t set_nonblocking(); };