void IUniversalDuplexContract.SendToService(DuplexMessage msg) { //We get here when we receive a message from a client IUniversalDuplexCallbackContract ch = OperationContext.Current.GetCallbackChannel <IUniversalDuplexCallbackContract>(); string session = OperationContext.Current.Channel.SessionId; //Any message from a client we haven't seen before causes the new client to be added to our list //(Basically, treated as a "Connect" message) lock (syncRoot) { if (!clients.ContainsKey(session)) { clients.Add(session, ch); OperationContext.Current.Channel.Closing += new EventHandler(Channel_Closing); OperationContext.Current.Channel.Faulted += new EventHandler(Channel_Faulted); OnConnected(session); } } //If it's a Disconnect message, treat as disconnection if (msg is DisconnectMessage) { ClientDisconnected(session); } //Otherwise, if it's a payload-carrying message (and not just a simple "Connect"), process it else if (!(msg is ConnectMessage)) { OnMessage(session, msg); } }
/// <summary> /// Pushes a message to one specific client /// </summary> /// <param name="clientSessionId">Session ID of the client that should receive the message</param> /// <param name="message">The message to push</param> protected void PushMessageToClient(string clientSessionId, DuplexMessage message) { if (clients != null && clients.ContainsKey(clientSessionId)) { IUniversalDuplexCallbackContract ch = clients[clientSessionId]; IAsyncResult iar = ch.BeginSendToClient(message, new AsyncCallback(OnPushMessageComplete), new PushMessageState(ch, clientSessionId)); if (iar.CompletedSynchronously) { CompletePushMessage(iar); } } }
public void CompletePushMessage(IAsyncResult iar) { IUniversalDuplexCallbackContract ch = ((PushMessageState)(iar.AsyncState)).ch; try { ch.EndSendToClient(iar); } catch (Exception ex) { //Any error while pushing out a message to a client //will be treated as if that client has disconnected System.Diagnostics.Debug.WriteLine(ex); ClientDisconnected(((PushMessageState)(iar.AsyncState)).sessionId); } }
/// <summary> /// Pushes a message to one specific client /// </summary> /// <param name="clientSessionId">Session ID of the client that should receive the message</param> /// <param name="message">The message to push</param> protected void PushMessageToClient(string clientSessionId, DuplexMessage message) { try //try to send message to client if it is still connected. Otherwise dont worry about it. { IUniversalDuplexCallbackContract ch = (clients[clientSessionId]).Channel; IAsyncResult iar = ch.BeginSendToClient(message, new AsyncCallback(OnPushMessageComplete), new PushMessageState(ch, clientSessionId)); if (iar.CompletedSynchronously) { CompletePushMessage(iar); } } catch { } }
internal PushMessageState(IUniversalDuplexCallbackContract channel, string session) { ch = channel; sessionId = session; }
public PushMessageState(IUniversalDuplexCallbackContract channel, string session) { Channel = channel; SessionId = session; }
public PushMessageState(IUniversalDuplexCallbackContract channel, string session) { Channel = channel; SessionId = session; }
public void SendToService(DuplexMessage msg) { //We get here when we receive a message from a client IUniversalDuplexCallbackContract ch = OperationContext.Current.GetCallbackChannel <IUniversalDuplexCallbackContract>(); string session = OperationContext.Current.Channel.SessionId; if (msg is ConnectMessage) { //lock (syncRoot) lock (clients) { if (!clients.ContainsKey(session)) // new client { System.Diagnostics.Debug.WriteLine("New client connected: "); System.Diagnostics.Debug.WriteLine(" " + (msg as ConnectMessage).NodeID); System.Diagnostics.Debug.WriteLine(" " + (msg as ConnectMessage).TimeSeriesDataRootUrl); System.Diagnostics.Debug.WriteLine(" " + (msg as ConnectMessage).CurrentDisplayType.ToString()); Client client = new Client(); client.Channel = ch; client.NodeID = (msg as ConnectMessage).NodeID; client.TimeSeriesDataRootUrl = (msg as ConnectMessage).TimeSeriesDataRootUrl; client.RealTimeStatisticRootUrl = (msg as ConnectMessage).RealTimeStatisticRootUrl; client.DataPointID = (msg as ConnectMessage).DataPointID; client.CurrentDisplayType = (msg as ConnectMessage).CurrentDisplayType; clients.Add(session, client); OperationContext.Current.Channel.Closing += Channel_Closing; OperationContext.Current.Channel.Faulted += Channel_Faulted; OnConnected(session); } else //existing connected client. Just trying to update its settings. { clients[session] = new Client() { Channel = ch, NodeID = (msg as ConnectMessage).NodeID, DataPointID = (msg as ConnectMessage).DataPointID, TimeSeriesDataRootUrl = (msg as ConnectMessage).TimeSeriesDataRootUrl, RealTimeStatisticRootUrl = (msg as ConnectMessage).RealTimeStatisticRootUrl, CurrentDisplayType = (msg as ConnectMessage).CurrentDisplayType }; } } Client currentClient = clients[session]; // Initially when client is connected, we will send them data only if client is connected from home page of the openPDCManager. if (currentClient.CurrentDisplayType == DisplayType.Home) { PushMessageToClient(session, new LivePhasorDataMessage() { //PmuDistributionList = CommonFunctions.GetPmuDistribution(), DeviceDistributionList = CommonFunctions.GetVendorDeviceDistribution(null, currentClient.NodeID), InterconnectionStatusList = CommonFunctions.GetInterconnectionStatus(null, currentClient.NodeID) } ); PushMessageToClient(session, new TimeSeriesDataMessage() { TimeSeriesData = CommonFunctions.GetTimeSeriesData(currentClient.TimeSeriesDataRootUrl + "/timeseriesdata/read/historic/" + currentClient.DataPointID.ToString() + "/*-30S/*/XML") //TimeSeriesData = CommonFunctions.GetTimeSeriesData(currentClient.TimeSeriesDataRootUrl + "current/" + currentClient.DataPointID.ToString() + "/XML") } ); } else if (currentClient.CurrentDisplayType == DisplayType.ServiceClient) { if (serviceClientList.ContainsKey(currentClient.NodeID)) { System.Diagnostics.Debug.WriteLine("Sending Cached Status to Client Connected on System Monitor Page."); PushMessageToClient(session, new ServiceUpdateMessage() { ServiceUpdateType = UpdateType.Information, ServiceUpdate = serviceClientList[currentClient.NodeID].CachedStatus }); } else { System.Diagnostics.Debug.WriteLine("Sending Empty Message to Client Connected on System Monitor Page."); PushMessageToClient(session, new ServiceUpdateMessage()); } } else if (currentClient.CurrentDisplayType == DisplayType.DeviceMeasurements) { KeyValuePair <int, int> minMaxPointID = minMaxPointIDsPerNode[currentClient.NodeID]; if (!string.IsNullOrEmpty(currentClient.TimeSeriesDataRootUrl)) // if TimeSeriesDataRootUrl is defined for the node, then only try to send data to client upon connection. { System.Diagnostics.Debug.WriteLine("Sending Measurements to Client Connected on Device Measurements Page."); PushMessageToClient(session, new TimeTaggedDataMessage() { TimeTaggedMeasurements = CommonFunctions.GetTimeTaggedMeasurements(currentClient.TimeSeriesDataRootUrl + "/timeseriesdata/read/current/" + minMaxPointID.Key.ToString() + "-" + minMaxPointID.Value.ToString() + "/XML") }); } else { System.Diagnostics.Debug.WriteLine("Sending Empty Message to Client Connected on Device Measurements Page."); PushMessageToClient(session, new TimeTaggedDataMessage()); } } else if (currentClient.CurrentDisplayType == DisplayType.RealTimeStatistics) { KeyValuePair <int, int> minMaxPointID = minMaxPointIDsPerNode[currentClient.NodeID]; if (!string.IsNullOrEmpty(currentClient.TimeSeriesDataRootUrl)) // if TimeSeriesDataRootUrl is defined for the node, then only try to send data to client upon connection. { System.Diagnostics.Debug.WriteLine("Sending Measurements to Client Connected on Device Measurements Page."); PushMessageToClient(session, new TimeTaggedDataMessage() { TimeTaggedMeasurements = CommonFunctions.GetStatisticMeasurements(currentClient.RealTimeStatisticRootUrl + "/timeseriesdata/read/current/" + minMaxPointID.Key.ToString() + "-" + minMaxPointID.Value.ToString() + "/XML", currentClient.NodeID) }); } else { System.Diagnostics.Debug.WriteLine("Sending Empty Message to Client Connected on Device Measurements Page."); PushMessageToClient(session, new TimeTaggedDataMessage()); } } } else if (msg is ServiceRequestMessage) { SendServiceRequest(clients[session].NodeID, (msg as ServiceRequestMessage).Request); } else if (msg is DisconnectMessage) //If it's a Disconnect message, treat as disconnection { ClientDisconnected(session); } else //if (!(msg is ConnectMessage)) //Otherwise, if it's a payload-carrying message (and not just a simple "Connect"), process it { OnMessage(session, msg); } }