private async Task <ITopologyElement> CreateNoScadaMeasurementAsync(ITopologyElement element) { string verboseMessage = $"{baseLogString} entering CreateNoScadaMeasurement method."; Logger.LogVerbose(verboseMessage); DMSType dMSType = GetDMSTypeOfTopologyElement(element.Id); if (dMSType == DMSType.LOADBREAKSWITCH || dMSType == DMSType.BREAKER || dMSType == DMSType.FUSE || dMSType == DMSType.DISCONNECTOR) { ArtificalDiscreteMeasurement measurement = GetNoScadaDiscreteMeasurement(); element.Measurements.Add(measurement.Id, "SWITCH_STATUS"); measurement.ElementId = element.Id; var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.AddDiscreteMeasurement(measurement); measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.AddMeasurementElementPair(measurement.Id, element.Id); } return(element); }
private async Task TurnOffAllMeasurement(Dictionary <long, string> measurements) { string verboseMessage = $"{baseLogString} TurnOffAllMeasurement method called => Measurements count: {measurements.Count}."; Logger.LogVerbose(verboseMessage); List <AnalogMeasurement> analogMeasurements = await GetMeasurements(measurements); var commands = new Dictionary <long, float>(); var modbusData = new Dictionary <long, AnalogModbusData>(); foreach (var meas in analogMeasurements) { Logger.LogDebug($"{baseLogString} TurnOffAllMeasurement => Adding Command method from measurement provider. Measurement GID {meas.Id:X16}."); commands.Add(meas.Id, 0); modbusData.Add(meas.Id, new AnalogModbusData(0, AlarmType.NO_ALARM, meas.Id, CommandOriginType.CE_COMMAND)); } var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.SendMultipleAnalogCommand(commands, CommandOriginType.CE_COMMAND); Logger.LogDebug($"{baseLogString} TurnOffAllMeasurement => SendAnalogCommand method from measurement provider has been called successfully."); Logger.LogDebug($"{baseLogString} TurnOffAllMeasurement => Calling UpdateAnalogMeasurement method from measurement provider."); await measurementProviderClient.UpdateAnalogMeasurement(modbusData); Logger.LogDebug($"{baseLogString} TurnOffAllMeasurement => UpdateAnalogMeasurement method from measurement provider has been called successfully."); }
private async Task TurnOnAllMeasurement(Dictionary <long, string> measurements) { string verboseMessage = $"{baseLogString} TurnOnAllMeasurement method called. Measurements count: {measurements.Count}"; Logger.LogVerbose(verboseMessage); List <AnalogMeasurement> analogMeasurements = await GetMeasurements(measurements); var commands = new Dictionary <long, float>(); var modbusData = new Dictionary <long, AnalogModbusData>(); foreach (var meas in analogMeasurements) { commands.Add(meas.Id, meas.NormalValue); modbusData.Add(meas.Id, new AnalogModbusData(meas.NormalValue, AlarmType.NO_ALARM, meas.Id, CommandOriginType.CE_COMMAND)); } var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.SendMultipleAnalogCommand(commands, CommandOriginType.CE_COMMAND); Logger.LogDebug($"{baseLogString} TurnOnAllMeasurement => Calling update analog measurement method from measurement provider."); await measurementProviderClient.UpdateAnalogMeasurement(modbusData); Logger.LogDebug($"{baseLogString} TurnOnAllMeasurement => Update analog measurement method from measurement provider successfully finished."); }
private async Task <List <AnalogMeasurement> > GetMeasurements(Dictionary <long, string> measurements) { string verboseMessage = $"{baseLogString} GetMeasurements method called."; Logger.LogVerbose(verboseMessage); List <AnalogMeasurement> analogMeasurements = new List <AnalogMeasurement>(); foreach (var measurement in measurements) { DMSType type = (DMSType)ModelCodeHelper.ExtractTypeFromGlobalId(measurement.Key); if (type == DMSType.ANALOG) { Logger.LogDebug($"{baseLogString} GetMeasurements => Calling GetAnalogMeasurement for GID {measurement.Key:X16} from measurement provider."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); AnalogMeasurement analogMeasurement = await measurementProviderClient.GetAnalogMeasurement(measurement.Key); Logger.LogDebug($"{baseLogString} GetMeasurements => GetAnalogMeasurement method from measurement provider has been called successfully."); if (analogMeasurement == null) { string message = $"{baseLogString} GetMeasurements => GetAnalogMeasurement from measurement provider returned null for measurement GID {measurement.Key:X16}"; Logger.LogWarning(message); continue; } if (measurement.Value.Equals(AnalogMeasurementType.POWER.ToString())) { analogMeasurements.Add(analogMeasurement); } else if (measurement.Value.Equals(AnalogMeasurementType.VOLTAGE.ToString())) { analogMeasurements.Add(analogMeasurement); } else if (measurement.Value.Equals(AnalogMeasurementType.CURRENT.ToString())) { analogMeasurements.Add(analogMeasurement); } else if (measurement.Value.Equals(AnalogMeasurementType.FEEDER_CURRENT.ToString())) { analogMeasurements.Add(analogMeasurement); } else { Logger.LogWarning($"{baseLogString} GetMeasurements => Unknown type [{measurement.Value}] of measurement with GID {measurement.Key:X16}."); } } } return(analogMeasurements); }
public async Task <bool> SendMultipleScadaCommandAsync(Dictionary <long, DiscreteCommandingType> elementGidCommandMap, Dictionary <long, CommandedElement> commandedElements, CommandOriginType commandOriginType) { var measurementMapClient = MeasurementMapClient.CreateClient(); var elementToMeasurementMap = await measurementMapClient.GetElementToMeasurementMap(); var commands = new Dictionary <long, int>(); foreach (var elementGid in elementGidCommandMap.Keys) { var discreteCommandingType = elementGidCommandMap[elementGid]; int reTryCount = 30; while (commandedElements.ContainsKey(elementGid) && commandedElements[elementGid].CommandingType == discreteCommandingType) { Logger.LogDebug($"{baseLogString} SendMultipleScadaCommandAsync => Trying to send duplicate command. Entering delay for 1000 ms and retrying the call."); await Task.Delay(1000); if (--reTryCount <= 0) { Logger.LogError($"{baseLogString} SendMultipleScadaCommandAsync => Trying to send duplicate command. ReTryCount reached 60 calls."); return(false); } } if (!elementToMeasurementMap.TryGetValue(elementGid, out List <long> measurementGids) || measurementGids.Count == 0) { Logger.LogWarning($"{baseLogString} SendMultipleScadaCommandAsync => Element with gid: 0x{elementGid:X16} has no measurements."); return(false); } var measurementGid = measurementGids.FirstOrDefault(); if (measurementGid == 0) { Logger.LogWarning($"{baseLogString} SendMultipleScadaCommandAsync => Measurement gid is 0."); return(false); } commands.Add(measurementGid, (int)elementGidCommandMap[elementGid]); } var measurementProviderClient = MeasurementProviderClient.CreateClient(); return(await measurementProviderClient.SendMultipleDiscreteCommand(commands, commandOriginType)); }
public async Task Notify(IPublishableMessage message, string publisherName) { Logger.LogDebug($"{baseLogString} Notify method invoked."); if (message is SingleAnalogValueSCADAMessage singleAnalog) { Dictionary <long, AnalogModbusData> data = new Dictionary <long, AnalogModbusData>(1) { { singleAnalog.AnalogModbusData.MeasurementGid, singleAnalog.AnalogModbusData }, }; Logger.LogDebug($"{baseLogString} Calling Update analog measurement from measurement provider."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.UpdateAnalogMeasurement(data); } else if (message is MultipleAnalogValueSCADAMessage multipleAnalog) { Logger.LogDebug($"{baseLogString} Calling Update analog measurement from measurement provider."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.UpdateAnalogMeasurement(multipleAnalog.Data); } else if (message is SingleDiscreteValueSCADAMessage singleDiscrete) { Dictionary <long, DiscreteModbusData> data = new Dictionary <long, DiscreteModbusData>(1) { { singleDiscrete.DiscreteModbusData.MeasurementGid, singleDiscrete.DiscreteModbusData }, }; Logger.LogDebug($"{baseLogString} Calling Update discrete measurement from measurement provider."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.UpdateDiscreteMeasurement(data); } else if (message is MultipleDiscreteValueSCADAMessage multipleDiscrete) { Logger.LogDebug($"{baseLogString} Calling Update discrete measurement from measurement provider."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.UpdateDiscreteMeasurement(multipleDiscrete.Data); } else { Logger.LogError($"{baseLogString} ERROR Message has unsupported type [{message.GetType().ToString()}]."); } }
public async Task <Dictionary <long, long> > GetMeasurementToElementMap() { string verboseMessage = $"{baseLogString} entering GetMeasurementToElementMap method."; Logger.LogVerbose(verboseMessage); try { var measurementProviderClient = MeasurementProviderClient.CreateClient(); return(await measurementProviderClient.GetMeasurementToElementMap()); } catch (Exception e) { string message = $"{baseLogString} GetMeasurementToElementMap => " + $"Failed to get measurement to element map from measurement provider client." + $"{Environment.NewLine} Exception message: {e.Message}"; Logger.LogError(message); throw; } }
public async Task <List <long> > GetMeasurementsOfElement(long elementId) { string verboseMessage = $"{baseLogString} entering GetMeasurementsOfElement method."; Logger.LogVerbose(verboseMessage); try { var measurementProviderClient = MeasurementProviderClient.CreateClient(); return(await measurementProviderClient.GetMeasurementsOfElement(elementId)); } catch (Exception e) { string message = $"{baseLogString} GetMeasurementsOfElement => " + $"Failed to get measurements of element with GID {elementId:X16} from measurement provider client." + $"{Environment.NewLine} Exception message: {e.Message}"; Logger.LogError(message); throw; } }
private async Task CommandToRecloser(long measurementGid, int value, CommandOriginType originType, ITopologyElement recloser) { string verboseMessage = $"{baseLogString} CommandToRecloser method called."; Logger.LogVerbose(verboseMessage); if (recloser == null) { string message = $"{baseLogString} CommandToRecloser => NULL value has been passed instead of element."; Logger.LogError(message); throw new Exception(message); } if (!(recloser is Recloser)) { string message = $"{baseLogString} CommandToRecloser => Element with GID {recloser.Id:X16} is not a recloser."; Logger.LogError(message); throw new Exception(message); } Logger.LogDebug($"{baseLogString} CommandToRecloser => Enetring in sleep for 20 seconds."); await Task.Delay(recloserInterval); Logger.LogDebug($"{baseLogString} CommandToRecloser => Waking up after 20 seconds."); var topologyProviderClient = TopologyProviderClient.CreateClient(); int counter = await topologyProviderClient.GetRecloserCount(recloser.Id); if (((Recloser)recloser).MaxNumberOfTries > counter) { topologyProviderClient = TopologyProviderClient.CreateClient(); await topologyProviderClient.RecloserOpened(recloser.Id); Logger.LogDebug($"{baseLogString} CommandToRecloser => Calling SendDiscreteCommand method from measurement provider. Measurement GID: {measurementGid:X16}, Value: {value}, OriginType {originType}."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.SendSingleDiscreteCommand(measurementGid, value, originType); Logger.LogDebug($"{baseLogString} CommandToRecloser => SendDiscreteCommand method has been successfully called."); } }
public async Task <bool> SendCloseCommand(long gid) { string verboseMessage = $"{baseLogString} entering SendCloseCommand method for GID {gid:X16}."; Logger.LogVerbose(verboseMessage); try { var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.SendSingleDiscreteCommand(gid, (int)DiscreteCommandingType.CLOSE, CommandOriginType.USER_COMMAND); return(true); } catch (Exception e) { string message = $"{baseLogString} SendCloseCommand => " + $"Failed to call send discrete command method measurement provider client." + $"{Environment.NewLine} Exception message: {e.Message}"; Logger.LogError(message); return(false); } }
public async Task <UIModel> ConvertTopologyToUIModel(TopologyModel topology) { string verboseMessage = $"{baseLogString} ConvertTopologyToUIModel method called."; Logger.LogVerbose(verboseMessage); if (topology == null) { string message = $"{baseLogString} ConvertTopologyToUIModel => Provider topology is null."; Logger.LogError(message); throw new Exception(message); } UIModel uIModel = new UIModel(); Stack <long> stack = new Stack <long>(); Logger.LogDebug($"{baseLogString} ConvertTopologyToUIModel => Calling GetReclosers method from model provider client."); var modelProviderClient = CeModelProviderClient.CreateClient(); var reclosers = await modelProviderClient.GetReclosers(); Logger.LogDebug($"{baseLogString} ConvertTopologyToUIModel => GetReclosers method from model provider client has been called successfully."); uIModel.FirstNode = topology.FirstNode; stack.Push(topology.FirstNode); long nextElementGid; while (stack.Count > 0) { nextElementGid = stack.Pop(); if (topology.GetElementByGid(nextElementGid, out ITopologyElement element)) { if (!reclosers.Contains(nextElementGid)) { foreach (var child in element.SecondEnd) { long nextElement = child.Id; if (ModelCodeHelper.ExtractTypeFromGlobalId(child.Id) == 0) { if (child is Field field && field.Members.Count > 0) { nextElement = field.Members.First().Id; } else { string message = $"{baseLogString} ConvertTopologyToUIModel => Error while getting field in Topology to UIModel convert. Element is not field or field is empty."; Logger.LogError(message); throw new Exception(message); } } uIModel.AddRelation(element.Id, nextElement); stack.Push(nextElement); } } List <UIMeasurement> measurements = new List <UIMeasurement>(); foreach (var measurementGid in element.Measurements.Keys) { DMSType type = (DMSType)ModelCodeHelper.ExtractTypeFromGlobalId(measurementGid); if (type == DMSType.ANALOG) { Logger.LogDebug($"{baseLogString} ConvertTopologyToUIModel => Calling GetAnalogMeasurement method from measurement provider client for measurement GID {measurementGid:X16}."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); AnalogMeasurement analogMeasurement = await measurementProviderClient.GetAnalogMeasurement(measurementGid); Logger.LogDebug($"{baseLogString} ConvertTopologyToUIModel => GetAnalogMeasurement method from measurement provider client has been called successfully."); measurements.Add(new UIMeasurement() { Gid = analogMeasurement.Id, Type = analogMeasurement.GetMeasurementType(), Value = analogMeasurement.GetCurrentValue() }); } else if (type == DMSType.DISCRETE) { Logger.LogDebug($"{baseLogString} ConvertTopologyToUIModel => Calling GetDiscreteMeasurement method from measurement provider client for measurement GID {measurementGid:X16}."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); DiscreteMeasurement discreteMeasurement = await measurementProviderClient.GetDiscreteMeasurement(measurementGid); Logger.LogDebug($"{baseLogString} ConvertTopologyToUIModel => GetDiscreteMeasurement method from measurement provider client has been called successfully."); measurements.Add(new UIMeasurement() { Gid = discreteMeasurement.Id, Type = discreteMeasurement.GetMeasurementType(), Value = discreteMeasurement.GetCurrentValue() }); } } if (!uIModel.Nodes.ContainsKey(element.Id)) { UINode newUINode = new UINode() { Id = element.Id, Name = element.Name, Mrid = element.Mrid, Description = element.Description, DMSType = element.DmsType, NominalVoltage = element.NominalVoltage, Measurements = measurements, IsActive = element.IsActive, IsRemote = element.IsRemote, NoReclosing = element.NoReclosing }; uIModel.AddNode(newUINode); } }
private async Task <Tuple <bool, float> > IsElementEnergized(ITopologyElement element) { string verboseMessage = $"{baseLogString} IsElementEnergized method called => Element: {element?.Id:X16}."; Logger.LogVerbose(verboseMessage); float load = 0; bool pastState = element.IsActive; element.IsActive = true; foreach (var measurement in element.Measurements) { if ((DMSType)ModelCodeHelper.ExtractTypeFromGlobalId(measurement.Key) == DMSType.DISCRETE || measurement.Key < 10000) { Logger.LogDebug($"{baseLogString} IsElementEnergized => Getting discrete value of {measurement.Key:X16} from measurement provider."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); bool isOpen = await measurementProviderClient.GetDiscreteValue(measurement.Key); Logger.LogDebug($"{baseLogString} IsElementEnergized => Discrete value of {measurement.Key:X16} has been delivered successfully. Result is [{isOpen}]."); // Value je true ako je prekidac otvoren, tada je element neaktivan element.IsActive = !isOpen; break; } } if (element.IsActive) { if (!pastState) { await TurnOnAllMeasurement(element.Measurements); } List <AnalogMeasurement> analogMeasurements = await GetMeasurements(element.Measurements); if (element.DmsType.Equals(DMSType.SYNCHRONOUSMACHINE.ToString())) { if (!syncMachines.ContainsKey(element.Id)) { syncMachines.Add(element.Id, element); } } else { if (element.IsRemote) { float power = 0; float voltage = 0; foreach (var analogMeasurement in analogMeasurements) { if (analogMeasurement.GetMeasurementType().Equals(AnalogMeasurementType.POWER.ToString())) { power = analogMeasurement.GetCurrentValue(); } else if (analogMeasurement.GetMeasurementType().Equals(AnalogMeasurementType.VOLTAGE.ToString())) { voltage = analogMeasurement.GetCurrentValue(); } } if (power != 0 && voltage != 0) { load = (float)Math.Round(power / voltage); } } else if (element is EnergyConsumer consumer) { if (dailyCurves.TryGetValue(EnergyConsumerTypeToDailyCurveConverter.GetDailyCurveType(consumer.Type), out DailyCurve curve)) { load = (float)Math.Round(curve.GetValue((short)DateTime.Now.Hour) * 1000 / 220); } } } } return(new Tuple <bool, float>(element.IsActive, load)); }
public async Task <IModelDelta> TryGetAllModelEntitiesAsync() { string verboseMessage = $"{baseLogString} entering TryGetAllModelEntities method."; Logger.LogVerbose(verboseMessage); while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } ModelDelta modelDelta = new ModelDelta(); try { //var clearTasks = new List<Task> //{ await TopologyElements.ClearAsync(); await Measurements.ClearAsync(); await EnergySources.ClearAsync(); await ElementConnections.ClearAsync(); await MeasurementToConnectedTerminalMap.ClearAsync(); await TerminalToConnectedElementsMap.ClearAsync(); await BaseVoltages.ClearAsync(); await Reclosers.ClearAsync(); //}; //Task.WaitAll(clearTasks.ToArray()); await energySources.SetAsync(ReliableDictionaryNames.EnergySources, new List <long>()); await reclosers.SetAsync(ReliableDictionaryNames.Reclosers, new HashSet <long>()); Logger.LogDebug($"{baseLogString} TryGetAllModelEntities => Getting all network model elements and converting them."); await GetBaseVoltagesAsync(); foreach (var model in ConcreteModels) { if (model != ModelCode.BASEVOLTAGE) { List <ModelCode> properties = modelResourcesDesc.GetAllPropertyIds(model); var elements = await networkModelGda.GetExtentValuesAsync(model, properties); foreach (var element in elements) { try { await TransformToTopologyElementAsync(element); } catch (Exception e) { Logger.LogError($"{baseLogString} TryGetAllModelEntitiesAsync failed." + $" {Environment.NewLine} {e.Message} " + $"{Environment.NewLine} {e.StackTrace}"); } } } } //Parallel.For(0, ConcreteModels.Count, async (i) => //{ // var model = ConcreteModels.ElementAt(i); // if (model != ModelCode.BASEVOLTAGE) // { // List<ModelCode> properties = modelResourcesDesc.GetAllPropertyIds(model); // var elements = await networkModelGda.GetExtentValuesAsync(model, properties); // foreach (var element in elements) // { // try // { // await TransformToTopologyElementAsync(element); // } // catch (Exception e) // { // Logger.LogError($"{baseLogString} TryGetAllModelEntitiesAsync failed." + // $" {Environment.NewLine} {e.Message} " + // $"{Environment.NewLine} {e.StackTrace}"); // } // } // } //}); var enumerableMeasurements = await Measurements.GetEnumerableDictionaryAsync(); List <IMeasurement> updatedMeasurements = new List <IMeasurement>(enumerableMeasurements.Count); foreach (var measurement in enumerableMeasurements.Values) { var elementId = await PutMeasurementsInElements(measurement); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.AddMeasurementElementPair(measurement.Id, elementId); updatedMeasurements.Add(measurement); } foreach (var updatedMeas in updatedMeasurements) { await Measurements.SetAsync(updatedMeas.Id, updatedMeas); } var enumerableTopologyElements = await TopologyElements.GetEnumerableDictionaryAsync(); List <ITopologyElement> updatedElements = new List <ITopologyElement>(enumerableTopologyElements.Count); foreach (var element in enumerableTopologyElements.Values) { if (element.Measurements.Count == 0) { await CreateNoScadaMeasurementAsync(element); updatedElements.Add(element); } } foreach (var updatedEl in updatedElements) { await TopologyElements.SetAsync(updatedEl.Id, updatedEl); } modelDelta.TopologyElements = enumerableTopologyElements; modelDelta.ElementConnections = await ElementConnections.GetEnumerableDictionaryAsync(); var reclosersResult = await Reclosers.TryGetValueAsync(ReliableDictionaryNames.Reclosers); if (reclosersResult.HasValue) { modelDelta.Reclosers = reclosersResult.Value; } else { Logger.LogWarning($"{baseLogString} Reliable collection '{ReliableDictionaryNames.Reclosers}' was not defined yet. Handling..."); await Reclosers.SetAsync(ReliableDictionaryNames.Reclosers, new HashSet <long>()); modelDelta.Reclosers = new HashSet <long>(); } var enegySourcesResult = await EnergySources.TryGetValueAsync(ReliableDictionaryNames.EnergySources); if (reclosersResult.HasValue) { modelDelta.EnergySources = enegySourcesResult.Value; } else { Logger.LogWarning($"{baseLogString} Reliable collection '{ReliableDictionaryNames.EnergySources}' was not defined yet. Handling..."); await EnergySources.SetAsync(ReliableDictionaryNames.EnergySources, new List <long>()); modelDelta.EnergySources = new List <long>(); } } catch (Exception e) { string message = $"{baseLogString} TryGetAllModelEntities => Failed in get all network model elements." + $"{Environment.NewLine} Exception message: {e.Message}" + $"{Environment.NewLine} Stack trace: {e.StackTrace}"; Logger.LogError(message); throw new Exception(message); } return(modelDelta); }
public async Task Notify(IPublishableMessage message, string publisherName) { Logger.LogDebug($"{baseLogString} Notify method started."); while (!ReliableDictionariesInitialized) { await Task.Delay(1000); } try { if (message is MultipleDiscreteValueSCADAMessage multipleDiscreteValueSCADAMessage) { Logger.LogDebug($"{baseLogString} MultipleDiscreteValueSCADAMessage received."); var discreteData = multipleDiscreteValueSCADAMessage.Data; #region HeadBreakers var enumerableHeadBreakerMeasurements = await MonitoredHeadBreakerMeasurements.GetEnumerableDictionaryAsync(); foreach (var headMeasurementGid in enumerableHeadBreakerMeasurements.Keys) { if (!discreteData.ContainsKey(headMeasurementGid)) { continue; } await MonitoredHeadBreakerMeasurements.SetAsync(headMeasurementGid, discreteData[headMeasurementGid]); } #endregion HeadBreakers #region CommandedElements var measurementProviderClient = MeasurementProviderClient.CreateClient(); var enumerableCommandedElements = await CommandedElements.GetEnumerableDictionaryAsync(); foreach (var commandedElementGid in enumerableCommandedElements.Keys) { var measurementGid = (await measurementProviderClient.GetMeasurementsOfElement(commandedElementGid)).FirstOrDefault(); var measurement = await measurementProviderClient.GetDiscreteMeasurement(measurementGid); if (measurement is ArtificalDiscreteMeasurement) { await CommandedElements.TryRemoveAsync(commandedElementGid); Logger.LogInformation($"{baseLogString} Notify => Command on element 0x{commandedElementGid:X16} executed (ArtificalDiscreteMeasurement). New value: {measurement.CurrentOpen}"); continue; } if (!discreteData.ContainsKey(measurementGid)) { continue; } if (discreteData[measurementGid].Value == (ushort)enumerableCommandedElements[commandedElementGid].CommandingType) { if ((await CommandedElements.TryRemoveAsync(commandedElementGid)).HasValue) { Logger.LogInformation($"{baseLogString} Notify => Command on element 0x{commandedElementGid:X16} executed. New value: {discreteData[measurementGid].Value}"); } } } #endregion CommandedElements } else if (message is OMSModelMessage omsModelMessage) { Logger.LogDebug($"{baseLogString} OMSModelMessage received. Count {omsModelMessage.OutageTopologyModel.OutageTopology.Count}"); OutageTopologyModel topology = omsModelMessage.OutageTopologyModel; await OutageTopologyModel.SetAsync(ReliableDictionaryNames.OutageTopologyModel, topology); var reportingOutageClient = PotentialOutageReportingClient.CreateClient(); while (true) { var result = await PotentialOutagesQueue.TryDequeueAsync(); if (!result.HasValue) { break; } var command = result.Value; await reportingOutageClient.ReportPotentialOutage(command.ElementGid, command.CommandOriginType, command.NetworkType); Logger.LogInformation($"{baseLogString} PotentianOutageCommand executed. ElementGid: 0x{command.ElementGid:X16}, OriginType: {command.CommandOriginType}"); } } else { Logger.LogWarning($"{baseLogString} Notify => unexpected type of message: {message.GetType()}"); return; } } catch (Exception e) { string errorMessage = $"{baseLogString} Notify => Exception: {e.Message}"; Logger.LogError(errorMessage, e); } }
private async Task <long> PutMeasurementsInElements(IMeasurement measurement) { string verboseMessage = $"{baseLogString} entering PutMeasurementsInElements method. Measurement GID {measurement?.Id:X16}."; Logger.LogVerbose(verboseMessage); var enumerableMeasurementToConnectedTerminalMap = await MeasurementToConnectedTerminalMap.GetEnumerableDictionaryAsync(); if (enumerableMeasurementToConnectedTerminalMap.TryGetValue(measurement.Id, out long terminalId)) { var enumerableTerminalToConnectedElementsMap = await TerminalToConnectedElementsMap.GetEnumerableDictionaryAsync(); if (enumerableTerminalToConnectedElementsMap.TryGetValue(terminalId, out List <long> connectedElements)) { try { var elementId = connectedElements.Find( e => GetDMSTypeOfTopologyElement(e) != DMSType.CONNECTIVITYNODE && GetDMSTypeOfTopologyElement(e) != DMSType.ANALOG); var enumerableTopologyElements = await TopologyElements.GetEnumerableDictionaryAsync(); if (enumerableTopologyElements.TryGetValue(elementId, out ITopologyElement element)) { if (!element.Measurements.ContainsKey(measurement.Id)) { element.Measurements.Add(measurement.Id, measurement.GetMeasurementType()); } else { Logger.LogWarning($"{baseLogString} PutMeasurementsInElements => element.Measurements contains key: 0x{measurement.Id:X16}"); } measurement.ElementId = elementId; if (measurement is DiscreteMeasurement) { var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.AddDiscreteMeasurement((DiscreteMeasurement)measurement); } if (measurement.GetMeasurementType().Equals(AnalogMeasurementType.FEEDER_CURRENT.ToString())) { await TopologyElements.SetAsync(elementId, new Feeder(element)); } else { await TopologyElements.SetAsync(elementId, element); } } else { Logger.LogError($"{baseLogString} PutMeasurementsInElement => Element with GID 0x{elementId:16X} does not exist in elements dictionary."); } } catch (Exception e) { Logger.LogError($"{baseLogString} PutMeasurementsInElement => {e.Message} {Environment.NewLine} {e.StackTrace}"); //Logger.LogError($"{baseLogString} PutMeasurementsInElement => Failed to find appropriate element for mesuremnt with GID {measurement.Id:16X}. There is no conducting equipment connected to common terminal."); } } else { Logger.LogError($"{baseLogString} PutMeasurementsInElement => Terminal with GID 0x{terminalId:X16} does not exist in terminal to element map."); } } else { Logger.LogError($"{baseLogString} PutMeasurementsInElement => Measurement with GID {measurement.Id:X16} does not exist in mesurement to terminal map."); } return(measurement.ElementId); }
private async Task TransformToTopologyElementAsync(ResourceDescription modelEntity) { string verboseMessage = $"{baseLogString} entering TransformToTopologyElement method."; Logger.LogVerbose(verboseMessage); DMSType dmsType; dmsType = GetDMSTypeOfTopologyElement(modelEntity.Id); if (dmsType == DMSType.DISCRETE) { Measurement newDiscrete = await GetPopulatedDiscreteMeasurement(modelEntity); if (!await Measurements.ContainsKeyAsync(newDiscrete.Id)) { await Measurements.SetAsync(newDiscrete.Id, newDiscrete); //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...) } var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.AddDiscreteMeasurement(newDiscrete as DiscreteMeasurement); } else if (dmsType == DMSType.ANALOG) { Measurement newAnalog = await GetPopulatedAnalogMeasurement(modelEntity); if (!await Measurements.ContainsKeyAsync(newAnalog.Id)) { await Measurements.SetAsync(newAnalog.Id, newAnalog); //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...) } var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.AddAnalogMeasurement(newAnalog as AnalogMeasurement); } else if (dmsType != DMSType.MASK_TYPE && dmsType != DMSType.BASEVOLTAGE) { ITopologyElement newElement = await GetPopulatedElement(modelEntity); //lock (syncObj) //{ if (!await TopologyElements.ContainsKeyAsync(newElement.Id)) { await TopologyElements.SetAsync(newElement.Id, newElement); //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...) } else { Logger.LogDebug($"{baseLogString} TransformToTopologyElementAsync => TopologyElements contain key {newElement.Id:X16}"); } //} if (dmsType == DMSType.ENERGYSOURCE) { var energySourcesResult = await EnergySources.TryGetValueAsync(ReliableDictionaryNames.EnergySources); if (energySourcesResult.HasValue) { var energySources = energySourcesResult.Value; energySources.Add(newElement.Id); await EnergySources.SetAsync(ReliableDictionaryNames.EnergySources, energySources); } else { Logger.LogWarning($"{baseLogString} Reliable collection '{ReliableDictionaryNames.EnergySources}' was not defined yet. Handling..."); await EnergySources.SetAsync(ReliableDictionaryNames.EnergySources, new List <long>() { newElement.Id }); } } //lock (syncObj) //{ if (!await ElementConnections.ContainsKeyAsync(modelEntity.Id)) { await ElementConnections.SetAsync(modelEntity.Id, await GetAllReferencedElements(modelEntity)); //contains moze da bude false, a da kad doje ova linija na red, da vrednost bude popunjena, zato SetAsync, ali onda je sam if suvisan (ne znam da li je kljucan za neku logiku...) } else { Logger.LogDebug($"{baseLogString} TransformToTopologyElementAsync => ElementConnections contain key {modelEntity.Id:X16}"); } //} } }
private async Task SyncMachine(ITopologyElement element, Dictionary <long, float> loadOfFeeders) { string verboseMessage = $"{baseLogString} SyncMachine method called. Element with GID {element?.Id:X16}"; Logger.LogVerbose(verboseMessage); if (element == null) { string message = $"{baseLogString} UpdateLoadFlow => Element is null."; Logger.LogError(message); throw new Exception(message); } if (!(element is SynchronousMachine)) { string message = $"{baseLogString} UpdateLoadFlow => Element is not SynchronousMachine."; Logger.LogError(message); throw new Exception(message); } AnalogMeasurement powerMeasurement = null; AnalogMeasurement voltageMeasurement = null; if (element.Feeder != null) { if (loadOfFeeders.TryGetValue(element.Feeder.Id, out float feederLoad)) { float machineCurrentChange; if (feederLoad > 36) { float improvementFactor = feederLoad - 36; machineCurrentChange = (((SynchronousMachine)element).Capacity >= improvementFactor) ? improvementFactor : ((SynchronousMachine)element).Capacity; } else { machineCurrentChange = 0; } foreach (var meas in element.Measurements) { if (meas.Value.Equals(AnalogMeasurementType.POWER.ToString())) { Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Calling GetAnalogMeasurement method from measurement provider. Measurement GID {meas.Key:X16}."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); powerMeasurement = await measurementProviderClient.GetAnalogMeasurement(meas.Key); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => GetAnalogMeasurement method called successfully."); if (powerMeasurement == null) { Logger.LogError($"{baseLogString} UpdateLoadFlow => Synchronous machine with GID {element.Id:X16} does not have POWER measurement."); } } if (meas.Value.Equals(AnalogMeasurementType.VOLTAGE.ToString())) { Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Calling GetAnalogMeasurement method from measurement provider. Measurement GID {meas.Key:X16}."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); voltageMeasurement = await measurementProviderClient.GetAnalogMeasurement(meas.Key); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => GetAnalogMeasurement method called successfully."); if (voltageMeasurement == null) { Logger.LogError($"{baseLogString} UpdateLoadFlow => Synchronous machine with GID {element.Id:X16} does not have VOLTAGE measurement."); } } } if (powerMeasurement != null && voltageMeasurement != null) { float newNeededPower = machineCurrentChange * voltageMeasurement.GetCurrentValue(); float newSMPower = (((SynchronousMachine)element).Capacity >= newNeededPower) ? newNeededPower : ((SynchronousMachine)element).Capacity; Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Calling SendAnalogCommand method from measurement provider. Measurement GID {powerMeasurement.Id:X16}, Value {newSMPower}."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.SendSingleAnalogCommand(powerMeasurement.Id, newSMPower, CommandOriginType.CE_COMMAND); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => SendAnalogCommand method called successfully."); Dictionary <long, AnalogModbusData> data = new Dictionary <long, AnalogModbusData>(1) { { powerMeasurement.Id, new AnalogModbusData(newSMPower, AlarmType.NO_ALARM, powerMeasurement.Id, CommandOriginType.CE_COMMAND) } }; Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Calling UpdateAnalogMeasurement method from measurement provider."); measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.UpdateAnalogMeasurement(data); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => UpdateAnalogMeasurement method called successfully."); loadOfFeeders[element.Feeder.Id] -= newSMPower / voltageMeasurement.GetCurrentValue(); } else { Logger.LogError($"{baseLogString} UpdateLoadFlow => Synchronous machine with GID {element.Id:X16} does not have measurements for calculating CURRENT."); } } } else { Logger.LogError($"{baseLogString} UpdateLoadFlow => Synchronous machine with GID {element.Id:X16} does not belond to any feeder."); } }
public async Task <TopologyModel> UpdateLoadFlow(TopologyModel inputTopology) { string verboseMessage = $"{baseLogString} UpdateLoadFlow method called."; Logger.LogVerbose(verboseMessage); TopologyModel topology = inputTopology; try { Dictionary <long, float> loadOfFeeders = new Dictionary <long, float>(); feeders = new Dictionary <long, ITopologyElement>(); syncMachines = new Dictionary <long, ITopologyElement>(); dailyCurves = DailyCurveReader.ReadDailyCurves(); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Getting reclosers from model provider."); var modelProviderClient = CeModelProviderClient.CreateClient(); reclosers = await modelProviderClient.GetReclosers(); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Reclosers were delivered successfully."); if (topology == null) { string message = $"{baseLogString} UpdateLoadFlow => Topology is null."; Logger.LogWarning(message); //throw new Exception(message); return(topology); } await CalculateLoadFlow(topology, loadOfFeeders); await UpdateLoadFlowFromRecloser(topology, loadOfFeeders); foreach (var syncMachine in syncMachines.Values) { await SyncMachine(syncMachine, loadOfFeeders); } var commands = new Dictionary <long, float>(); var modbusData = new Dictionary <long, AnalogModbusData>(); foreach (var loadFeeder in loadOfFeeders) { if (feeders.TryGetValue(loadFeeder.Key, out ITopologyElement feeder)) { long signalGid = 0; foreach (var measurement in feeder.Measurements) { if (measurement.Value.Equals(AnalogMeasurementType.FEEDER_CURRENT.ToString())) { signalGid = measurement.Key; } } if (signalGid != 0) { Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Calling SendAnalogCommand method from measurement provider. Measurement GID {signalGid:X16}, Value {loadFeeder.Value}."); commands.Add(signalGid, loadFeeder.Value); AlarmType alarmType = (loadFeeder.Value >= 36) ? AlarmType.HIGH_ALARM : AlarmType.NO_ALARM; modbusData.Add(signalGid, new AnalogModbusData(loadFeeder.Value, alarmType, signalGid, CommandOriginType.CE_COMMAND)); } else { Logger.LogWarning($"{baseLogString} UpdateLoadFlow => Feeder with GID 0x{feeder.Id:X16} does not have FEEDER_CURRENT measurement."); } } } var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.SendMultipleAnalogCommand(commands, CommandOriginType.CE_COMMAND); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => SendAnalogCommand method from measurement provider successfully finished."); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Calling update analog measurement method from measurement provider."); await measurementProviderClient.UpdateAnalogMeasurement(modbusData); Logger.LogDebug($"{baseLogString} UpdateLoadFlow => Update analog measurement method from measurement provider successfully finished."); } catch (Exception e) { string errorMessage = $"{baseLogString} UpdateLoadFlow => Exception: {e.Message}"; Logger.LogError(errorMessage, e); } return(topology); }
private async Task <TopologyModel> CalculateLoadFlowFromRecloser(ITopologyElement recloser, TopologyModel topology, Dictionary <long, float> loadOfFeeders) { string verboseMessage = $"{baseLogString} CalculateLoadFlowFromRecloser method called. Element with GID {recloser?.Id:X16}."; Logger.LogVerbose(verboseMessage); if (recloser == null) { string message = $"{baseLogString} CalculateLoadFlowUpsideDown => NULL value has been passed instead of recloser."; Logger.LogError(message); throw new Exception(message); } if (topology == null) { string message = $"{baseLogString} CalculateLoadFlowUpsideDown => NULL value has been passed instead of topology."; Logger.LogError(message); throw new Exception(message); } long measurementGid = 0; if (recloser.Measurements.Count == 1) { //dogovor je da prekidaci imaju samo discrete measurement measurementGid = recloser.Measurements.First().Key; } else { Logger.LogWarning($"{baseLogString} CalculateLoadFlowUpsideDown => Recloser with GID {recloser.Id:X16} does not have proper measurements."); } bool isEnergized = false; if (recloser.FirstEnd != null && recloser.SecondEnd.Count == 1) { if (recloser.FirstEnd.IsActive && !recloser.SecondEnd.First().IsActive) { Tuple <bool, float> tuple = await IsElementEnergized(recloser); isEnergized = tuple.Item1; float load = tuple.Item2; if (isEnergized) { await CalculateLoadFlowUpsideDown(recloser.SecondEnd.First(), recloser.Id, recloser.FirstEnd.Feeder, loadOfFeeders); } else if (!recloser.IsActive) { Thread thread = new Thread(async() => await CommandToRecloser(measurementGid, (int)DiscreteCommandingType.CLOSE, CommandOriginType.CE_COMMAND, recloser)); thread.Start(); } } else if (!recloser.FirstEnd.IsActive && recloser.SecondEnd.First().IsActive) { Tuple <bool, float> tuple = await IsElementEnergized(recloser); isEnergized = tuple.Item1; float load = tuple.Item2; if (isEnergized) { await CalculateLoadFlowUpsideDown(recloser.FirstEnd, recloser.Id, recloser.SecondEnd.First().Feeder, loadOfFeeders); } else if (!recloser.IsActive) { Thread thread = new Thread(async() => await CommandToRecloser(measurementGid, (int)DiscreteCommandingType.CLOSE, CommandOriginType.CE_COMMAND, recloser)); thread.Start(); } } else if (recloser.IsActive) { Logger.LogDebug($"{baseLogString} TurnOnAllMeasurement => Calling SendDiscreteCommand method from measurement provider. Measurement GID {measurementGid:X16}, Value 1."); var measurementProviderClient = MeasurementProviderClient.CreateClient(); await measurementProviderClient.SendSingleDiscreteCommand(measurementGid, (int)DiscreteCommandingType.OPEN, CommandOriginType.CE_COMMAND); Logger.LogDebug($"{baseLogString} TurnOnAllMeasurement => SendDiscreteCommand method from measurement provider successfully finished."); recloser.IsActive = false; } } else { Logger.LogDebug($"{baseLogString} TurnOnAllMeasurement => Recloser with GID {recloser.Id:X16} does not have both ends, or have more than one on one end."); } return(topology); }