diff --git a/.gitignore b/.gitignore index 580f1f1..671ab89 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ wheels/ *.egg-info/ .installed.cfg *.egg +*.exe +*.zip # PyInstaller # Usually these files are written by a python script from a template diff --git a/README.md b/README.md index a1166b9..cd5915b 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,19 @@ # SerialToKbd SerialToKbd is a simple helper program that allows MagTek USB check/credit card -readers 22523003 and 22533007 to be used with software that doesn't specifically support check readers. +readers 22533003 and 22533007 to be used with software that doesn't specifically support check readers. It is intended as a replacement for the MicrSend program that MagTek used to provide but which no longer works with recent versions of Windows. You do NOT need this program if: -* Your app supports the check reader directly (for example PowerChurch running locally) -* You have a USB MiniMicr that does keyboard emulation (part number 22523009 and similar) -* You have a keyboard "wedge" MiniMicr that plugs into the PS/2 keyboard port of your computer +* Your app supports the check reader directly (for example PowerChurch versions 10, 11, and 11.5 running locally) +* You have a USB MiniMicr that does keyboard emulation (part number 22523009 or 22523012 and similar) +* You have a keyboard "wedge" MiniMicr (22520001) that plugs into the PS/2 keyboard port of your computer This program MAY help if you have non-keyboard-emulation USB MiniMicr or a MiniMicr that plugs into the serial port on your computer AND your app doesn't support the MiniMicr directly (for example -PowerChurch online) (tested with 22533007 readers). +PowerChurch Online and PowerChurch versions 8.5 and 9 running locally) (tested with 22533003 and 22533007 +readers and PowerChurch Online). Before using SerialToKbd you should install the MagTek drivers for your device. @@ -28,7 +29,7 @@ The USB Mini Micr should be listed as such. A MiniMicr attached with a serial ca try launching SerialToKbd from a command prompt and passing the COM port name (e.g. COM1) as a parameter: SerialToKbd COM1 -You can test whether the MiniMicr, SerialToKbd, and other apps on your computer are working by +You can test whether the MiniMicr and SerialToKbd are working by opening NotePad or WordPad and placing the cursor in it. Then scan a check: you should see the check information appear as characters in the document. @@ -48,13 +49,25 @@ License: see 'License.txt' Source code for the program may be found at the project github page: http://github.com/chauser/SerialToKbd -## Running and Building +## Download +Select the 'Releases' tab above and download the zip file for the latest release. Extract the contained files, +then double-click 'SerialToKbd' to run the program. If you need to run from a command prompt in order to +supply a 'COMn' parameter, open a command prompt, change directory to the folder where you extracted the files, +and type + SerialToKbd COMn +where 'n' is the number of the COM port you want to monitor. -### Run directly from source: +## Running from source and Building + +### Run directly from source (assumes you have python installed): python SerialToKbd.py +or + python SerialToKbd.py COMn -### Package as .exe +### Package as .exe (assumes you have pyinstaller installed) pyinstaller -F SerialToKbd.py The created .exe is 'dist/SerialToKbd.exe' + + diff --git a/SerialToKbd.py b/SerialToKbd.py index 743ec4c..13f51a1 100644 --- a/SerialToKbd.py +++ b/SerialToKbd.py @@ -168,12 +168,19 @@ def get_option_info(port): } import serial -def start_capture(port): +def capture(port): + global keepAlive serial_params = get_option_info(port) try: serial_port = serial.Serial(**serial_params) - except (serial.SerialException, OSError): + except serial.SerialException as SE: print ('Can\'t open serial port: %s' % port) + print ("Serial exception occurred.") + print (SE.strerror) + return + except OSError as OSE: + print ("OSError occurred") + print (OSE.strerror) return if not serial_port.isOpen(): @@ -186,6 +193,7 @@ def start_capture(port): # Grab data from the serial port. raw = serial_port.read(1) + keepAlive = True if not raw: continue @@ -193,28 +201,52 @@ def start_capture(port): kbd_emulator.send_string(chr(raw[0])) except KeyboardInterrupt: pass + +import time +def keepAliveThread(): + global keepAlive + keepAlive = True + while keepAlive: + keepAlive = False + time.sleep(5) + print("\n%s stopped responding. Was the device unplugged?" % device) + print("Close and restart this program when the device is again available") + # sys.stdin.readline() + + import serial.tools.list_ports as LP import sys -device = None -if len(sys.argv) > 1: - device = sys.argv[1] -else: - print ("Looking for a Magtek reader") - ports = LP.comports() - for p in ports: - if p.manufacturer=='MagTek': - print("Found a MagTek reader with Vendor ID: 0x%x and Product ID: 0x%x on %s" % - (p.vid, p.pid, p.device)) - device=p.device -if device: - print("Opening reader on %s" % device) - print("Type Ctrl-C or close this window to exit") - start_capture(device) -else: - print("Did not find a supported reader; Use the device manager to identify the COM port") - print("and then enter the command") - print(" SerialToKbd COMn") - print("where n is the number of the COM port you identified in the device manager") - sys.stdin.readline() + +import threading +if __name__ == "__main__": + device = None + if len(sys.argv) > 1: + device = sys.argv[1] + else: + print ("Looking for a Magtek reader") + ports = LP.comports() + for p in ports: + if p.manufacturer=='MagTek': + print("Found a MagTek reader with Vendor ID: 0x%x and Product ID: 0x%x on %s" % + (p.vid, p.pid, p.device)) + device=p.device + try: + if device: + print("Opening reader on %s" % device) + print("Type Ctrl-C or close this window to exit") + # This whole multi-threaded design is ridiculous, but required, + # because when the device is unplugged, and even perhaps + # when the system sleeps or hibernates, the serial.read() function + # hangs, never timing out again. + threading.Thread(target=keepAliveThread,daemon=True).start() + capture(device) + else: + print("Did not find a supported reader; Use the device manager to identify the COM port") + print("and then enter the command") + print(" SerialToKbd COMn") + print("where n is the number of the COM port you identified in the device manager") + sys.stdin.readline() + except KeyboardInterrupt: + pass diff --git a/makeRelease.bat b/makeRelease.bat new file mode 100644 index 0000000..2ff49bd --- /dev/null +++ b/makeRelease.bat @@ -0,0 +1,6 @@ +pyinstaller -F SerialToKbd.py +copy /Y dist\SerialToKbd.exe . +del /Q SerialToKbd.zip +zip SerialToKbd.zip SerialToKeybd.py keyboardlayout.py LICENSE README.md SerialToKbd.exe +powershell Compress-Archive -Path SerialToKbd.py,keyboardlayout.py,LICENSE,README.md,SerialToKbd.exe,makeRelease.bat -DestinationPath SerialToKbd.zip +