The script I had posted above works, but it didn’t always work reliably. As I was trying to figure out why, I realized something: Rohos Logon Key really expects UIDs to come in specific data formats from the serial readers it supports nominally. The script however simply passes it raw LF-terminated ASCII UIDs.
So I modified it a bit: now it simulates an Easyident FS-2044 RFID reader (one of the readers Rohos Logon Key explicitely supports). With that new version, Rohos unlocks each and every time without fail.
Here it is:
#!/usr/bin/python3
# This program emulates an Easyident FS-2044 RFID reader with UIDs read from a
# generic, 10-digit UID, 9600 baud serial RFID reader, for use as an input
# device by Rohos Logon Key.
#
# This program requires a virtual null modem cable such as com0com, with
# Rohos Logon Key listening to one end of the null modem cable, and this
# program outputting fake Easyident frames to the other end.
#
# Additionally, this program can kill a running Windows screensaver whenever a
# UID is read, so that the Windows logon screen is automatically brought up
# before passing the UID to Rohos Logon Key, thereby alleviating the need to
# press a key to activate the logon screen.
# Parameters
incomport="COM2" # Input COM port for the generic serial reader
outcomport="COM4" # Output COM port for the virtual null modem
# Rohos Logon Key is connected to the
# other end of
screensaver="ribbons.scr" # Set to None to bypass killing the screensaver
# Modules
import os
import time
import serial
# Main program
incomport_fd=None
outcomport_fd=None
hexdigits = "0123456789ABCDEF"
while True:
uid=None
if not incomport_fd:
try:
incomport_fd = serial.Serial(incomport)
except:
print("Error opening input COM port {}".format(incomport))
incomport_fd = None
time.sleep(0.2)
continue
# Read a UID from the serial RFID reader
try:
uid=incomport_fd.readline().strip().decode("ascii")
except:
print("Read error")
incomport_fd = None
time.sleep(0.2)
continue
if not outcomport_fd:
try:
outcomport_fd = serial.Serial(outcomport)
except:
print("Error opening output COM port {}".format(outcomport))
outcomport_fd = None
time.sleep(0.2)
continue
uid = "".join([c for c in uid.upper() if c in hexdigits])
print("UID read in:", uid)
if len(uid) != 10:
print(" Incompatible UID (not 10 digits) - giving up")
continue
# Kill the screensaver
if screensaver:
try:
os.system("taskkill /f /t /im {}".format(screensaver))
except:
pass
# Create a simulated Easyident data frame
csum = sum([ord(c) - ord("0" if c.isdigit() else "7") for c in uid]) & 0xf
easyident_frame = b"\x8a" + (uid + hexdigits[csum]).encode("ascii") + b"\r\n"
# Pass on the fake Easyident frame to Rohos Logon Key
try:
outcomport_fd.write(easyident_frame)
outcomport_fd.flush()
print(" UID sent out")
except:
print(" Write error")
incomport_fd = None
time.sleep(0.2)