[Из песочницы] Зачем 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» в конфигураторе.

Теперь добавим на страницу элементы управления.
Если включить «Digital tag», возникнет авария.Добавим на страницу тренд.

Задание языка окна Для отображения строк в соответствии с региональными настройками (дата, время и прочее), необходимо изменить XmlLanguage в конструкторе окна: using System.Threading; using System.Windows; using System.Windows.Markup;
namespace ClientSample
{
///
