Skip to content

duduyoyo/WebSocket4OPC

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

98 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

WebSocket4OPC

Enable WebSocket in OPC DA/AE/HDA Server with JSON return, FIRST TIME ever!

COM/DCOM was developed more than 2 decades ago, which was the pillar of classic OPC servers. Nowadays people embrace dynamical languages (Python/JavaScript etc) due to their simplicity and productivity rather than steep-learning-curve COM/DCOM programming. Luckily with the popular adoption of WebSocket in every modern programming language, it is possible to glue dynamical languages and legacy COM/DCOM together.

This innovative solution is a perfect combination of all its tech stack's advantages as below,

1. WebSocket (standard network protocol for cross-platform/full duplex)
2. Microsoft IIS (authorization/authentication/firewall/certificate/encryption)
3. Classic OPC servers (the most widely adopted industry interfaces)

Compared to OPC UA, is there any piece missing above? Not all but simple, fast and straightforward. It can't be easier anymore to access classic OPC servers safely and securely with this solution. Unparalleled experience to your desktop and mobile device is ready for you to explore! GoodBye COM/DCOM!

Benefits

.Worldwide the exclusive solution to access AE/HDA data in Python/JavaScript
.No any OPC or 3rd party SDK needed
.No COM/DCOM when connecting to a classic OPC server
.No future DCOM vulnerability or hardening to worry
.Dynamical languages (Python/JavaScript) support
.Built-in account authorization and authentication by IIS
.Built-in secure connection with certificate by IIS
.Built-in data encryption by IIS
.Cross-platform in client gurantted(Linux/Mac/Windows)
.No expensive OPC corporate membership fee
.Intuitive and easy-to-remember commands instead of long REST API URL
.Native mobile APP development feasible
.No tedious 1250-page OPC UA documents to consult
.No OPC UA certificate configuration
.No OPC UA firewall configuration
.No OPC DA->UA conversion needed
.Edge or Gateway deployment ready without any expensive custom hardware

Pre-requiste

1. Install in the same server where classic OPC DA/AE/HDA server is running
2. WebSocket feature for IIS need be enabled in the same server
3. Microsoft VC++ Runtim for X64 required (download here and install it if needed)

Installation

Download all files from server folder to your desired one. Launch a command line with administrator privilege and enter to your download folder. Run command "install.bat userAccount userPassword" to complete installation. userAccount/userPassword need be your own Windows credential and make sure that it has administrator privilege. This credential is only used by IIS in configuring a new app pool and not used by this solution or stored anywhere else.

To verify, launch browser (Chrome/Safari/Edge) and enter URL "http://localhost/OPC/websocket.html"

If installed in a multiple server environment, a config file under program data folder is available to specify your desired server with its prog ID

Uninstallation

Run command "uninstall.bat" in command line with administrator privilege in your download folder.

Usage

  1. DA commands

    1.1 Browse

    "browse" - Show all child tags under top level of DA server

    "browse:tagID" - Show all child tags under a parent tag of DA server

    "browse:tagID -countsInPagenation -pageNumber" - Show a subset of children tags based on pagenation under a specific tag in DA server. For example, if there are total 10,000 children tags under a specific tag, command "browse: tagID -2000 -3" will only display a tag's 2000 children tags (4000th to 5999th) for 3rd page in DA server

    JSON returns {"parentNodeID":[{"n": "tagName1", "i": "tagID1", "b": 1}, {"n": "tagName2", "i": "tagID2", "b": 0}, ...]}
    (parentNodeID - parent node id or "" at top level, n - name, i - ID, b - branch)

    When command "browse: Random" is sent, response will be like

    1.2 Read

    "read: tagID1, tagID2, ..."- Read tag latest values from DA server

    JSON returns {"DA":[{"i": "tagID1", "v": "20.308", "t": 1643759756112, "q": 192}, {"i": "tagID2", "v": "4", "t": 1643769859342, "q": 192}, ...]}
    (i - ID, v - value, t - time stamp in milliseconds of epoch UTC, q - quality)

    When command "read: Random.Real4, Random.Int2" is sent, response will be like

    1.3 Write

    "write: tagID1 -value1; tagID2 -value2; ..."- Write tag values to DA server. It is strongly recommended NOT to use this command in a production environment when Internet access is available. Contact developer to have a version without this command for production use.

    No JSON return but writing status (success/failure) will be reported as info. Use read command to verify writing's success

    When command "write: Bucket Brigade.Int2 -34; Random.Int2 -12" is sent, response will be like

    1.4 Subscribe

    "subscribe: tagID1, tagID2, ..." - Add monitored tags to DA server and receive updates when new values are available

    JSON returns {"DA":[{"i": "tagID1", "v": "20.308", "t": 1643759756112, "q": 192}, {"i": "tagID2", "v": "4", "t": 1643769859342, "q": 192}, ...]}
    (i - ID, v - value, t - time stamp in milliseconds of epoch UTC, q - quality)

    When command "subscribe:Saw-toothed Waves.Int1,Saw-toothed Waves.Int2" is sent, response will be like

    1.5 Unsubscribe

    "unsubscribe" - Remove all monitored tags from DA server

    "unsubscribe: tagID1, tagID2, ..." - Remove specific monitored tags from DA server

  2. HDA commands

    2.1 Browse

    "browseHDA" - Show all child tags under top level of HDA server

    "browseHDA:tagID" - Show all child tags under a specific tag of HDA server

    "browseHDA:tagID -countsInPagenation -pageNumber" - Show a subset of children tags based on pagenation for a specific tag in HDA server. For example, if there are total 10,000 children tags under a specific tag, command "browseHDA: tagID -2000 -3" will only display a tag's 2000 children tags (4000th to 5999th) for 3rd page in HDA server.

    JSON returns {"parentNodeID":[{"n": "tagName1", "i": "tagID1", "b": 1}, {"n": "tagName2", "i": "tagID2", "b": 0}, ...]}
    (parentNodeID - parent node id or "" at top level, n - name, i - ID, b - branch)

    When command "browseHDA: Random" is sent, response will be like

    2.2 ReadRaw

    "readRaw: tagID1, tagID2,..., tagIDx -startTimeStamp -endTimeStamp" - Read tags' history raw data based on start and end time stamps

    JSON returns {"HDA":[{"tagID1":[{"v":"24201","t":1665632091123,"q":262336}, {"v":"19168","t":1665632092334,"q":262336},...]}, {"tagID2":[{"v":"24","t":1665632091445,"q":262336}, {"v":"168","t":1665632092667,"q":262336},...]}]}
    (v - value, t - time stamp in milliseconds of epoch UTC, q - quality which need be parsed with OPC HDA and DA masks to have results like Raw/Interpolated and Good/Bad)

    When command "readRaw: Saw-toothed Waves.Int1,Saw-toothed Waves.Int2 -1672977528112 -1672977529338" is sent, response will be like

    2.3 ReadAtTime

    "readAtTime: tagID1, tagID2, ..., tagIDx -timeStamp1 -timsStamp2 -timeStampX" - Read tags' history data based on various time stamps

    JSON returns {"HDA":[{"tagID1":[{"v":"24201","t":1665632091231,"q":262336}, {"v":"19168","t":1665632092354,"q":262336},...]}, {"tagID2":[{"v":"24","t":1665632091341,"q":262336}, {"v":"168","t":1665632092321,"q":262336},...]}]}
    (v - value, t - time stamp in milliseconds of epoch UTC, q - quality which need be parsed with OPC HDA and DA masks to have results like Raw/Interpolated and Good/Bad)

    When command "readAtTime: Saw-toothed Waves.Int1,Saw-toothed Waves.Int2 -1672978265112 -1672978266338" is sent, response will be like

    2.4 ReadModified

    "readModified: tagID1, tagID2,..., tagIDx -startTimeStamp -endTimeStamp" - Read tags' modified history data based on start and end time stamps

    JSON returns {"HDA":[{"tagID1":[{"v":"24201","t":1665632091231,"q":262336}, {"v":"19168","t":1665632092354,"q":262336},...]}, {"tagID2":[{"v":"24","t":1665632091341,"q":262336}, {"v":"168","t":1665632092321,"q":262336},...]}]}
    (v - value, t - time stamp in milliseconds of epoch UTC, q - quality which need be parsed with OPC HDA and DA masks to have results like Raw/Interpolated and Good/Bad)

    2.5 ReadProcessed

    "readProcessed: tagID1, tagID2,..., tagIDx -startTimeStamp -endTimeStamp -intervalInMilliseconds -aggregate" - Read tags' history processed data based on start and end time stamps at a given interval for an aggregate method from the list below(vendor specific aggregate methods not shown)

    image

    JSON returns {"HDA":[{"tagID1":[{"v":"24201","t":1665632091231,"q":262336}, {"v":"19168","t":1665632092354,"q":262336},...]}, {"tagID2":[{"v":"24","t":1665632091341,"q":262336}, {"v":"168","t":1665632092321,"q":262336},...]}]}
    (v - value, t - time stamp in milliseconds of epoch UTC, q - quality which need be parsed with OPC HDA and DA masks to have results like Raw/Interpolated and Good/Bad)

    When command "readProcessed: random.Int1,random.Int4 -1705350325000 -1705350425000 -5000 -10" is sent, response will be like

    2.6 InsertReplace

    "insertReplace: tagID1 -value -timeStamp -quality;tagID2 -value -timeStamp -quality;..." - Insert or replace tags' history data and quality for specific time stamps in epoch milliseconds

    No JSON returns except an operation status message

    When command "insertReplace: Bucket Brigade.Int1 -234 -1710719956000 -192; Bucket Brigade.Int4 -567 -1710720852000 -192" is sent, response will be like

    2.7 DeleteAtTime

    "deleteAtTime: tagID1, tagID2,..., tagIDX -timeStamp1 -timeStamp2 ... -timeStampX" - Delete tags' history data based on various time stamps in epoch milliseconds

    No JSON returns except an operation status message

    When command "deleteAtTime: Write Error.Int1, Bucket Brigade.Int1 -1713118247000 -1713116556000" is sent, response will be like

  3. AE commands

    3.1 Subscribe

    "subscribeAE" - Receive notification on alarms and events

    JSON returns {"AE":[{"s":"tagName1","m":"tagName1 Deviation is Low","c":"DEVIATION","sc":"LO","t":1643760803334,"q":192,"tp":4,"ec":2,"st":200,"a":1,"at":""}, {"s":"tagName2","m":"tagName2 Limit is Normal","c":"PVLEVEL","sc":"HIHI","t":1643760808112,"q":192,"tp":4,"ec":1,"st":500,"a":1,"at":""}]}
    (s - source, m - message, c - condition, sc - sub condition, t - time stamp in milliseconds of epoch UTC, q - quality, tp - type, ec - category, st - severity, a - acknowledgement, at - actor)

    When command "subscribeAE" is sent, response will be like

    3.2 Unsubscribe

    "unsubscribeAE" - Remove notification on alarms and events

  4. Disconnect

    "disconnect" - Close connection with server

  5. Help

    "help" or "?" - Display all supported commands and usages

Sample code output

Sample codes for different languages (Python/Swift/C#/C++/Java) are available in client folder

Python

Swift

RecordIt-C32C9C56-5A8F-4BDE-B100-E520E731FCEC.mp4

C#

C++

Java

Roadmap

- Full-fledged open source native client for iOS and partners/contributors are welcome

Related contribution

OLEDB4OPC, the fastest way to transfer OPC data to database!

About

Liberate and access plant data anywhere, any way!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published