JSON over TCP

When the SpringCore device is configured for Smart Reader mode + JSON over TCP, it accepts the host as a TCP client (the device is TCP server). Once the host is connected, the device sends READER EVENT Messages and accepts READER COMMAND Messages over the TCP channel.

The JSON META and STATUS Messages are not implemented over the TCP channel.

IMPORTANT NOTE: The SpringCore device running as a TCP Server can accept only one TCP Client at a time.

Configuration checklist

  • Define the IPv4 configuration of the device in register 0280. Leave this register empty to get the configuration from DHCP.
  • Set register 02C0 to 24 (TCP server, Smart Reader operation)
  • Set register 02A0 to 00xxxx02xx (JSON format over the Network link)
  • (Optionaly) define the Port for UDP and TCP servers in register 0285. Default port is 4000.

Sample host software

Use the following Python script as a reference for using the Smart Reader with configuration JSON over TCP.

The script does the following:

  • Connect to the Smart Reader device specified using the --addr= parameter (provide the IP address of the device, or its hostname if it has been registered in your DNS system),
  • Wait for incoming messages and display them
  • If the --wink, --accept or --deny parameters have been set, send back the corresponding sequence command to the device.
# libraries import
from threading import Thread, Event
import logging
import socket
import getopt
import sys
import os


# helpers import
from helpers.ctrlccatcher import CtrlCCatcher


# display_help function
def display_help( script_name ):

    print( script_name )
    print( "[--addr=<addr>]                 Address of the target device" )
    print( "[--port=<port>]                 TCP port on the target device (default: 4000)" )
    print( "[--wink]                        Send wink message in reply to every incoming message" )
    print( "[--accept]                      Send accept message in reply to every incoming message" )
    print( "[--deny]                        Send deny message in reply to every incoming message" )
    sys.exit()


# main function  
def main( script_name, argv ):
    
    # default settings
    port = 4000
    addr = ""
    reply = False

    # options parsing
    try:
        opts, _ = getopt.getopt(argv,"h",[ "help", "addr=", "ip=", "port=", "nolog", "logtofile", "wink", "accept", "deny" ])
    except getopt.GetoptError as e:
        print(e)
        display_help( script_name )

    for opt, arg in opts:
        if opt in ( "-h", "--help"):
            display_help( script_name )
        elif opt == "--addr":
            addr = str(arg)
        elif opt == "--ip":
            addr = str(arg)
        elif opt == "--port":                
            try:
                port = int(arg)
            except ValueError:
                print( "Port must be an integer number!" )
                sys.exit()
        elif opt == "--wink":
            reply = b"{ \"Sequence\": \"0E\" }"                
        elif opt == "--accept":
            reply = b"{ \"Sequence\": \"60\" }"
        elif opt == "--deny":
            reply = b"{ \"Sequence\": \"61\" }"

    if addr == "":
        print( "Server IP address must be specified!" )
        sys.exit()       

    # set logging options
    logging.basicConfig(level=logging.DEBUG)

    # CTRL+C catcher thread (this could be useful on some Windows platforms)
    ctrlccatch = CtrlCCatcher()
    ctrlccatch.start()

    # Create a TCP/IP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)    
    sock.setblocking(0)
    sock.settimeout(0.5)

    # TCP mode, try to connect to our SCRDR server
    logging.info( f"connecting to {addr} port {port}" )
    try:
        # try to connect to this server
        sock.connect( ( addr, port ) )
        logging.info( f"connected, use Ctrl+C to exit" )
        # look for CTRL+C
        while ctrlccatch.wait():
            try:
                # wait for new data
                data, address = sock.recvfrom(512)
                if data:
                    data = data.decode( "ascii" )
                    logging.info( data )
                    if reply:
                        logging.info( "Sending reply: " + str(reply) )
                        sock.send( reply )                    
            except socket.timeout:
                pass
    
    except socket.timeout:
        logging.info( "Can't connect to this server..." )

    # stop all process and exit
    logging.info( "Cleaning..." )
    ctrlccatch.terminate()
    ctrlccatch.join()
    logging.info( "Done." )


# entry point
if __name__ == "__main__":
    # add "this script" folder to the library search path
    # could be useful on Windows platform
    sys.path.append( os.path.dirname( os.path.realpath( __file__ ) ) )
  
    # start our application
    main( os.path.basename( __file__ ), sys.argv[1:] )
    
# EOF