using System; using System.Threading.Tasks; using NativeWebSocket; using UnityEngine; public class WebSocketService { /// /// Constructor initializes WebSocket /// /// websocket url to Amazon Transcribe public WebSocketService(string url, WebSocketOpenEventHandler onOpen = null, WebSocketCloseEventHandler onClose = null, MessageCompleteEventHandler onMessageComplete = null) { _websocket = new WebSocket(url); _websocket.OnOpen += () => { Debug.Log("[WebSocketService] Connection Open"); }; _websocket.OnError += (e) => { Debug.Log($"[WebSocketService] Connection Error. {e}"); }; _websocket.OnClose += (e) => { Debug.Log($"[WebSocketService] Connection Close. {e}"); }; _websocket.OnMessage += HandleMessage; if (onOpen != null) { _websocket.OnOpen += onOpen; } if (onClose != null) { _websocket.OnClose += onClose; } if (onMessageComplete != null) { this.OnMessageComplete += onMessageComplete; } } public delegate void MessageCompleteEventHandler(WebSocketEventArgs args); public event MessageCompleteEventHandler OnMessageComplete; private WebSocket _websocket; private bool _IsOpen { get { return _websocket != null && _websocket.State == WebSocketState.Open; } } public async Task Connect() { await _websocket.Connect(); } public async Task Send(byte[] payload) { if (_IsOpen) { await _websocket.Send(payload); } } public void Update() { if (_websocket != null) { #if !UNITY_WEBGL || UNITY_EDITOR _websocket.DispatchMessageQueue(); #endif } } public void Reset() { if (_IsOpen) { _websocket.OnMessage -= HandleMessage; } } public async Task Dispose() { if (_IsOpen) { _websocket.OnMessage -= HandleMessage; await _websocket.Close(); } } /// /// Parses the payload response from Amazon Transcribe /// /// byte array payload private void HandleMessage(byte[] bytes) { //First 8 bytes are the prelude with info about header lengths and total length. byte[] totalByteLengthBytes = new byte[4]; Array.Copy(bytes, totalByteLengthBytes, 4); if (BitConverter.IsLittleEndian) { Array.Reverse(totalByteLengthBytes); } //an int32 is 4 bytes int totalByteLength = BitConverter.ToInt32(totalByteLengthBytes, 0); byte[] headersByteLengthBytes = new byte[4]; Array.Copy(bytes, 4, headersByteLengthBytes, 0, 4); if (BitConverter.IsLittleEndian) { Array.Reverse(headersByteLengthBytes); } int headersByteLength = BitConverter.ToInt32(headersByteLengthBytes, 0); //Use the prelude to get the offset of the message. int offset = headersByteLength + 12; //Message length is everything but the headers, CRCs, and prelude. int payloadLength = totalByteLength - (headersByteLength + 16); byte[] payload = new byte[payloadLength]; Array.Copy(bytes, offset, payload, 0, payloadLength); string message = System.Text.Encoding.UTF8.GetString(payload); //Convert the message to and object so we can easily get the results. if (!string.IsNullOrEmpty(message)) { TranslateWebsocketMessage jsonMessage = JsonUtility.FromJson(message); // invoke event to send message to other resources OnMessageComplete?.Invoke(new WebSocketEventArgs(jsonMessage)); } } } public class WebSocketEventArgs : EventArgs { public WebSocketEventArgs(IWebSocketMessage message) { this.message = message; } public IWebSocketMessage message; }