📜 ⬆️ ⬇️

Why SCADA when there is .NET?

I work in a company that automates production processes. Sign not by hearsay with programmable logic controllers (PLC), human-machine interface (HMI) and SCADA (dispatch control and data collection).

And I also enjoy programming. Mostly in C # and Java (Android). When I became acquainted with the WPF technology and saw how simple it is implemented on a graphical user interface, there was no limit to my delight. “Yes, this is a SCADA systems killer,” I thought. You just need to somehow connect the .NET project with input-output devices (PLC).

And then an idea came to me, which at a certain moment comes to every submachine gunner. Make your SCADA system. And not just a SCADA system, but a SCADA system for .NET developers (first of all for myself). Because sometimes when you switch from Visual Studio to the editor of a “modern” SCADA system, you want to pull out your last hair. But the real difficulties begin when it is necessary to implement the functionality that goes beyond the base. Another thing - the world of programmers. The answer to almost any question can be quickly found on stackoverflow.com through its google.com search interface.

Next, I will describe what I did manage to do. Project source code is available at https://github.com/phmi/phmi .
')

Installation


To use PHmi (as I called it), the following conditions must be met:


Project development


Project development can be divided into two phases: server configuration and client project development.

Server configuration

Run PHmiConfigurator.exe. The following window will appear:



Click on the “New project” button. The “New project” window will appear:



Enter the communication parameters with PostgreSQL and the desired database name:



After pressing the “Ok” button, a new project will be created:



Click on the “I / O devices” button. The “I / O devices” tab will open in the configurator:



Add a new “IoDev” I / O device of “Generic” type. "Generic" is an input / output device for debugging purposes. Or it is used when you do not need to connect to a real device. It supports any tag address:





Click on the “Save” button and close the tab.
Open the “Digital tags” tab and create a new digital tag.



Open the “Numeric tags” tab and create a new analog tag:



Description, format, unit of measurement, calibration boundaries are optional and can be omitted.
Create a new category of accidents:



Create a new alarm tag:



Create a category of trends:



Create a new trend tag:



Development of the client's project

In the configurator, click on the “Build client” button:



Select the path to the files to create them.
"Namespace" should coincide with the name of the future project of Visual Studio.
Click on the “Build” button.
At the specified path the following files should appear:



Let's start Microsoft Visual Studio and create a new WPF project. The target framework must be “.Net Framework 4.0” or higher:





Add a link to PHmiClient.dll:







Add the PHmi.cs and PHmiResources.resx files created in advance:





Double click on PHmiResources.resx and change the “Access modifier” to Public:



Open MainWindow.xaml. Add the knotrol Root to the root Grid.

<Window x:Class="ClientSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:pHmiControls="clr-namespace:PHmiClient.Controls;assembly=PHmiClient" Title="MainWindow" Height="350" Width="525"> <Grid> <pHmiControls:Root/> </Grid> </Window> 

Let's tie PHmi to the DataContext Root. To do this, create a new PHmi object in the window's resources.

 <Window x:Class="ClientSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:pHmiControls="clr-namespace:PHmiClient.Controls;assembly=PHmiClient" xmlns:clientSample="clr-namespace:ClientSample" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <clientSample:PHmi x:Key="PHmi"/> </Window.Resources> <Grid> <pHmiControls:Root DataContext="{StaticResource PHmi}"/> </Grid> </Window> 

Add a folder “Pages” for pages. Add a UserControl called "HomePage" there.



Pages must implement the IPage interface. Listing HomePage.xaml.cs is presented below.

 using PHmiClient.Controls.Pages; using System; using System.Windows.Controls; namespace ClientSample.Pages { /// <summary> /// Interaction logic for HomePage.xaml /// </summary> public partial class HomePage : UserControl, IPage { public HomePage() { InitializeComponent(); } public object PageName { get { return "Home page"; } } public PHmiClient.Controls.IRoot Root { get; set; } } } 

But the Xaml file markup:

 <UserControl x:Class="ClientSample.Pages.HomePage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:clientSample="clr-namespace:ClientSample" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance clientSample:PHmi, IsDesignTimeCreatable=True}"> <Grid> <StackPanel> <TextBlock Text="{Binding Path=IoDev.DigitalTag.Value}"/> <TextBlock Text="{Binding Path=IoDev.NumericTag.ValueString}"/> </StackPanel> </Grid> </UserControl> 

We added a textblock to display the value of tags.
Link the type of homepage to Root:

 <Window x:Class="ClientSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:pHmiControls="clr-namespace:PHmiClient.Controls;assembly=PHmiClient" xmlns:clientSample="clr-namespace:ClientSample" xmlns:pages="clr-namespace:ClientSample.Pages" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <clientSample:PHmi x:Key="PHmi"/> </Window.Resources> <Grid> <pHmiControls:Root DataContext="{StaticResource PHmi}" HomePage="{x:Type pages:HomePage}"/> </Grid> </Window> 

Run the application and see what happened:



Tag values ​​are not visible. This is because PHmiRunner.exe is not running. Click the “Run” button in the configurator.



Now add to the page controls.

 <UserControl x:Class="ClientSample.Pages.HomePage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:clientSample="clr-namespace:ClientSample" xmlns:pHmiControls="clr-namespace:PHmiClient.Controls;assembly=PHmiClient" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance clientSample:PHmi, IsDesignTimeCreatable=True}"> <Grid> <StackPanel> <TextBlock Text="{Binding Path=IoDev.DigitalTag.Value}"/> <TextBlock Text="{Binding Path=IoDev.NumericTag.ValueString}"/> <CheckBox IsChecked="{Binding Path=IoDev.DigitalTag.Value, Mode=TwoWay}" Content="{Binding Path=IoDev.DigitalTag.Description}"/> <pHmiControls:NumericInput NumericTag="{Binding Path=IoDev.NumericTag}"/> </StackPanel> </Grid> </UserControl> 



If you turn on the “digital tag", a crash will occur.
Add a trend to the page.

 <UserControl x:Class="ClientSample.Pages.HomePage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:clientSample="clr-namespace:ClientSample" xmlns:pHmiControls="clr-namespace:PHmiClient.Controls;assembly=PHmiClient" xmlns:trends="clr-namespace:PHmiClient.Controls.Trends;assembly=PHmiClient" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance clientSample:PHmi, IsDesignTimeCreatable=True}"> <Grid> <StackPanel> <TextBlock Text="{Binding Path=IoDev.DigitalTag.Value}"/> <TextBlock Text="{Binding Path=IoDev.NumericTag.ValueString}"/> <CheckBox IsChecked="{Binding Path=IoDev.DigitalTag.Value, Mode=TwoWay}" Content="{Binding Path=IoDev.DigitalTag.Description}"/> <pHmiControls:NumericInput NumericTag="{Binding Path=IoDev.NumericTag}"/> <trends:TrendViewer Height="400"> <trends:TrendPen TrendTag="{Binding Path=Trends.NumericTagTrend}" Brush="Red"/> </trends:TrendViewer> </StackPanel> </Grid> </UserControl> 




Setting the window language

To display strings in accordance with the regional settings (date, time, etc.), you need to change the XmlLanguage in the window constructor:

 using System.Threading; using System.Windows; using System.Windows.Markup; namespace ClientSample { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { Language = XmlLanguage.GetLanguage( Thread.CurrentThread.CurrentUICulture.IetfLanguageTag); InitializeComponent(); } } } 

Thank!

Source: https://habr.com/ru/post/248423/


All Articles