예제 #1
0
        public async Task Commit()
        {
            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            try
            {
                await reliableDictionaryHelper.TryCopyToReliableDictionary <long, IScadaModelPointItem>(ReliableDictionaryNames.IncomingGidToPointItemMap, ReliableDictionaryNames.GidToPointItemMap, this.stateManager);

                await reliableDictionaryHelper.TryCopyToReliableDictionary <short, Dictionary <ushort, long> >(ReliableDictionaryNames.IncomingAddressToGidMap, ReliableDictionaryNames.AddressToGidMap, this.stateManager);

                await IncomingGidToPointItemMap.ClearAsync();

                await IncomingAddressToGidMap.ClearAsync();

                await ModelChanges.ClearAsync();

                await CommandDescriptionCache.ClearAsync();

                await MeasurementsCache.ClearAsync();

                string message = $"{baseLogString} Commit => Incoming SCADA model is confirmed.";
                Logger.LogInformation(message);

                await SendModelUpdateCommands();
                await LogAllReliableCollections();
            }
            catch (Exception e)
            {
                string errorMessage = $"{baseLogString} Commit => Exception: {e.Message}";
                Logger.LogError(errorMessage, e);
            }
        }
        public async Task <Dictionary <long, CommandDescription> > GetCommandDescriptionCache()
        {
            string verboseMessage = $"{baseLogString} entering GetCommandDescriptionCache method.";

            Logger.LogVerbose(verboseMessage);

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            verboseMessage = $"{baseLogString} GetCommandDescriptionCache => about to execut CommandDescriptionCache.GetDataCopy().";
            Logger.LogVerbose(verboseMessage);

            var copy = await CommandDescriptionCache.GetDataCopyAsync();

            if (copy.Count > 0)
            {
                var sb = new StringBuilder();
                sb.AppendLine("GettingCommandDescriptionCache => elements:");

                foreach (var element in copy.Values)
                {
                    sb.AppendLine($"Gid: {element.Gid}, Address: {element.Address}, Value: {element.Value}, CommandOrigin: {element.CommandOrigin}");
                }

                Logger.LogDebug(sb.ToString());
            }

            verboseMessage = $"{baseLogString} GetCommandDescriptionCache => CommandDescriptionCache.GetDataCopy() SUCCESSFULLY executed. Returning the collection with {copy.Count} elements.";
            Logger.LogVerbose(verboseMessage);

            return(copy);
        }
예제 #3
0
        public async Task AddOrUpdateMultipleCommandDescriptions(Dictionary <long, CommandDescription> commandDescriptions)
        {
            string verboseMessage = $"{baseLogString} entering AddOrUpdateMultipleCommandDescriptions method.";

            Logger.LogVerbose(verboseMessage);

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            var tasks = new List <Task>();

            foreach (var commandDescription in commandDescriptions.Values)
            {
                tasks.Add(Task.Run(async() =>
                {
                    await CommandDescriptionCache.SetAsync(commandDescription.Gid, commandDescription);

                    string infoMessage = $"{baseLogString} AddOrUpdateMultipleCommandDescriptions => CommandDescription successfuly set to CommandDescriptionCache. Gid: {commandDescription.Gid:X16}, Address: {commandDescription.Address}, Value: {commandDescription.Value}, CommandOrigin: {commandDescription.CommandOrigin}";
                    Logger.LogInformation(infoMessage);
                }));
            }

            Task.WaitAll(tasks.ToArray());

            string message = $"{baseLogString} AddOrUpdateMultipleCommandDescriptions => collection of CommandDescriptions SUCCESSFULLY set to CommandDescriptionCache. collection count: {commandDescriptions.Count}";

            Logger.LogInformation(message);
        }
예제 #4
0
        public async Task <bool> RemoveCommandDescription(long gid)
        {
            string verboseMessage = $"{baseLogString} entering RemoveCommandDescription method.";

            Logger.LogVerbose(verboseMessage);

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            return((await CommandDescriptionCache.TryRemoveAsync(gid)).HasValue);
        }
예제 #5
0
        public async Task AddOrUpdateCommandDescription(long gid, CommandDescription commandDescription)
        {
            string verboseMessage = $"{baseLogString} entering AddOrUpdateCommandDescription method.";

            Logger.LogVerbose(verboseMessage);

            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            await CommandDescriptionCache.SetAsync(gid, commandDescription);
        }
예제 #6
0
        private async Task LogAllReliableCollections()
        {
            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("Reliable Collections");

            sb.AppendLine("CurrentGidToPointItemMap =>");
            var currentGidToPointItemMap = await CurrentGidToPointItemMap.GetEnumerableDictionaryAsync();

            foreach (var element in currentGidToPointItemMap)
            {
                sb.AppendLine($"Key => {element.Key}, Value => Gid: 0x{element.Value.Gid:X16}, Address: {element.Value.Address}, Name: {element.Value.Name}, RegisterType: {element.Value.RegisterType}, Alarm: {element.Value.Alarm}, Initialized: {element.Value.Initialized}");
            }
            sb.AppendLine();

            sb.AppendLine("IncomingGidToPointItemMap =>");
            var incomingGidToPointItemMap = await IncomingGidToPointItemMap.GetEnumerableDictionaryAsync();

            foreach (var element in incomingGidToPointItemMap)
            {
                sb.AppendLine($"Key => {element.Key}, Value => Gid: 0x{element.Value.Gid:X16}, Address: {element.Value.Address}, Name: {element.Value.Name}, RegisterType: {element.Value.RegisterType}, Alarm: {element.Value.Alarm}, Initialized: {element.Value.Initialized}");
            }
            sb.AppendLine();

            sb.AppendLine("CurrentAddressToGidMap =>");
            var currentAddressToGidMap = await CurrentAddressToGidMap.GetEnumerableDictionaryAsync();

            foreach (var element in currentAddressToGidMap)
            {
                sb.AppendLine($"Key => {element.Key}, Value => Dictionary Count: {element.Value.Count}");
            }
            sb.AppendLine();

            sb.AppendLine("IncomingAddressToGidMap =>");
            var incomingAddressToGidMap = await IncomingAddressToGidMap.GetEnumerableDictionaryAsync();

            foreach (var element in incomingAddressToGidMap)
            {
                sb.AppendLine($"Key => {element.Key}, Value => Dictionary Count: {element.Value.Count}");
            }
            sb.AppendLine();

            sb.AppendLine("InfoCache =>");
            var infoCache = await InfoCache.GetEnumerableDictionaryAsync();

            foreach (var element in infoCache)
            {
                sb.AppendLine($"Key => {element.Key}, Value => {element.Value}");
            }
            sb.AppendLine();

            sb.AppendLine("ModelChanges =>");
            var modelChanges = await ModelChanges.GetEnumerableDictionaryAsync();

            foreach (var element in modelChanges)
            {
                sb.AppendLine($"Key => {element.Key}, Value => List Count: {element.Value.Count}");
            }
            sb.AppendLine();

            sb.AppendLine("MeasurementsCache =>");
            var measurementsCache = await MeasurementsCache.GetEnumerableDictionaryAsync();

            foreach (var element in measurementsCache)
            {
                sb.AppendLine($"Key => {element.Key}, Value => MeasurementGid: {element.Value.MeasurementGid:X16}, Alarm: {element.Value.Alarm}, CommandOrigin: {element.Value.CommandOrigin}");
            }
            sb.AppendLine();

            sb.AppendLine("CommandDescriptionCache =>");
            var commandDescriptionCache = await CommandDescriptionCache.GetEnumerableDictionaryAsync();

            foreach (var element in commandDescriptionCache)
            {
                sb.AppendLine($"Key => {element.Key}, Value => Gid: {element.Value.Gid:X16}, Address: {element.Value.Address}, Value: {element.Value.Value}, CommandOrigin: {element.Value.CommandOrigin}");
            }
            sb.AppendLine();

            Logger.LogDebug($"{baseLogString} LogAllReliableCollections => {sb}");
        }
        public async Task <ScadaPublication> GetIntegrityUpdateForSpecificTopic(Topic topic)
        {
            while (!ReliableDictionariesInitialized)
            {
                await Task.Delay(1000);
            }

            if (GidToPointItemMap == null)
            {
                string message = $"GetIntegrityUpdate => GidToPointItemMap is null.";
                Logger.LogError(message);
                throw new InternalSCADAServiceException(message);
            }

            if (CommandDescriptionCache == null)
            {
                string message = $"GetIntegrityUpdate => CommandDescriptionCache is null.";
                Logger.LogError(message);
                throw new InternalSCADAServiceException(message);
            }

            Dictionary <long, AnalogModbusData>   analogModbusData   = new Dictionary <long, AnalogModbusData>();
            Dictionary <long, DiscreteModbusData> discreteModbusData = new Dictionary <long, DiscreteModbusData>();

            var enumerableGidToPointItemMap = await GidToPointItemMap.GetEnumerableDictionaryAsync();

            foreach (long gid in enumerableGidToPointItemMap.Keys)
            {
                CommandOriginType commandOrigin = CommandOriginType.UNKNOWN_ORIGIN;

                if (topic == Topic.MEASUREMENT && enumerableGidToPointItemMap[gid] is IAnalogPointItem analogPointItem)
                {
                    var result = await CommandDescriptionCache.TryGetValueAsync(gid);

                    if (result.HasValue && result.Value.Value == analogPointItem.CurrentRawValue)
                    {
                        commandOrigin = result.Value.CommandOrigin;
                    }

                    AnalogModbusData analogValue = new AnalogModbusData(analogPointItem.CurrentEguValue, analogPointItem.Alarm, gid, commandOrigin);
                    analogModbusData.Add(gid, analogValue);
                }
                else if (topic == Topic.SWITCH_STATUS && enumerableGidToPointItemMap[gid] is IDiscretePointItem discretePointItem)
                {
                    var result = await CommandDescriptionCache.TryGetValueAsync(gid);

                    if (result.HasValue && result.Value.Value == discretePointItem.CurrentValue)
                    {
                        commandOrigin = result.Value.CommandOrigin;
                    }


                    DiscreteModbusData discreteValue = new DiscreteModbusData(discretePointItem.CurrentValue, discretePointItem.Alarm, gid, commandOrigin);
                    discreteModbusData.Add(gid, discreteValue);
                }
            }

            ScadaPublication scadaPublication;

            if (topic == Topic.MEASUREMENT)
            {
                MultipleAnalogValueSCADAMessage analogValuesMessage = new MultipleAnalogValueSCADAMessage(analogModbusData);
                scadaPublication = new ScadaPublication(Topic.MEASUREMENT, analogValuesMessage);
            }
            else if (topic == Topic.SWITCH_STATUS)
            {
                MultipleDiscreteValueSCADAMessage discreteValuesMessage = new MultipleDiscreteValueSCADAMessage(discreteModbusData);
                scadaPublication = new ScadaPublication(Topic.SWITCH_STATUS, discreteValuesMessage);
            }
            else
            {
                string message = $"GetIntegrityUpdate => argument topic is neither Topic.MEASUREMENT nor Topic.SWITCH_STATUS.";
                Logger.LogError(message);
                throw new ArgumentException(message);
            }

            return(scadaPublication);
        }