/// <summary> /// Listener to react when a "WebSocket closed" event occurs. /// </summary> private void OnWebSocketClose() { DebugLogs.LogWarning("[GeeoWS:OnWebSocketClose] WebSocket closed"); // Reset the Geeo Data instances connectedAgent = null; connectedViewport = null; agents.Clear(); pointsOfInterest.Clear(); // Stop the connect coroutine if still running if (webSocketConnectCoroutine != null) { Geeo.Instance.StopCoroutine(webSocketConnectCoroutine); webSocketConnectCoroutine = null; } // Stop the network check (ping) if (networkCheckPings) { webSocket.NetworkCheckStop(); } // Trigger the OnDisconnected event if any callback registered to it if (OnDisconnected != null) { OnDisconnected(); } }
/// <summary> /// GetGuestToken coroutine. (do not block the current thread while waiting for the request response) /// </summary> /// <param name="agentId">The ID to use for the agent.</param> /// <param name="viewportId">The ID to use for the viewport.</param> /// <param name="OnSuccess">The callback in case of request success.</param> /// <param name="OnError">The callback in case of request error.</param> private IEnumerator GetGuestToken_Coroutine(string agentId, string viewportId, Action <string> OnSuccess, Action <string> OnError) { // Build the "get guest token" request URL string requestUrl = string.Format(getGuestToken_requestUrlFormat, httpUrl, agentId, viewportId); DebugLogs.LogVerbose("[GeeoHTTP:GetGuestToken] Request URL (GET): " + requestUrl); // Send the request with the GET method using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(requestUrl)) { yield return(unityWebRequest.Send()); // If the request failed, call the error callback if (unityWebRequest.isError) { GetGuestToken_OnError(unityWebRequest.error, OnError); } else { // If the request failed, call the error callback if (unityWebRequest.responseCode != 200L) { GetGuestToken_OnError(unityWebRequest.downloadHandler.text, OnError); } // If the request succeeded, call the success callback else { DebugLogs.LogVerbose("[GeeoHTTP:GetGuestToken] Request Success: " + unityWebRequest.downloadHandler.text); OnSuccess(unityWebRequest.downloadHandler.text); } } } }
/// <summary> /// Listener to react when a "WebSocket error" event occurs. /// </summary> /// <param name="error">The error's message.</param> private void OnWebSocketError(string error) { DebugLogs.LogError("[GeeoWS:OnWebSocketError] WebSocket error ›› " + error); // Trigger the OnError event if any callback registered to it if (OnError != null) { OnError(error); } }
/// <summary> /// Register the singleton instance at Awake. /// </summary> protected virtual void Awake() { if (instance == null) { instance = this; } else { DebugLogs.LogError("[MonoSingleton:Awake] Found more than one instance of " + this.GetType().Name + " ›› Destroying the last one"); Destroy(this); } }
/// <summary> /// Listener to react when a "WebSocket opened" event occurs. /// </summary> private void OnWebSocketOpen() { DebugLogs.LogVerbose("[GeeoWS:OnWebSocketOpen] WebSocket opened"); // Create new Geeo Data instances connectedAgent = new Agent(); connectedViewport = new Viewport(); // Trigger the OnConnected event if any callback registered to it if (OnConnected != null) { OnConnected(); } }
/// <summary> /// Use a JWT WebSocket token previously provided by the Geeo server to open a WebSocket connection. /// If development routes are allowed, you may use the GeeoHTTP.GetGuestToken() method to get a token. /// Once the connection is opened, the OnConnected event will be triggered (so you should register a callback to it). /// </summary> /// <param name="wsToken">The JWT WebSocket token previously provided by the Geeo server.</param> public void Connect(string wsToken) { DebugLogs.LogVerbose("[GeeoWS:Connect] Connecting..."); // Keep the token used to connect the WebSocket lastWsToken = wsToken; // Register listeners for future WebSocket events webSocket.OnOpen += OnWebSocketOpen; webSocket.OnClose += OnWebSocketClose; webSocket.OnError += OnWebSocketError; webSocket.OnMessage += OnWebSocketMessage; // Create a WebSocket and connect to the Geeo server webSocketConnectCoroutine = Geeo.Instance.StartCoroutine(WebSocketConnect(wsToken)); }
/// <summary> /// Handle an "error report" type received WebSocket message from the Geeo server to report an error. /// </summary> /// <param name="errorData">Received message data about an error.</param> private void WebSocketMessage_ErrorReport(ErrorJson errorData) { DebugLogs.LogError("[GeeoWS:WebSocketMessage_ErrorReport] Server error: " + errorData); // Trigger the OnError event if any callback registered to it if (OnError != null) { if (errorData.message != null) { OnError(errorData.error + " ›› " + errorData.message); } else { OnError(errorData.error); } } }
/// <summary> /// Connect the WebSocket with a token previously provided by the Geeo server. /// </summary> /// <param name="wsToken">The WebSocket token provided by the Geeo server.</param> private IEnumerator WebSocketConnect(string wsToken) { // Build the "websocket connect" request URL string requestUrl = string.Format(webSocketConnect_requestUrlFormat, wsUrl, wsToken); DebugLogs.LogVerbose("[GeeoWS:WebSocketConnect] Request URL: " + requestUrl); // Wait for the connection to be established yield return(webSocket.Connect(requestUrl)); // Start the network check (ping) if (networkCheckPings) { webSocket.NetworkCheckStart(); } webSocketConnectCoroutine = null; }
/// <summary> /// Remove the last used WebSocket token and registered listeners, then close the current WebSocket connection. /// Once the connection is closed, the OnDisconnected event will be triggered (so you should register a callback to it). /// </summary> public void Disconnect() { DebugLogs.LogVerbose("[GeeoWS:Disconnect] Disconnecting..."); // Unvalidate the last used WebSocket token lastWsToken = null; // Unregister listeners for future WebSocket events webSocket.OnOpen -= OnWebSocketOpen; webSocket.OnError -= OnWebSocketError; webSocket.OnMessage -= OnWebSocketMessage; // Disconnect from the Geeo server WebSocketClose(); // Unregister the OnClose listener only after the close call to get this event triggered webSocket.OnClose -= OnWebSocketClose; }
/// <summary> /// If the user leaves the application and this option is enabled, close the WebSocket to avoid useless data transfers. /// When the user comes back, try to connect to the Geeo server again with the last used WebSocket token. /// </summary> /// <param name="paused">If the application lost the focus.</param> internal void OnApplicationPause(bool paused) { // Check if the "disconnect on application pause" option is enabled if (disconnectOnApplicationPause) { // User leaves the application (close the WebSocket connection but keep the WebSocket token to connect again later) if (paused && webSocket.isConnected) { DebugLogs.LogWarning("[GeeoWS:OnApplicationPause] Application paused ›› Closing connection..."); WebSocketClose(); } // User resumes the application and there is a stored WebSocket token (try to connect the WebSocket again) else if (!paused && !string.IsNullOrEmpty(lastWsToken)) { DebugLogs.LogWarning("[GeeoWS:OnApplicationPause] Application resumed ›› Reopening connection..."); webSocketConnectCoroutine = Geeo.Instance.StartCoroutine(WebSocketConnect(lastWsToken)); } } }
/// <summary> /// Listener to react when a "WebSocket message" event occurs. /// </summary> /// <param name="message">The received message.</param> private void OnWebSocketMessage(string message) { DebugLogs.LogVerbose("[GeeoWS:OnWebSocketMessage] WebSocket message ›› " + message); // Parse Json data from the received WebSocket message from the Geeo server JsonData messageJson = JsonMapper.ToObject(message); // Check if messageJson is an "error" type object if (messageJson.IsObject) { WebSocketMessage_ErrorReport(JsonMapper.ToObject <ErrorJson>(message)); } // Check if messageJson is an "view update" type array else if (messageJson.IsArray) { // Identify each "update" of the array from the "view update" message foreach (JsonData messageUpdate in messageJson) { // Update type: agent data if (messageUpdate.Keys.Contains("agent_id")) { WebSocketMessage_AgentUpdate(JsonMapper.ToObject <AgentJson>(messageUpdate.ToJson())); } // Update type: point of interest data else if (messageUpdate.Keys.Contains("poi_id")) { WebSocketMessage_PointOfInterestUpdate(JsonMapper.ToObject <PointOfInterestJson>(messageUpdate.ToJson())); } } // Trigger the OnViewUpdated event if any callback registered to it if (OnViewUpdated != null) { OnViewUpdated(); } } }
/// <summary> /// Handle a "point of interest update" type received WebSocket message from the Geeo server to update the points of interest list. /// </summary> /// <param name="pointOfInterestData">Received message data about a point of interest.</param> private void WebSocketMessage_PointOfInterestUpdate(PointOfInterestJson pointOfInterestData) { PointOfInterest pointOfInterest; // If the point of interest just entered the viewport if (pointOfInterestData.entered) { // If the point of interest already exists in the points of interest list, just ignore this update if (pointsOfInterest.ContainsKey(pointOfInterestData.poi_id)) { DebugLogs.LogWarning("[GeeoWS:WebSocketMessage_PointOfInterestUpdate] Point of interest ‘" + pointOfInterestData.poi_id + "’ received 2 ‘entered’ updates without any ‘left’ one"); // Get the point of interest corresponding to its identifier from the points of interest list pointOfInterest = pointsOfInterest[pointOfInterestData.poi_id]; } // If the point of interest doesn't exist in the points of interest list, add this point of interest to the list else { // Create a new PointOfInterest instance and fill its data from the received message pointOfInterest = new PointOfInterest(); pointOfInterest.id = pointOfInterestData.poi_id; pointOfInterest.latitude = pointOfInterestData.pos[1]; pointOfInterest.longitude = pointOfInterestData.pos[0]; pointOfInterest.publicData = pointOfInterestData.publicData; pointOfInterest.creatorId = pointOfInterestData.creator; // Add the new point of interest to the points of interest list pointsOfInterest.Add(pointOfInterestData.poi_id, pointOfInterest); } // Trigger the OnPointOfInterestEntered event if any callback registered to it if (OnPointOfInterestEntered != null) { OnPointOfInterestEntered(pointOfInterest); } } // If the point of interest just left the viewport else if (pointOfInterestData.left) { // If the point of interest doesn't exist in the points of interest list, just ignore this update if (!pointsOfInterest.ContainsKey(pointOfInterestData.poi_id)) { DebugLogs.LogWarning("[GeeoWS:WebSocketMessage_PointOfInterestUpdate] Point of interest ‘" + pointOfInterestData.poi_id + "’ received a ‘left’ update after another ‘left’ one or no prior ‘entered’ one"); // Create a new PointOfInterest instance and fill its data from the received message pointOfInterest = new PointOfInterest(); pointOfInterest.id = pointOfInterestData.poi_id; } // If the point of interest does exist in the points of interest list, remove this point of interest from the list else { // Get the point of interest corresponding to its identifier from the points of interest list pointOfInterest = pointsOfInterest[pointOfInterestData.poi_id]; // Remove the point of interest from the points of interest list pointsOfInterest.Remove(pointOfInterestData.poi_id); } // Trigger the OnPointOfInterestLeft event if any callback registered to it if (OnPointOfInterestLeft != null) { OnPointOfInterestLeft(pointOfInterest); } } }
/// <summary> /// Handle an "agent update" type received WebSocket message from the Geeo server to update the agents list. /// </summary> /// <param name="agentData">Received message data about an agent.</param> private void WebSocketMessage_AgentUpdate(AgentJson agentData) { Agent agent; // If the agent just entered the viewport if (agentData.entered) { // If the agent already exists in the agents list, only update this agent's position if (agents.ContainsKey(agentData.agent_id)) { DebugLogs.LogWarning("[GeeoWS:WebSocketMessage_AgentUpdate] Agent ‘" + agentData.agent_id + "’ received 2 ‘entered’ updates without any ‘left’ one"); // Get the agent corresponding to its identifier from the agents list agent = agents[agentData.agent_id]; // Update agent's data from the received message agent.latitude = agentData.pos[1]; agent.longitude = agentData.pos[0]; } // If the agent doesn't exist in the agents list, add this agent to the list else { // Create a new Agent instance and fill its data from the received message agent = new Agent(); agent.id = agentData.agent_id; agent.latitude = agentData.pos[1]; agent.longitude = agentData.pos[0]; agent.publicData = agentData.publicData; // Add the new agent to the agents list agents.Add(agentData.agent_id, agent); } // Trigger the OnAgentEntered event if any callback registered to it if (OnAgentEntered != null) { OnAgentEntered(agent); } } // If the agent just left the viewport else if (agentData.left) { // If the agent doesn't exist in the agents list, just ignore this update if (!agents.ContainsKey(agentData.agent_id)) { DebugLogs.LogWarning("[GeeoWS:WebSocketMessage_AgentUpdate] Agent ‘" + agentData.agent_id + "’ received a ‘left’ update after another ‘left’ one or no prior ‘entered’ one"); // Create a new Agent instance and fill its data from the received message agent = new Agent(); agent.id = agentData.agent_id; } // If the agent does exist in the agents list, remove this agent from the list else { // Get the agent corresponding to its identifier from the agents list agent = agents[agentData.agent_id]; // Remove the agent from the agents list agents.Remove(agentData.agent_id); } // Trigger the OnAgentLeft event if any callback registered to it if (OnAgentLeft != null) { OnAgentLeft(agent); } } // If the agent just moved in the viewport else { // If the agent doesn't exist in the agents list, add this agent to the list if (!agents.ContainsKey(agentData.agent_id)) { DebugLogs.LogWarning("[GeeoWS:WebSocketMessage_AgentUpdate] Agent ‘" + agentData.agent_id + "’ received a ‘moved’ update without any prior ‘entered’ one"); // Create a new Agent instance and fill its data from the received message agent = new Agent(); agent.id = agentData.agent_id; agent.latitude = agentData.pos[1]; agent.longitude = agentData.pos[0]; // Add the new agent to the agents list agents.Add(agentData.agent_id, agent); } // If the agent does exist in the agents list, update this agent's position else { // Get the agent corresponding to its identifier from the agents list agent = agents[agentData.agent_id]; // Update agent's data from the received message agent.latitude = agentData.pos[1]; agent.longitude = agentData.pos[0]; } // Trigger the OnAgentMoved event if any callback registered to it if (OnAgentMoved != null) { OnAgentMoved(agent); } } }
/// <summary> /// Close the WebSocket when application is killed. /// </summary> internal void OnApplicationQuit() { DebugLogs.LogWarning("[GeeoWS:OnApplicationQuit] Application quit ›› Closing connection..."); WebSocketClose(); }
/// <summary> /// Error callback for the GetGuestToken request. /// </summary> /// <param name="error">Error description.</param> /// <param name="OnError">The callback in case of request error.</param> private void GetGuestToken_OnError(string error, Action <string> OnError) { DebugLogs.LogError("[GeeoHTTP:GetGuestToken] Request Error: " + error); OnError(error); }