#include "server.h" constexpr int32_t pingInterval = 10000; constexpr uint32_t pongTimeout = 5000; uint8_t disconnectTimeoutCount = 3; ServerConnection::ServerConnection() { } void ServerConnection::configure(ServerConfiguration configuration, ServerConnectionCallbacks *callbacks) { controller = callbacks; this->configuration = configuration; } void ServerConnection::connect() { if (webSocket.isConnected()) { return; } if (controller == NULL) { Serial.println("[ERROR] No callbacks set for server"); return; } isConnecting = true; Serial.printf("[INFO] Connecting to %s:%d%s\n", configuration.url, configuration.port, configuration.path); connectionTimeout = currentTime + configuration.socketHeartbeatIntervalMs; webSocket.begin(configuration.url, configuration.port, configuration.path); webSocket.setAuthorization(configuration.key); std::function f = [this](WStype_t type, uint8_t *payload, size_t length) { this->webSocketEventHandler(type, payload, length); }; webSocket.onEvent(f); webSocket.setReconnectInterval(configuration.reconnectTime); } void ServerConnection::didDisconnect() { if (shouldReconnect || isConnecting) { return; // Disconnect already registered. } Serial.println("[INFO] Socket disconnected"); nextReconnectAttemptMs = currentTime + configuration.socketHeartbeatIntervalMs; shouldReconnect = true; } void ServerConnection::didConnect() { isConnecting = false; Serial.println("[INFO] Socket connected"); webSocket.sendTXT(configuration.key); webSocket.enableHeartbeat(configuration.socketHeartbeatIntervalMs, configuration.socketHeartbeatTimeoutMs, configuration.socketHeartbeatFailureReconnectCount); } void ServerConnection::disconnect() { webSocket.disconnect(); } void ServerConnection::loop(uint32_t millis) { currentTime = millis; webSocket.loop(); if (shouldReconnect && !isConnecting) { shouldReconnect = false; connect(); } if (isConnecting && millis > connectionTimeout) { Serial.println("[INFO] Failed to connect"); disconnect(); shouldReconnect = true; isConnecting = false; } } void ServerConnection::webSocketEventHandler(WStype_t type, uint8_t * payload, size_t length) { switch(type) { case WStype_DISCONNECTED: didDisconnect(); break; case WStype_CONNECTED: didConnect(); break; case WStype_TEXT: controller->sendServerError(MessageResult::TextReceived); break; case WStype_BIN: controller->handleServerMessage(payload, length); break; case WStype_PONG: break; case WStype_PING: break; case WStype_ERROR: case WStype_FRAGMENT_TEXT_START: case WStype_FRAGMENT_BIN_START: case WStype_FRAGMENT: case WStype_FRAGMENT_FIN: Serial.printf("[WARN] Unexpected socket event %d\n", type); controller->sendServerError(MessageResult::UnexpectedSocketEvent); break; } } void ServerConnection::sendResponse(uint8_t* buffer, uint16_t length) { if (socketIsConnected()) { webSocket.sendBIN(buffer, length); } }