/// <summary> /// This is the main entry point for your service instance. /// </summary> /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service instance.</param> protected override async Task RunAsync(CancellationToken cancellationToken) { IScadaConfigData configData; try { InitializeReliableCollections(); string debugMessage = $"{baseLogString} RunAsync => ReliableDictionaries initialized."; Logger.LogDebug(debugMessage); IScadaModelReadAccessContract readAccessClient = ScadaModelReadAccessClient.CreateClient(); configData = await readAccessClient.GetScadaConfigData(); string infoMessage = $"{baseLogString} RunAsync => FunctionExecutorCycle initialized."; Logger.LogInformation(infoMessage); } catch (Exception e) { string errorMessage = $"{baseLogString} RunAsync => exception {e.Message}"; Logger.LogError(errorMessage, e); throw e; } var functionExecutionCycleCount = 0; while (true) { string message = $"{baseLogString} RunAsync => FunctionExecutionCycleCount: {functionExecutionCycleCount}"; if (functionExecutionCycleCount % 100 == 0) { Logger.LogInformation(message); } else if (functionExecutionCycleCount % 10 == 0) { Logger.LogDebug(message); } else { Logger.LogVerbose(message); } try { await functionExecutorCycle.Start(); string verboseMessage = $"{baseLogString} RunAsync => FunctionExecutorCycle executed."; Logger.LogVerbose(verboseMessage); } catch (Exception e) { string errorMessage = $"{baseLogString} RunAsync => exception {e.Message}"; Logger.LogError(errorMessage, e); } await Task.Delay(TimeSpan.FromMilliseconds(configData.FunctionExecutionInterval), cancellationToken); functionExecutionCycleCount++; } }
public ModelProviderService(StatefulServiceContext context) : base(context) { this.baseLogString = $"{this.GetType()} [{this.GetHashCode()}] =>{Environment.NewLine}"; Logger.LogDebug($"{baseLogString} Ctor => Logger initialized"); try { //DONE THIS WAY (in this order) BECAUSE: there is a mechanism that tracks the initialization process of reliable collections, which is set in constructors of these classes var modelResourceDesc = new ModelResourcesDesc(); var enumDescs = new EnumDescs(); //this.scadaModelImporter = new ScadaModelImporter(this.StateManager, modelResourceDesc, enumDescs); this.modelReadAccessProvider = new ModelReadAccessProvider(this.StateManager); this.modelUpdateAccessProvider = new ModelUpdateAccessProvider(this.StateManager); this.integrityUpdateProvider = new IntegrityUpdateProvider(this.StateManager); this.scadaNotifyNetworkModelUpdate = new ScadaNotifyNetworkModelUpdate(this.StateManager); this.scadaTransactionActorProviders = new ScadaTransactionActor(this.StateManager, modelResourceDesc, enumDescs); string infoMessage = $"{baseLogString} Ctor => Contract providers initialized."; Logger.LogInformation(infoMessage); ServiceEventSource.Current.ServiceMessage(this.Context, $"[SCADA.ModelProviderService | Information] {infoMessage}"); } catch (Exception e) { string errorMessage = $"{baseLogString} Ctor => Exception caught: {e.Message}."; Logger.LogError(errorMessage, e); ServiceEventSource.Current.ServiceMessage(this.Context, $"[SCADA.ModelProviderService | Error] {errorMessage}"); } }
public async Task <bool> SendMultipleAnalogCommand(Dictionary <long, float> commandingValues, CommandOriginType commandOriginType) { if (commandingValues.Count == 0) { string warnMessage = $"{baseLogString} SendMultipleAnalogCommand => commandingValues is empty and thus aborting the call."; Logger.LogWarning(warnMessage); return(false); } #region Log commanding values var sb = new StringBuilder(); foreach (var kvp in commandingValues) { sb.AppendLine($"Gid: 0x{kvp.Key:X16} | Value: {kvp.Value}"); } Logger.LogInformation($"{baseLogString} SendMultipleAnalogCommand => Origin: {commandOriginType} Values {Environment.NewLine}{sb}"); #endregion Log commanding values ushort startAddress = 1; //EasyModbus spec IScadaModelReadAccessContract scadaModelReadAccessClient = ScadaModelReadAccessClient.CreateClient(); Dictionary <long, IScadaModelPointItem> gidToPointItemMap = await scadaModelReadAccessClient.GetGidToPointItemMap(); Dictionary <short, Dictionary <ushort, long> > addressToGidMap = await scadaModelReadAccessClient.GetAddressToGidMap(); if (gidToPointItemMap == null) { string message = $"{baseLogString} SendMultipleAnalogCommand => SCADA model is null."; Logger.LogError(message); return(false); } int analogOutputCount = addressToGidMap[(short)PointType.ANALOG_OUTPUT].Count; int[] multipleCommandingValues = new int[addressToGidMap[(short)PointType.ANALOG_OUTPUT].Count]; foreach (ushort address in addressToGidMap[(short)PointType.ANALOG_OUTPUT].Keys) { long gid = addressToGidMap[(short)PointType.ANALOG_OUTPUT][address]; if (!gidToPointItemMap.ContainsKey(gid)) { string message = $"{baseLogString} SendMultipleAnalogCommand => Entity with gid: 0x{gid:X16} does not exist in current SCADA model."; Logger.LogError(message); return(false); } else if (!(gidToPointItemMap[gid] is IAnalogPointItem analogPointItem)) { string message = $"{baseLogString} SendMultipleAnalogCommand => Entity with gid: 0x{gid:X16} does not implement IAnalogPointItem interface."; Logger.LogError(message); return(false); }
public async Task <bool> SendMultipleAnalogCommand(Dictionary <long, float> commandingValues, CommandOriginType commandOriginType) { if (commandingValues.Count == 0) { string warnMessage = $"{baseLogString} SendMultipleAnalogCommand => commandingValues is empty and thus aborting the call."; Logger.LogWarning(warnMessage); return(false); } ushort startAddress = 1; //EasyModbus spec IScadaModelReadAccessContract scadaModelReadAccessClient = ScadaModelReadAccessClient.CreateClient(); Dictionary <long, IScadaModelPointItem> gidToPointItemMap = await scadaModelReadAccessClient.GetGidToPointItemMap(); Dictionary <short, Dictionary <ushort, long> > addressToGidMap = await scadaModelReadAccessClient.GetAddressToGidMap(); if (gidToPointItemMap == null) { string message = $"{baseLogString} SendMultipleAnalogCommand => SCADA model is null."; Logger.LogError(message); //throw new InternalSCADAServiceException(message); return(false); } int analogOutputCount = addressToGidMap[(short)PointType.ANALOG_OUTPUT].Count; int[] multipleCommandingValues = new int[addressToGidMap[(short)PointType.ANALOG_OUTPUT].Count]; //for (ushort address = 1; address <= analogOutputCount; address++) //{ foreach (ushort address in addressToGidMap[(short)PointType.ANALOG_OUTPUT].Keys) { long gid = addressToGidMap[(short)PointType.ANALOG_OUTPUT][address]; if (!gidToPointItemMap.ContainsKey(gid)) { string message = $"{baseLogString} SendMultipleAnalogCommand => Entity with gid: 0x{gid:X16} does not exist in current SCADA model."; Logger.LogError(message); //throw new ArgumentException(message); return(false); } else if (!(gidToPointItemMap[gid] is IAnalogPointItem analogPointItem)) { string message = $"{baseLogString} SendMultipleAnalogCommand => Entity with gid: 0x{gid:X16} does not implement IAnalogPointItem interface."; Logger.LogError(message); //throw new InternalSCADAServiceException(message); return(false); }
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); } }