private async Task SendModelUpdateCommands()
        {
            var scadaCommandingClient           = ScadaCommandingClient.CreateClient();
            var enumerableAddressToGidMapResult = await AddressToGidMap.GetEnumerableDictionaryAsync();

            var tasks = new List <Task>()
            {
                Task.Run(async() =>
                {
                    var key = (short)PointType.ANALOG_OUTPUT;
                    if (!enumerableAddressToGidMapResult.ContainsKey(key))
                    {
                        return;
                    }

                    var analogItemsAddressToGidMap = enumerableAddressToGidMapResult[key];
                    var analogCommandingValues     = new Dictionary <long, float>(analogItemsAddressToGidMap.Count);

                    foreach (long gid in analogItemsAddressToGidMap.Values)
                    {
                        var result          = await GidToPointItemMap.TryGetValueAsync(gid);
                        var analogPointItem = result.Value as IAnalogPointItem;

                        analogCommandingValues.Add(gid, analogPointItem.CurrentEguValue);
                    }

                    if (analogCommandingValues.Count > 0)
                    {
                        await scadaCommandingClient.SendMultipleAnalogCommand(analogCommandingValues, CommandOriginType.MODEL_UPDATE_COMMAND);
                    }
                }),

                Task.Run(async() =>
                {
                    var key = (short)PointType.DIGITAL_OUTPUT;
                    if (!enumerableAddressToGidMapResult.ContainsKey(key))
                    {
                        return;
                    }

                    var discreteItemsAddressToGidMap = enumerableAddressToGidMapResult[key];
                    var discreteCommandingValues     = new Dictionary <long, ushort>(discreteItemsAddressToGidMap.Count);

                    foreach (long gid in discreteItemsAddressToGidMap.Values)
                    {
                        var result            = await GidToPointItemMap.TryGetValueAsync(gid);
                        var discretePointItem = result.Value as IDiscretePointItem;

                        discreteCommandingValues.Add(gid, discretePointItem.CurrentValue);
                    }

                    if (discreteCommandingValues.Count > 0)
                    {
                        await scadaCommandingClient.SendMultipleDiscreteCommand(discreteCommandingValues, CommandOriginType.MODEL_UPDATE_COMMAND);
                    }
                }),
            };

            Task.WaitAll(tasks.ToArray());
        }
        public async Task <bool> ImportModel(bool isRetry = false)
        {
            bool success;

            await GidToPointItemMap.ClearAsync();

            var enumerableCurrentAddressToGidMap = await AddressToGidMap.GetEnumerableDictionaryAsync();

            foreach (var key in enumerableCurrentAddressToGidMap.Keys)
            {
                var dictionary = enumerableCurrentAddressToGidMap[key];
                dictionary.Clear();

                await AddressToGidMap.SetAsync(key, dictionary);
            }

            string message = $"{baseLogString} ImportModel => Importing analog measurements started...";

            Logger.LogInformation(message);

            bool analogImportSuccess = await ImportAnalog();

            message = $"{baseLogString} ImportModel =>Importing analog measurements finished. ['success' value: {analogImportSuccess}]";
            Logger.LogInformation(message);

            message = $"{baseLogString} ImportModel => Importing discrete measurements started...";
            Logger.LogInformation(message);

            bool discreteImportSuccess = await ImportDiscrete();

            message = $"{baseLogString} ImportModel => Importing discrete measurements finished. ['success' value: {discreteImportSuccess}]";
            Logger.LogInformation(message);

            success = analogImportSuccess && discreteImportSuccess;

            if (!success)
            {
                await GidToPointItemMap.ClearAsync();

                enumerableCurrentAddressToGidMap = await AddressToGidMap.GetEnumerableDictionaryAsync();

                foreach (var key in enumerableCurrentAddressToGidMap.Keys)
                {
                    var dictionary = enumerableCurrentAddressToGidMap[key];
                    dictionary.Clear();

                    await AddressToGidMap.SetAsync(key, dictionary);
                }
            }

            return(success);
        }
        public async Task <Dictionary <long, IScadaModelPointItem> > GetGidToPointItemMap()
        {
            string verboseMessage = $"{baseLogString} entering GetGidToPointItemMap method.";

            Logger.LogVerbose(verboseMessage);

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

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

            var copy = await GidToPointItemMap.GetDataCopyAsync();

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

            return(copy);
        }
        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);
        }
Exemplo n.º 5
0
        public async Task <IScadaModelPointItem> UpdatePointItemRawValue(long gid, int rawValue)
        {
            string verboseMessage = $"{baseLogString} entering UpdatePointItemRawValue method.";

            Logger.LogVerbose(verboseMessage);

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

            if (!await GidToPointItemMap.ContainsKeyAsync(gid))
            {
                string message = $"{baseLogString} UpdatePointItemRawValue => Entity with Gid: 0x{gid:X16} does not exist in GidToPointItemMap.";
                Logger.LogError(message);
                throw new ArgumentException(message);
            }

            if ((await GidToPointItemMap.TryGetValueAsync(gid)).Value is IAnalogPointItem analogPoint)
            {
                if (!analogPoint.Initialized)
                {
                    string errorMessage = $"{baseLogString} SendSingleAnalogCommand => PointItem was initialized. Gid: 0x{analogPoint.Gid:X16}, Addres: {analogPoint.Address}, Name: {analogPoint.Name}, RegisterType: {analogPoint.RegisterType}, Initialized: {analogPoint.Initialized}";
                    Logger.LogError(errorMessage);
                }

                analogPoint.CurrentEguValue = analogPoint.RawToEguValueConversion(rawValue);
                await GidToPointItemMap.SetAsync(analogPoint.Gid, analogPoint);

                var result = await GidToPointItemMap.TryGetValueAsync(analogPoint.Gid);

                if (result.HasValue)
                {
                    return(result.Value as IAnalogPointItem);
                }
                else
                {
                    string errorMessage = $"{baseLogString} UpdateAnalogPointItemEguValue => TryGetValueAsync() returns no value";
                    Logger.LogError(errorMessage);
                    throw new Exception(errorMessage);
                }
            }
            else if ((await GidToPointItemMap.TryGetValueAsync(gid)).Value is IDiscretePointItem discretePoint)
            {
                discretePoint.CurrentValue = (ushort)rawValue;
                await GidToPointItemMap.SetAsync(discretePoint.Gid, discretePoint);

                var result = await GidToPointItemMap.TryGetValueAsync(discretePoint.Gid);

                if (result.HasValue)
                {
                    return(result.Value as IDiscretePointItem);
                }
                else
                {
                    string errorMessage = $"{baseLogString} UpdateAnalogPointItemEguValue => TryGetValueAsync() returns no value.";
                    Logger.LogError(errorMessage);
                    throw new Exception(errorMessage);
                }
            }
            else
            {
                string errorMessage = $"{baseLogString} UpdatePointItemRawValue => Entity with Gid: 0x{gid:X16} does not implement IAnalogPointItem nor IDiscretePointItem.";
                Logger.LogError(errorMessage);
                throw new ArgumentException(errorMessage);
            }
        }
        private async Task <bool> ImportDiscrete()
        {
            bool             success;
            int              numberOfResources = 1000;
            List <ModelCode> props             = modelResourceDesc.GetAllPropertyIds(ModelCode.DISCRETE);

            try
            {
                var nmsGdaClient = NetworkModelGdaClient.CreateClient();
                int iteratorId   = await nmsGdaClient.GetExtentValues(ModelCode.DISCRETE, props);

                int resourcesLeft = await nmsGdaClient.IteratorResourcesLeft(iteratorId);

                while (resourcesLeft > 0)
                {
                    List <ResourceDescription> rds = await nmsGdaClient.IteratorNext(numberOfResources, iteratorId);

                    for (int i = 0; i < rds.Count; i++)
                    {
                        if (rds[i] == null)
                        {
                            continue;
                        }

                        long      gid  = rds[i].Id;
                        ModelCode type = modelResourceDesc.GetModelCodeFromId(gid);

                        DiscretePointItem discretePoint = new DiscretePointItem(AlarmConfigDataHelper.GetAlarmConfigData());

                        string debugMessage = $"{baseLogString} ImportDiscrete => Before Initialization => Gid: 0x{discretePoint.Gid:X16}, Address: {discretePoint.Address}, CurrentValue: {discretePoint.CurrentValue}, Alarm: {discretePoint.Alarm}, AbnormalValue: {discretePoint.AbnormalValue}, DiscreteType: {discretePoint.DiscreteType}, MinValue: {discretePoint.MinValue}, MaxValue: {discretePoint.MaxValue}, NormalValue: {discretePoint.NormalValue}, RegisterType: {discretePoint.RegisterType}, Name: {discretePoint.Name}, Initialized: {discretePoint.Initialized}";
                        Logger.LogDebug(debugMessage);

                        pointItemHelper.InitializeDiscretePointItem(discretePoint, rds[i].Properties, ModelCode.DISCRETE, enumDescs);

                        debugMessage = $"{baseLogString} ImportDiscrete => After Initialization => Gid: 0x{discretePoint.Gid:X16}, Address: {discretePoint.Address}, CurrentValue: {discretePoint.CurrentValue}, Alarm: {discretePoint.Alarm}, AbnormalValue: {discretePoint.AbnormalValue}, DiscreteType: {discretePoint.DiscreteType}, MinValue: {discretePoint.MinValue}, MaxValue: {discretePoint.MaxValue}, NormalValue: {discretePoint.NormalValue}, RegisterType: {discretePoint.RegisterType}, Name: {discretePoint.Name}, Initialized: {discretePoint.Initialized}";
                        Logger.LogDebug(debugMessage);

                        if (await GidToPointItemMap.ContainsKeyAsync(gid))
                        {
                            string errorMessage = $"{baseLogString} ImportDiscrete => SCADA model is invalid => Gid: 0x{gid:X16} belongs to more than one entity.";
                            Logger.LogError(errorMessage);
                            throw new InternalSCADAServiceException(errorMessage);
                        }

                        await GidToPointItemMap.SetAsync(gid, discretePoint);

#if DEBUG
                        var pointItemResult = await GidToPointItemMap.TryGetValueAsync(gid);

                        if (pointItemResult.HasValue)
                        {
                            DiscretePointItem controlPointItem = pointItemResult.Value as DiscretePointItem;
                            debugMessage = $"{baseLogString} ImportDiscrete => Control after CurrentGidToPointItemMap.SetAsync => Gid: 0x{controlPointItem.Gid:X16}, Address: {controlPointItem.Address}, CurrentValue: {controlPointItem.CurrentValue}, Alarm: {controlPointItem.Alarm}, AbnormalValue: {controlPointItem.AbnormalValue}, DiscreteType: {controlPointItem.DiscreteType}, MinValue: {controlPointItem.MinValue}, MaxValue: {controlPointItem.MaxValue}, NormalValue: {controlPointItem.NormalValue}, RegisterType: {controlPointItem.RegisterType}, Name: {controlPointItem.Name}, Initialized: {controlPointItem.Initialized}";
                            Logger.LogDebug(debugMessage);
                        }
                        else
                        {
                            string warningMessage = $"{baseLogString} ImportDiscrete => Control after CurrentGidToPointItemMap.SetAsync => Gid: 0x{gid:X16} was not found in reliable collection '{ReliableDictionaryNames.GidToPointItemMap}' after the value was supposedly set.";
                            Logger.LogWarning(warningMessage);
                        }
#endif
                        short registerType = (short)discretePoint.RegisterType;
                        if (!(await AddressToGidMap.ContainsKeyAsync(registerType)))
                        {
                            await AddressToGidMap.SetAsync(registerType, new Dictionary <ushort, long>());
                        }

                        var addressToGidDictionaryResult = await AddressToGidMap.TryGetValueAsync(registerType);

                        if (!addressToGidDictionaryResult.HasValue)
                        {
                            string message = $"{baseLogString} ImportDiscrete => reliable collection '{ReliableDictionaryNames.AddressToGidMap}' is not initialized properly.";
                            Logger.LogError(message);
                            throw new InternalSCADAServiceException(message);
                        }

                        var addressToGidDictionary = addressToGidDictionaryResult.Value;

                        if (addressToGidDictionary.ContainsKey(discretePoint.Address))
                        {
                            string errorMessage = $"{baseLogString} ImportDiscrete => SCADA model is invalid => Address: {discretePoint.Address} (RegType: {registerType}) belongs to more than one entity.";
                            Logger.LogError(errorMessage);
                            throw new InternalSCADAServiceException(errorMessage);
                        }

                        addressToGidDictionary.Add(discretePoint.Address, rds[i].Id);
                        await AddressToGidMap.SetAsync(registerType, addressToGidDictionary);

                        debugMessage = $"{baseLogString} ImportDiscrete => ANALOG measurement added to SCADA model [Gid: 0x{gid:X16}, Address: {discretePoint.Address}]";
                        Logger.LogDebug(debugMessage);
                    }

                    resourcesLeft = await nmsGdaClient.IteratorResourcesLeft(iteratorId);
                }

                await nmsGdaClient.IteratorClose(iteratorId);

                success = true;
            }
            catch (Exception ex)
            {
                success = false;
                string errorMessage = $"{baseLogString} ImportDiscrete => failed with error: {ex.Message}";
                Console.WriteLine(errorMessage);
                Logger.LogError(errorMessage, ex);
            }

            return(success);
        }