public void GenerateOutage(ActiveOutageBindingModel outage) { CancellationTokenSource tokenSource = new CancellationTokenSource(); CancellationToken token = tokenSource.Token; Task task = Task.Run(() => { token.ThrowIfCancellationRequested(); ScadaNotification scadaCallback = new ScadaNotification("OUTAGE_SIMULATOR", outage); SubscriberProxy scadaSubscriber = proxyFactory.CreateProxy <SubscriberProxy, ISubscriber>(scadaCallback, EndpointNames.SubscriberEndpoint); if (scadaSubscriber == null) { string message = "GenerateOutage task => SubscriberProxy is null"; Logger.LogError(message); return; } scadaSubscriber.Subscribe(Topic.SWITCH_STATUS); bool toContinue = !token.IsCancellationRequested; while (toContinue) { //TODO: OUTAGE LOGIC if (token.IsCancellationRequested) { // Clean up here scadaSubscriber.Close(); toContinue = false; //token.ThrowIfCancellationRequested(); } } }, token); outageTokenMap.Add(outage.OutageElement.GID, tokenSource); ActiveOutages.Add(outage); activeOutagesMap.Add(outage.OutageElement.GID, outage); Dispatcher.BeginInvoke((Action)(() => parent.TabControl.SelectedIndex = 0)); }
public void Dispose() { dbContext.Dispose(); subscriberProxy.Close(); }
public bool StartIsolationAlgorthm(OutageEntity outageToIsolate) { List <long> defaultIsolationPoints = outageToIsolate.DefaultIsolationPoints.Select(point => point.EquipmentId).ToList(); bool isIsolated; bool isFirstBreakerRecloser; if (defaultIsolationPoints.Count > 0 && defaultIsolationPoints.Count < 3) { long headBreaker = -1; long recloser = -1; try { isFirstBreakerRecloser = CheckIfBreakerIsRecloser(defaultIsolationPoints[0]); //TODO is second recloser (future) } catch (Exception e) { Logger.LogWarn("Exception on method CheckIfBreakerIsRecloser()", e); throw e; } GetHeadBreakerAndRecloser(defaultIsolationPoints, isFirstBreakerRecloser, ref headBreaker, ref recloser); if (headBreaker != -1) { ModelCode mc = outageModel.modelResourcesDesc.GetModelCodeFromId(headBreaker); if (mc == ModelCode.BREAKER) { long headBreakerMeasurementId, recloserMeasurementId; using (MeasurementMapProxy measurementMapProxy = proxyFactory.CreateProxy <MeasurementMapProxy, IMeasurementMapContract>(EndpointNames.MeasurementMapEndpoint)) { try { headBreakerMeasurementId = measurementMapProxy.GetMeasurementsOfElement(headBreaker)[0]; if (recloser != -1) { recloserMeasurementId = measurementMapProxy.GetMeasurementsOfElement(recloser)[0]; } else { recloserMeasurementId = -1; } } catch (Exception e) { Logger.LogError("Error on GetMeasurementsForElement() method.", e); throw e; } } Logger.LogInfo($"Head breaker id: 0x{headBreaker:X16}, recloser id: 0x{recloser:X16} (-1 if no recloser)."); //ALGORITHM AutoResetEvent autoResetEvent = new AutoResetEvent(false); CancelationObject cancelationObject = new CancelationObject() { CancelationSignal = false }; Timer timer = InitalizeAlgorthmTimer(cancelationObject, autoResetEvent); ScadaNotification scadaNotification = new ScadaNotification("OutageModel_SCADA_Subscriber", new OutageIsolationAlgorithm.OutageIsolationAlgorithmParameters(headBreakerMeasurementId, recloserMeasurementId, autoResetEvent)); SubscriberProxy subscriberProxy = proxyFactory.CreateProxy <SubscriberProxy, ISubscriber>(scadaNotification, EndpointNames.SubscriberEndpoint); subscriberProxy.Subscribe(Topic.SWITCH_STATUS); long currentBreakerId = headBreaker; while (!cancelationObject.CancelationSignal) { if (outageModel.TopologyModel.OutageTopology.ContainsKey(currentBreakerId)) { currentBreakerId = outageModel.GetNextBreaker(currentBreakerId); Logger.LogDebug($"Next breaker is 0x{currentBreakerId:X16}."); if (currentBreakerId == -1 || currentBreakerId == recloser) { //TODO: planned outage string message = "End of the feeder, no outage detected."; Logger.LogWarn(message); isIsolated = false; subscriberProxy.Close(); outageModel.commandedElements.Clear(); throw new Exception(message); } //TODO: SCADACommand SendSCADACommand(currentBreakerId, DiscreteCommandingType.OPEN); SendSCADACommand(headBreaker, DiscreteCommandingType.CLOSE); timer.Start(); Logger.LogDebug("Timer started."); autoResetEvent.WaitOne(); if (timer.Enabled) { timer.Stop(); Logger.LogDebug("Timer stoped"); SendSCADACommand(currentBreakerId, DiscreteCommandingType.CLOSE); } } } long nextBreakerId = outageModel.GetNextBreaker(currentBreakerId); if (currentBreakerId != 0 && currentBreakerId != recloser) { outageToIsolate.OptimumIsolationPoints = outageModel.GetEquipmentEntity(new List <long> { currentBreakerId, nextBreakerId }); if (!outageModel.TopologyModel.OutageTopology.ContainsKey(nextBreakerId)) { string message = $"Breaker (next breaker) with id: 0x{nextBreakerId:X16} is not in topology"; Logger.LogError(message); throw new Exception(message); } long outageElement = outageModel.TopologyModel.OutageTopology[nextBreakerId].FirstEnd; if (!outageModel.TopologyModel.OutageTopology[currentBreakerId].SecondEnd.Contains(outageElement)) { string message = $"Outage element with gid: 0x{outageElement:X16} is not on a second end of current breaker id"; Logger.LogError(message); throw new Exception(message); } //TODO: SCADA Command subscriberProxy.Close(); outageModel.optimumIsolationPoints.Add(currentBreakerId); outageModel.optimumIsolationPoints.Add(nextBreakerId); SendSCADACommand(currentBreakerId, DiscreteCommandingType.OPEN); SendSCADACommand(nextBreakerId, DiscreteCommandingType.OPEN); outageToIsolate.IsolatedTime = DateTime.UtcNow; outageToIsolate.OutageElementGid = outageElement; outageToIsolate.OutageState = OutageState.ISOLATED; Logger.LogInfo($"Isolation of outage with id {outageToIsolate.OutageId}. Optimum isolation points: 0x{currentBreakerId:X16} and 0x{nextBreakerId:X16}, and outage element id is 0x{outageElement:X16}"); isIsolated = true; } else { string message = "End of the feeder, no outage detected."; Logger.LogWarn(message); isIsolated = false; subscriberProxy.Close(); outageModel.commandedElements.Clear(); throw new Exception(message); } } else { Logger.LogWarn($"Head breaker type is {mc}, not a {ModelCode.BREAKER}."); isIsolated = false; } } else { Logger.LogWarn("Head breaker not found."); isIsolated = false; } } else { Logger.LogWarn($"Number of defaultIsolationPoints ({defaultIsolationPoints.Count}) is out of range [1, 2]."); isIsolated = false; } outageModel.commandedElements.Clear(); return(isIsolated); }