I’ve encountered a problem with the UDP driver. I’m trying to bring in a sequence of bytes which contain binary representations of different values (e.g. 32-bit integers and 32-bit IEEE floating point numbers). I’ve set the Message Delimiter Type to PacketBased, which brings the whole sequence in as a string.
The problem with this is that it cannot cope with byte values greater than 127. If it finds any it replaces them with 0xfd.
Any ideas how we can access the correct values? We were hoping to use the Python struct library in a tag’s Value Changed event to parse the values and write them out to other Memory tags.
I don’t think these messages can survive a round trip from binary -> unicode -> binary again. Or, at least, I haven’t figured out a way to get the original binary out of a unicode string yet.
The UDP driver message tag may not be the appropriate conduit for your data. Maybe you can do the UDP part in scripting as well.
Yeah, maybe start something up in a gateway startup script that runs until shutdown. I think simple socket communication is easy enough to do in Python/Jython that you should try to avoid the overhead involved with writing a module.
but my Designer now hangs when I try to save it. I’d imagine the Gateway is now thrashing non-stop at the script - is there any way of avoiding this and still running quickly enough to read each packet as it arrives?
I saw that just as you posted Jordan I’m now getting an ‘Address already in use’ error. It doesn’t seem to be closing the socket before trying to open another one the next time I save the project.
You’re going to need to shutdown the socket you create, in a shutdown script perhaps?
But then you’ll need to be able to get ahold of the socket… maybe you can store it as a global singleton? Seems there was just a thread about that kind of thing.
Anyone from IA able to help with this one? Kevin’s suggestion about storing the socket as a global variable so it can be closed properly sounds good but is beyond my ability
I just finished implementing and testing controlled, organized, supported global storage in Ignition.
It is called “gstore”, short for Global Storage. It provides a simple way to have and use global state in Ignition.
Global project state is stored in a global dictionary at pa.gstore. pa.gstore is global to each project. It can be used in Gateway scripts or client/designer scripts.
Here’s the code to use in your circumstance:
Put this code in a Gateway Startup Script:[code]def read_udp():
import socket
import binascii
while True:
data, addr = sock.recvfrom(1024)
print “Received %s from %s” % (binascii.hexlify(data), addr)
system.tag.write("[default]udp_byte", data)
system.util.invokeAsynchronous(read_udp)[/code]
The only difference to your code is adding the socket to gstore.
Then add the following code to the Gateway Shutdown Script:pa.gstore["sock"].close()gstore has more functionality than this but I haven’t updated the documentation yet, but I will soon. If you want to use this and need any help let me know.
I tried testing it out. I’m having problems with reconnecting the socket once it is closed. The OS doesn’t want to use a port for awhile once it is closed.
I found that using this code before binding and not closing the socket seems to work:
Thanks Nick, that seems to have sorted in out. It took a bit to get going - I had to change to another port for a while before going back to the original port - so I’m not sure yet how reliable it is, but this lets me keep testing.