CSWorks: web-based industrial automation

Of CSWorks and software development

Modbus support in CSWorks

clock February 27, 2012 21:51 by author Sergey Sorokin

Starting from version 2.1, CSWorks installation package includes Modbus TCP data source provider. Now you can build web-based solutions that can communicate with Modbus devices - controllers, modules, thermostats - any kind of hardware that supports Modbus. Here is a quick demonstration.

Hardware

We will need:

  • room thermostat that supports Modbus RTU (in this demo we use Tstat6 thermostat provided by Temco Controls);
  • Modbus TCP to serial adapter;
  • local network;
  • desktop computer (server);
  • notebook computer (client).


We have to use Modbus TCP to serial adapter, because CSWorks supports only TCP version of the Modbus protocol, and our thermostat provides only Modbus RTU (good old RS-485) connectivity. Make sure that:

  • both computers and Modbus adapter are connected to your local network;
  • thermostat is connected to the adapter via RS-485.

Modbus thermostat SCADA/HMI diagram

Software

The following software will be used:

  • CSWorks 2.1 on the server; full CSWorks version is required, CSWorks Light will not let clients from other computers access the application;
  • Microsoft VisualStudio 2010 on the server;
  • web browser on the notebook.

Build demo application

On the server computer, open VisualStudio project at C:\Program Files\CSWorks\Demo\Src\ModbusThermostatIntegrationDemo\ and build it. Please note that these connection points used in this sample are specific to the particular thermostat, your connections points will be different - see Modbus integration guide for your thermostat. Build Release|x86 (for 32-bit installations) or Release|x64 (for 64-bit installations) configuration. Build script will place the compiled application file (CSWorks.Client.ModbusThermostatIntegrationDemo.xap) and hosting HTML file (ModbusThermostatIntegrationDemo.html) to the correspondent locations under C:\Program Files\CSWorks\Demo\Web\. Your client demo application is ready.

Add LiveData source

CSWorks LiveData Service must be aware of the new data source - Modbus device. Our client application will connect to a data source called "Tstat6" (see MainPage.xaml of the client application), so we have to add a new data source with this name. Add the following piece to the LiveData Service configuration file (see C:\Program Files\CSWorks\Framework\Server\CSWorks.Server.LiveDataService.exe.config):

<modbusTcpLiveDataSource name="Tstat6" ipPort="502" ipAddress="192.168.1.71" unitId="254" sampleBufferLength="16" updateRate="500">
  <templates>
    <template name="analogOutputHoldingRegisterInt16" type="Int16" readPath="AnalogOutputHoldingRegister(($address))" canWrite="true" />
  </templates>
</modbusTcpLiveDataSource>


This demo works only with Analog Output Holding Registers, so there is only one template is defined for this data source. Please make sure that unitId attribute corresponds to the device identifier of the thermostat, otherwise CSWorks may not be able to communicate to it. When done, restart CSWorks LiveData Service.

Configure LiveData web service

LiveData web service must be aware of the "Tstat6" data source as well. Add an antry for "Tstat6" to the LiveData Web Service configuration file (C:\Program Files\CSWorks\Demo\Web\LiveDataWebService\web.config):

<liveDataTopology>
  <liveDataPartitions>
    <liveDataPartition name="partition1" primaryLiveDataServer="liveDataServer_1_primary" secondaryLiveDataServer="">
       <dataSources>
         ...
         <dataSource name="Tstat6"/>

Run the application

On the client notebook, open a browser and navigate to the CSWorks application page:

http://<server_computer_name_or_ip_address>/CSWorksDemo/ModbusThermostatIntegrationDemo.html

After a few seconds of initialization, you will see the demo reading values from the thermostat (click on the image to enlarge it):

Modbus Thermostat picture

Congratulations! Your thermostat is web-enabled now.



CSWorks 2.1.4386.0 released

clock January 16, 2012 00:00 by author Sergey Sorokin

What's new:

  • SQL LiveData provider tested with PostgreSQL 9.0.4, npgsql provider 2.0.11.91
  • Server: Modbus TCP support
  • Client: Modbus thermostat integration demo

 



Important: CSWorks security release 2.0.4115.1

clock October 27, 2011 09:23 by author Sergey Sorokin

Date: October 27, 2011
Subject: DoS vulnerability in CSWorks LiveData Service
Versions: 2.0.4115.0 and earlier
Summary: Remote attackers can perform a denial of service(software crash).


Description
CSWorks LiveData Service 2.0.4115.0 and earlier allows remote attackers to cause a denial of service after sending crafted TCP
packets. Isolating communication between CSWorks LiveData Service and web servers that accept requests from client applications mitigates the issue.


Patch availability
CSWorks 2.0.4115.1 has been issued as security release to correct the defect. CSWorks administrators running affected versions are advised to upgrade to 2.0.4115.1 as soon as possible. The security release can be downloaded from CSWorks web site http://www.controlsystemworks.com/DownloadDescription.aspx.


Credits

The vulnerability was reported by Kuang-Chun Hung, Security Research and Service Institute - Information and Communication Security Technology Center (ICST), Taiwan R.O.C


References
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3996 (will be available after confirmation by MITRE)
http://jvn.jp/en/jp/JVN98649286/index.html (will be available after confirmation by JPCERT/CC)



PostgreSQL support

clock July 29, 2011 14:09 by author Sergey Sorokin
Recently, we have tested CSWorks SQL LiveData provider (version 2.0.4115.0) against PostgreSQL database (connecting using npgsql 2.0.11.91), and it worked fine. Here are the settings we used in the CSWorks.Server.LiveDataService.config.

Provider reference:

<system.data>
  <DbProviderFactories>
    ...
    <!-- Make sure that npgsql and its dependencies are accessible -->
    <remove invariant="npgsql"/>
    <add invariant="npgsql" name="PostreSQL Provider for .NET"
      description=".NET PostreSQL Provider for .NET"
      type="Npgsql.NpgsqlFactory, npgsql, Version=2.0.11.91, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7" />
  </DbProviderFactories>
</system.data>

Data source description:

<sqlLiveDataSource name="Database01" sampleBufferLength="16" sqlProviderInvariantName="npgsql"
  connectionString="User Id=postgres;Password=pg123!;Server=localhost;Port=5432;Database=postgres;"
  updateRate="1000" maxQueryLength="65535" queryDelimiter=";" useZeroAndOneForBoolean="false">

Yes, you can use boolean data type to store discrete values, see our sample PostgreSQL table definition:

CREATE TABLE measurements(
PointName varchar(64) NULL,
Sensor1 int2 NULL,
Sensor2 smallint NULL,
Sensor4 int NULL,
Sensor8 bigint NULL,
Sensor1u int2 NULL,
Sensor2u smallint NULL,
Sensor4u int NULL,
Sensor8u bigint NULL,
Sensor10 float NULL,
Sensor50 varchar(64) NULL,
Sensor100 boolean NULL)
insert into measurements values('Point101', 1,2,4,8,1,2,4,8,8.0,'TestString',true)

Another SQL database under CSWorks' belt!



BACnet IP performance - Lab 05

clock July 19, 2011 20:31 by author Sergey Sorokin

If you are curious how well our new BACnet IP implementation can perform, you may find this post interesting. I used  CSWorks 2.0.4115.0 LiveData Service installed on a Core2 Quad Q6600 @2.40 GHz machine with 4GB RAM running 64-bit Windows 7. As a testing client, I used four instances of a simple LiveData client application that subscribes to updates from 5000 BACnet analog inputs, requesting for updates every second. Test applications talks to CSWorks LiveData Service directly over WCF (exctly the same way WCF LiveData Agent demo does). All hardware is connected via 100mb Ethernet.

My LiveData Service config file referenced four BACnet IP datasources, from "BacnetIpDemo01" to "BacnetIpDemo04" with ids from 260001 to 260004, you can see correspondent fragment of the config file on the screenshot below.
 
Test application expected every analog input data item to change on every update request. If a data item is not changed, the test application increases item's "skip" count. In the ideal world, skip count for all data items would be zero, since every BACnet device changes every item once a second. But due to the discretization process that occurs twice (once between LiveData Service and the BACnet device, another time between the client application and the server) it is hard to avoid these misses.

Performance monitors shows an average rate of ~18000 updates per second. If there was no device-to-server discretization and UDP packet loss, the rate would be exactly 20000 updates per second. LiveData Service was consuming 5-7% CPU.

Click to enlarge



CSWorks 2.0 talks BACnet

clock May 31, 2011 20:02 by author Sergey Sorokin

Starting from version 2.0, CSWorks installation package includes BACnet IP data source provider. That means: now you can build web-based solutions that can communicate with BACnet devices - controllers, modules, thermostats - any kind of hardware that supports BACnet. Here is a quick demonstration.

Hardware

We will need:
- room thermostat that supports BACnet MSTP;
- BACnet IP to MSTP adapter;
- local network;
- desktop computer (server);
- notebook computer (client).

We have to use BACnet IP to MSTP adapter, because CSWorks supports only IP version of the BACnet protocol, and our thermostat provides only BACnet MSTP (good old RS-485) connectivity. Make sure that:
- both computers and BACnet adapter are connected to your local network;
- thermostat is connected to the adapter via RS-485.

BACnet thermostat in the local network diagram

Software

The following software will be used:
- CSWorks 2.0 on the server; full CSWorks version is required, CSWorks Light will not let clients from other computers access the application;
- Microsoft VisualStudio 2010 on the server;
- web browser on the notebook.

Build demo application

On the server computer, open VisualStudio project at C:\Program Files\CSWorks\Demo\Src\BacnetThermostatIntegrationDemo\ and have a look at MainPage.xaml. BACnet connection points are defined in the very beginning:

<!-- AnalogValue(0): mode (Heat, Cool, Idle, Afterhours, Unoccupied Idle, Unoccupied Heat, Unoccupied Cool) -->
<data:DoubleDataItem x:Key="mode" Id="..." DataSource="RoomThermostat01" TemplateName="analogValue" Parameters="tagIndex=0;"/>
<!-- AnalogValue(6): heating setpoint -->
<data:DoubleDataItem x:Key="heatingSP" Id="..." DataSource="RoomThermostat01" TemplateName="analogValue" Parameters="tagIndex=6;"/>
<!-- AnalogValue(7): cooling setpoint -->
<data:DoubleDataItem x:Key="coolingSP" Id="..." DataSource="RoomThermostat01" TemplateName="analogValue" Parameters="tagIndex=7;"/>
<!-- AnalogValue(20): room temperature -->
<data:DoubleDataItem x:Key="roomTemp" Id="..." DataSource="RoomThermostat01" TemplateName="analogValue" Parameters="tagIndex=20;"/>
<!-- AnalogValue(87): fan speed (off, 1, 2, 3, auto, on) -->
<data:DoubleDataItem x:Key="fanSpeed" Id="..." DataSource="RoomThermostat01" TemplateName="analogValue" Parameters="tagIndex=87;"/>


and used later in the UI definition part:

<TextBlock Text="{Binding Value, Source={StaticResource roomTemp}, ..." .../>
...
<TextBlock Text="{Binding Value, Source={StaticResource mode}, ..." .../>
...
<TextBlock Text="{Binding Value, Source={StaticResource heatingSP}, ..." .../>
...
<TextBlock Text="{Binding Value, Source={StaticResource coolingSP}, ..." .../>
...
<TextBlock Text="{Binding Value, Source={StaticResource fanSpeed}, ..." .../>



Please note that these BACnet connection points are specific to the particular thermostat used in this demo, your connections points will be different - see BACnet integration guide for your thermostat. Build Release|x86 (for 32-bit installations) or Release|x64 (for 64-bit installations) configuration. Build script will place the compiled application file (CSWorks.Client.BacnetThermostatIntegrationDemo.xap) and hosting HTML file (BacnetThermostatIntegrationDemo.html) to the correspondent locations under C:\Program Files\CSWorks\Demo\Web\. Your client demo application is ready.

Add LiveData source

CSWorks LiveData Service must be aware of the new data source - BACnet device. Our client application will connect to a data source called "RoomThermostat01" (see MainPage.xaml above), so we have to add a new data source with this name. Add the following piece to the LiveData Service configuration file (see C:\Program Files\CSWorks\Framework\Server\CSWorks.Server.LiveDataService.exe.config):

<dataSourceProviders>
  <bacnetIpLiveDataSources type="CSWorks.Server.DataSource.Bacnet.BacnetIpLiveDataSource, CSWorks.Server.BacnetIpProvider">
    ...
    <bacnetIpLiveDataSource name="RoomThermostat01" sampleBufferLength="16" deviceId="99102" ipPort="47808" updateRate="250">
      <templates>
        <template name="analogValue" type="Single" readPath="AnalogValue(($tagIndex)).PresentValue" canWrite="true" />
      </templates>
    </bacnetIpLiveDataSource>


This demo works only with AV (analog value) BACnet connection points, so there is only one template is defined for this data source. Please make sure that deviceId attribute corresponds to the device identifier of the thermostat, otherwise CSWorks will not be able to locate it in the BACnet network. When done, restart CSWorks LiveData Service.

Configure LiveData web service

LiveData web service must be aware of the "RoomThermostat01" data source as well. Add an antry for "RoomThermostat01" to the LiveData Web Service configuration file (C:\Program Files\CSWorks\Demo\Web\LiveDataWebService\web.config):

<liveDataTopology>
  <liveDataPartitions>
    <liveDataPartition name="partition1" primaryLiveDataServer="liveDataServer_1_primary" secondaryLiveDataServer="">
      <dataSources>
        ...
        <dataSource name="RoomThermostat01"/>


Run the application

On the client notebook, open a browser and navigate to the CSWorks application page:

http://<server_computer_name_or_ip_address>/CSWorksDemo/BacnetThermostatIntegrationDemo.html

After a few seconds of initialization, you will see the demo reading values from the thermostat (click on the image to enlarge it):

BACnet integration with thermostat

Congratulations! Your thermostat is web-enabled now.



CSWorks 2.0.4115.0 released

clock May 30, 2011 23:00 by author Sergey Sorokin

What's new:

  • SQL LiveData provider: improved boolean data type support
  • Server: analogDeadband property for LiveData sources
  • Server: revised thread concurrency model in LiveData and Alarm servers (better data source error handling performance)
  • OPC LiveData provider: OPC group size limit
  • Server: BACnet IP support
  • Client: LiveData Manager - improved connectivity error handling
  • Client: BACnet Provider demo
  • Client: BACnet thermostat integration demo

 



CSWorks 1.7.5000.0 released

clock March 14, 2011 15:56 by author Sergey Sorokin

What's new:

  • HVAC symbol library


A minor release. CSWorks installation package now includes a symbol library for building automation industry. Click on the image below to see our online demo.

HVAC interactive demo: AHU




CSWorks 1.7.4050.0 released

clock February 11, 2011 12:28 by author Sergey Sorokin

What's new:

  • Windows Phone 7 client

The following video shows CSWorks Windows Phone client in action:




Building Silverlight applications: remove unused cultures

clock December 7, 2010 11:46 by author Sergey Sorokin

When building Silverlight projects, msbuild puts a lot of internationalized resource content to the intermediate folder (obj) and output folder (ClientBin or bin): look at all those ar, bg, ca folders. In 99% of cases, these files are just waste of build time and disk space. In 1% of cases - when you are building an application that actually supports all those cultures - those files will end up in your XAPs and your app will use them.


It's always a good idea to have a good internationalization plan and explicitly support only a number of cultures. An additional reason to do that is saving build time and disk space by eliminated unnecessary culture files. You can remove unused cultures from "Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client\" (or better move them to "UnusedCultures" folder). This will save you a lot of space on the build machine and improve your building time.

Three things to keep in mind:

1. Do not forget to put correspondent cultures back when you add a new supported culture to your project.

2. Do not forget to re-arrange your culture libraries after every Silverlight SDK refresh.

3. I doubt this approach is recommended by Microsoft, so use it at your own risk :)