Event Streams Driver for generic ethernet TCP barcode readers

Hi All,

I have just released a very simple but useful driver for Event Streams in 8.3.
This driver starts up a TCP server listening on a given port for any connections from a barcode reader.
Any received barcodes are generated as an event, with the source IP and the received ASCII string delivered with a timestamp as the payload.
This driver was made to remove the hacked up TCP listener scripts that get built in Ignition for logging barcodes to databases etc... In theory, due to it's event based architecture, there is no throughput limits for this driver, and it will queue events in the Event Streams system.
I will be conducting more testing, but I believe that this is much more scalable than the existing options I have seen.

Currently tested working on:

  • Cognex DataMan DM280

For testing purposes, you can use this LLM generated python script to send barcodes to it manually, remember to upen the chosen port on your gateway firewall:

python3 tcp_send.py <IP Address> <Chosen Port> "barcode string"

tcp_send.py
#!/usr/bin/env python3
"""
Simple TCP Client

Sends a string to a specified TCP host and port.
"""

import socket
import sys


def send_message(host, port, message, timeout=5):
    """
    Send a message to a TCP server
    
    Args:
        host: Target hostname or IP address
        port: Target port number
        message: Message to send
        timeout: Connection timeout in seconds (default: 5)
    
    Returns:
        True if successful, False otherwise
    """
    try:
        # Create a TCP socket
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            # Set timeout
            sock.settimeout(timeout)
            
            # Connect to the server
            print(f"Connecting to {host}:{port}...")
            sock.connect((host, port))
            print(f"Connected!")
            
            # Send the message (add newline if not present)
            if not message.endswith('\n'):
                message += '\n'
            
            sock.sendall(message.encode('utf-8'))
            print(f"Sent: {message.strip()}")
            
            return True
            
    except socket.timeout:
        print(f"Error: Connection timeout after {timeout} seconds", file=sys.stderr)
        return False
    except ConnectionRefusedError:
        print(f"Error: Connection refused - is the server running on {host}:{port}?", file=sys.stderr)
        return False
    except socket.gaierror:
        print(f"Error: Could not resolve hostname '{host}'", file=sys.stderr)
        return False
    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        return False


def main():
    """Main function with command-line interface"""
    import argparse
    
    parser = argparse.ArgumentParser(
        description='Send a string to a TCP server',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
Examples:
  %(prog)s localhost 1000 "Hello World"
  %(prog)s 192.168.1.100 8080 "Test message"
  %(prog)s -t 10 example.com 9000 "Message with custom timeout"
        '''
    )
    
    parser.add_argument('host', help='Target hostname or IP address')
    parser.add_argument('port', type=int, help='Target port number')
    parser.add_argument('message', help='Message to send')
    parser.add_argument('-t', '--timeout', type=int, default=5,
                        help='Connection timeout in seconds (default: 5)')
    
    args = parser.parse_args()
    
    # Send the message
    success = send_message(args.host, args.port, args.message, args.timeout)
    
    # Exit with appropriate code
    sys.exit(0 if success else 1)


if __name__ == '__main__':
    main()
4 Likes

I have done a bit of work on this now to make it simpler to use the data in streams, now the ASCII string is included raw as the event.payload and the timestamp and the source IP are included as part of event.metadata, which is how I believe IA intended the data to emerge.

1 Like