Пример #1
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); // признак успешности запроса
        }
Пример #2
0
        /// <summary>Приёмник сообщений архивной станции</summary>
        /// <param name="Response">Единичный элемент данных архивной станции</param>
        /// <returns>Признак готовности к приёму следующего сообщения</returns>
        private int _get_historical_data(ref Services.QAResponse Response)
        {
            try
            {
                user_data_reference _user_data_ref = (user_data_reference)Marshal.PtrToStructure(Response.UserData, typeof(user_data_reference)); // копирует локальную копию индекса кэша в управляемую память

                if (Response.Status == Services.RS_OK)
                {
                    _pipe_active = true; // приём любого ответа со статусом RS_OK означает рабочее состояние канала связи с архивной станцией

                    if (Response.ParamId.CardId != 0 && Response.ParamId.ParamNo != 0)
                    {
                        if (Response.ParamId.Category == 7)
                        {
                            if (Response.ValueFormat == (int)Services.QAValueFormat.VF_QR8)
                            {
                                KvintArchive.VT_QR8 vt_f = (KvintArchive.VT_QR8)Marshal.PtrToStructure(Response.Value, typeof(KvintArchive.VT_QR8));
                                _user_data_ref.data.table.write_value(_user_data_ref.data.parameter_index, Response.Time.AsDateTime, vt_f.value, vt_f.quality < 64);
                                if (vt_f.quality < 64)
                                {
                                    _user_data_ref.data.count++;
                                }
                            }

                            if (Response.ValueFormat == (int)Services.QAValueFormat.VF_QUI4)
                            {
                                KvintArchive.VT_QUI4 vt_i = (KvintArchive.VT_QUI4)Marshal.PtrToStructure(Response.Value, typeof(KvintArchive.VT_QUI4));
                                _user_data_ref.data.table.write_value(_user_data_ref.data.parameter_index, Response.Time.AsDateTime, (double)vt_i.value, vt_i.quality < 64);
                                if (vt_i.quality < 64)
                                {
                                    _user_data_ref.data.count++;
                                }
                            }

                            if (Response.ValueFormat == (int)Services.QAValueFormat.VF_QUI2)
                            {
                                KvintArchive.VT_QUI2 vt_i = (KvintArchive.VT_QUI2)Marshal.PtrToStructure(Response.Value, typeof(KvintArchive.VT_QUI2));
                                _user_data_ref.data.table.write_value(_user_data_ref.data.parameter_index, Response.Time.AsDateTime, (double)vt_i.value, vt_i.quality < 64);
                                if (vt_i.quality < 64)
                                {
                                    _user_data_ref.data.count++;
                                }
                            }
                        }
                    }

                    return(1); // продолжать приём данных
                }

                if (Response.Status == Services.RS_PIPEERROR)
                {
                    _pipe_active = false;                                                // ошибка программного канала - связь с АС потеряна
                }
                if (Response.Status == Services.RS_OPENPIPEFAILED)
                {
                    _pipe_active = false;                                                // ошибка открытия программного канала - связь с АС не установлена
                }
                if (_pipe_active == false)
                {
                    return(0);                       // 0 - прекращает приём данных, завершая текущий запрос
                }
            }
            catch (Exception ex)
            {
                Logger.Log(0, String.Format(" ERROR: [{0}] ошибка при приёме данных: {1}", _station, ex.Message));
            }

            return(0); // прекратить приём данных
        }