How to work with data from TCP driver

I have a weigher that spits out data per box to the TCP driver, the string is simply “051.4g” etc. What I want to is record every new output of data to SQL. Is there a way of triggering the transaction group on every new string? (There may be 2 boxes every second) The only thing I can see is the lastChange. Could this be used to trigger the group? I am thinking to compare it and if it changes then trigger. If this is the way to go about it then I would need the timestamp in milliseconds. I have read on the forum somewhere about converting to Java using gettime() as this is in milliseconds but if this is true I dont know how to do this! One other concern is that the lastChange does not seem to change if the data is the same as the last transmission so is there a better way to pick up each and every transmission.

Yes, there is a way of triggering a transaction group off of a value change. Bring the tag into the group and go to the Trigger tab on the right hand side. There you can select the item as the trigger and select the Active On Change option. The group will run every x seconds (depending on the group rate) and only execute if the tag has changed.

The only problem there is if there is a new transmission and the value is the same the group will not execute because Ignition didn’t register a change. You would need some other way of knowing a new transmission happened.

If you want to store milliseconds your database must support milliseconds. For example, MySQL does not. I don’t think you need to do anything special in order to store milliseconds if your database support it.

Thanks I will give this a go. But in simple terms am I right in saying that the TCP driver cannot differentiate between two transmissions if they are the same i.e. 2 barcodes the same as this seems to make it very limited?? We have a lot of Ethernet barcode readers that are stand alone (no PLC) so there would be no way of counting product etc?

Right, the barcode would have to go to empty string and back to the same barcode for Ignition to recognize it. If the tag value hasn’t changed Ignition has no way of knowing about it. That is how OPC works.

Can you just reset the incoming tag back to a blank, then? Or would that generate an error?

Set the barcode scanner to send the time along w/ it(most of the fancy ones can do this), the time should never be the same, so activate on change based on that?

Did try resetting the tag to zero but it errors as “non-writable” or something similar. Sending the time is a good idea as long as your talking about a barcode reader but no good when its a simple device like a set of weigh scales (RS232 through Ethernet converter - which port light flashes everytime so in my naivety I expected some tag/bit/byte that could be picked up which says “incoming transmission”) bah :frowning:

Does the scale only send a value once it settles? or is there a trigger for that somewhere?

The weighscale I’m testing with uses a “print” pushbutton (manual), the checkweighers in the factories for our product spit out the weight of every product - if thats what you mean - but the only signal being picked up into Ignition is a comms signal (TCP driver). I know R&D record the signal (possibly Excel) so I was surprised on this limitation with OPC. I will see if the data from the checkweighers can have a time or incremented number added to the signal to differentiate one transmission from the next.

OK sorry to go on but the more I think about it the more annoying this is!!! I had two possible uses - weights from a checkweigher and barcodes from Ethernet barcodes readers - and both methods are now a no-go. Anybody got any ideas (outside of Ignition???) to get around this. I’ve used PLC serial ports and BASIC cards in the past and all of these pick up a new transmission. If its not possible they so be it but every use I can think of for something on TCP I would want to differentiate one signal to the next.

I interface directly with ethernet devices in my projects extensively (PLCs, bar code readers, RFID readers, printers, etc) and just do it in an Ignition client app that runs on the gateway PC (actually, it doesn’t matter where it runs as long as the devices can reach it).

It works great, and although this isn’t OPC, I don’t think things like this were ever meant to be OPC compliant anyway. Still, you can take the output from the messages and then make tags from them.

I use both UDP and TCP, and some starting hints can be found in this thread: http://inductiveautomation.com/forum/viewtopic.php?f=70&t=5358&p=13319&hilit=socket#p13319

It’s out of the scope of what IA offers in a way, but on the other hand it’s easy to do. Just think out of the box a bit and read up on Jython and Java sockets.

Step7 - Are you saying that there is a way to solve my issue - i.e. that a new transmission could drive a tag etc. I would like to know if you have achieved what I am trying to do as the method you are suggesting is WAY above me and I dont understand one bit of it :slight_smile: But if it is do-able then I can research it or get external help etc. Thanks very much for your input.

I don’t know what you mean by driving a tag, but I can tell you that you can detect a new transmission and act on the new data, even if the data itself was identical.

I guarantee that it isn’t over your head. Here’s something I threw together the other day that grabs a serial download (via an ethernet converter) from an NC controller. Basically, there are two buttons: One is the “Connect” that creates the socket and connects, and the second button starts an asynchonous listen on the socket. I use global variables and dictionaries because, well, I like to, but there are other ways it could be done as well.

Anyway, I am pretty sure that if you modify the following code with the correct IP and ports, it would just start grabbing barcode data. Then, you can do whatever you want with it.

The Connect button:

global barCode
global ReadActive
global EOF
EOF = 0
ReadActive=0
barCode=''

global tcpCliSock
import socket
HOST = '192.168.0.7'
PORT = 10001
ADDR = (HOST, PORT)

tcpCliSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpCliSock.connect(ADDR)	

The Listen button:


def doAsynch():
	import socket
	import system
	global ReadActive
	global barCode
	global EOF
	global tcpCliSock

	while 1:
		data = tcpCliSock.recv(16384)
		if not data: break 
		if ReadActive==0 and  len(data)>1:
			barCode=''
			EOF=0
		ReadActive=1
		
		barCode+=str(d)
		if ord(str(d)[-1])==26:
			EOF=1
			ReadActive=0
		print barCode
		
system.util.invokeAsynchronous(doAsynch)

Note that there is additional code that needs to be written to close the socket, and you may need to use a different way to detect the end of file. I haven’t included comments, but tell me the parts you don’t understand and I’ll clarify. I think you could use the EOF variable as your indication that a new message was received, and you could act on that. This should at least get you started if you want to take a stab at it.

Of course, one thing we could do would be to tweak the TCP driver to include a tag that indicates the last time data was received. Then you could just trigger on that, right? No big deal… (Kevin says he’ll do it this morning)

Regards,

Thanks Step7 and Thanks Colby that sounds really promising. I’m looking forward to trying both. I’m actually a little amazed that anyone one has a use for barcode readers and other things (check weighers in my case) without knowing that a new signal has arrived to count or make a decision etc. :scratch:

I am surprised we haven’t heard of this before. I think a lot of serial to ethernet devices send empty strings or special strings if no signal. So, every time a new one comes there is value change.

Hi Brett,

All of the barcode or scale usages that I know of simply make use of the change of data value itself, or user intervention. That is, in the cases I’m thinking of, either the fact that the same exact event might happen twice in a row isn’t a concern, or the data is being used as a “realtime” tag on a screen, which then has a button to store to db, after the operator confirms it.

Doesn’t mean there’s anything wrong with what you want, it just hasn’t come up yet.

Regards,

Step7, I tried your script but it returns the following error in the console message:

emUtilities$3$1-AWT-EventQueue-0] Error running function from fpmi.system.invokeAsynchronous
Traceback (innermost last):
File “event:actionPerformed”, line 18, in doAsynch
NameError: d

at org.python.core.Py.NameError(Py.java)
at org.python.core.PyFrame.getglobal(PyFrame.java)
at org.python.pycode._pyx20.doAsynch$1(<event:actionPerformed>:18)
at org.python.pycode._pyx20.call_function(<event:actionPerformed>)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyFunction.__call__(PyFunction.java)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:403)
at com.inductiveautomation.factorypmi.application.script.builtin.ClientSystemUtilities$3.run(ClientSystemUtilities.java:265)
at java.lang.Thread.run(Unknown Source)

This is way beyond my current knowledge but I am giving it a go so if you could help I would appreciate it. As you probably read on this topic, Inductive are hoping to sort out my issue with the TCP driver but I am still going to try your method. Must buy “Jython for Dummies” at the weekend!!!

Darn it, in my quick attempt to make the code more readable, I forgot to rename one of the variables. Just rename ‘d’ to ‘data’ and the error will go away.

Step7 - I am at home now but I’m sure I did try replacing the d with data (in two places) and I’m sure I still had errors of some sort BUT please don’t put yourself out until I can confirm this, just thought I would mention it.

Colby - You said that the TCP driver would be tweaked to have an extra tag to indicate a fresh transmission has come in. May I ask when this will be available and will it be in the form of a new Ignition version (can I identify it through the log change document you publish?)

Thanks