[Из песочницы] Зачем SCADA, когда есть .NET?
Я работаю в компании, которая занимается автоматизацией производственных процессов. Знаком не по наслышке с программируемыми логическими контроллерами (PLC), человеко-машинным интерфейсом (HMI) и SCADA (диспетчерское управление и сбор данных).А еще я увлекаюсь программированием. В основном на языках C# и Java (Android). Когда я познакомился с технологией WPF и увидел как просто на ней реализуется графический интерфейс пользователя, восторгу моему не было предела. «Да это же убийца SCADA-систем», — подумал я. Надо просто каким-то образом связать .NET проект с устройствами ввода-вывода (PLC).И тут ко мне пришла идея, которая в определенный момент приходит к каждому автоматчику. Сделать свою SCADA-систему. И не просто SCADA-систему, а SCADA-систему для .NET разработчиков (прежде всего для себя самого). Потому что порой когда переключаешься из Visual Studio в редактор «современной» SCADA-системы, хочется вырвать себе последние волосы. Но настоящие трудности начинаются, когда необходимо реализовать функционал, выходящий за рамки базового. Другое дело — мир программистов. Ответ практически на любой вопрос можно быстро найти на сайте stackoverflow.com через его поисковый интерфейс google.com.
Далее я опишу то, что у меня получилось сделать. Исходный код проекта доступен по ссылке https://github.com/phmi/phmi.
УстановкаДля использования PHmi (так я ее назвал) должны быть удовлетворены следующие условия: PHmi СУБД PostgreSQL v9.2 или выше (ее можно скачать с сайта www.postgresql.com) Microsoft Visual Studio 2010 или выше (экспресс версия или Community Edition подойдет) Разработка проекта Разработку проекта можно разделить на две фазы: конфигурирование сервера и разработку проекта клиента.Конфигурирование сервера Запустим PHmiConfigurator.exe. Появится следующее окно:
Нажмем на кнопку «New project». Появится окно «New project»:
Введем параметры связи с PostgreSQL и желаемое название базы данных:
После нажатия на кнопку «Ok» новый проект будет создан:
Нажмем на кнопку «I/O devices». В конфигураторе откроется вкладка «I/O devices»:
Добавим новое устройство ввода-вывода «IoDev» типа «Generic». «Generic» — это устройство ввода вывода для отладочных целей. Либо оно используется, когда не нужно соединяться с реальным устройством. Оно поддерживает любые адреса тегов:
Нажмем на кнопку «Save» и закроем вкладку.Откроем вкладку «Digital tags» и создадим новый цифровой тег.
Откроем вкладку «Numeric tags» и создадим новый аналоговый тег:
Поля описания, формата, единицы измерения, калибровочные границы необязательны и могут быть опущены.Создадим новую категорию аварий:
Создадим новый тег аварий:
Создадим категорию трендов:
Создадим новый тег трендов:
Разработка проекта клиента В конфигураторе нажмем на кнопку «Build client»:
Выберем путь к файлам, чтобы их создать.«Namespace» должно совпадать с названием будущего проекта Visual Studio.Нажмем на кнопку «Build».По указанному пути должны появиться файлы:
Запустим Microsoft Visual Studio и создадим новый проект WPF. Целевой фреймворк должен быть ».Net Framework 4.0» или выше:
Добавим ссылку к PHmiClient.dll:
Добавим файлы PHmi.cs и PHmiResources.resx, созданные заранее:
Кликнем двойным щелчком по PHmiResources.resx и поменяем «Access modifier» на Public:
Откроем MainWindow.xaml. Добавим кнотрол Root в корневой Grid.
Страницы должны реализовывать интерфейс IPage. Листинг HomePage.xaml.cs представлен ниже.
using PHmiClient.Controls.Pages; using System; using System.Windows.Controls;
namespace ClientSample.Pages
{
///
public object PageName { get { return «Home page»; } }
public PHmiClient.Controls.IRoot Root
{
get; set;
}
}
}
А вот разметка Xaml файла:
Значений тегов не видно. Это потому что не запущен PHmiRunner.exe. Нажмем кнопку «Run» в конфигураторе.
Теперь добавим на страницу элементы управления.
Задание языка окна Для отображения строк в соответствии с региональными настройками (дата, время и прочее), необходимо изменить XmlLanguage в конструкторе окна: using System.Threading; using System.Windows; using System.Windows.Markup;
namespace ClientSample
{
///