private async Task HandleUpdateOperation(IScadaModelPointItem incomingPointItem, long gid) { var pointItemResult = await IncomingGidToPointItemMap.TryGetValueAsync(gid); if (!pointItemResult.HasValue) { string errorMessage = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Updating entity with gid: {gid:X16}, that does not exists in IncomingGidToPointItemMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } IScadaModelPointItem oldPointItem = pointItemResult.Value; var addressToGidMapResult = await IncomingAddressToGidMap.TryGetValueAsync((short)oldPointItem.RegisterType); if (!addressToGidMapResult.HasValue) { string errorMessage = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Updating entity with gid: {gid:X16}, {oldPointItem.RegisterType} registry type does not exist in incoming IncomingAddressToGidMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } var incomingAddressToGidMapDictionary = addressToGidMapResult.Value; if (!incomingAddressToGidMapDictionary.ContainsKey(oldPointItem.Address)) { string message = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Updating point with address: {oldPointItem.Address}, that does not exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } if (oldPointItem.Address != incomingPointItem.Address && incomingAddressToGidMapDictionary.ContainsKey(incomingPointItem.Address)) { string message = $"{baseLogString} HandleUpdateOperation => Model update data in fault state. Trying to add point with address: {incomingPointItem.Address}, that already exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } string appendMessage = ""; string oldAddressText = ""; //LOGIC await IncomingGidToPointItemMap.SetAsync(gid, incomingPointItem); if (oldPointItem.Address != incomingPointItem.Address) { incomingAddressToGidMapDictionary.Remove(oldPointItem.Address); incomingAddressToGidMapDictionary.Add(incomingPointItem.Address, gid); await IncomingAddressToGidMap.SetAsync((short)oldPointItem.RegisterType, incomingAddressToGidMapDictionary); appendMessage = " and IncomingAddressToGidMap"; oldAddressText = $", Old address: {oldPointItem.Address}"; } string debugMessage = $"{baseLogString} HandleUpdateOperation => SUCCESSFULLY updated point from IncomingGidToPointItemMap{appendMessage}. Gid: 0x{incomingPointItem.Gid:X16}, Address: {incomingPointItem.Address}{oldAddressText}"; Logger.LogDebug(debugMessage); }
private async Task HandleDeleteOperation(long gid) { var pointItemResult = await IncomingGidToPointItemMap.TryGetValueAsync(gid); if (!pointItemResult.HasValue) { string errorMessage = $"{baseLogString} HandleDeleteOperation => Model update data in fault state. Deleting entity with gid: {gid:X16}, that does not exists in IncomingGidToPointItemMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } IScadaModelPointItem oldPointItem = pointItemResult.Value; Dictionary <ushort, long> incomingAddressToGidMapDictionary; var type = (short)oldPointItem.RegisterType; var addressToGidMapResult = await IncomingAddressToGidMap.TryGetValueAsync(type); if (!addressToGidMapResult.HasValue) { incomingAddressToGidMapDictionary = new Dictionary <ushort, long>(); } else { incomingAddressToGidMapDictionary = addressToGidMapResult.Value; } if (!incomingAddressToGidMapDictionary.ContainsKey(oldPointItem.Address)) { string message = $"{baseLogString} HandleDeleteOperation => Model update data in fault state. Deleting point with address: {oldPointItem.Address}, that does not exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } //LOGIC await IncomingGidToPointItemMap.TryRemoveAsync(gid); incomingAddressToGidMapDictionary.Remove(oldPointItem.Address); await IncomingAddressToGidMap.SetAsync(type, incomingAddressToGidMapDictionary); string debugMessage = $"{baseLogString} HandleDeleteOperation => SUCCESSFULLY deleted point from IncomingGidToPointItemMap and IncomingAddressToGidMap. Gid: 0x{oldPointItem.Gid:X16}, Address: {oldPointItem.Address}"; Logger.LogDebug(debugMessage); }
private async Task InitializeIncomingScadaModel() { var enumerableCurrentGidToPointItemMap = await CurrentGidToPointItemMap.GetEnumerableDictionaryAsync(); foreach (long gid in enumerableCurrentGidToPointItemMap.Keys) { //NODO: to tasks, await all (performanse) IScadaModelPointItem pointItem = enumerableCurrentGidToPointItemMap[gid].Clone(); await IncomingGidToPointItemMap.SetAsync(gid, pointItem); short registerType = (short)pointItem.RegisterType; if (!(await IncomingAddressToGidMap.ContainsKeyAsync(registerType))) { await IncomingAddressToGidMap.SetAsync(registerType, new Dictionary <ushort, long>()); } var addressToGidDictionaryResult = await IncomingAddressToGidMap.TryGetValueAsync(registerType); if (!addressToGidDictionaryResult.HasValue) { string message = $"{baseLogString} InitializeIncomingScadaModel => reliable collection '{ReliableDictionaryNames.IncomingAddressToGidMap}' is not initialized properly."; Logger.LogError(message); throw new InternalSCADAServiceException(message); } var addressToGidDictionary = addressToGidDictionaryResult.Value; if (addressToGidDictionary.ContainsKey(pointItem.Address)) { string message = $"{baseLogString} InitializeIncomingScadaModel => SCADA model is invalid => Address: {pointItem.Address} (RegType: {registerType}) belongs to more than one entity."; Logger.LogError(message); throw new InternalSCADAServiceException(message); } addressToGidDictionary.Add(pointItem.Address, pointItem.Gid); await IncomingAddressToGidMap.SetAsync(registerType, addressToGidDictionary); string debugMessage = $"{baseLogString} InitializeIncomingScadaModel => measurement added to Incoming SCADA model [Gid: 0x{gid:X16}, Address: {pointItem.Address}]"; Logger.LogDebug(debugMessage); } }
private async Task HandleInsertOperation(IScadaModelPointItem incomingPointItem, long gid) { var pointItemResult = await IncomingGidToPointItemMap.TryGetValueAsync(gid); if (pointItemResult.HasValue) { string errorMessage = $"{baseLogString} HandleInsertOperation => Model update data in fault state. Inserting entity with gid: {gid:X16}, that already exists in IncomingGidToPointItemMap."; Logger.LogError(errorMessage); throw new ArgumentException(errorMessage); } Dictionary <ushort, long> incomingAddressToGidMapDictionary; var type = (short)incomingPointItem.RegisterType; var addressToGidMapResult = await IncomingAddressToGidMap.TryGetValueAsync(type); if (!addressToGidMapResult.HasValue) { incomingAddressToGidMapDictionary = new Dictionary <ushort, long>(); } else { incomingAddressToGidMapDictionary = addressToGidMapResult.Value; } if (incomingAddressToGidMapDictionary.ContainsKey(incomingPointItem.Address)) { string message = $"{baseLogString} HandleInsertOperation => Model update data in fault state. Inserting entity with address: {incomingPointItem.Address}, that already exists in IncomingAddressToGidMap."; Logger.LogError(message); throw new ArgumentException(message); } //LOGIC await IncomingGidToPointItemMap.SetAsync(gid, incomingPointItem); incomingAddressToGidMapDictionary.Add(incomingPointItem.Address, gid); await IncomingAddressToGidMap.SetAsync(type, incomingAddressToGidMapDictionary); string debugMessage = $"{baseLogString} HandleInsertOperation => SUCCESSFULLY inserted point into IncomingGidToPointItemMap and IncomingAddressToGidMap. Gid: 0x{incomingPointItem.Gid:X16}, Address: {incomingPointItem.Address}"; Logger.LogDebug(debugMessage); }
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> SendSingleAnalogCommand(long gid, float commandingValue, CommandOriginType commandOriginType) { string verboseMessage = $"{baseLogString} SendSingleAnalogCommand method called. gid: {gid:X16}, commandingValue: {commandingValue}, commandOriginType: {commandOriginType}"; Logger.LogVerbose(verboseMessage); IScadaModelReadAccessContract scadaModelReadAccessClient = ScadaModelReadAccessClient.CreateClient(); Dictionary <long, IScadaModelPointItem> gidToPointItemMap = await scadaModelReadAccessClient.GetGidToPointItemMap(); if (gidToPointItemMap == null) { string message = $"{baseLogString} SendSingleAnalogCommand => SendSingleAnalogCommand => SCADA model is null."; Logger.LogError(message); //throw new InternalSCADAServiceException(message); return(false); } if (!gidToPointItemMap.ContainsKey(gid)) { string message = $"{baseLogString} SendSingleAnalogCommand => Entity with gid: 0x{gid:X16} does not exist in current SCADA model."; Logger.LogError(message); //throw new ArgumentException(message); return(false); } IScadaModelPointItem pointItem = gidToPointItemMap[gid]; if (!(pointItem is IAnalogPointItem analogPointItem && pointItem.RegisterType == PointType.ANALOG_OUTPUT)) { string message = $"{baseLogString} SendSingleAnalogCommand => Either RegistarType of entity with gid: 0x{gid:X16} is not ANALOG_OUTPUT or entity does not implement IAnalogPointItem interface."; Logger.LogError(message); //throw new ArgumentException(message); return(false); } try { if (!analogPointItem.Initialized) { string errorMessage = $"{baseLogString} SendSingleAnalogCommand => PointItem was initialized. Gid: 0x{analogPointItem.Gid:X16}, Addres: {analogPointItem.Address}, Name: {analogPointItem.Name}, RegisterType: {analogPointItem.RegisterType}, Initialized: {analogPointItem.Initialized}"; Logger.LogError(errorMessage); } //LOGIC int modbusValue = analogPointItem.EguToRawValueConversion(commandingValue); string debugMessage = $"{baseLogString} SendSingleAnalogCommand => Calling SendSingleCommand({pointItem}, {modbusValue}, {commandOriginType})"; Logger.LogDebug(verboseMessage); //KEY LOGIC await SendSingleCommand(pointItem, modbusValue, commandOriginType); debugMessage = $"{baseLogString} SendSingleAnalogCommand => SendSingleCommand() executed SUCCESSFULLY"; Logger.LogDebug(debugMessage); return(true); } catch (Exception e) { string message = $"{baseLogString} SendSingleAnalogCommand => Exception in SendAnalogCommand() method."; Logger.LogError(message, e); //throw new InternalSCADAServiceException(message, e); return(false); } }