public bool SendAnalogCommand(long gid, float commandingValue, CommandOriginType commandOriginType) { bool success; if (CommandService.scadaModel == null) { string message = $"SendAnalogCommand => SCADA model is null."; Logger.LogError(message); throw new InternalSCADAServiceException(message); } var currentScadaModel = CommandService.scadaModel.CurrentScadaModel; if (!currentScadaModel.ContainsKey(gid)) { string message = $"Entity with gid: 0x{gid:X16} does not exist in current SCADA model."; Logger.LogError(message); throw new ArgumentException(message); } ISCADAModelPointItem pointItem = currentScadaModel[gid]; if (pointItem is IAnalogSCADAModelPointItem analogPointItem && pointItem.RegisterType == PointType.ANALOG_OUTPUT) { try { int modbusValue = analogPointItem.EguToRawValueConversion(commandingValue); success = SendCommand(pointItem, modbusValue, commandOriginType); } catch (Exception e) { string message = $"Exception in SendAnalogCommand() method."; Logger.LogError(message, e); throw new InternalSCADAServiceException(message, e); } }
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); }
public bool EnqueueModelUpdateCommands(List <long> measurementGids) { bool success; ushort length = 6; Dictionary <long, AnalogModbusData> analogData = new Dictionary <long, AnalogModbusData>(); Dictionary <long, DiscreteModbusData> discreteData = new Dictionary <long, DiscreteModbusData>(); MeasurementsCache.Clear(); try { Dictionary <long, ISCADAModelPointItem> currentScadaModel = SCADAModel.CurrentScadaModel; foreach (long measurementGID in measurementGids) { ISCADAModelPointItem scadaPointItem = currentScadaModel[measurementGID]; IWriteModbusFunction modbusFunction; if (scadaPointItem is IAnalogSCADAModelPointItem analogSCADAModelPointItem) { modbusFunction = FunctionFactory.CreateWriteModbusFunction(new ModbusWriteCommandParameters(length, (byte)ModbusFunctionCode.WRITE_SINGLE_REGISTER, analogSCADAModelPointItem.Address, analogSCADAModelPointItem.CurrentRawValue), CommandOriginType.MODEL_UPDATE_COMMAND); AnalogModbusData analogModbusData = new AnalogModbusData(analogSCADAModelPointItem.CurrentEguValue, analogSCADAModelPointItem.Alarm, measurementGID, CommandOriginType.MODEL_UPDATE_COMMAND); analogData.Add(measurementGID, analogModbusData); } else if (scadaPointItem is IDiscreteSCADAModelPointItem discreteSCADAModelPointItem) { modbusFunction = FunctionFactory.CreateWriteModbusFunction(new ModbusWriteCommandParameters(length, (byte)ModbusFunctionCode.WRITE_SINGLE_COIL, discreteSCADAModelPointItem.Address, discreteSCADAModelPointItem.CurrentValue), CommandOriginType.MODEL_UPDATE_COMMAND); DiscreteModbusData discreteModbusData = new DiscreteModbusData(discreteSCADAModelPointItem.CurrentValue, discreteSCADAModelPointItem.Alarm, measurementGID, CommandOriginType.MODEL_UPDATE_COMMAND); discreteData.Add(measurementGID, discreteModbusData); } else { Logger.LogWarn("Unknown type of ISCADAModelPointItem."); continue; } this.modelUpdateQueue.Enqueue(modbusFunction); } MakeAnalogEntryToMeasurementCache(analogData, true); MakeDiscreteEntryToMeasurementCache(discreteData, false); success = true; this.writeCommandQueue = new ConcurrentQueue <IWriteModbusFunction>(); this.readCommandQueue = new ConcurrentQueue <IReadModbusFunction>(); this.commandEvent.Set(); } catch (Exception e) { success = false; string message = "Exception caught in EnqueueModelUpdateCommands() method."; Logger.LogError(message, e); } return(success); }