public bool SendLocationIsolationCrew(long outageId) { OutageEntity outageEntity = null; List <OutageEntity> activeOutages = null; long reportedGid = 0; bool result = false; try { outageEntity = dbContext.OutageRepository.Get(outageId); } catch (Exception ex) { Logger.LogError($"OutageModel::SendLocationIsolationCrew => exception in UnitOfWork.OutageRepository.Get()", ex); } try { activeOutages = dbContext.OutageRepository.GetAllActive().ToList(); } catch (Exception ex) { Logger.LogError("OutageModel::SendLocationIsolationCrew => excpetion in UnitOfWork.OutageRepository.GetAllActive()", ex); return(false); } if (outageEntity == null) { Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database."); return(false); } reportedGid = outageEntity.DefaultIsolationPoints.First().EquipmentId; Task algorithm = Task.Run(() => StartLocationAndIsolationAlgorithm(outageEntity)).ContinueWith(task => { result = task.Result; if (task.IsCompleted) { dbContext.Complete(); } }, TaskContinuationOptions.OnlyOnRanToCompletion).ContinueWith(task => { outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageEntity)); }, TaskContinuationOptions.OnlyOnRanToCompletion); algorithm.Wait(); return(result); }
public async Task <bool> SendLocationIsolationCrew(long outageId) { Logger.LogVerbose($"{baseLogString} SendLocationIsolationCrew method started. OutageId {outageId}"); while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } try { var result = await lifecycleHelper.GetCreatedOutage(outageId); if (!result.HasValue) { Logger.LogError($"{baseLogString} SendLocationIsolationCrew => Created Outage is null. OutageId {outageId}"); return(false); } var outageEntity = result.Value; var enumerableTopology = await OutageTopologyModel.GetEnumerableDictionaryAsync(); if (!enumerableTopology.ContainsKey(ReliableDictionaryNames.OutageTopologyModel)) { Logger.LogError($"{baseLogString} Start => Topology not found in Rel Dictionary: {ReliableDictionaryNames.OutageTopologyModel}."); return(false); } var topology = enumerableTopology[ReliableDictionaryNames.OutageTopologyModel]; if (!await StartLocationAndIsolationAlgorithm(outageEntity, topology)) { return(false); } return(await lifecycleHelper.PublishOutageAsync(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageEntity))); } catch (Exception e) { string message = $"{baseLogString} SendLocationIsolationCrew => Exception: {e.Message}"; Logger.LogError(message, e); return(false); } }
public void IsolateOutage(long outageId) { //bool success = false; OutageEntity outageToIsolate = dbContext.OutageRepository.Get(outageId); if (outageToIsolate != null) { if (outageToIsolate.OutageState == OutageState.CREATED) { Task.Run(() => StartIsolationAlgorthm(outageToIsolate)) .ContinueWith(task => { if (task.Result) { dbContext.Complete(); } }, TaskContinuationOptions.OnlyOnRanToCompletion) .ContinueWith(task => { try { outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageToIsolate)); Logger.LogInfo($"Outage with id: 0x{outageToIsolate.OutageId:x16} is successfully published."); } catch (Exception e) { //TODO: mozda publish neke greske?? Logger.LogError("Error occured while trying to publish outage.", e); } }, TaskContinuationOptions.OnlyOnRanToCompletion); } else { Logger.LogWarn($"Outage with id 0x{outageId:X16} is in state {outageToIsolate.OutageState}, and thus cannot be isolated."); } } else { Logger.LogWarn($"Outage with id 0x{outageId:X16} is not found in database."); //success = false; } //return success; }
public async Task <bool> ResolveOutage(long outageId) { Logger.LogVerbose($"{baseLogString} ResolveOutage method started. OutageId: {outageId}"); while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } try { var result = await lifecycleHelper.GetValidatedRepairedOutage(outageId); if (!result.HasValue) { Logger.LogError($"{baseLogString} ResolveOutage => GetValidatedRepairedOutage did not return a value. OutageId: {outageId}"); return(false); } var outageDbEntity = result.Value; outageDbEntity.ArchivedTime = DateTime.UtcNow; outageDbEntity.OutageState = OutageState.ARCHIVED; var outageModelAccessClient = OutageModelAccessClient.CreateClient(); await outageModelAccessClient.UpdateOutage(outageDbEntity); Logger.LogInformation($"{baseLogString} ResolveOutage => Outage on element with gid: 0x{outageDbEntity.OutageElementGid:x16} is SUCCESSFULLY archived."); return(await lifecycleHelper.PublishOutageAsync(Topic.ARCHIVED_OUTAGE, outageMessageMapper.MapOutageEntity(outageDbEntity))); } catch (Exception e) { string message = $"{baseLogString} ResolveOutage => Exception: {e.Message}"; Logger.LogError(message, e); return(false); } }
public async Task <bool> ReportPotentialOutage(long elementGid, CommandOriginType commandOriginType, NetworkType networkType) { Logger.LogVerbose($"{baseLogString} ReportPotentialOutage method started. ElementGid: 0x{elementGid:X16}, CommandOriginType: {commandOriginType}, NetworkType: {networkType}"); while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } try { #region Preconditions var ceModelProviderClient = CeModelProviderClient.CreateClient(); if (await ceModelProviderClient.IsRecloser(elementGid)) { Logger.LogWarning($"{baseLogString} ReportPotentialOutage => Element with gid 0x{elementGid:X16} is a Recloser. Call to ReportPotentialOutage aborted."); return(false); } var enumerableTopology = await OutageTopologyModel.GetEnumerableDictionaryAsync(); if (!enumerableTopology.ContainsKey(ReliableDictionaryNames.OutageTopologyModel)) { Logger.LogError($"{baseLogString} ReportPotentialOutage => Topology not found in Rel Dictionary: {ReliableDictionaryNames.OutageTopologyModel}."); return(false); } var topology = enumerableTopology[ReliableDictionaryNames.OutageTopologyModel]; var affectedConsumersGids = lifecycleHelper.GetAffectedConsumers(elementGid, topology, networkType); var historyDBManagerClient = HistoryDBManagerClient.CreateClient(); if (!(await CheckPreconditions(elementGid, commandOriginType, affectedConsumersGids, historyDBManagerClient))) { Logger.LogWarning($"{baseLogString} ReportPotentialOutage => Parameters do not satisfy required preconditions. ElementId: 0x{elementGid:X16}, CommandOriginType: {commandOriginType}"); return(false); } #endregion Preconditions Logger.LogInformation($"{baseLogString} ReportPotentialOutage => Reporting outage for gid: 0x{elementGid:X16}, CommandOriginType: {commandOriginType}"); var result = await StoreActiveOutage(elementGid, affectedConsumersGids, topology); if (!result.HasValue) { Logger.LogError($"{baseLogString} ReportPotentialOutage => Storing outage on element 0x{elementGid:X16} FAILED."); return(false); } var createdOutage = result.Value; Logger.LogInformation($"{baseLogString} ReportPotentialOutage => Outage on element with gid: 0x{createdOutage.OutageElementGid:x16} is successfully stored in database."); //await historyDBManagerClient.OnSwitchOpened(elementGid, createdOutage.OutageId); //await historyDBManagerClient.OnConsumerBlackedOut(affectedConsumersGids, createdOutage.OutageId); return(await lifecycleHelper.PublishOutageAsync(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(createdOutage))); } catch (Exception e) { string message = $"{baseLogString} ReportPotentialOutage => exception: {e.Message}"; Logger.LogError(message, e); return(false); } }
private async Task <bool> FinishIndividualAlgorithmCycle(IsolationAlgorithm algorithm, OutageTopologyModel topology) { var algorithmBaseLogString = $"{baseLogString} [HeadBreakerGid: 0x{algorithm.HeadBreakerGid:X16}]"; Logger.LogInformation($"{algorithmBaseLogString} entering FinishIndividualAlgorithmCycle."); if (algorithm.CurrentBreakerGid <= 0 || algorithm.CurrentBreakerGid == algorithm.RecloserGid) { string message = $"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => End of the feeder, no outage detected."; Logger.LogWarning(message); return(false); } var getCreatedOutageResult = await lifecycleHelper.GetCreatedOutage(algorithm.OutageId); if (!getCreatedOutageResult.HasValue) { Logger.LogError($"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Created Outage is null. OutageId: {algorithm.OutageId}"); return(false); } var outageToIsolate = getCreatedOutageResult.Value; await SetDefaultIsolationPoints(outageToIsolate, algorithm); await SetOptimumIsolationPoints(outageToIsolate, algorithm, topology); //ISOLATE on optimum points var firstOptimumPoint = outageToIsolate.OptimumIsolationPoints[0]; var secondOptimumPoint = outageToIsolate.OptimumIsolationPoints[1]; var commands = new Dictionary <long, DiscreteCommandingType> { { algorithm.HeadBreakerGid, DiscreteCommandingType.CLOSE }, { firstOptimumPoint.EquipmentId, DiscreteCommandingType.OPEN }, { secondOptimumPoint.EquipmentId, DiscreteCommandingType.OPEN }, { algorithm.RecloserGid, DiscreteCommandingType.CLOSE }, }; var enumerableCommandedElements = await CommandedElements.GetEnumerableDictionaryAsync(); if (!await SendCommands(algorithm, commands, enumerableCommandedElements)) { string message = $"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Failed on SendMultipleScadaCommandAsync."; Logger.LogError(message); return(false); } long outageElementGid = topology.OutageTopology[secondOptimumPoint.EquipmentId].FirstEnd; //element iznad donjeg pointa - moze biti samo jedan gornji element (parent) if (!topology.OutageTopology[firstOptimumPoint.EquipmentId].SecondEnd.Contains(outageElementGid)) { string message = $"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Outage element with gid: 0x{outageElementGid:X16} is not on a second end of current breaker id"; Logger.LogError(message); return(false); } outageToIsolate.IsolatedTime = DateTime.UtcNow; outageToIsolate.OutageElementGid = outageElementGid; outageToIsolate.OutageState = OutageState.ISOLATED; var outageModelAccessClient = OutageModelAccessClient.CreateClient(); await outageModelAccessClient.UpdateOutage(outageToIsolate); Logger.LogInformation($"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Isolation of outage with id: {outageToIsolate.OutageId}. Optimum isolation points: 0x{outageToIsolate.OptimumIsolationPoints[0].EquipmentId:X16} and 0x{outageToIsolate.OptimumIsolationPoints[1].EquipmentId:X16}, and outage element id is 0x{outageElementGid:X16}"); await lifecycleHelper.PublishOutageAsync(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageToIsolate)); Logger.LogInformation($"{algorithmBaseLogString} FinishIndividualAlgorithmCycle => Outage with id: 0x{outageToIsolate.OutageId:x16} is successfully published."); await OnEndAlgorithmCleanUp(algorithm.HeadBreakerGid); return(true); }
public bool ResolveOutage(long outageId) { OutageEntity activeOutageDbEntity = null; try { activeOutageDbEntity = dbContext.OutageRepository.Get(outageId); } catch (Exception e) { string message = "OutageModel::SendRepairCrew => exception in UnitOfWork.ActiveOutageRepository.Get()"; Logger.LogError(message, e); throw e; } if (activeOutageDbEntity == null) { Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database."); return(false); } if (activeOutageDbEntity.OutageState != OutageState.REPAIRED) { Logger.LogError($"Outage with id 0x{outageId:X16} is in state {activeOutageDbEntity.OutageState}, and thus repair crew can not be sent. (Expected state: {OutageState.REPAIRED})"); return(false); } if (!activeOutageDbEntity.IsResolveConditionValidated) { //TODO: mozda i ovde odraditi proveru uslova? Logger.LogWarn("ResolveOutage => resolve conditions not validated."); return(false); } OutageEntity createdArchivedOutage = new OutageEntity() { OutageId = activeOutageDbEntity.OutageId, OutageState = OutageState.ARCHIVED, OutageElementGid = activeOutageDbEntity.OutageElementGid, IsResolveConditionValidated = activeOutageDbEntity.IsResolveConditionValidated, ReportTime = activeOutageDbEntity.ReportTime, IsolatedTime = activeOutageDbEntity.IsolatedTime, RepairedTime = activeOutageDbEntity.RepairedTime, ArchivedTime = DateTime.UtcNow, DefaultIsolationPoints = new List <Equipment>(activeOutageDbEntity.DefaultIsolationPoints), OptimumIsolationPoints = new List <Equipment>(activeOutageDbEntity.OptimumIsolationPoints), AffectedConsumers = new List <Consumer>(activeOutageDbEntity.AffectedConsumers), }; bool success; dbContext.OutageRepository.Remove(activeOutageDbEntity); OutageEntity archivedOutageDbEntity = dbContext.OutageRepository.Add(createdArchivedOutage); try { dbContext.Complete(); Logger.LogDebug($"ArchivedOutage on element with gid: 0x{archivedOutageDbEntity.OutageElementGid:x16} is successfully stored in database."); success = true; } catch (Exception e) { string message = "OutageModel::ResolveOutage method => exception on Complete()"; Logger.LogError(message, e); Console.WriteLine($"{message}, Message: {e.Message})"); //TODO: da li je dobar handle? dbContext.Dispose(); dbContext = new UnitOfWork(); success = false; } if (success && archivedOutageDbEntity != null) //TODO: ne svidja mi se ova konstrukcija... { try { success = outageModel.PublishOutage(Topic.ARCHIVED_OUTAGE, outageMessageMapper.MapOutageEntity(archivedOutageDbEntity)); if (success) { Logger.LogInfo($"ArchivedOutage on element with gid: 0x{archivedOutageDbEntity.OutageElementGid:x16} is successfully published"); } } catch (Exception e) //TODO: Exception over proxy or enum... { Logger.LogError("OutageModel::ResolveOutage => exception on PublishActiveOutage()", e); success = false; } } return(success); }
public bool ValidateResolveConditions(long outageId) { OutageEntity outageDbEntity = null; try { outageDbEntity = dbContext.OutageRepository.Get(outageId); } catch (Exception e) { string message = "OutageModel::SendRepairCrew => exception in UnitOfWork.ActiveOutageRepository.Get()"; Logger.LogError(message, e); throw e; } if (outageDbEntity == null) { Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database."); return(false); } if (outageDbEntity.OutageState != OutageState.REPAIRED) { Logger.LogError($"Outage with id 0x{outageId:X16} is in state {outageDbEntity.OutageState}, and thus repair crew can not be sent. (Expected state: {OutageState.REPAIRED})"); return(false); } List <Equipment> isolationPoints = new List <Equipment>(); isolationPoints.AddRange(outageDbEntity.DefaultIsolationPoints); isolationPoints.AddRange(outageDbEntity.OptimumIsolationPoints); bool resolveCondition = true; foreach (Equipment isolationPoint in isolationPoints) { if (outageModel.TopologyModel.GetElementByGid(isolationPoint.EquipmentId, out IOutageTopologyElement element)) { if (element.NoReclosing != element.IsActive) { resolveCondition = false; break; } } } outageDbEntity.IsResolveConditionValidated = resolveCondition; dbContext.OutageRepository.Update(outageDbEntity); try { dbContext.Complete(); outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageDbEntity)); } catch (Exception e) { string message = "OutageModel::ValidateResolveConditions => exception in Complete method."; Logger.LogError(message, e); } return(true); }
public bool SendRepairCrew(long outageId) { OutageEntity outageDbEntity = null; try { outageDbEntity = dbContext.OutageRepository.Get(outageId); } catch (Exception e) { string message = "OutageModel::SendRepairCrew => exception in UnitOfWork.ActiveOutageRepository.Get()"; Logger.LogError(message, e); throw e; } if (outageDbEntity == null) { Logger.LogError($"Outage with id 0x{outageId:X16} is not found in database."); return(false); } if (outageDbEntity.OutageState != OutageState.ISOLATED) { Logger.LogError($"Outage with id 0x{outageId:X16} is in state {outageDbEntity.OutageState}, and thus repair crew can not be sent. (Expected state: {OutageState.ISOLATED})"); return(false); } Task task = Task.Run(() => { Task.Delay(10000).Wait(); using (OutageSimulatorServiceProxy proxy = proxyFactory.CreateProxy <OutageSimulatorServiceProxy, IOutageSimulatorContract>(EndpointNames.OutageSimulatorServiceEndpoint)) { if (proxy == null) { string message = "OutageModel::SendRepairCrew => OutageSimulatorServiceProxy is null"; Logger.LogError(message); throw new NullReferenceException(message); } if (proxy.StopOutageSimulation(outageDbEntity.OutageElementGid)) { outageDbEntity.OutageState = OutageState.REPAIRED; outageDbEntity.RepairedTime = DateTime.UtcNow; dbContext.OutageRepository.Update(outageDbEntity); try { dbContext.Complete(); outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(outageDbEntity)); } catch (Exception e) { string message = "OutageModel::SendRepairCrew => exception in Complete method."; Logger.LogError(message, e); } } else { string message = "OutageModel::SendRepairCrew => ResolvedOutage() not finished with SUCCESS"; Logger.LogError(message); } } }); return(true); }
public bool ReportPotentialOutage(long gid, CommandOriginType commandOriginType) { bool success = false; List <long> affectedConsumersIds = new List <long>(); affectedConsumersIds = GetAffectedConsumers(gid); if (commandOriginType != CommandOriginType.USER_COMMAND && commandOriginType != CommandOriginType.ISOLATING_ALGORITHM_COMMAND) { Logger.LogDebug($"Reporting outage for gid: 0x{gid:X16}"); if (outageModel.commandedElements.Contains(gid) || outageModel.optimumIsolationPoints.Contains(gid)) { outageModel.SwitchOpened?.Invoke(gid, null); outageModel.ConsumersBlackedOut?.Invoke(affectedConsumersIds, null); return(false); } if (affectedConsumersIds.Count == 0) { bool isSwitchInvoked = false; if (recloserOutageMap.TryGetValue(gid, out Dictionary <long, List <long> > outageAffectedPair)) { foreach (var pair in outageAffectedPair) { outageModel.ConsumersBlackedOut?.Invoke(pair.Value, pair.Key); outageModel.SwitchOpened?.Invoke(gid, pair.Key); isSwitchInvoked = true; } } if (!isSwitchInvoked) { outageModel.SwitchOpened?.Invoke(gid, null); } Logger.LogInfo("There is no affected consumers => outage report is not valid."); return(false); } OutageEntity activeOutageDbEntity = null; if (dbContext.OutageRepository.Find(o => o.OutageElementGid == gid && o.OutageState != OutageState.ARCHIVED).FirstOrDefault() != null) { Logger.LogWarn($"Malfunction on element with gid: 0x{gid:x16} has already been reported."); return(false); } List <Consumer> consumerDbEntities = outageModel.GetAffectedConsumersFromDatabase(affectedConsumersIds); if (consumerDbEntities.Count != affectedConsumersIds.Count) { Logger.LogWarn("Some of affected consumers are not present in database"); return(false); } long recloserId; try { recloserId = outageModel.GetRecloserForHeadBreaker(gid); } catch (Exception) { return(false); } List <Equipment> defaultIsolationPoints = outageModel.GetEquipmentEntity(new List <long> { gid, recloserId }); OutageEntity createdActiveOutage = new OutageEntity { AffectedConsumers = consumerDbEntities, OutageState = OutageState.CREATED, ReportTime = DateTime.UtcNow, DefaultIsolationPoints = defaultIsolationPoints, }; activeOutageDbEntity = dbContext.OutageRepository.Add(createdActiveOutage); try { dbContext.Complete(); Logger.LogDebug($"Outage on element with gid: 0x{activeOutageDbEntity.OutageElementGid:x16} is successfully stored in database."); success = true; if (recloserOutageMap.TryGetValue(recloserId, out Dictionary <long, List <long> > outageAffectedPair)) { if (outageAffectedPair.TryGetValue(createdActiveOutage.OutageId, out List <long> affected)) { affected = new List <long>(affectedConsumersIds); } else { outageAffectedPair.Add(createdActiveOutage.OutageId, affectedConsumersIds); } } else { Dictionary <long, List <long> > dict = new Dictionary <long, List <long> >() { { createdActiveOutage.OutageId, affectedConsumersIds } }; recloserOutageMap.Add(recloserId, dict); } outageModel.SwitchOpened?.Invoke(gid, createdActiveOutage.OutageId); outageModel.ConsumersBlackedOut?.Invoke(affectedConsumersIds, createdActiveOutage.OutageId); } catch (Exception e) { string message = "OutageModel::ReportPotentialOutage method => exception on Complete()"; Logger.LogError(message, e); Console.WriteLine($"{message}, Message: {e.Message}, Inner Message: {e.InnerException.Message})"); //TODO: da li je dobar handle? dbContext.Dispose(); dbContext = new UnitOfWork(); success = false; } if (success && activeOutageDbEntity != null) { try { success = outageModel.PublishOutage(Topic.ACTIVE_OUTAGE, outageMessageMapper.MapOutageEntity(activeOutageDbEntity)); if (success) { Logger.LogInfo($"Outage on element with gid: 0x{activeOutageDbEntity.OutageElementGid:x16} is successfully published"); } } catch (Exception e) //TODO: Exception over proxy or enum... { Logger.LogError("OutageModel::ReportPotentialOutage => exception on PublishActiveOutage()", e); success = false; } } } else { //USER COMANDA - korisnik rucno otvara neki breaker -> nije outage ali korisnici potencijalno ostaju bez napajanja outageModel.SwitchOpened?.Invoke(gid, null); outageModel.ConsumersBlackedOut?.Invoke(affectedConsumersIds, null); } return(success); }