/// <summary> /// Test alert condition for nodes /// </summary> /// <param name="searchSpan"></param> /// <param name="appUri"></param> /// <param name="topologyNode"></param> /// <param name="node"></param> public async Task <ContosoPerformanceStatus> CheckAlert(DateTimeRange searchSpan, string appUri, ContosoTopologyNode topologyNode, ContosoOpcUaNode node) { double value = await _opcUaQueries.GetLatestQuery(searchSpan.To, appUri, node.NodeId); // Check for an alert condition. if (node.Minimum != null && value < node.Minimum) { // Add an alert to the server this OPC UA node belongs to. ContosoAlert alert = new ContosoAlert(ContosoAlertCause.AlertCauseValueBelowMinimum, appUri, node.NodeId, searchSpan.To); topologyNode.AddAlert(alert); node.Status = ContosoPerformanceStatus.Poor; } else if (node.Maximum != null && value > node.Maximum) { // Add an alert to the server this OPC UA node belongs to. ContosoAlert alert = new ContosoAlert(ContosoAlertCause.AlertCauseValueAboveMaximum, appUri, node.NodeId, searchSpan.To); topologyNode.AddAlert(alert); node.Status = ContosoPerformanceStatus.Poor; } else { node.Status = ContosoPerformanceStatus.Good; } return(node.Status); }
public string AlertActionExecute(long alertId, int alertActionId) { var jsonResponse = new List <object>(); try { // Lookup the alert. ContosoAlert alert = Startup.Topology.FindAlert(alertId); if (alert != null) { // Validate the action id. ContosoTopologyNode topologyNode = Startup.Topology[alert.Key] as ContosoTopologyNode; List <ContosoAlertActionDefinition> alertActions = topologyNode.GetAlertActions(alert.Cause, alert.SubKey); if (alertActions == null || alertActionId >= alertActions.Count) { Trace.TraceError($"alertActionId '{alertActionId}' is out of scope or unknown."); Response.StatusCode = 1; jsonResponse.Add(new { errorMessage = Strings.AlertIdUnknown }); } else { bool updateSessionAlerts = false; // Process the requested action. switch (alertActions[alertActionId].Type) { case ContosoAlertActionType.AcknowledgeAlert: // Update alert status. if (topologyNode.AcknowledgeAlert(alertId) == false) { Trace.TraceError( $"alertId '{alertId}' in node '{topologyNode.Key}' could not be acknowledged."); Response.StatusCode = 1; jsonResponse.Add(new { errorMessage = Strings.AlertIdUnknown }); } updateSessionAlerts = true; jsonResponse.Add(new { actionType = ContosoAlertActionType.AcknowledgeAlert }); break; case ContosoAlertActionType.CloseAlert: // Update alert status. if (topologyNode.CloseAlert(alertId) == false) { Trace.TraceError( $"alertId '{alertId}' in node '{topologyNode.Key}' could not be acknowledged."); Response.StatusCode = 1; jsonResponse.Add(new { errorMessage = Strings.AlertIdUnknown }); } updateSessionAlerts = true; jsonResponse.Add(new { actionType = ContosoAlertActionType.CloseAlert }); break; case ContosoAlertActionType.CallOpcMethod: // Validate that this is a OPC UA server. if (topologyNode.GetType() != typeof(Station)) { Trace.TraceError($"Toplogy node '{topologyNode.Key}' is not an OPC UA server. No method call possible."); Response.StatusCode = 1; jsonResponse.Add(new { errorMessage = Strings.AlertIdUnknown }); break; } // Parameter format: "<parent nodeId>, <method nodeId>, <opcua server uri>" string[] parameter = alertActions[alertActionId].Parameter.Split(','); jsonResponse.Add(new { errorMessage = CallOpcMethod(parameter[2].Trim(), parameter[0].Trim(), parameter[1].Trim()) }); break; case ContosoAlertActionType.OpenWebPage: jsonResponse.Add(new { actionType = ContosoAlertActionType.OpenWebPage }); string urlPath = alertActions[alertActionId].Parameter; jsonResponse.Add(new { url = urlPath }); break; case ContosoAlertActionType.None: default: Trace.TraceWarning($"alert type '{alertActions[alertActionId].Type}' of alert '{alertId}' resulted in no action."); break; } // Update session alerts if requested. if (updateSessionAlerts) { // Prepare the updated alert list. AlertDataUpdate[] sessionAlertDataUpdate = new AlertDataUpdate[Startup.SessionList.Count]; int sessionUpdateIndex = 0; foreach (KeyValuePair <string, DashboardModel> session in Startup.SessionList) { AlertDataUpdate sessionAlertData = new AlertDataUpdate(); string topNodeKey = session.Value.TopNode.Key; // Update the alert data. sessionAlertData.SessionId = Session.SessionID; sessionAlertData.TopNode = topNodeKey; sessionAlertData.Alerts = Startup.Topology.GetAlerts(topNodeKey); // Update the data sent to the clients. sessionAlertDataUpdate[sessionUpdateIndex] = sessionAlertData; sessionUpdateIndex++; } // Update all clients string sessionAlertDataUpdateJson = JsonConvert.SerializeObject(sessionAlertDataUpdate); if (Startup.SessionList.Count > 0 && sessionUpdateIndex > 0) { IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext <TelemetryHub>(); hubContext.Clients.All.updateSessionAlertData(sessionAlertDataUpdateJson); } } } } else { Trace.TraceError($"alertId '{alertId}' is out of scope or unknown."); Response.StatusCode = 1; jsonResponse.Add(new { errorMessage = Strings.AlertIdUnknown }); } } catch (Exception ex) { Trace.TraceError($"exception '{ex.Message}' while processing alertId '{alertId}' and alertActionId '{alertActionId}"); Response.StatusCode = 1; jsonResponse.Add(new { errorMessage = Strings.AlertIdUnknown }); } return(JsonConvert.SerializeObject(jsonResponse)); }