Ejemplo n.º 1
0
        public ArchivedOutageMessage MapOutageEntityToArchived(OutageEntity outage)
        {
            ArchivedOutageMessage outageMessage;

            if (outage.OutageState == OutageState.ARCHIVED)
            {
                outageMessage = new ArchivedOutageMessage
                {
                    OutageId               = outage.OutageId,
                    ReportTime             = outage.ReportTime,
                    IsolatedTime           = outage.IsolatedTime,
                    RepairedTime           = outage.RepairedTime,
                    ArchivedTime           = outage.ArchivedTime ?? DateTime.UtcNow,
                    OutageElementGid       = outage.OutageElementGid,
                    DefaultIsolationPoints = equipmentMapper.MapEquipments(outage.DefaultIsolationPoints),
                    OptimumIsolationPoints = equipmentMapper.MapEquipments(outage.OptimumIsolationPoints),
                    AffectedConsumers      = consumerMapper.MapConsumers(outage.AffectedConsumers)
                };
            }
            else
            {
                throw new ArgumentException($"MapOutageEntityToArchived => Outage state: {outage.OutageState}, but {OutageState.ARCHIVED} was expected.");
            }


            return(outageMessage);
        }
Ejemplo n.º 2
0
        public ActiveOutageMessage MapOutageEntityToActive(OutageEntity outage)
        {
            ActiveOutageMessage outageMessage;

            if (outage.OutageState != OutageState.ARCHIVED)
            {
                outageMessage = new ActiveOutageMessage()
                {
                    OutageId                    = outage.OutageId,
                    OutageState                 = outage.OutageState,
                    ReportTime                  = outage.ReportTime,
                    IsolatedTime                = outage.IsolatedTime,
                    RepairedTime                = outage.RepairedTime,
                    OutageElementGid            = outage.OutageElementGid,
                    DefaultIsolationPoints      = equipmentMapper.MapEquipments(outage.DefaultIsolationPoints),
                    OptimumIsolationPoints      = equipmentMapper.MapEquipments(outage.OptimumIsolationPoints),
                    AffectedConsumers           = consumerMapper.MapConsumers(outage.AffectedConsumers),
                    IsResolveConditionValidated = outage.IsResolveConditionValidated,
                };
            }
            else
            {
                throw new ArgumentException($"MapOutageEntityToActive => Outage state: { OutageState.ARCHIVED}.");
            }


            return(outageMessage);
        }
        public Task <OutageEntity> AddOutage(OutageEntity outage)
        {
            return(Task.Run(() =>
            {
                //MODO: razmisliti o ConditonalValue<OutageEntity>
                OutageEntity outageEntityDb = null;

                using (var unitOfWork = new UnitOfWork())
                {
                    try
                    {
                        List <Consumer> consumersFromDb = GetConsumersFromDb(outage.AffectedConsumers, unitOfWork);
                        if (consumersFromDb.Count != outage.AffectedConsumers.Count)
                        {
                            Logger.LogError($"{baseLogString} AddOutage => Some of AffectedConsumers are not present in database.");
                            return outageEntityDb;
                        }

                        List <Equipment> defaultIsolationPointsFromDb = GetEquipmentFromDb(outage.DefaultIsolationPoints, unitOfWork);
                        if (defaultIsolationPointsFromDb.Count != outage.DefaultIsolationPoints.Count)
                        {
                            Logger.LogError($"{baseLogString} AddOutage => Some of DefaultIsolationPoints are not present in database.");
                            return outageEntityDb;
                        }

                        List <Equipment> optimumIsolationPointsFromDb = GetEquipmentFromDb(outage.OptimumIsolationPoints, unitOfWork);
                        if (optimumIsolationPointsFromDb.Count != outage.OptimumIsolationPoints.Count)
                        {
                            Logger.LogError($"{baseLogString} AddOutage => Some of OptimumIsolationPoints are not present in database.");
                            return outageEntityDb;
                        }

                        outage.AffectedConsumers.Clear();
                        outage.AffectedConsumers.AddRange(consumersFromDb);

                        outage.DefaultIsolationPoints.Clear();
                        outage.DefaultIsolationPoints.AddRange(defaultIsolationPointsFromDb);

                        outage.OptimumIsolationPoints.Clear();
                        outage.OptimumIsolationPoints.AddRange(optimumIsolationPointsFromDb);

                        outageEntityDb = unitOfWork.OutageRepository.Add(outage);
                        unitOfWork.Complete();
                    }
                    catch (Exception e)
                    {
                        string message = $"{baseLogString} AddOutage => Exception: {e.Message}";
                        Logger.LogError(message, e);
                    }
                }

                return outageEntityDb;
            }));
        }
Ejemplo n.º 4
0
 public ArchivedOutageViewModel MapArchivedOutage(OutageEntity outage)
 => new ArchivedOutageViewModel
 {
     Id                     = outage.OutageId,
     ReportedAt             = outage.ReportTime,
     IsolatedAt             = outage.IsolatedTime,
     RepairedAt             = outage.RepairedTime,
     ArchivedAt             = (DateTime)outage.ArchivedTime,
     ElementId              = outage.OutageElementGid,
     DefaultIsolationPoints = _equipmentMapper.MapEquipments(outage.DefaultIsolationPoints),
     OptimalIsolationPoints = _equipmentMapper.MapEquipments(outage.OptimumIsolationPoints),
     AffectedConsumers      = _consumerMapper.MapConsumers(outage.AffectedConsumers),
 };
Ejemplo n.º 5
0
 public ActiveOutageViewModel MapActiveOutage(OutageEntity outage)
 => new ActiveOutageViewModel
 {
     Id         = outage.OutageId,
     State      = (OutageLifecycleState)outage.OutageState,
     ReportedAt = outage.ReportTime,
     IsolatedAt = outage.IsolatedTime,
     RepairedAt = outage.RepairedTime,
     ElementId  = outage.OutageElementGid,
     IsResolveConditionValidated = outage.IsResolveConditionValidated,
     DefaultIsolationPoints      = _equipmentMapper.MapEquipments(outage.DefaultIsolationPoints),
     OptimalIsolationPoints      = _equipmentMapper.MapEquipments(outage.OptimumIsolationPoints),
     AffectedConsumers           = _consumerMapper.MapConsumers(outage.AffectedConsumers),
 };
        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);
        }
Ejemplo n.º 7
0
        private async Task <ConditionalValue <OutageEntity> > StoreActiveOutage(long elementGid, List <long> affectedConsumersGids, OutageTopologyModel topology)
        {
            var outageModelAccessClient = OutageModelAccessClient.CreateClient();
            var allOutages = await outageModelAccessClient.GetAllOutages();

            var targetedOutages = allOutages.Where(outage => outage.OutageElementGid == elementGid && outage.OutageState != OutageState.ARCHIVED);

            if (targetedOutages.FirstOrDefault() != null)
            {
                Logger.LogWarning($"{baseLogString} StoreActiveOutage => Malfunction on element with gid: 0x{elementGid:x16} has already been reported.");
                return(new ConditionalValue <OutageEntity>(false, null));
            }

            List <Consumer> consumerDbEntities = await lifecycleHelper.GetAffectedConsumersFromDatabase(affectedConsumersGids);

            if (consumerDbEntities.Count != affectedConsumersGids.Count)
            {
                Logger.LogWarning($"{baseLogString} StoreActiveOutage => Some of affected consumers are not present in database.");
                return(new ConditionalValue <OutageEntity>(false, null));
            }

            long recloserId = GetRecloserForHeadBreaker(elementGid, topology);

            List <Equipment> defaultIsolationPoints = await lifecycleHelper.GetEquipmentEntityAsync(new List <long> {
                elementGid, recloserId
            });

            OutageEntity createdActiveOutage = new OutageEntity
            {
                OutageElementGid       = elementGid,
                AffectedConsumers      = consumerDbEntities,
                OutageState            = OutageState.CREATED,
                ReportTime             = DateTime.UtcNow,
                DefaultIsolationPoints = defaultIsolationPoints,
            };

            var activeOutageDbEntity = await outageModelAccessClient.AddOutage(createdActiveOutage);

            if (activeOutageDbEntity == null)
            {
                Logger.LogError($"{baseLogString} StoreActiveOutage => activeOutageDbEntity is null.");
                return(new ConditionalValue <OutageEntity>(false, null));
            }

            await UpdateRecloserOutageMap(recloserId, affectedConsumersGids, activeOutageDbEntity);

            return(new ConditionalValue <OutageEntity>(true, activeOutageDbEntity));
        }
        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 Task RemoveOutage(OutageEntity outage)
 {
     return(Task.Run(() =>
     {
         using (var unitOfWork = new UnitOfWork())
         {
             try
             {
                 unitOfWork.OutageRepository.Remove(outage);
                 unitOfWork.Complete();
             }
             catch (Exception e)
             {
                 string message = $"{baseLogString} RemoveOutage => Exception: {e.Message}";
                 Logger.LogError(message, e);
             }
         }
     }));
 }
        private async Task SetOptimumIsolationPoints(OutageEntity outageEntity, IsolationAlgorithm algorithm, OutageTopologyModel topology)
        {
            var algorithmBaseLogString = $"{baseLogString} [HeadBreakerGid: 0x{algorithm.HeadBreakerGid:X16}]";

            long firstOptimumIsolationPointGid  = algorithm.CurrentBreakerGid;
            long secondOptimumIsolationPointGid = lifecycleHelper.GetNextBreaker(firstOptimumIsolationPointGid, topology);

            if (!topology.OutageTopology.ContainsKey(secondOptimumIsolationPointGid))
            {
                string message = $"{algorithmBaseLogString} SetOptimumIsolationPoints => Breaker (next breaker) with id: 0x{secondOptimumIsolationPointGid:X16} is not in topology";
                Logger.LogError(message);
                throw new Exception(message);
            }

            long outageElement = topology.OutageTopology[secondOptimumIsolationPointGid].FirstEnd;

            if (!topology.OutageTopology[firstOptimumIsolationPointGid].SecondEnd.Contains(outageElement))
            {
                string message = $"{algorithmBaseLogString} SetOptimumIsolationPoints => Outage element with gid: 0x{outageElement:X16} is not on a second end of current breaker id";
                Logger.LogError(message);
                throw new Exception(message);
            }

            outageEntity.OptimumIsolationPoints = await lifecycleHelper.GetEquipmentEntityAsync(new List <long>() { firstOptimumIsolationPointGid, secondOptimumIsolationPointGid });

            if (outageEntity.OptimumIsolationPoints.Count != 2 ||
                !outageEntity.OptimumIsolationPoints.Any(point => point.EquipmentId == firstOptimumIsolationPointGid) ||
                !outageEntity.OptimumIsolationPoints.Any(point => point.EquipmentId == secondOptimumIsolationPointGid))
            {
                string message = $"{algorithmBaseLogString} SetOptimumIsolationPoints => first OptimumIsolationPointGid [0x{firstOptimumIsolationPointGid:X16}] or second OptimumIsolationPointGid [0x{secondOptimumIsolationPointGid:X16}] were not found or created successfully.";
                Logger.LogError(message);
                throw new Exception(message);
            }

            await OptimumIsolationPoints.SetAsync(firstOptimumIsolationPointGid, algorithm.HeadBreakerGid);

            await OptimumIsolationPoints.SetAsync(secondOptimumIsolationPointGid, algorithm.HeadBreakerGid);

            Logger.LogInformation($"{algorithmBaseLogString} SetOptimumIsolationPoints => Optimum points 0x{firstOptimumIsolationPointGid:X16} and 0x{secondOptimumIsolationPointGid:X16}");
        }
Ejemplo n.º 11
0
        public OutageMessage MapOutageEntity(OutageEntity outage)
        {
            OutageMessage outageMessage;

            if (outage.OutageState != OutageState.ARCHIVED)
            {
                outageMessage = new ActiveOutageMessage()
                {
                    OutageId                    = outage.OutageId,
                    OutageState                 = outage.OutageState,
                    ReportTime                  = outage.ReportTime,
                    IsolatedTime                = outage.IsolatedTime,
                    RepairedTime                = outage.RepairedTime,
                    OutageElementGid            = outage.OutageElementGid,
                    DefaultIsolationPoints      = equipmentMapper.MapEquipments(outage.DefaultIsolationPoints),
                    OptimumIsolationPoints      = equipmentMapper.MapEquipments(outage.OptimumIsolationPoints),
                    AffectedConsumers           = consumerMapper.MapConsumers(outage.AffectedConsumers),
                    IsResolveConditionValidated = outage.IsResolveConditionValidated,
                };
            }
            else
            {
                outageMessage = new ArchivedOutageMessage
                {
                    OutageId               = outage.OutageId,
                    ReportTime             = outage.ReportTime,
                    IsolatedTime           = outage.IsolatedTime,
                    RepairedTime           = outage.RepairedTime,
                    ArchivedTime           = outage.ArchivedTime ?? DateTime.UtcNow,
                    OutageElementGid       = outage.OutageElementGid,
                    DefaultIsolationPoints = equipmentMapper.MapEquipments(outage.DefaultIsolationPoints),
                    OptimumIsolationPoints = equipmentMapper.MapEquipments(outage.OptimumIsolationPoints),
                    AffectedConsumers      = consumerMapper.MapConsumers(outage.AffectedConsumers)
                };
            }


            return(outageMessage);
        }
        public Task <OutageEntity> GetOutage(long gid)
        {
            return(Task.Run(() =>
            {
                //MODO: razmisliti o ConditonalValue<OutageEntity>
                OutageEntity outageEntityDb = null;

                using (var unitOfWork = new UnitOfWork())
                {
                    try
                    {
                        outageEntityDb = unitOfWork.OutageRepository.Get(gid);
                    }
                    catch (Exception e)
                    {
                        string message = $"{baseLogString} GetOutage => Exception: {e.Message}";
                        Logger.LogError(message, e);
                    }
                }

                return outageEntityDb;
            }));
        }
        private async Task SetDefaultIsolationPoints(OutageEntity outageEntity, IsolationAlgorithm algorithm)
        {
            var algorithmBaseLogString = $"{baseLogString} [HeadBreakerGid: 0x{algorithm.HeadBreakerGid:X16}]";

            var       equipmentAccessClient = EquipmentAccessClient.CreateClient();
            Equipment headBreakerEquipment  = await equipmentAccessClient.GetEquipment(algorithm.HeadBreakerGid);

            Equipment recloserEquipment = await equipmentAccessClient.GetEquipment(algorithm.RecloserGid);

            if (headBreakerEquipment == null || recloserEquipment == null)
            {
                string message = $"{algorithmBaseLogString} SetDefaultIsolationPoints => Recloser [0x{algorithm.HeadBreakerGid:X16}] or HeadBreaker [0x{algorithm.RecloserGid:X16}] were not found in database";
                Logger.LogError(message);
                throw new Exception(message);
            }

            outageEntity.DefaultIsolationPoints = new List <Equipment>()
            {
                headBreakerEquipment, recloserEquipment
            };

            Logger.LogInformation($"{algorithmBaseLogString} SetDefaultIsolationPoints => Optimum points 0x{headBreakerEquipment:X16} and 0x{recloserEquipment:X16}");
        }
        private async Task <bool> StartIsolationAlgorthm(OutageEntity outageToIsolate)
        {
            var result = await CreateIsolatingAlgorithm(outageToIsolate);

            if (!result.HasValue)
            {
                Logger.LogError($"{baseLogString} StartIsolationAlgorthm => CreateIsolatingAlgorithm did not return a vaule.");
                return(false);
            }

            var algorithm = result.Value;

            Logger.LogInformation($"{baseLogString} StartIsolationAlgorthm => HeadBreakerGid: 0x{algorithm.HeadBreakerGid:X16}, RecloserGd: 0x{algorithm.RecloserGid:X16} (Recloser gid is -1 if there is no recloser...).");

            var scadaClient      = ScadaIntegrityUpdateClient.CreateClient();
            var scadaPublication = await scadaClient.GetIntegrityUpdateForSpecificTopic(Topic.SWITCH_STATUS);

            if (!(scadaPublication.Message is MultipleDiscreteValueSCADAMessage multipleDiscreteValueSCADAMessage))
            {
                Logger.LogError($"{baseLogString} StartIsolationAlgorthm => ScadaPublication message is not of expected type: {typeof(MultipleDiscreteValueSCADAMessage)}, but of type: {scadaPublication.Message.GetType()}");
                return(false);
            }

            if (!multipleDiscreteValueSCADAMessage.Data.ContainsKey(algorithm.HeadBreakerMeasurementGid))
            {
                Logger.LogError($"{baseLogString} StartIsolationAlgorthm => HeadBreakerMeasurement with gid: 0x{algorithm.HeadBreakerMeasurementGid:X16} not found in integrity update data received from scada.");
                return(false);
            }

            var discreteModbusData = multipleDiscreteValueSCADAMessage.Data[algorithm.HeadBreakerMeasurementGid];
            await MonitoredHeadBreakerMeasurements.SetAsync(algorithm.HeadBreakerMeasurementGid, discreteModbusData);

            await StartedIsolationAlgorithms.SetAsync(algorithm.HeadBreakerGid, algorithm);

            return(true);
        }
        private async Task <ConditionalValue <IsolationAlgorithm> > CreateIsolatingAlgorithm(OutageEntity outageToIsolate)
        {
            List <long> defaultIsolationPoints = outageToIsolate.DefaultIsolationPoints.Select(point => point.EquipmentId).ToList();

            if (defaultIsolationPoints.Count != 1 && defaultIsolationPoints.Count != 2)
            {
                Logger.LogWarning($"{baseLogString} CreateIsolatingAlgorithm => Number of defaultIsolationPoints ({defaultIsolationPoints.Count}) is out of range [1, 2].");
                return(new ConditionalValue <IsolationAlgorithm>(false, null));
            }

            var  measurementMapClient   = MeasurementMapClient.CreateClient();
            var  ceModelProvider        = CeModelProviderClient.CreateClient();
            bool isFirstBreakerRecloser = await ceModelProvider.IsRecloser(defaultIsolationPoints[0]);

            #region HeadBreaker
            long headBreakerGid = await GetHeadBreakerAsync(defaultIsolationPoints, isFirstBreakerRecloser);

            if (headBreakerGid <= 0)
            {
                Logger.LogWarning($"{baseLogString} CreateIsolatingAlgorithm => Head breaker not found.");
                return(new ConditionalValue <IsolationAlgorithm>(false, null));
            }

            ModelCode headBreakerModelCode = modelResourcesDesc.GetModelCodeFromId(headBreakerGid);

            if (headBreakerModelCode != ModelCode.BREAKER)
            {
                Logger.LogError($"{baseLogString} CreateIsolatingAlgorithm => Head breaker type is {headBreakerModelCode}, not a {ModelCode.BREAKER}.");
                return(new ConditionalValue <IsolationAlgorithm>(false, null));
            }

            var headBreakerMeasurementGid = (await measurementMapClient.GetMeasurementsOfElement(headBreakerGid)).FirstOrDefault();

            if (headBreakerMeasurementGid <= 0)
            {
                Logger.LogWarning($"{baseLogString} CreateIsolatingAlgorithm => Head breaker measurement not found.");
                return(new ConditionalValue <IsolationAlgorithm>(false, null));
            }
            #endregion HeadBreaker

            #region Recloser
            long recloserGid = await GetRecloserAsync(defaultIsolationPoints, isFirstBreakerRecloser);

            long recloserMeasurementGid = -1;

            if (recloserGid > 0) //ne mora postojati recloser
            {
                ModelCode recloserModelCode = modelResourcesDesc.GetModelCodeFromId(recloserGid);

                if (recloserModelCode != ModelCode.BREAKER)
                {
                    Logger.LogError($"{baseLogString} CreateIsolatingAlgorithm => Recloser type is {headBreakerModelCode}, not a {ModelCode.BREAKER}.");
                    return(new ConditionalValue <IsolationAlgorithm>(false, null));
                }

                var ceModelProviderClient = CeModelProviderClient.CreateClient();
                if (!await ceModelProviderClient.IsRecloser(recloserGid))
                {
                    Logger.LogError($"{baseLogString} CreateIsolatingAlgorithm => Breaker with gid 0x{recloserGid:X16} is not a Recloser.");
                    return(new ConditionalValue <IsolationAlgorithm>(false, null));
                }

                recloserMeasurementGid = (await measurementMapClient.GetMeasurementsOfElement(headBreakerGid)).FirstOrDefault();

                if (recloserMeasurementGid <= 0)
                {
                    Logger.LogWarning($"{baseLogString} CreateIsolatingAlgorithm => Head breaker measurement not found.");
                    return(new ConditionalValue <IsolationAlgorithm>(false, null));
                }
            }
            #endregion Recloser

            var algorithm = new IsolationAlgorithm()
            {
                OutageId                     = outageToIsolate.OutageId,
                HeadBreakerGid               = headBreakerGid,
                HeadBreakerMeasurementGid    = headBreakerMeasurementGid,
                CurrentBreakerGid            = headBreakerGid,
                CurrentBreakerMeasurementGid = headBreakerMeasurementGid,
                RecloserGid                  = recloserGid,
                RecloserMeasurementGid       = recloserMeasurementGid,
                CycleCounter                 = 0,
            };

            return(new ConditionalValue <IsolationAlgorithm>(true, algorithm));
        }
        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);
        }
        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);
        }
Ejemplo n.º 18
0
        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 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 Task UpdateOutage(OutageEntity outage)
        {
            return(Task.Run(() =>
            {
                using (var unitOfWork = new UnitOfWork())
                {
                    try
                    {
                        OutageEntity outageFromDb = unitOfWork.OutageRepository.Get(outage.OutageId);

                        if (outageFromDb == null)
                        {
                            Logger.LogError($"{baseLogString} UpdateOutage => Outage with id {outage.OutageId} is not present in database.");
                            return;
                        }


                        List <Consumer> consumersFromDb = GetConsumersFromDb(outage.AffectedConsumers, unitOfWork);
                        if (consumersFromDb.Count != outage.AffectedConsumers.Count)
                        {
                            Logger.LogError($"{baseLogString} UpdateOutage => Some of AffectedConsumers are not present in database.");
                            return;
                        }

                        List <Equipment> defaultIsolationPointsFromDb = GetEquipmentFromDb(outage.DefaultIsolationPoints, unitOfWork);
                        if (defaultIsolationPointsFromDb.Count != outage.DefaultIsolationPoints.Count)
                        {
                            Logger.LogError($"{baseLogString} UpdateOutage => Some of DefaultIsolationPoints are not present in database.");
                            return;
                        }

                        List <Equipment> optimumIsolationPointsFromDb = GetEquipmentFromDb(outage.OptimumIsolationPoints, unitOfWork);
                        if (optimumIsolationPointsFromDb.Count != outage.OptimumIsolationPoints.Count)
                        {
                            Logger.LogError($"{baseLogString} UpdateOutage => Some of OptimumIsolationPoints are not present in database.");
                            return;
                        }

                        outageFromDb.AffectedConsumers.Clear();
                        outageFromDb.AffectedConsumers.AddRange(consumersFromDb);

                        outageFromDb.DefaultIsolationPoints.Clear();
                        outageFromDb.DefaultIsolationPoints.AddRange(defaultIsolationPointsFromDb);

                        outageFromDb.OptimumIsolationPoints.Clear();
                        outageFromDb.OptimumIsolationPoints.AddRange(optimumIsolationPointsFromDb);

                        outageFromDb.OutageState = outage.OutageState;
                        outageFromDb.ArchivedTime = outage.ArchivedTime;
                        outageFromDb.IsolatedTime = outage.IsolatedTime;
                        outageFromDb.IsResolveConditionValidated = outage.IsResolveConditionValidated;
                        outageFromDb.OutageElementGid = outage.OutageElementGid;
                        outageFromDb.RepairedTime = outage.RepairedTime;
                        outageFromDb.ReportTime = outage.ReportTime;

                        unitOfWork.OutageRepository.Update(outageFromDb);
                        unitOfWork.Complete();
                    }
                    catch (Exception e)
                    {
                        string message = $"{baseLogString} UpdateOutage => Exception: {e.Message}";
                        Logger.LogError(message, e);
                    }
                }
            }));
        }
        private async Task <bool> StartLocationAndIsolationAlgorithm(OutageEntity outageEntity, OutageTopologyModel topology)
        {
            long reportedGid = outageEntity.DefaultIsolationPoints.First().EquipmentId;

            if (!topology.GetElementByGid(reportedGid, out OutageTopologyElement topologyElement))
            {
                Logger.LogError($"{baseLogString} StartLocationAndIsolationAlgorithm => element with gid 0x{reportedGid:X16} not found in outage topology model.");
                return(false);
            }

            long upBreaker;
            long outageElementGid = -1;

            Logger.LogInformation($"{baseLogString} StartLocationAndIsolationAlgorithm => Entering 10 sec delay.");
            await Task.Delay(10_000);

            Logger.LogInformation($"{baseLogString} StartLocationAndIsolationAlgorithm => 10 sec delay ended.");

            var outageSimulatorClient   = OutageSimulatorClient.CreateClient();
            var outageModelAccessClient = OutageModelAccessClient.CreateClient();

            //Da li je prijaveljen element OutageElement
            if (await outageSimulatorClient.IsOutageElement(reportedGid))
            {
                outageElementGid = reportedGid;
            }
            //Da li je mozda na ACL-novima ispod prijavljenog elementa
            else
            {
                for (int i = 0; i < topologyElement.SecondEnd.Count; i++)
                {
                    var potentialOutageElementGid = topologyElement.SecondEnd[i];

                    if (!(await outageSimulatorClient.IsOutageElement(potentialOutageElementGid)))
                    {
                        continue;
                    }

                    if (outageElementGid == -1)
                    {
                        outageElementGid = potentialOutageElementGid;
                        outageEntity.OutageElementGid = outageElementGid;
                        //outageEntity.AffectedConsumers = await lifecycleHelper.GetAffectedConsumersFromDatabase(lifecycleHelper.GetAffectedConsumers(outageElementGid, topology, NetworkType.NON_SCADA_NETWORK));
                    }
                    else
                    {
                        //KAKO SE ULAZI U OVAJ ELSE? => u else se ulazi tako sto se ide kroz for i prvi element se oznaci kao outage element, zatim se pronaje jos neki... znaci ovo je nacin da se kreira drugi, treci outage, na racvanju ispod elementa, po for-u....
                        var entity = new OutageEntity()
                        {
                            OutageElementGid = potentialOutageElementGid,
                            ReportTime       = DateTime.UtcNow
                        };

                        await outageModelAccessClient.AddOutage(entity);
                    }
                }
            }

            //Tragamo za ACL-om gore ka source-u
            while (outageElementGid == -1 && !topologyElement.IsRemote && topologyElement.DmsType != "ENERGYSOURCE")
            {
                if (await outageSimulatorClient.IsOutageElement(topologyElement.Id))
                {
                    outageElementGid = topologyElement.Id;
                    outageEntity.OutageElementGid = outageElementGid;
                }

                topology.GetElementByGid(topologyElement.FirstEnd, out topologyElement);
            }

            if (outageElementGid == -1)
            {
                outageEntity.OutageState = OutageState.REMOVED;
                await outageModelAccessClient.RemoveOutage(outageEntity);

                Logger.LogError($"{baseLogString} StartLocationAndIsolationAlgorithm => End of feeder no outage detected.");
                return(false);
            }

            topology.GetElementByGidFirstEnd(outageEntity.OutageElementGid, out topologyElement);
            while (topologyElement.DmsType != "BREAKER")
            {
                topology.GetElementByGidFirstEnd(topologyElement.Id, out topologyElement);
            }

            upBreaker = topologyElement.Id;
            long nextBreaker = lifecycleHelper.GetNextBreaker(outageEntity.OutageElementGid, topology);

            if (!topology.OutageTopology.ContainsKey(nextBreaker))
            {
                string message = $"{baseLogString} StartLocationAndIsolationAlgorithm => Breaker (next breaker) with id: 0x{nextBreaker:X16} is not in topology";
                Logger.LogError(message);
                throw new Exception(message);
            }

            long outageElement = topology.OutageTopology[nextBreaker].FirstEnd;

            if (!topology.OutageTopology[upBreaker].SecondEnd.Contains(outageElement))
            {
                string message = $"{baseLogString} StartLocationAndIsolationAlgorithm => Outage element with gid: 0x{outageElement:X16} is not on a second end of current breaker id";
                Logger.LogError(message);
                throw new Exception(message);
            }

            outageEntity.OptimumIsolationPoints = await lifecycleHelper.GetEquipmentEntityAsync(new List <long>() { upBreaker, nextBreaker });

            outageEntity.IsolatedTime = DateTime.UtcNow;
            outageEntity.OutageState  = OutageState.ISOLATED;

            await outageModelAccessClient.UpdateOutage(outageEntity);

            var commands = new Dictionary <long, DiscreteCommandingType>
            {
                { upBreaker, DiscreteCommandingType.OPEN },
                { nextBreaker, DiscreteCommandingType.OPEN },
            };

            var enumerableCommandedElements = await CommandedElements.GetEnumerableDictionaryAsync();

            if (!await lifecycleHelper.SendMultipleScadaCommandAsync(commands, enumerableCommandedElements, CommandOriginType.LOCATION_AND_ISOLATING_ALGORITHM_COMMAND))
            {
                string message = $"{baseLogString} StartLocationAndIsolationAlgorithm => Sending multiple command failed.";
                Logger.LogError(message);
                return(false);
            }

            commands.Keys.ToList().ForEach(async commandedElementGid =>
            {
                await ElementsToBeIgnoredInReportPotentialOutage.SetAsync(commandedElementGid, DateTime.UtcNow);
                Logger.LogDebug($"{baseLogString} SendCommands => Element 0x{commandedElementGid:X16} set to collection '{ReliableDictionaryNames.ElementsToBeIgnoredInReportPotentialOutage}' at {DateTime.UtcNow}.");
            });

            return(true);
        }
 public Task UpdateOutage(OutageEntity outage)
 {
     return(InvokeWithRetryAsync(client => client.Channel.UpdateOutage(outage)));
 }
        public bool StartLocationAndIsolationAlgorithm(OutageEntity outageEntity)
        {
            IOutageTopologyElement topologyElement = null;

            long reportedGid     = outageEntity.DefaultIsolationPoints.First().EquipmentId;
            long outageElementId = -1;
            long UpBreaker;

            Task.Delay(5000).Wait();
            using (OutageSimulatorServiceProxy proxy = proxyFactory.CreateProxy <OutageSimulatorServiceProxy, IOutageSimulatorContract>(EndpointNames.OutageSimulatorServiceEndpoint))
            {
                if (proxy == null)
                {
                    string message = "OutageModel::SendLocationIsolationCrew => OutageSimulatorProxy is null";
                    Logger.LogError(message);
                    throw new NullReferenceException(message);
                }
                //Da li je prijaveljen element OutageElement
                if (proxy.IsOutageElement(reportedGid))
                {
                    outageElementId = reportedGid;
                }
                else
                {
                    //Da li je mozda na ACL-novima ispod prijavljenog elementa
                    if (outageModel.TopologyModel.GetElementByGid(reportedGid, out topologyElement))
                    {
                        try
                        {
                            for (int i = 0; i < topologyElement.SecondEnd.Count; i++)
                            {
                                if (proxy.IsOutageElement(topologyElement.SecondEnd[i]))
                                {
                                    if (outageElementId == -1)
                                    {
                                        outageElementId = topologyElement.SecondEnd[i];
                                        outageEntity.OutageElementGid = outageElementId;
                                    }
                                    else
                                    {
                                        OutageEntity entity = new OutageEntity()
                                        {
                                            OutageElementGid = topologyElement.SecondEnd[i], ReportTime = DateTime.UtcNow
                                        };
                                        dbContext.OutageRepository.Add(entity);
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.LogError("OutageModel::SendLocationIsolationCrew => failed with error", ex);
                            throw;
                        }
                    }
                }
                //Tragamo za ACL-om gore ka source-u
                while (outageElementId == -1 && !topologyElement.IsRemote && topologyElement.DmsType != "ENERGYSOURCE")
                {
                    if (proxy.IsOutageElement(topologyElement.Id))
                    {
                        outageElementId = topologyElement.Id;
                        outageEntity.OutageElementGid = outageElementId;
                    }
                    outageModel.TopologyModel.GetElementByGid(topologyElement.FirstEnd, out topologyElement);
                }
                if (outageElementId == -1)
                {
                    outageEntity.OutageState = OutageState.REMOVED;
                    dbContext.OutageRepository.Remove(outageEntity);
                    Logger.LogError("End of feeder no outage detected.");
                    return(false);
                }
                outageModel.TopologyModel.GetElementByGidFirstEnd(outageEntity.OutageElementGid, out topologyElement);
                while (topologyElement.DmsType != "BREAKER")
                {
                    outageModel.TopologyModel.GetElementByGidFirstEnd(topologyElement.Id, out topologyElement);
                }
                UpBreaker = topologyElement.Id;
                long nextBreaker = outageModel.GetNextBreaker(outageEntity.OutageElementGid);

                if (!outageModel.TopologyModel.OutageTopology.ContainsKey(nextBreaker))
                {
                    string message = $"Breaker (next breaker) with id: 0x{nextBreaker:X16} is not in topology";
                    Logger.LogError(message);
                    throw new Exception(message);
                }

                long outageElement = outageModel.TopologyModel.OutageTopology[nextBreaker].FirstEnd;

                if (!outageModel.TopologyModel.OutageTopology[UpBreaker].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);
                }
                outageEntity.OptimumIsolationPoints = outageModel.GetEquipmentEntity(new List <long>()
                {
                    UpBreaker, nextBreaker
                });
                outageEntity.IsolatedTime = DateTime.UtcNow;
                outageEntity.OutageState  = OutageState.ISOLATED;

                dbContext.OutageRepository.Update(outageEntity);
                SendSCADACommand(UpBreaker, DiscreteCommandingType.OPEN);
                SendSCADACommand(nextBreaker, DiscreteCommandingType.OPEN);
            }

            return(true);
        }
Ejemplo n.º 24
0
        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);
        }
Ejemplo n.º 25
0
        private async Task UpdateRecloserOutageMap(long recloserId, List <long> affectedConsumersGids, OutageEntity createdActiveOutage)
        {
            var enumerableRecloserOutageMap = await RecloserOutageMap.GetEnumerableDictionaryAsync();

            if (enumerableRecloserOutageMap.TryGetValue(recloserId, out Dictionary <long, List <long> > outageToAffectedConsumersMap))
            {
                if (outageToAffectedConsumersMap.ContainsKey(createdActiveOutage.OutageId))
                {
                    outageToAffectedConsumersMap[createdActiveOutage.OutageId] = new List <long>(affectedConsumersGids);
                }
                else
                {
                    outageToAffectedConsumersMap.Add(createdActiveOutage.OutageId, affectedConsumersGids);
                }

                await RecloserOutageMap.SetAsync(recloserId, outageToAffectedConsumersMap);
            }
            else
            {
                var outageIdToAffectedConsumersMap = new Dictionary <long, List <long> >()
                {
                    { createdActiveOutage.OutageId, affectedConsumersGids }
                };

                await RecloserOutageMap.SetAsync(recloserId, outageIdToAffectedConsumersMap);
            }
        }
 public Task <OutageEntity> AddOutage(OutageEntity outage)
 {
     return(InvokeWithRetryAsync(client => client.Channel.AddOutage(outage)));
 }