python

ScadaPy — использование OPC UA

  • понедельник, 6 ноября 2017 г. в 03:12:47
https://habrahabr.ru/post/341728/
  • SCADA
  • Python


В предыдущих нескольких статьях, мною были описаны возможности применения протокола modbus для создания собственной Scada системы на базе python. В этот раз хочется поделиться опытом построения системы опроса подчиненных устройств с использованием ОРС технологии.
Недостатки OPC серверов в том, что их можно использовать только в операционных системах семейства Microsoft Windows (как правило они платные), а об устройствах использующих ОС Linux можно было забыть.

Но со временем была создана спецификация OPC Unified Architecture (англ. Унифицированная архитектура OPC), что дало возможность использовать данную технологию передачи данных на иных операционных системах отличных от Windows. Это касается и встраиваемых систем, где может быть запущен полноценный Linux.

Подробнее можно прочитать здесь.

Например, на одноплатном компьютере Raspberry Pi можно запустить одновременно несколько различных OPC UA серверов для опроса терминальных устройств, счетчиков, датчиков и т.д., при этом система будет работать вполне стабильно.

image

Установка библиотек


Для работы с OPC UA и modbus серверами используются Xubuntu 17.04 Desktop и Windows 8.1. В Xubuntu 17.04 уже установлены Python 2.7 и Python 3.5 по умолчанию. Выбираем Python 3.5.

Если после установки операционной системы на компьютер не были добавлены необходимые пакеты, то нужно выполнить:

sudo apt-get install python3-pip
sudo pip3 install pytz PyQt5
sudo apt-get install python3-opcua, libxml2-dev, python3-lxml

Решаем проблему зависимостей:

sudo apt-get –f install

После поставим еще необходимые библиотеки:

sudo pip3 install requests pyserial

Для windows можно установить через pip3.exe, библиотека и примеры находятся здесь

Для запуска сервера, библиотеку нужно импортировать:

import sys
from opcua import ua, Server

Теперь создаем OPC UA сервер.

server = Server()
#можно прописать IP адрес сетевого интерфейса сервера, если их несколько
server.set_endpoint("opc.tcp://0.0.0.0:4840/")
#Записываем название сервера
server.set_server_name("Server")
#здесь указываем расположение сертификатов шифрования
# можно обойтись и без них , тогда данные между клиентом и сервером не будут шифроваться
server.load_certificate("server_cert.der")
server.load_private_key("server_private_key.pem")
#настраиваем собственное пространство имен
uri = "http://server"
idx = server.register_namespace(uri)
#получаем ссылку на объект где будут располагаться наши узлы
objects = server.get_objects_node()
#создаем объект и присваиваем ему имя 
Object_1 =objects.add_object(idx,’MyFirstObject)
Object_2 =objects.add_object(idx,’MySecondObject)
Object_3 =objects.add_object(idx,’MyThirdObject)
#теперь создаем переменные
Discret_1 = Object_1.add_variable(idx,'Discret_1',[0,0,0,0,0,0,0,0])  
Discret_2 = Object_2.add_variable(idx,'Discret_2',[0,0,0,0,0,0,0,0])  
Analog_3  = Object_3.add_variable(idx,'Analog_3',[10,20,30,40,50])  
#запускаем сервер
server.start() 

Вот и весь код на python для запуска OPC UA. Как оказалось ничего сложного, и если теперь подключиться к запущенному серверу с помощью UA Expert, то можно увидеть иерархический список наших объектов и переменных со значениями.

Для модификации значений переменных используется функция set_value типа:

Discret_1.set_value([1,1,1,1,1,1,1,1]) 

Конечно это очень примитивный пример, но в библиотеке OPC UA заложено намного больше возможностей, о которых можно прочитать здесь.

Единственное в чем не удалось разобраться, так это, как установить логин и пароль на сервер, вроде как-то посредством politics, думаю позже решу эту проблему.

Конфигуратор серверов


В продолжение к вышесказанному, возникла задача по оперативному конфигурированию каждого вновь создаваемого сервера.

Для данной цели был написан «Конфигуратор серверов» на библиотеке PyQt5.

image

Принцип работы:

— создается база данных на sqlite3
— формируются таблицы для slave и master частей сервера.
— таблицы заполняются необходимыми параметрами.
— формируется скрипт запуска.

Основная идея – серверы должны одинаково работать как в Windows, так и в Linux.
Скачать можно здесь

Структура каталогов:
srvconf.py – программа «Конфигуратор сервера»
db – находится файл базы данных srvDb.db.
img – файлы .png для кнопок
source – файлы шаблонов серверов

  • mercury.py – библиотека для опроса счетчиков меркурий 230
  • modbustcp_master_dcon.py – slave-сервер modbusTCP, master – опрашивает подчиненные устройства по протоколу DCON (Advantech). В настоящий момент только модуль 4050.
  • modbustcp_master_http.py – slave-сервер modbusTCP, master – формирует запрос методом GET по URL или IP, в ответ получаем список значений типа int или string разделенных запятыми. Используется для встроенных систем с http серверами на борту, я использовал для ESP8266 c wi-fi соединением.
  • modbustcp_master_ping.py – slave-сервер modbusTCP, master – отправляет ICMP пакет ping на указанный сервер, в случае true формирует дискретную 1, в случае false – 0.
  • modbustcp_master_rtu.py — slave-сервер modbusTCP, master – modbusRTU. Используется для опроса подчиненных устройств по протоколу modbusRTU
  • modbustcp_master_tcp.py — slave-сервер modbusTCP, master – modbusTCP. Используется для опроса удаленных устройств по протоколу modbusTCP.
  • opcua_master_dcon.py — slave-сервер OPC-UA, master – опрашивает подчиненные устройства по протоколу DCON (Advantech). В настоящий момент только модуль 4050.
  • opcua_master_http.py — slave-сервер OPC-UA, master – формирует запрос методом GET по URL или IP, в ответ получаем список значений типа int или string разделенных запятыми. Используется для встроенных систем с http серверами на борту, я использовал для ESP8266 c wi-fi соединением.
  • opcua_master_mercury230.py — slave-сервер OPC-UA, master – формируются команды опроса счетчиков меркурий 230. Реализация исключительно только для OPCUA, поскольку не все параметры ответа по данному протоколу можно однозначно обработать для того чтобы поместить в регистры modbus.
  • opcua_master_ping.py — slave-сервер OPC-UA,master – отправляет ICMP пакет ping на указанный сервер, в случае true формирует дискретную 1, в случае false – 0.
  • opcua_master_rtu.py — slave-сервер OPC-UA,master – modbusRTU. Используется для опроса подчиненных устройств по протоколу modbusRTU.
  • opcua_master_tcp.py — slave-сервер OPC-UA, master – modbusTCP. Используется для опроса удаленных устройств по протоколу modbusTCP.

scr – файлы сценариев для запуска сервера.

Для Windows будет создан файл типа start_XX.bat, для Linux файл типа start_XX.sh, где ХХ порядковый номер сервера в таблице servers.

Содержимое файла start_XX.bat:

rem Скрипт создан в программе 'ScadaPy Конфигуратор сервера v.3.11'
rem Название сервера 'Windows opcua_mercury230 '
rem Slave адрес '192.168.0.103'
rem Slave порт '4840'
rem Тип master 'master_mercury230'
rem Тип slave 'opcUA'
rem Интерфейс tty 'com6'
rem Скорость tty '9600'
start c:\Python35\python.exe F:\scadapy\config\source\opcua_master_mercury230.py 68 F:\scadapy\config\db\srvDb.db

Содержимое файла start_XX.sh для Linux:
# Скрипт создан в программе 'ScadaPy Конфигуратор сервера v.3.09'
# Название сервера 'Modbus TCP'
# Slave адрес '192.168.0.101'
# Slave порт '504'
# Тип master 'master_modbusTCP'
# Тип slave 'modbusTCP'
# Интерфейс tty '/dev/ttyUSB0'
# Скорость tty '9600'
/home/jack/config/source/modbustcp_master_tcp.py 67 /home/jack/config/db/srvDb.db

В параметрах запуска для Linux используется xfce4-terminal, т.к. работаю в Xubuntu 17.04,
но можно указать и другой тип запуска, вроде gnome-terminal.

xfce4-terminal --command='sudo  /home/jack/config/scr/start_67.sh'

В примерах довольно понятно описаны параметры заполнения таблиц.

Примечательно, что на raspberry Pi запускалось одновременно 4 сервера — mobus_ping, opcua_http, opcua_mercury230 на /dev/ttyUSB0 и modbus_dcon на /dev/ttyUSB1, при этом он работал довольно стабильно и без сбоев.

Управление на данный момент реализовано частично и только в master_dcon, поэтому используется только телесигнализация и телеизмерения. В дальнейшем думаю добавить и телеуправление.