/// <summary> /// Return the Oee Kpi scale factor to the display time span. /// Oee are percentage values and do not require scaling. /// Kpi are scaled to common time span. /// </summary> private double OeeKpiScaleFactor(ContosoPerformanceRelevance relevance, TimeSpan interval, TimeSpan scaledInterval) { switch (relevance) { case ContosoPerformanceRelevance.Kpi1: case ContosoPerformanceRelevance.Kpi2: return(scaledInterval.TotalSeconds / interval.TotalSeconds); case ContosoPerformanceRelevance.OeeQuality: case ContosoPerformanceRelevance.OeePerformance: case ContosoPerformanceRelevance.OeeAvailability: case ContosoPerformanceRelevance.OeeOverall: return(1.0); } throw new Exception("Invalid Performance Relevance"); }
/// <summary> /// Get the relevant Oee Kpi data item. /// </summary> private ContosoDataItem GetData(ContosoAggregatedOeeKpiTimeSpan oeeKpi, ContosoPerformanceRelevance relevance) { switch (relevance) { case ContosoPerformanceRelevance.Kpi1: return(oeeKpi.Kpi1); case ContosoPerformanceRelevance.Kpi2: return(oeeKpi.Kpi2); case ContosoPerformanceRelevance.OeeQuality: return(oeeKpi.OeeQuality); case ContosoPerformanceRelevance.OeePerformance: return(oeeKpi.OeePerformance); case ContosoPerformanceRelevance.OeeAvailability: return(oeeKpi.OeeAvailability); case ContosoPerformanceRelevance.OeeOverall: return(oeeKpi.OeeOverall); } throw new Exception("Invalid Performance Relevance"); }
/// <summary> /// Return the time series for a relevance /// </summary> public AggregatedTimeSeriesResult AggregatedOeeKpiTimeSeries(AggregationView aggregationView, ContosoPerformanceRelevance relevance, TimeSpan scaledTimeSpan) { int aggregateIndex = (int)aggregationView; int count = Aggregations[aggregateIndex].Intervals.Count; AggregatedTimeSeriesResult result = new AggregatedTimeSeriesResult(count, Aggregations[aggregateIndex].EndTime, Aggregations[aggregateIndex].IntervalTimeSpan); double scaleFactor = 100.0 * OeeKpiScaleFactor(relevance, Aggregations[aggregateIndex].IntervalTimeSpan, scaledTimeSpan); for (int i = 0; i < count; i++) { result.YValues[count - i - 1] = Math.Round(scaleFactor * GetData(Aggregations[aggregateIndex].Intervals[i], relevance).Value) / 100.0; } return(result); }
public string GetOeeKpiData(string key, ContosoTopologyNode.AggregationView view, ContosoPerformanceRelevance relevance) { AggregatedTimeSeriesResult timeSeries; ContosoTopologyNode node = (ContosoTopologyNode)Startup.Topology[key]; if (node == null) { return(JsonConvert.SerializeObject("Error")); } else { timeSeries = node.AggregatedOeeKpiTimeSeries(view, relevance, TimeSpan.FromHours(1)); } return(JsonConvert.SerializeObject(timeSeries)); }
/// <summary> /// Ctor of the node using topology description data. /// </summary> /// <param name="stationDescription">The topology description for the station.</param> public Station(StationDescription stationDescription) : base(stationDescription.OpcUri, stationDescription.Name, stationDescription.Description, stationDescription) { // List of node relevances. List <ContosoPerformanceRelevance> opcUaNodeRelevances = null; foreach (var opcNode in stationDescription.OpcNodes) { // Initialize relevance and alerts. opcUaNodeRelevances = null; // Initialize relevance of the OPC UA node. This will be used to detect, when dashboard values needs to be udpated. if (opcNode.Relevance != null && opcNode.Relevance.Count > 0) { opcUaNodeRelevances = new List <ContosoPerformanceRelevance>(); ContosoPerformanceRelevance relevance = ContosoPerformanceRelevance.NotRelevant; foreach (var relevanceDescription in opcNode.Relevance) { switch (relevanceDescription) { case "OeeOverall": case "OeeAvailability": case "OeePerformance": case "OeeQuality": throw new Exception(string.Format("The node '{0}' in Station wit URI '{1}' shows '{2}' relevance. This is not allowed since this tag is used for internal processing only. Pllease change.", opcNode.NodeId, Key, relevanceDescription)); case "OeeAvailability_Running": case "OeeAvailability_Fault": case "OeeAvailability_Station_Running": case "OeeAvailability_Station_Fault": if (stationDescription.OeeAvailability == null) { throw new Exception(string.Format("The node '{0}' in Station wit URI '{1}' shows '{2}' relevance, but there are no performance settings for 'OeeAvailability' defined for the Station. Please change.", opcNode.NodeId, Key, relevanceDescription)); } goto case "SetRelevanceOperation"; case "OeePerformance_Ideal": case "OeePerformance_Actual": if (stationDescription.OeePerformance == null) { throw new Exception(string.Format("The node '{0}' in Station wit URI '{1}' shows '{2}' relevance, but there are no performance settings for 'OeePerformance' defined for the Station. Please change.", opcNode.NodeId, Key, relevanceDescription)); } goto case "SetRelevanceOperation"; case "OeeQuality_Good": case "OeeQuality_Bad": case "OeeQuality_Station_Good": case "OeeQuality_Station_Bad": if (stationDescription.OeeQuality == null) { throw new Exception(string.Format("The node '{0}' in Station wit URI '{1}' shows '{2}' relevance, but there are no performance settings for 'OeeQuality' defined for the Station. Please change.", opcNode.NodeId, Key, relevanceDescription)); } goto case "SetRelevanceOperation"; case "Kpi1": case "Kpi1_Station": if (stationDescription.Kpi1 == null) { throw new Exception(string.Format("The node '{0}' in Station wit URI '{1}' shows '{2}' relevance, but there are no performance settings for 'Kpi1' defined for the Station. Please change.", opcNode.NodeId, Key, relevanceDescription)); } goto case "SetRelevanceOperation"; case "Kpi2": if (stationDescription.Kpi2 == null) { throw new Exception(string.Format("The node '{0}' in Station wit URI '{1}' shows '{2}' relevance, but there are no performance settings for 'Kpi2' defined for the Station. Please change.", opcNode.NodeId, Key, relevanceDescription)); } goto case "SetRelevanceOperation"; default: throw new Exception(string.Format("The 'Relevance' value '{0}' in node '{1}' of Station with URI '{2}' is unknown. Please change.", relevanceDescription, opcNode.NodeId, Key)); case "SetRelevanceOperation": if (Enum.TryParse(relevanceDescription, out relevance)) { opcUaNodeRelevances.Add(relevance); } break; } } } // Add the OPC UA node to this station. AddOpcServerNode(opcNode, opcUaNodeRelevances); } }
/// <summary> /// Callback for a query to update the relevance data of a topology node. /// </summary> public void UpdateRelevanceItem(ContosoAggregatedOeeKpiTimeSpan topologyNode, ContosoPerformanceRelevance relevance, ContosoDataItem data) { switch (relevance) { case ContosoPerformanceRelevance.Kpi2: topologyNode.Kpi2.Kpi = data.Value; topologyNode.Kpi2.Time = data.Time; break; case ContosoPerformanceRelevance.Kpi1: topologyNode.Kpi1.Kpi = data.Value; topologyNode.Kpi1.Time = data.Time; break; case ContosoPerformanceRelevance.OeeQuality_Bad: topologyNode.OeeQuality.Bad = data.Value; topologyNode.OeeQuality.Time = new DateTime(Math.Max(topologyNode.OeeQuality.Time.Ticks, data.Time.Ticks), DateTimeKind.Utc); topologyNode.OeeOverall.Quality = topologyNode.OeeQuality.OeeQuality; break; case ContosoPerformanceRelevance.OeeQuality_Good: topologyNode.OeeQuality.Good = data.Value; topologyNode.OeeQuality.Time = new DateTime(Math.Max(topologyNode.OeeQuality.Time.Ticks, data.Time.Ticks), DateTimeKind.Utc); topologyNode.OeeOverall.Quality = topologyNode.OeeQuality.OeeQuality; break; case ContosoPerformanceRelevance.OeePerformance_Ideal: topologyNode.OeePerformance.IdealCycleTime = data.Value; topologyNode.OeePerformance.Time = new DateTime(Math.Max(topologyNode.OeePerformance.Time.Ticks, data.Time.Ticks), DateTimeKind.Utc); topologyNode.OeeOverall.Performance = topologyNode.OeePerformance.OeePerformance; break; case ContosoPerformanceRelevance.OeePerformance_Actual: topologyNode.OeePerformance.ActualCycleTime = data.Value; topologyNode.OeePerformance.Time = new DateTime(Math.Max(topologyNode.OeePerformance.Time.Ticks, data.Time.Ticks), DateTimeKind.Utc); topologyNode.OeeOverall.Performance = topologyNode.OeePerformance.OeePerformance; break; case ContosoPerformanceRelevance.OeeAvailability_Running: topologyNode.OeeAvailability.OverallRunningTime = data.Value; topologyNode.OeeAvailability.Time = new DateTime(Math.Max(topologyNode.OeeAvailability.Time.Ticks, data.Time.Ticks), DateTimeKind.Utc); topologyNode.OeeOverall.Availability = topologyNode.OeeAvailability.OeeAvailability; break; case ContosoPerformanceRelevance.OeeAvailability_Fault: topologyNode.OeeAvailability.OverallFaultTime = data.Value; topologyNode.OeeAvailability.Time = new DateTime(Math.Max(topologyNode.OeeAvailability.Time.Ticks, data.Time.Ticks), DateTimeKind.Utc); topologyNode.OeeOverall.Availability = topologyNode.OeeAvailability.OeeAvailability; break; } }