public bool Prepare() { bool success = false; transactionDbContext = new UnitOfWork(); Dictionary <long, ResourceDescription> resourceDescriptions = GetExtentValues(ModelCode.ENERGYCONSUMER, modelResourcesDesc.GetAllPropertyIds(ModelCode.ENERGYCONSUMER)); List <Consumer> consumerDbEntities = transactionDbContext.ConsumerRepository.GetAll().ToList(); foreach (Consumer consumer in consumerDbEntities) { if (modelChanges[DeltaOpType.Delete].Contains(consumer.ConsumerId)) { transactionDbContext.ConsumerRepository.Remove(consumer); } else if (modelChanges[DeltaOpType.Update].Contains(consumer.ConsumerId)) { consumer.ConsumerMRID = resourceDescriptions[consumer.ConsumerId].GetProperty(ModelCode.IDOBJ_MRID).AsString(); //TODO other prop, when added in model } } foreach (long gid in modelChanges[DeltaOpType.Insert]) { ModelCode type = modelResourcesDesc.GetModelCodeFromId(gid); if (type == ModelCode.ENERGYCONSUMER) { ResourceDescription resourceDescription = resourceDescriptions[gid]; if (resourceDescription != null) { Consumer consumer = new Consumer { ConsumerId = resourceDescription.Id, ConsumerMRID = resourceDescription.GetProperty(ModelCode.IDOBJ_MRID).AsString(), FirstName = "Added", //TODO: resourceDescription.GetProperty(ModelCode.ENERGYCONSUMER_FIRSTNAME).AsString() LastName = "Consumer" //TODO: resourceDescription.GetProperty(ModelCode.ENERGYCONSUMER_LASTNAME).AsString() other prop, when added in model }; transactionDbContext.ConsumerRepository.Add(consumer); } else { Logger.LogWarn($"Consumer with gid 0x{gid:X16} is not in network model"); } } } success = true; return(success); }
//popunjavanje 3. comboboxa iz 3. taba private void comboBox5_SelectedIndexChanged(object sender, EventArgs e) { listaPropertija.Clear(); button3.Enabled = false; richTextBox2.Text = string.Empty; comboBox6.Items.Clear(); richTextBox4.Controls.Clear(); richTextBox4.Clear(); try { long gid = (long)comboBox5.SelectedItem; ModelCode mc = modelRD.GetModelCodeFromId(gid); ResourceDescription rd = gda.GetValues(gid); for (int i = 0; i < rd.Properties.Count; i++) { switch (rd.Properties[i].Type) { case PropertyType.Reference: listaPropertija.Add(rd.Properties[i].Id); break; case PropertyType.ReferenceVector: listaPropertija.Add(rd.Properties[i].Id); break; } } foreach (var v in listaPropertija) { comboBox6.Items.Add(v); } } catch { richTextBox2.Text = "ERROR!"; } if (comboBox5.SelectedItem != null) { comboBox6.Enabled = true; tipoviReferenciranihKlasa.Clear(); } else { comboBox6.Enabled = false; } }
public TopologyStatus GetElementTopologyStatus(long gid) { logger.LogDebug($"Getting element topology status for GID {gid}."); TopologyStatus retVal; DMSType type = ModelCodeHelper.GetTypeFromModelCode(modelResourcesDesc.GetModelCodeFromId(gid)); foreach (var item in elementsStatus) { if (item.Value.Contains(type)) { retVal = item.Key; return(retVal); } } return(TopologyStatus.Regular); }
public async Task Notify(IPublishableMessage message, string publisherName) { while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } if (message is EmailToOutageMessage emailMessage) { if (emailMessage.Gid == 0) { Logger.LogError("Invalid email received."); return; } Logger.LogInformation($"Received call from Energy Consumer with GID: 0x{emailMessage.Gid:X16}."); if (!modelResourcesDesc.GetModelCodeFromId(emailMessage.Gid).Equals(ModelCode.ENERGYCONSUMER)) { Logger.LogWarning($"Received GID 0x{emailMessage.Gid:X16} is not id of energy consumer."); return; } var topologyProviderClient = TopologyProviderClient.CreateClient(); var topology = await topologyProviderClient.GetOMSModel(); if (!topology.GetElementByGid(emailMessage.Gid, out OutageTopologyElement elment)) { Logger.LogWarning($"Received GID 0x{emailMessage.Gid:X16} is not part of topology."); return; } if (!timer.Enabled) { timer.Start(); } await Calls.SetAsync(emailMessage.Gid, emailMessage.Gid); Logger.LogInformation($"Current number of calls is: {await Calls.GetCountAsync()}."); if (await Calls.GetCountAsync() >= expectedCalls) { await trackingAlgorithm.Start((await Calls.GetDataCopyAsync()).Keys.ToList()); await Calls.ClearAsync(); timer.Stop(); } } }
public void Notify(IPublishableMessage message) { if (message is EmailToOutageMessage emailMessage) { if (emailMessage.Gid == 0) { Logger.LogError("Invalid email received."); return; } Logger.LogInfo($"Received call from Energy Consumer with GID: 0x{emailMessage.Gid:X16}."); if (!resourcesDesc.GetModelCodeFromId(emailMessage.Gid).Equals(ModelCode.ENERGYCONSUMER)) { Logger.LogWarn("Received GID is not id of energy consumer."); } else if (!outageModel.TopologyModel.OutageTopology.ContainsKey(emailMessage.Gid) && outageModel.TopologyModel.FirstNode != emailMessage.Gid) { Logger.LogWarn("Received GID is not part of topology"); } else { if (!timer.Enabled) //first message { StartTimer(); } calls.Enqueue(emailMessage.Gid); Logger.LogInfo($"Current number of calls is: {calls.Count}."); if (calls.Count >= expectedCalls) { trackingAlgorithm.Start(calls); StopTimer(); } } } else { Logger.LogWarn("Received message is not EmailToOutageMessage."); } }
public async Task <bool> Prepare() { bool success; while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } try { //INIT INCOMING SCADA MODEL with current model values await InitializeIncomingScadaModel(); //IMPORT ALL measurements from NMS and create PointItems for them var enumerableModelChanges = await ModelChanges.GetEnumerableDictionaryAsync(); Dictionary <long, IScadaModelPointItem> incomingPointItems = await CreatePointItemsFromNetworkModelMeasurements(enumerableModelChanges); //ORDER IS IMPORTANT due to IncomingAddressToGidMap validity: DELETE => UPDATE => INSERT var orderOfOperations = new List <DeltaOpType>() { DeltaOpType.Delete, DeltaOpType.Update, DeltaOpType.Insert }; foreach (var operation in orderOfOperations) { foreach (long gid in enumerableModelChanges[(byte)operation]) { ModelCode type = modelResourceDesc.GetModelCodeFromId(gid); if (type != ModelCode.ANALOG && type != ModelCode.DISCRETE) { continue; } if (operation == DeltaOpType.Delete) { await HandleDeleteOperation(gid); } else if (operation == DeltaOpType.Update) { IScadaModelPointItem incomingPointItem = incomingPointItems[gid]; await HandleUpdateOperation(incomingPointItem, gid); } else if (operation == DeltaOpType.Insert) { IScadaModelPointItem incomingPointItem = incomingPointItems[gid]; await HandleInsertOperation(incomingPointItem, gid); } } } success = await CheckSuccessiveAddressCondition(); ; } catch (Exception e) { string errorMessage = $"{baseLogString} Prepare => Exception: {e.Message}"; Logger.LogError(errorMessage, e); success = false; } return(success); }
public async Task <bool> Prepare() { bool success; try { //INIT INCOMING SCADA MODEL with current model values //can not go with just 'incomingScadaModel = new Dictionary<long, ISCADAModelPointItem>(CurrentScadaModel)' because IncomingAddressToGidMap must also be initialized incomingScadaModel = new Dictionary <long, ISCADAModelPointItem>(CurrentScadaModel.Count); foreach (long gid in CurrentScadaModel.Keys) { ModelCode type = modelResourceDesc.GetModelCodeFromId(gid); ISCADAModelPointItem pointItem = CurrentScadaModel[gid].Clone(); IncomingScadaModel.Add(gid, pointItem); if (!IncomingAddressToGidMap[pointItem.RegisterType].ContainsKey(pointItem.Address)) { IncomingAddressToGidMap[pointItem.RegisterType].Add(pointItem.Address, gid); } } //IMPORT ALL measurements from NMS and create PointItems for them Dictionary <long, ISCADAModelPointItem> incomingPointItems = await CreatePointItemsFromNetworkModelMeasurements(); //ORDER IS IMPORTANT due to IncomingAddressToGidMap validity: DELETE => UPDATE => INSERT foreach (long gid in modelChanges[DeltaOpType.Delete]) { ModelCode type = modelResourceDesc.GetModelCodeFromId(gid); if (type == ModelCode.ANALOG || type == ModelCode.DISCRETE) { if (!IncomingScadaModel.ContainsKey(gid)) { success = false; string message = $"Model update data in fault state. Deleting entity with gid: {gid}, that does not exists in SCADA model."; Logger.LogError(message); throw new ArgumentException(message); } ISCADAModelPointItem oldPointItem = IncomingScadaModel[gid]; IncomingScadaModel.Remove(gid); IncomingAddressToGidMap[oldPointItem.RegisterType].Remove(oldPointItem.Address); } } foreach (long gid in modelChanges[DeltaOpType.Update]) { ModelCode type = modelResourceDesc.GetModelCodeFromId(gid); if (type == ModelCode.ANALOG || type == ModelCode.DISCRETE) { if (!IncomingScadaModel.ContainsKey(gid)) { success = false; string message = $"Model update data in fault state. Updating entity with gid: 0x{gid:X16}, that does not exists in SCADA model."; Logger.LogError(message); throw new ArgumentException(message); } ISCADAModelPointItem incomingPointItem = incomingPointItems[gid]; ISCADAModelPointItem oldPointItem = IncomingScadaModel[gid]; if (!IncomingAddressToGidMap[oldPointItem.RegisterType].ContainsKey(oldPointItem.Address)) { success = false; string message = $"Model update data in fault state. Updating point with address: {oldPointItem.Address}, that does not exists in SCADA model."; Logger.LogError(message); throw new ArgumentException(message); } if (oldPointItem.Address != incomingPointItem.Address && IncomingAddressToGidMap[incomingPointItem.RegisterType].ContainsKey(incomingPointItem.Address)) { success = false; string message = $"Model update data in fault state. Trying to add point with address: {incomingPointItem.Address}, that already exists in SCADA model."; Logger.LogError(message); throw new ArgumentException(message); } IncomingScadaModel[gid] = incomingPointItem; if (oldPointItem.Address != incomingPointItem.Address) { IncomingAddressToGidMap[oldPointItem.RegisterType].Remove(oldPointItem.Address); IncomingAddressToGidMap[incomingPointItem.RegisterType].Add(incomingPointItem.Address, gid); } } } foreach (long gid in modelChanges[DeltaOpType.Insert]) { ModelCode type = modelResourceDesc.GetModelCodeFromId(gid); if (type == ModelCode.ANALOG || type == ModelCode.DISCRETE) { if (IncomingScadaModel.ContainsKey(gid)) { success = false; string message = $"Model update data in fault state. Inserting gid: {gid}, that already exists in SCADA model."; Logger.LogError(message); throw new ArgumentException(message); } ISCADAModelPointItem incomingPointItem = incomingPointItems[gid]; if (IncomingAddressToGidMap[incomingPointItem.RegisterType].ContainsKey(incomingPointItem.Address)) { success = false; string message = $"Model update data in fault state. Trying to add point with address: {incomingPointItem.Address}, that already exists in SCADA model."; Logger.LogError(message); throw new ArgumentException(message); } IncomingScadaModel.Add(gid, incomingPointItem); IncomingAddressToGidMap[incomingPointItem.RegisterType].Add(incomingPointItem.Address, gid); } } success = true; } catch (Exception e) { Logger.LogError($"Exception caught in Prepare method on SCADAModel.", e); success = false; } return(success); }
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 async Task <bool> Prepare() { bool success; try { Logger.LogDebug("Enter prepare method"); this.unitOfWork = new UnitOfWork(); List <Consumer> consumerDbEntities = this.unitOfWork.ConsumerRepository.GetAll().ToList(); var resourceDescriptions = await GetExtentValues(ModelCode.ENERGYCONSUMER, modelResourcesDesc.GetAllPropertyIds(ModelCode.ENERGYCONSUMER)); var modelChangesEnumerable = await HistoryModelChanges.GetEnumerableDictionaryAsync(); List <OutageEntity> activeOutages = this.unitOfWork.OutageRepository.GetAllActive().ToList(); this.unitOfWork.OutageRepository.RemoveRange(activeOutages); //this.unitOfWork.OutageRepository.RemoveAll(); //this.unitOfWork.EquipmentRepository.RemoveAll(); //this.unitOfWork.EquipmentHistoricalRepository.RemoveAll(); //this.unitOfWork.ConsumerHistoricalRepository.RemoveAll(); foreach (Consumer consumer in consumerDbEntities) { if (modelChangesEnumerable[(byte)DeltaOpType.Delete].Contains(consumer.ConsumerId)) { this.unitOfWork.ConsumerRepository.Remove(consumer); } else if (modelChangesEnumerable[(byte)DeltaOpType.Update].Contains(consumer.ConsumerId)) { consumer.ConsumerMRID = resourceDescriptions[consumer.ConsumerId].GetProperty(ModelCode.IDOBJ_MRID).AsString(); consumer.FirstName = resourceDescriptions[consumer.ConsumerId].GetProperty(ModelCode.ENERGYCONSUMER_FIRSTNAME).AsString(); consumer.LastName = resourceDescriptions[consumer.ConsumerId].GetProperty(ModelCode.ENERGYCONSUMER_LASTNAME).AsString(); consumer.Type = (EnergyConsumerType)resourceDescriptions[consumer.ConsumerId].GetProperty(ModelCode.ENERGYCONSUMER_TYPE).AsEnum(); consumer.Outages.Clear(); this.unitOfWork.ConsumerRepository.Update(consumer); } } foreach (long gid in modelChangesEnumerable[(byte)DeltaOpType.Insert]) { ModelCode type = modelResourcesDesc.GetModelCodeFromId(gid); if (type != ModelCode.ENERGYCONSUMER) { continue; } ResourceDescription resourceDescription = resourceDescriptions[gid]; if (resourceDescription == null) { Logger.LogWarning($"Consumer with gid 0x{gid:X16} is not in network model"); continue; } Consumer consumer = new Consumer { ConsumerId = resourceDescription.Id, ConsumerMRID = resourceDescription.GetProperty(ModelCode.IDOBJ_MRID).AsString(), FirstName = resourceDescription.GetProperty(ModelCode.ENERGYCONSUMER_FIRSTNAME).AsString(), LastName = resourceDescription.GetProperty(ModelCode.ENERGYCONSUMER_LASTNAME).AsString(), Type = (EnergyConsumerType)resourceDescriptions[resourceDescription.Id].GetProperty(ModelCode.ENERGYCONSUMER_TYPE).AsEnum(), }; if (this.unitOfWork.ConsumerRepository.Get(consumer.ConsumerId) == null) { this.unitOfWork.ConsumerRepository.Add(consumer); } else { Logger.LogWarning($"{baseLogString} Prepare => Consumer with gid 0x{consumer.ConsumerId:X16} already exists in DB. Delta Operation: {DeltaOpType.Insert}. Potential fixes: " + $"{Environment.NewLine}If MongoDB is empty => Delte rows from Consumer Table. " + $"{Environment.NewLine}If Mongo contains stored NetworkModel => Ignore this warn as it is part of initialization (part of the first distributed transaction)."); } } success = true; } catch (Exception e) { string message = $"{baseLogString} Prepare => Exception: {e.Message}"; Logger.LogError(message, e); success = false; this.unitOfWork.Dispose(); } return(success); }
private async Task <bool> ImportAnalog() { bool success; int numberOfResources = 1000; List <ModelCode> props = modelResourceDesc.GetAllPropertyIds(ModelCode.ANALOG); try { var nmsGdaClient = NetworkModelGdaClient.CreateClient(); int iteratorId = await nmsGdaClient.GetExtentValues(ModelCode.ANALOG, props); int resourcesLeft = await nmsGdaClient.IteratorResourcesLeft(iteratorId); while (resourcesLeft > 0) { List <ResourceDescription> rds = await nmsGdaClient.IteratorNext(numberOfResources, iteratorId); for (int i = 0; i < rds.Count; i++) { if (rds[i] == null) { continue; } long gid = rds[i].Id; ModelCode type = modelResourceDesc.GetModelCodeFromId(gid); AnalogPointItem analogPoint = new AnalogPointItem(AlarmConfigDataHelper.GetAlarmConfigData()); string debugMessage = $"{baseLogString} ImportAnalog => Before Initialization => Gid: 0x{analogPoint.Gid:X16}, Address: {analogPoint.Address}, CurrentRawValue: {analogPoint.CurrentRawValue}, Alarm: {analogPoint.Alarm}, ScalingFactor: {analogPoint.ScalingFactor}, Deviation: {analogPoint.Deviation}, MinRawValue: {analogPoint.MinRawValue}, MaxRawValue: {analogPoint.MaxRawValue}, NormalValue: {analogPoint.NormalValue}, RegisterType: {analogPoint.RegisterType}, Name: {analogPoint.Name}, Initialized: {analogPoint.Initialized}"; Logger.LogDebug(debugMessage); pointItemHelper.InitializeAnalogPointItem(analogPoint, rds[i].Properties, ModelCode.ANALOG, enumDescs); debugMessage = $"{baseLogString} ImportAnalog => After Initialization => Gid: 0x{analogPoint.Gid:X16}, Address: {analogPoint.Address}, CurrentRawValue: {analogPoint.CurrentRawValue}, Alarm: {analogPoint.Alarm}, ScalingFactor: {analogPoint.ScalingFactor}, Deviation: {analogPoint.Deviation}, MinRawValue: {analogPoint.MinRawValue}, MaxRawValue: {analogPoint.MaxRawValue}, NormalValue: {analogPoint.NormalValue}, RegisterType: {analogPoint.RegisterType}, Name: {analogPoint.Name}, Initialized: {analogPoint.Initialized}"; Logger.LogDebug(debugMessage); if (await GidToPointItemMap.ContainsKeyAsync(gid)) { string errorMessage = $"{baseLogString} ImportAnalog => SCADA model is invalid => Gid: 0x{gid:16} belongs to more than one entity."; Logger.LogError(errorMessage); throw new InternalSCADAServiceException(errorMessage); } await GidToPointItemMap.SetAsync(gid, analogPoint); #if DEBUG var pointItemResult = await GidToPointItemMap.TryGetValueAsync(gid); if (pointItemResult.HasValue) { AnalogPointItem controlPointItem = pointItemResult.Value as AnalogPointItem; debugMessage = $"{baseLogString} ImportAnalog => Control after CurrentGidToPointItemMap.SetAsync => Gid: 0x{controlPointItem.Gid:X16}, Address: {controlPointItem.Address}, CurrentRawValue: {controlPointItem.CurrentRawValue}, Alarm: {controlPointItem.Alarm}, ScalingFactor: {controlPointItem.ScalingFactor}, Deviation: {controlPointItem.Deviation}, MinRawValue: {controlPointItem.MinRawValue}, MaxRawValue: {controlPointItem.MaxRawValue}, NormalValue: {controlPointItem.NormalValue}, RegisterType: {controlPointItem.RegisterType}, Name: {controlPointItem.Name}, Initialized: {controlPointItem.Initialized}"; Logger.LogDebug(debugMessage); } else { string warningMessage = $"{baseLogString} ImportAnalog => Control after CurrentGidToPointItemMap.SetAsync => Gid: 0x{gid:X16} was not found in reliable collection '{ReliableDictionaryNames.GidToPointItemMap}' after the value was supposedly set."; Logger.LogWarning(warningMessage); } #endif short registerType = (short)analogPoint.RegisterType; if (!(await AddressToGidMap.ContainsKeyAsync(registerType))) { await AddressToGidMap.SetAsync(registerType, new Dictionary <ushort, long>()); } var addressToGidDictionaryResult = await AddressToGidMap.TryGetValueAsync(registerType); if (!addressToGidDictionaryResult.HasValue) { string message = $"{baseLogString} ImportAnalog => reliable collection '{ReliableDictionaryNames.AddressToGidMap}' is not initialized properly."; Logger.LogError(message); throw new InternalSCADAServiceException(message); } var addressToGidDictionary = addressToGidDictionaryResult.Value; if (addressToGidDictionary.ContainsKey(analogPoint.Address)) { string message = $"{baseLogString} ImportAnalog => SCADA model is invalid => Address: {analogPoint.Address} (RegType: {registerType}) belongs to more than one entity."; Logger.LogError(message); throw new InternalSCADAServiceException(message); } addressToGidDictionary.Add(analogPoint.Address, rds[i].Id); await AddressToGidMap.SetAsync(registerType, addressToGidDictionary); debugMessage = $"{baseLogString} ImportAnalog => ANALOG measurement added to SCADA model [Gid: 0x{gid:X16}, Address: {analogPoint.Address}]"; Logger.LogDebug(debugMessage); } resourcesLeft = await nmsGdaClient.IteratorResourcesLeft(iteratorId); } await nmsGdaClient.IteratorClose(iteratorId); success = true; } catch (Exception ex) { success = false; string errorMessage = $"{baseLogString} ImportAnalog => failed with error: {ex.Message}"; Trace.WriteLine(errorMessage); Logger.LogError(errorMessage, ex); } return(success); }