Ejemplo n.º 1
0
        /// <summary>Получить значения параметров источника данных за указанный час</summary>
        /// <param name="begin_time">Начало часового интервала</param>
        /// <param name="source">Описатель источника данных</param>
        /// <param name="table">Буфер в памяти для приёма значений параметров</param>
        private static bool ReadInterval(SourceConfiguration source, DateTime begin_time, out MemoryTable table)
        {
            // диагностическая переменная для определения успешных запросов к группам источников данных
            bool result = false;

            // инициализация таблицы в памяти для приёма сырых данных
            table = new MemoryTable();

            foreach (string _station in source.Stations)
            {
                // диагностическая переменная для определения успешных запросов к отдельным источникам данных
                bool _result_per_station = false;

                // чтение истории значений каждого параметра по отдельности
                foreach (KeyValuePair <ushort, ParameterConfiguration> __parameter in source.Parameters)
                {
                    // обращение к источникам данных по типу
                    switch (source.SourceType)
                    {
                    case SourceType.Kvint:
                        _result_per_station = kvint_stations[_station].get_hour_interval(begin_time, __parameter.Key, __parameter.Value.Name, ref table);
                        break;

                    case SourceType.Odbc:
                        _result_per_station = odbc_sources[_station].get_hour_interval(begin_time, __parameter.Key, __parameter.Value.sql_queries, ref table);
                        break;

                    default:
                        break;
                    }

                    if (!_result_per_station)
                    {
                        break;                       // при отсутствии данных по одному из параметров, дальнейший запрос источника прекращается
                    }
                }

                result = result || _result_per_station; // чтение интервала успешно, если успешен запрос хотя бы одного источника
            }

            return(result);
        }
Ejemplo n.º 2
0
        /// <summary>Преобразование сырых данных в набор строк по шаблону</summary>
        /// <param name="config">Конфигурация</param>
        /// <param name="begin_time">Начало часового интервала</param>
        /// <param name="table">Таблица в памяти для принятых данных</param>
        /// <param name="buffer">Буфер в памяти для обработанных данных</param>
        private static long ProcessInterval(Configuration config, SourceConfiguration source, DateTime begin_time, ref MemoryTable table, out MemoryStream buffer)
        {
            long quality = 0;                                              // результирующее качество выборки по числу строк с хорошим качеством

            buffer = new MemoryStream();                                   // создаёт поток в памяти для записи выборки из текущего источника
            StreamWriter writer = new StreamWriter(buffer, Encoding.UTF8); // создаёт писатель текстовых данных в бинарный поток

            for (uint row = 0; row < 3600; row++)
            {
                int    row_quality = 0; // результирующее качество строки данных
                string result      = config.pattern;

                // запрос строки: названия параметров заменяются ближайшими по времени значениями
                foreach (string _str in Regex.Split(config.pattern, @"[;:]+"))
                {
                    result = result.Replace("_row_", row.ToString()); // вставка номера строки (секунды)

                    if (Regex.IsMatch(_str, @"^[$][A-z]+[$]$"))
                    {
                        // чтобы получить номер параметра по его абстрактному имени, выполняем поиск ключа по значению перебором
                        foreach (KeyValuePair <ushort, string> __abstract_name in config.abstract_parameter_names)
                        {
                            if (__abstract_name.Value == _str.Trim('$'))
                            {
                                // объявления переменных для запроса значения параметра
                                bool     column_quality;
                                double   column_value;
                                DateTime column_timestamp;

                                // запрос значения параметра, ближайшего по запрашиваемому времени
                                if (table.read_sample(__abstract_name.Key, begin_time.AddSeconds(row), out column_timestamp, out column_value, out column_quality))
                                {
                                    // для шумоподобных параметров анализируется отставание метки времени последнего полученного значения от времени запроса
                                    // если отставание превышает maximum_latency секунд, строке присваивается плохое качество
                                    if (source.Parameters[__abstract_name.Key].Type == ParameterType.Noisy &&
                                        (begin_time.AddSeconds(row) - column_timestamp).CompareTo(new TimeSpan(0, 0, config.maximum_latency)) > 0)
                                    {
                                        column_quality = false;
                                    }

                                    // замещение названий параметров значениями
                                    result = result.Replace(_str, String.Format(nfi, "{0:F" + config.precision + "}", column_value));

                                    // подсчёт количества значений с хорошим качеством для последующей оценки качества строки
                                    row_quality = row_quality + (column_quality ? 1 : 0);
                                }
                            }
                        }
                    }
                }

                // вставка интегрального качества выборки, вычисляется сравнением количества значений с хорошим качеством, с общим количеством зарегистрированных параметров
                result = result.Replace("_quality_", row_quality == config.abstract_parameter_names.Count ? "1" : "0");

                // запись строки с результатом в поток с результатом для текущего источника
                writer.WriteLine("{0}", result);

                // подсчёт строк с хорошим качеством
                if (row_quality > 0)
                {
                    quality++;
                }
            }

            writer.Flush();                   // сброс буфера текстового писателя потока
            buffer.Seek(0, SeekOrigin.Begin); // перемещение файлового указателя потока в начальную позицию
            return(quality);                  // возврат интегрального качества выборки
        }
Ejemplo n.º 3
0
        /// <summary>Получает часовой набор значений указанного параметра за указанный период</summary>
        /// <param name="start_time">Начало интервала</param>
        /// <param name="parameter_index">Индекс параметра</param>
        /// <param name="station_parameter_name">Локальное название параметра архивной станции</param>
        /// <param name="table">Ссылка на таблицу в памяти для приёма истории значений параметра</param>
        /// <returns>Запрос успешен: параметр существует и получены данные с хорошим качеством</returns>
        internal bool get_hour_interval(DateTime start_time, ushort parameter_index, string station_parameter_name, ref MemoryTable table)
        {
            user_data_reference _user_data_ref = new user_data_reference();                   // структура для передачи ссылки на дополнительные параметры через неуправляемый код
            UserData            _user_data     = new UserData();                              // структура для транзита дополнительных параметров через неуправляемый код

            _user_data_ref.data = _user_data;                                                 // вставляем в структуру UserData ссылку на класс с дополнительными полями данных
            _user_data_ref.data.parameter_index = parameter_index;                            // индекс параметра
            _user_data_ref.data.count           = 0;                                          // счётчик принятых значений параметров с хорошим качеством
            _user_data_ref.data.table           = table;                                      // указательно на таблицу в памяти для приёма сырых значений

            IntPtr pointer = Marshal.AllocHGlobal(Marshal.SizeOf(_user_data_ref));            // распределяем память в куче для копирования туда индекса кэша

            Marshal.StructureToPtr(_user_data_ref, pointer, false);                           // копируем индекс кэша в кучу

            Services.QAQuery query = new Services.QAQuery();                                  // структура, описывающая запрос к АС
            query.LinkId    = _link_id;                                                       // дескриптор подключения к архивной станции
            query.Callback  = new Services.QACallback(_get_historical_data);                  // процедура для приёма данных от АС
            query.BeginTime = new Services.QATime(start_time);                                // начало запрашиваемого интервала
            query.EndTime   = new Services.QATime(start_time.AddHours(1));                    // конец запрашиваемого интервала
            query.Flags     = Services.QF_BEGINOUTSIDE | Services.QF_FILTLAST;                // флаги запроса
            query.Accuracy  = 1;                                                              // шаг времени для просеивания
            query.UserData  = pointer;                                                        // указатель на буфер в неуправляемой памяти с дополнительными параметрами запроса

            bool parameter_exist = load_parameter(station_parameter_name, out query.ParamId); // проверка наличия параметра на АС и получение его атрибутов

            if (parameter_exist)
            {
                Logger.Log(4, String.Format(" INFO4: [{0}] запрос значений параметра {1}", _station, station_parameter_name));

                _execute_query(ref query);
            }

            Marshal.FreeHGlobal(pointer);          // освобождаем выделенную в куче память

            return(_user_data_ref.data.count > 0); // признак успешности запроса
        }
Ejemplo n.º 4
0
        /// <summary>Получает часовой набор значений указанного параметра за указанный период</summary>
        /// <param name="start_time">Начало интервала</param>
        /// <param name="parameter_index">Индекс параметра</param>
        /// <param name="sql_queries">Название параметра (не используется в ODBC)</param>
        /// <param name="table">Ссылка на таблицу в памяти для приёма истории значений параметра</param>
        /// <returns>Запрос успешен: параметр существует и получены данные с хорошим качеством</returns>
        internal bool get_hour_interval(DateTime start_time, ushort index, Collection <string> sql_queries, ref MemoryTable table)
        {
            // счётчик принятых успешно данных
            uint count = 0;

            // обработка каждого, из ассоциированных с параметром, запросов
            foreach (var _query in sql_queries)
            {
                // выполняем вставку начала обрабатываемого часа в sql запрос
                string _sql_query = Regex.Replace(_query, "_unix_basetime_", (start_time - new DateTime(1970, 1, 1)).TotalSeconds.ToString());

                // проверка доступности источника данных
                if (_source_active)
                {
                    // выполнение запроса
                    using (OdbcDataReader _reader = new OdbcCommand(_sql_query, _odbc_connection).ExecuteReader())
                    {
                        // циклическое чтение данных
                        while (_reader.Read())
                        {
                            // подсчёт успешно принятых строк данных
                            count++;

                            // запись результатов в таблицу в памяти
                            table.write_value(index, new DateTime(1970, 1, 1).AddSeconds(_reader.GetDouble(0)), _reader.GetDouble(1), true);
                        }
                    }
                }
            }

            return(count > 0);
        }