High Speed TCP Driver

We work with shipping diverters that send out TCP messages that are the disposition for each package.

At first we started with the TCP driver available in Ignition but even with 25ms polling, have determined it is not the appropriate driver because message counts always come up short. When testing with the python socket library there is the following call that can specify a buffer size:

socket.recv(1024)

This method can capture all messages.

Streaming the data this way, we can clearly see the problem is that messages arrive at nearly the same time so polling will not work, the only way to capture the data is to read from a buffer.

This then presents the challenge of how to deploy in Ignition because we want the socket instance, once connected to stay alive and project scripts, tag change scripts, etc. are not the place for this.

We are imagining a module that once the socket connection is made, it sticks that connection object in a hashmap and makes the receive call available with a script function like this:

data = system.tcp.getData("Instance Name")  

Such type of module also seems needed to close the socket connection properly.

Does anyone else on the forum have a practical example of how they have acquired high speed TCP data?

We are looking at this module, if nothing else, to get clues on how to write our own module:

Thanks,

Nick

For high speed TCP data that you want to bring into tags the Managed Tag Provider may be a better fit than a driver for the OPC UA server.

This is the same thing the MQTT modules use, though they aren’t exactly high speed.

I open java sockets, monitored with a background thread, spawning additional threads for accepted connections if appropriate. I avoid python sockets like the plague. The listening thread(s) can publish the received data to memory tags or cached jython structures.

I keep track of running threads (and caches) in a persistent dictionary, using system.util.getGlobals() for Ignition versions where it is truly persistent, and using system.util.persistent() otherwise (from my LifeCycle module).

In particularly demanding cases, I have the listening thread simply parse into messages, which then are stuffed into a LinkedBlockingDeque(). Or converted to runnables in a custom thread pool.

I suppose when you say java sockets you are referring to this?

import java.net
import java.nio

If so, does this mean you are doing this in a start up and or shut down script, or a module?

Yes, java.net and/or java.nio. No module (unless you count LifeCycle for certain Ignition versions). Just jython. With all of the critical code in one or more project script modules. The beginning of the script module manages persistence of the primary thread(s), interrupting the old version(s) and replacing it (them). Calling into the module from a gateway startup script is sufficient, even if that function is do-nothing. Simply calling it will cause the top level of the script to run, starting/replacing the background.

A timer script that pulls statistics out of your cache for monitor purposes would also suffice.

We ended up going this way:

Having it as a module makes startup, shutdown, and status monitoring quite convenient. When the read call is made, it reads everything from the buffer and returns it as a comma separated string.

By doing this we stopped missing messages and there is no need to drive it faster than 1 second, because the incoming messages are buffered.

Thanks for all the help and advice.

Nick

Hi Kevin,

Just curious, why would you say the Managed Tag Provider is better than an OPC driver? I’m trying to find distinctions between the two before I go too far down a rabbit hole, and you seem to indicate that a Managed Tag Provider would perform better. Is that because data is duplicated when making an OPC driver (one OPC tag managed by the driver, then an Ignition tag managed by the standard tag provider)? Or it just that the high speed nature of this use case would needlessly burden the OPC server?

I need to pull in a whole lot of UDP data and before reading your post I was leaning towards an OPC driver.

Managed Tag Provider is a more direct route into Ignition. So yeah, you have duplication of data, plus you have OPC UA subscriptions “in the way” of getting your data into Ignition. The way they work is not ideal if the thing you care about most is getting values as fast as possible.

In OPC UA subscriptions publish at one interval while the monitored items belonging to them sample at their own interval. Those items can have a queue as well, which allows you to sample very quickly and deliver batches of changes at a slower interval. All of this is great for the kind of scale you see with OPC UA connections, but not as great if you just want to ingest a value and display it on your screen in, say… sub-50ms times.

Hello Kevin,
I believe the linked drivers from this thread will be a good solution to a problem I'm having. I have been unable to find installation instructions. To install any of the linked modules from Github that are in this thread it does not appear it's as easy as importing the .modl file.
Do you have any reference material?

Hi Nicholas,

I'm experiencing the same issue as this forum post you have created. But the buffered TCP module package doesn't have installation instructions.

Could you provide some guidance on how did you go about installing this module?

Regards,

Andy

I haven't used this myself, however;

there is a .modl file in the device-build folder,

https://docs.inductiveautomation.com/display/DOC81/Installing+or+Upgrading+a+Module

Apologies, I should have elaborated previously.

I tried to move the .modl files in the respective directory (C:\Program Files\Inductive Automation\Ignition\user-lib\modules), restarted the Ignition service but the module did not appear in OPC Device Connections.

I tried interrogating the XML files that are throughout the folders - there are clear linkages to multiple property files and repository callouts. So, I thought I try moving the complete folder package over but that also did not work.

As per the first link I provided, you don't copy over a module, you install a module:

1 Like

Apologies, I completely missed the link. Looks like this is the missing piece. Thanks for support!

1 Like

Just adding so it's clear and this applies to any module. Whenever you don't have that ".modl" file you do have to build and sign it. I think somehow there are already build modules there so you can probably use them.

Typically, a module needs to be signed. If you are using an unsigned module for development purposes, there are some gateway settings needed to make that possible. Many of those things are described below. As alluded to, how to "do modules" is not really fully written down anywhere and once you go through the process a few times it becomes a lot clearer.

How do you create your own MODL file - Module Development - Inductive Automation Forum

Nick

2 Likes

I'll just briefly call out, though it's by no means comprehensive:

And our documentation team is actively working on improving the SDK docs: NEW Ignition SDK Programmer's Guide

2 Likes