В этой статье я сделал обзор одного из возможных подходов к созданию гибких и стабильных MES систем классической клиент-серверной архитектуры с использованием "чистого" SQL с программированием потоковых операций через легкий разработанный скриптовый язык. Старый добрый проверенный способ разработки в двухзвенной архитектуре здесь стал палочкой-выручалочкой, позволив сравнительно просто и относительно быстро командой из 2-х человек создать довольно сложную систему на базе разработанного для этого специального языка типа DSL. Конечно, это не язык в общем смысле, а табличный скрипт, эмулирующий программу с линейным и циклическим алгоритмом и поддержки косвенной адресации внутри цикла. Со своей специализированной задачей он справляется и дает возможность строить простые и сложные тесты "железа".

Постановка задачи

А задача была такая: необходимом было разработать программную систему для производства, поверки и тестирования интеллектуальных датчиков с протоколом HART на тестовых станциях с программируемым оборудованием. Кто не знает что такое HART - это протокол "точка-точка" частотной модуляции тока , который накладывается на токовую петлю 4-20 мА датчика и используется для калибровки,настройки и поверки интеллектуальных датчиков с токовой петлей 4-20 mA/HART. Тестирование таких изделий включает в себя линеаризацию передаточной характеристики датчика, поверку, множество тестов на этапах отработки и периодических испытаний с использованием циклов по давлению, температурам, напряжению питания и HART обмену. Желательно иметь возможность редактировать функционал Тестов, то есть изменять программу тестирования. Естественно, нужно сохранять "сырые" данные тестирования и формировать протоколы тестирования.

Одна тестовая станция должна поддерживать несколько десятков датчиков и включать такое оборудование как компьютер, задатчик воздействий на датчики, климатическую камеру, измерительное оборудование и коммутатор, эталон сопротивления, HART модем. Все приборы имеют различные интерфейсы управления, такие как USB, GPIB, TCP/IP, RS232. Тестовых станций может быть тоже не одна и не две, а в перспективе десяток и больше. Отсюда вытекает необходимость в некой системе мониторинга этих станций, которая бы показывала что происходит на каждой станции тестирования, режимы работы оборудования, логи и т п.

Задача поначалу казалась очень непростой. Но какая бы ни была сложная система, стандартный подход к решению сложных задач состоит в их декомпозиции, разбивке сложной задачи на несколько более простых. Следуя этому принципу, можно выделить в данной системе несколько подсистем. Первая - это управление и работа с оборудованием и датчиками. Вторая - это программирование тестов и работа с базой данных. Третья- это обработка данных и расчеты, формирование протоколов. Четвертая - мониторинг тестирования. Такое структурирование уже проясняет архитектуру требующейся программной системы и можно рассматривать различные варианты создания подсистем.

Работа с оборудованием и датчиками

Первый вариант, который пришел в голову - использовать какой либо универсальный язык с ООП, описать на нем структуру команд всех интерфейсов приборов и т п. Вариант был сразу отметен ввиду сложности и длительности процесса такой разработки на универсальном языке типа С# и других. Тот же С# , к примеру, плохо подходит для создания предметных сущностей для работы с оборудованием. Я видел такие подходы в компании где работал до этого и в общем, это как-то работало, но требовало создания кучи дополнительных абстактных сущностей и классов. У меня не было ни команды, ни возможности и времени для подобного подхода к разработке. А сейчас тенденции в мире измерений и тестирования электроники такие, что ведущие компании по производству интеллектуальных приборов переходят (или уже перешли) в таких задачах на оборудование и программную систему LabView компании National Instruments (теперь это ЭМЕРСОН). Все необходимые интерфейсы к приборам и оборудованию в системе LabView есть и использовать их относительно просто (тому кто знаком с языком управления приборами SCPI, к примеру). Оставалось найти программиста LabView. Их не очень много, так как графическая среда разработки в которой вообще нет кода, довольно специфична. Такой человек в команду нашелся и довольно хорошей квалификации в этой области программирования.

Сразу было понятно, что если в качестве клиентской части применять LabView на тестовой станции, то использовать ООП не получится, так как эта система его не поддерживает. Вообще любой ЯП в парадигме создания ПО с применением ООП страдает не только излишней нагруженностью абстракциями, но и потребностью в сложном тестировании относительно несложных вещей. У нас не было таких возможностей. Поэтому архитектурные варианты с бизнес-логикой на клиенте сразу были исключены из рассмотрения. Тот кто видел программы на Labview, тот сразу поймет , что усложнять и без того сложные диаграммы LabView можно, но не нужно, мы бы погрязли в болоте взимозависимостей бизнес-логики очень надолго. Вся логика тестирования ( а это потоки операций) должна быть вынесена наружу, в программу или в скрипт теста. Сам скрипт может храниться в файле или таблице базы данных. После некоторых раздумий было принят�� решение хранить скрипт теста в таблице базы данных, так как вся обработка данных (или почти вся) в этой архитектуре тоже должна быть в базе данных.

Программирование тестов и работа с базой данных

Идея с редактируемым скриптом теста сразу натолкнула на мысль, что клиент LabView тестовой станции должен быть по сути интерпретатором, выполняющим команды из скрипта теста. Здесь не требовалалась скорость работы, так как операции были длительные. Фактически это означало, что надо разработать некую систему команд в виде табличного скрипта, которая будет включать работу с оборудованием, базой данных, климатической камерой, датчиками и Тест в данном случае будет состоять из таблицы строк команд с параметрами в виде линейного алгоритма, соответствующий определенному функционалу Теста, который будет выполнятся на тестовой станции клиентом LabView в режиме интерпретатора. Функционал Теста как поток тогда можно строить из "кирпичиков" - операций Теста. Оставалась одна сложность - как разбивать Tесты на операции ( команды) по функционалу. Видов тестов требовалось довольно много. Если разбить мелко - будет слишком длинные тесты в табличном виде и редактировать их будет неудобно. Если разбить крупно - снижается гибкость программирования теста. Золотая середина была найдена так - первый вариант основного теста температурной калибровки датчика делался с жесткой логикой на клиенте Labview в виде линейного алгоритма потока операций. Это помогло понять подходы к разбиению теста на операции. Далее все вылилось в создание специфического для данной области табличного скрипта ( DSL ) , на котором можно было составлять программы тестирования. Сначала был реализован линейный алгоритм выполнения операций, но еще и хотелось использовать циклы для уменьшения количества строк программы теста. Обычно циклы делаются в клиентском приложении. Но в этой задаче я решил сделать наоборот и циклы были сделаны в БД. Задача была решена очень просто добавлением нескольких таблиц и доработкой одной хранимой процедуры. Но чтобы до этого дойти пришлось немного поразмышлять и поэкспериментировать с кодом SQL. Эксперименты показали что все работает и циклы можно применить в хранимых процедурах и хранить параметры циклов таблицах.

Исходя из этого в систему команд табличных скриптов тестов были добавлены команды инициализации цикла и проверки окончания цикла. Также реализованы были операции с таймерами, инициализация циклов по видам воздействий. Всего видов циклов по воздействиям было сделано 3 плюс общий цикл. Реализация общего цикла была сделана в базе данных в отдельной таблице, в которую записывались параметры цикла ( начальное значение переменной цикла, конечное значение переменной цикла, текущее значение, активный тестируемый пул датчиков, станция тестирования) при выполнении операции инициализации цикла. Также был создан цикл таймера, внутри которого крутились операции в течение времени инициализированного таймера. Введение оператора цикла и таймера позволило резко сократить ( почти в два раза ) количество строк Теста и увеличить гибкость программирования.

Перед выполнением цикла выполнялись операции загрузки на клиентское ПО статических моделей воздействий из таблиц БД. Для инициализации циклов по воздействиям и каналам, получения величин воздействий из самого скрипта теста использовался тот же вид цикла что уже был, но для операций инициализации цикла ( в зависмости от вида воздействия) потребовалась дополнительная таблица циклов по по типам воздействий с указанием начальных и конечных значений параметров воздействий, шага воздействия и способа модификации переменной цикла до или после начала цикла ( ++i и i++ по аналогии с циклами в С++).

Цикл в программе с учетом пропускаемых операций в программе.
Цикл в программе с учетом пропускаемых операций в программе.

При этом был вопрос - сколько нужно параметров для операций (команд), которые будут использоваться в скрипте теста? Не хотелось использовать много параметров, так как это усложняло программирование теста. Архитектура таблиц циклов была сделана так, что всего 2 параметра было достаточно для всех созданных операций в скриптах ( всего было разработано больше 100 операций, из которых можно строить программы тестирования датчиков). Некоторые операции внутри цикла в зависимости от параметров были сделаны в двух ипостасях- как зависимые от номера цикла если привязывались к циклу , так и независимые от номера цикла и также могли использоваться внутри цикла таймера и там зацикливаться на себя. То есть можно крутить эту операцию пока таймер работает и после пректащения работы таймера управление передается на следующую операцию программы тестирования.

Сначала все тесты программировались в хранимой процедуре. Позже был разработан табличный редактор Теста в отдельной программе. Он позволял копировать Тесты , редактировать и "компилировать" их ( стирать старый тест и заменять его новым). Так как операций и вариантов параметров было разработатно много, то запомнить их было сложно. Была добавлена интерактивня помощь при разработке теста. При выборе строки Теста показывалось описание параметров. Получилось довольно не затратно - программист Теста заботится только о порядке операций, добавлении или удалении операций и значениях 2-х параметров. Все остальное ( расстановка нумерации строк, ссылок на следующ��ю команду теста, комментарии к операциям с учетом циклов и т п) взяла на себя система SQL на сервере ( используется встроенная хранимая процедура корректировки указанного Теста, которая автоматически формирует тест и все ссылки в таблицах теста). Доступно и копирование тестов. Новый Тест можно делать не с нуля, а скопировать похожий и отредактировать. Всего сейчас сделано более 100 программ тестирования, которые используются как для производства, так и для тестирования приборов с интерфейсом 4-20мА\HART.

Работа с базой данных и формирование протокола тестирования

Клиент Labview работает с базой данных и датчиками через программу теста в режиме интерпретатора. Программа может включать множество операций. Операции разработаны разные, и контрольные и расчетные , вплоть до транспонирования матриц в SQL для расчета коэффициентов полиномов, применяемых для линеаризации передаточной характеристики и компенсации температурной погрешности метрологических параметров датчиков. Использовании метода наименьших квадратов для расчетов в БД я посчитал сложным. Поэтому использовали компонент на клиенте labview скармливая ему транспонированные матрицы и подобрав метод расчета , дающий наибольшую точность обратным расчетом. Другой пример сложной обработки в операции - формирование протокола тестирования пула датчиков, внутри которой при вызове соответствующей хранимой процедуры по данным Теста рассчитываются метрологические параметры датчиков пула и определяется класс точности по формулам из описания типа в зависимости от диапазона перестройки датчиков.

Работа клиентской части в качестве интерпретатора происходит следующим образом. Считывание строки скрипта из программы и выполнение операции происходит построчно из таблицы скрипта вместо загрузки его полностью. Табличный скрипт представляет собой односвязный список, где каждая строка связывается со следующей ссылкой с помощью ссылки новой строки в таблице Теста.

Такой режим построчной загрузки был выбран для того, чтобы был доступен режим корректировки Теста в процессе его выполнения, подобно тому, как запускается любая программа в режиме отладки. Скрипт теста связывает строки по ссылке, но она скрыта от пользователя и формируется автоматически при "компиляции" табличного теста после его создания. Ссылка на следующую команду в операции проверки конца цикла указывает на следующую строку программы Теста и когда переменная цикла достигает указанное количество циклов, программа переходит на следующую строку после операции проверки конца цикла. Все эти простые "хитрости" cо скриптами и циклами, были реализованы в хранимой процедуре, которая проходя по таблице теста автоматически формировала связный список, делала автоматическую расстановку ссылок на операции, циклы и таймеры. В итоге получилась неограниченная вложенность циклов, режим пошагового выполнения программы Теста для отладки операций, остановка выполнения операций , ручной переход на любую строку программы вперед и назад. Практика показала что это очень удобно при отладке теста и важно при различных нестандартных ситуациях в процессе тестирования, когда нужно повторить ранее выполненные операции , пропустить операции и даже добавить операцию в выполняемый Тест и т д. Циклы в БД помогли и в том, что при внезапных отключениях питания тестовых станций появился режим перезапуска теста. Так как основная информация, данные программы и длительные циклы хранятся в SQL базе данных, а не на клиенте и соединение с ней не обрывается, так как БД защищена от пропадания питания, то режим перезапуска позволяет не запускать тест заново, а вернуться при перезапуске в ту же точку где программа теста была остановлена.

Рис. 3  Добавление и корректировка программы Теста.
Рис. 3 Добавление и корректировка программы Теста.

Для программирования теста и его изменения программисту теста нужно меня только два параметра в колонках PROCESS_TEST и AUTO_OR_HAND. Комментарии к строкам, все скрытые ссылки связности операций и циклов формируются автоматически при "компиляции" теста, что делает соответствующая хранимая процедура в БД. Режим интерактивной помощи позволяет при добавлении операции или ее корректировке и просмотре программы сразу показывать аргументы и их описание. После того как программа Теста составлена из операций, достаточно ее "скомпилировать" ( запустить операцию, которая автоматичеки ее упакует в таблицу и напишет комментарии), чтобы использовать для работы или отладки. Как и в любом языке, при составлении программмы Теста надо учитывать порядок выполнения операций исходя из логики Теста. Пошаговый режим работы интерпретатора позволяет отладить работу программы даже в режиме активного тестирования.

Мониторинг тестовых станций

Сбор параметров оборудования для мониторинга тестовых станций делает клиент Labview, который сохраняет их в БД c интервалом 1 сек для каждой станции и ведет лог операций. Для исключения взаимоблокировок у каждой станции тестирования есть своя таблица параметров мониторинга. Первоначальный вариант содержал общую таблицу параметров, но в дальнешем , при масштабировании системы таблица параметров состояния станций была разделена на отдельные таблицы для исключения взаимоблокировок. Анализ взаимоблокировок показывал, что они периодически возникали в мониторинге и не то чтобы сильно мешали, так как сервер автоматически разруливал ситуацию, но в связи с масшабированием системы желательно было их устранить. Новые таблицы параметров всех станций были объединены представлением и данные в них записывались через триггер INSTEAD OF для представления. Лог всех выполненных операций сохранялся в БД. Для оптимизации мониторинга лог операций, на котором он был основан, был разделен на оперативный и архивный. Такое разделение необходимо было сделать для системы онлайн мониторинга выполняемых тестов для минимизации времени выполнения хранимых процедур мониторинга. Каждая процедура мониторинга была оптимизирована с учетом плана выполнения хранимой процедуры и создания нужных индексов. Мониторинг выполняемых тестов в онлайн использует только оперативный лог, который через триггер дублируется в архивный. Оперативный лог каждой станции при запуске нового теста сначала очищается. Вся история тестов далее хранится в архивном логе. Под систему мониторинга было сделано отдельное приложение, которое используя параметрф оборудования и логи операций формирует и показывает следующие указанные на рис дашборды и представления в режиме on-line c интервалом 1,6 сек. Кроме того, для всей экосистемы программ на SQL ( не только стенды , есть еще несколько приложений , использующих сервер SQL) добавил просмотр запущенных приложений SQL, логи пользователей приложений, историю всех изменений DDL на сервере включая индексы, функции, хранимые процедуры.

В итоге при работе мониторинга загрузка ЦП стала пренебрежимо мала и взаимоблокировки ресурсов сервера полностью отсутствуют. Ниже для примера показан краткий перечень основных возможностей отображения и контроля параметров тестирования. Что показывается и какие отчеты можно получить в режиме онлайн:

  • cписок станций тестирования, показ статуса режима работы станций  и длительности активного текущего теста на них,

  • тесты и операции, выполненные и выполняемые  в реальном времени  на каждой станции тестирования,

    статусы и текущие параметры оборудования  выбранной тестовой станции.

  • Данные тестирования в онлайн режиме

  • Выгрузка данных в csv.

  • Полный контроль прохождения теста с удаленного компьютера.

  • История прохождения теста и даннные тестирования.

Система отличается высокой стабильностью и предсказуемостью. Нестандартные ситуации с получением данных обрабатываются в базе данных и в случае ошибок программа уходит в режим паузы для выбора дальнейших действий оператором Теста. Нестандартные ситуации с приборами и задатчиками обрабатываются на клиенте LabView.  Все такие ситуации отображаются в операционном логе и в программе мониторинга станций тестирования. 

Сложно в небольшой статье описать все что удалось реализовать в связке SQL + LabView с использованием разработанного скиптового языка (DSL) и функционального подхода к программированию потоковых операций. Эта связка показала , что при использовании скриптового DSL в БД можно относительно быстро и просто реализовать сложные тесты сбора и обработки данных с интеллектуальных приборов без усложнения клиентского приложения.

PS.

Система начиналась с одного стенда и сейчас увеличилась и насчитывает больше 10 станций тестирования. Никаких особых проблем ПО с бизнес-логикой в хранимых процедурах при масштабировании системы в несколько раз не было. Как я описал выше, на всякий случай была изменена только архитектура части системы поддержки мониторинга для исключения взаимоблокировок и проверены и оптимизированы планы запросов мониторинга на предмет загрузки ЦП.