I'm looking for advice on how to handle an issue I'm trying to solve.
I'm using a UDP device in the ignition OPCUA Server to receive a data stream from an existing service at my facility. There is a fleet of tools(roughly 250) that use the service to forward me(and another server) their tag information. I have a tag change script that generates the tags of the device from the UDP string. Each tool sends data on a ten second interval. To be clear the Tools message the service, the service then messages me(on just one port =/) as well as other subscribers.
My issue seems to be that if the packets from multiple tools arrive within the same evaluation cycle of the tag group of the UDP Device Message tag, only one is evaluated. This will result in dropped packets and the occasional loss of comm false alarm.
I've also tried approaching this without the OPCUA server. I attempted to have a startup script that asynchronously evaluates the UDP packets as they come in, but haven't had much success there. I learned quickly that you need to store the socket as a global and close it with the gateway! Anyway, something seems wrong with my async scripting as the loggers aren't logging.
My backup plan is to utilize the MQTT engine, the service mentioned above is also feeding into a mqtt broker.
EDIT:
Did some more debugging today:
Getting a SystemUtilities logger error: Error running function from system.util.invokeAsynchronous.
Specifically, NameError: global name 'MFG' is not defined.
MFG is a script in the project library of the project that has the startup script and is also the gateway scripting project. MFG is where the function that does the parsing lives. Oddly, I can run the parsing function from MFG via a tag change script when I try using the opcua strategy above. I'm not sure why the Startup Script can't see it.
EDIT2:
Was able to get the script async pulling in data from the UDP port. Oddly I can't get more than 2048 bytes. The expected packets are 10500ish bytes.
I'm passing 16384 to socket.recv but stilling getting truncated data.
def read_udp():
import socket
import system
import MFG
UDP_IP = "10.4.16.69"
UDP_PORT = 49401
read_udp_logger = system.util.getLogger("read_udp")
read_udp_logger.info("starting read_udp socket")
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65535)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 65535)
read_udp_logger.info(str(sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)))
sock.bind((UDP_IP, UDP_PORT))
system.util.globals['udp_socket'] = socket
while True:
try:
"""BUFF_SIZE = 2048
data =''
while True:
part = sock.recv(BUFF_SIZE)
data += part
if len(part) < BUFF_SIZE:
# either 0 or end of data
break"""
#read_udp_logger.trace(str(sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)))
#data = bytearray(65535)
#bytesRec, addr = sock.recvfrom_into(data)
data = sock.recv(65535)
#read_udp_logger.trace("bytes recv: " + str(bytesRec))
read_udp_logger.trace("len of casted str: " + str(len(str(data))))
read_udp_logger.trace(str(data))
result = MFG.parseTools(data)
print(str(result))
except Exception as e:
read_udp_logger.debug(str(e))
logger = system.util.getLogger("startup_script")
logger.info("starting read_udp socket")
system.util.invokeAsynchronous(read_udp)