/// <summary> /// If any variable values are received from FS, send to subscribed clients /// </summary> /// <param name="sender">FSConnector instance</param> /// <param name="e">SimVarRequestResult containing requested valiable, unit and value</param> private void MessageReceived(object sender, SimVarRequestResult e) { try { var lastRequest = requestResults.SingleOrDefault(x => x.Request.Name == e.Request.Name && x.Request.Unit == e.Request.Unit); // Only send value to client if values is different from last value sent, or we configured to alsways send value if (lastRequest != null && ((lastRequest.Value == null && e.Value != null) || !lastRequest.Value.Equals(e.Value) || AlwaysSendVariable)) { // Request has changed value or we are forcing retransmission - send to SockListener, for retransmission to remote clients lock (requestResults) { // Update our local list to the latest value requestResults[requestResults.IndexOf(lastRequest)].Value = e.Value; } WriteLog(this, new LogMessage { Message = string.Format("Value Received: {0} - {1} ({2}) = {3}", e.Request.ID, e.Request.Name, e.Request.Unit, e.Value), Type = LogEventLevel.Information }); // Send this variable to Socket Listener to retransmit values to Remote Clients listener.SendVariable(e); } } catch (Exception ex) { WriteLog(ex); } }
/// <summary> /// SimVar result updated, find any subscribed clients and send, if value has changed or send is forced /// </summary> /// <param name="result">Latest value for a SimVar Request</param> /// <param name="forceSend">Should value always sent, even if value is unchanged?</param> public void SendVariable(SimVarRequestResult result, bool forceSend = false) { // Find any Clients requesting this variable and send latest result to them if (latestValues.Any(x => x.Request.Name == result.Request.Name && x.Request.Unit == result.Request.Unit)) { if (forceSend || latestValues.Any(x => x.Request.Name == result.Request.Name && x.Request.Unit == result.Request.Unit && x.Value != result.Value)) { // Value has been changed - rmember latest value and send to all subscribed clients latestValues.Single(x => x.Request.Name == result.Request.Name && x.Request.Unit == result.Request.Unit).Value = result.Value; var clientResponse = new ClientRequestResult { Request = new RemoteCockpitClasses.ClientRequest { Name = result.Request.Name, Unit = result.Request.Unit }, Result = result.Value }; var subscribedClients = clients.Where(x => x.Requests.Any(y => y.Name == result.Request.Name && y.Unit == result.Request.Unit)); var resultString = JsonConvert.SerializeObject(clientResponse) + "\r\r"; foreach (var client in subscribedClients) { WriteLog(string.Format("Sending Value: Client: {0}; Name: {1}; Value: {2}", client.Client.ConnectionID, result.Request.Name, result.Value)); try { client.Client.workSocket.Send(Encoding.UTF8.GetBytes(resultString)); } catch//(Exception ex) { // Often happens if the connection is dropped - should be removed from subscribedClients list } } } } }
/// <summary> /// Client connection request received /// </summary> /// <param name="sender">Connection Handler</param> /// <param name="e">Connection Request</param> private void ClientConnect(object sender, StateObject e) { try { // New client connection - always send current FS CONNECTION value var currentConnection = requestResults.SingleOrDefault(x => x.Request.Name == "FS CONNECTION" && x.Request.Unit == "bool"); if (currentConnection != null) { listener.SendVariable(currentConnection, true); } // Fetch the current Update Frequency currentConnection = new SimVarRequestResult { Request = new SimVarRequest { Name = "UPDATE FREQUENCY", Unit = "millisecond" }, Value = _updateFrequency }; if (currentConnection != null) { listener.SendVariable(currentConnection, true); } } catch (Exception ex) { WriteLog(ex); } }
/// <summary> /// Process SinVar result from MSFS2020 /// </summary> /// <param name="sender">SimConnect</param> /// <param name="data">SimVariable value</param> void Sim_Data(object sender, SIMCONNECT_RECV_SIMOBJECT_DATA_BYTYPE data) { var request = simVarRequests.SingleOrDefault(x => (int)x.ReqID == (int)data.dwRequestID); if (request != null && data?.dwData?.Length > 0 && DataReceived != null) { var result = new SimVarRequestResult { Request = request, Value = data.dwData[0] is SimVarString ? ((SimVarString)data.dwData[0]).Value : data.dwData[0] }; DataReceived.DynamicInvoke(this, result); } }
/// <summary> /// Notification of when FS is connected/disconnected /// </summary> /// <param name="sender">FSConnector instance</param> /// <param name="connected">True = Connected; False = Disconnected;</param> private void ConnectionStateChanged(object sender, bool connected) { try { var connectionChanged = new SimVarRequestResult { Request = new SimVarRequest { Name = "FS CONNECTION", Unit = "bool" }, Value = connected }; MessageReceived(this, connectionChanged); } catch (Exception ex) { WriteLog(ex); } }