Host Interfaces Network UDP Server $SCRDR
September 3, 2025 at 3:36 AM$SCRDR over UDP
When the SpringCore device is configured for Smart Reader mode + $SCRDR over UDP, it sends $SCRDR Messages to a remote UDP server, and opens a local UDP port where it can receive $SCCMD Messages.
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
44
(UDP server, Smart Reader operation) - Set register 02A0 to
00xxxx01xx
(SCRDR format over the Network link) - Insert the name or the address of the host into register 0294. Leave empty or set to 255.255.255.255 for broadcast.
- (Optionaly) define the options in register 0295. Check that the $SCCMD Message comes from the expected source to increase the security of the system.
- (Optionaly) define the Port for UDP and TCP servers in register 0285. Default port is 4000. Host and device must use the same port.
Security considerations
This protocol is intrinsically insecure: it provides neither confidentiality nor integrity protection. It must therefore only be used on a trusted local or private network.
Sample host software
Use the following Python scripts as a reference for using the Smart Reader with configuration $SCRDR over UDP.
Listener
The Listener script is an UDP server, running on the host, that receives and shows any text message coming on port 4000.
NB: since this sample script doesn’t do any processing of the message but only displays it, it is suitable for both $SCRDR and JSON formats.
# 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( "[--port=<port>] UDP port to listen to (default: 4000)" )
sys.exit()
# main function
def main( script_name, argv ):
# default settings
port = 4000
# options parsing
try:
opts, _ = getopt.getopt(argv,"h",[ "help", "port=" ])
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 == "--port":
try:
port = int(arg)
except ValueError:
print( "Port must be an integer number!" )
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 an UDP listening socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setblocking(0)
sock.settimeout(0.5)
# Bind the socket to the port
server_address = ("0.0.0.0", port)
logging.info( f"starting up on {server_address} port {port}" )
sock.bind(server_address)
# Messages are read from the socket using recvfrom(), which returns the data as well as the address of the client from which it was sent.
logging.info( "waiting for messages" )
while ctrlccatch.wait():
try:
data, address = sock.recvfrom(4096)
if data:
data = data.decode( "ascii" )
logging.info( data )
except socket.timeout:
pass
# 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
Sender
The Sender script is an UDP client, running on the host, that sends a $SCCMD Message to a target device, or broadcasts the Message.
For demonstration purpose, we send the $SCCMD;SEQ:0E
message to play the Wink sequence.
Change message to $SCCMD;SEQ=60
for the Access Granted sequence or $SCCMD;SEQ=61
for Access Denied. For a complete list of sequences, refer to the PLAY SEQUENCE instruction.
# libraries import
from threading import Thread, Event
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 (default: broadcast)" )
print( "[--port=<port>] UDP port on the target device (default: 4000)" )
print( "[--message=\"<message>\"] Message to send to the device (default: WINK Sequence)" )
sys.exit()
# main function
def main( script_name, argv ):
# default settings
message = b"$SCCMD;SEQ=0E"
addr = '<broadcast>'
port = 4000
# options parsing
try:
opts, _ = getopt.getopt(argv,"h",[ "help", "addr=", "port=", "message=" ])
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 == "--message":
message = bytearray(arg.encode())
elif opt == "--addr":
addr = str(arg)
elif opt == "--port":
try:
port = int(arg)
except ValueError:
print( "Port must be an integer number!" )
sys.exit()
# Create an UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
# Enable broadcasting mode
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# Send the message to the target address and port
sock.sendto(message, (addr, port))
# 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