1

I have an RFID reader (Neuftech USB RFID Reader, https://www.amazon.de/Neuftech-Reader-Kartenleseger%C3%A4t-Kartenleser-Kontaktlos/dp/B018OYOR3E) that attaches via USB. Via /var/log/syslog I found out, that it is available as /dev/tty1. The following Python script should read and print the scanned RFID tags:

#!/usr/bin/python3
import sys,datetime

def main():
    while True:
        sys.stdin = open('/dev/tty1', 'r')
        rfid = input()
        print("Read code from RFID reader: "+str(rfid.rstrip()))
        sys.stdin.close()

main()

While this usually works fine, it is not reliable at all. For the first scan, the reader beeps as if it read successfully, but the script doesn't print anything.

Sometimes the read RFID by the script is a mangled. Mostly is okay, some are skipped, or not read but the reader beeps as if it read just fine. After a while the script crashes.

Read code from RFID reader: 0015766026
Read code from RFID reader: 0015766026
Read code from RFID reader: 0015766026
Read code from RFID reader: 0015766026
Read code from RFID reader: 0015766026
Read code from RFID reader: 0015766026
Read code from RFID reader: 0015766026
Read code from RFID reader: 0014090374
Read code from RFID reader: 0004284829
Read code from RFID reader: 0016658737
Read code from RFID reader: 0003342559
Read code from RFID reader: 0003342559
Read code from RFID reader: 0016658737
Read code from RFID reader: 0016658737
Read code from RFID reader: 0004284829
Read code from RFID reader: 0048890004284829
Read code from RFID reader: 0016658737
Read code from RFID reader: 0016658737
Traceback (most recent call last):
  File "rfid.py", line 14, in <module>
    main()
  File "rfid.py", line 7, in main
    rfid = input()
EOFError: EOF when reading a line

How can I modify the script to be more reliable. In the end the Raspberry Pi 2 should log the days and time where specific tags are scanned.


Attempted approaches from the suggestions. Neither of these prints anything, even after repeated scanning of different RFID tags.

import serial
ser = serial.Serial('/dev/tty1', 9600)
ser.flushInput()

while True:
    try:
        ser_bytes = ser.readline()
        print(str(ser_bytes))
    except:
        print("Keyboard Interrupt")
        break

Second approach:

import sys

for line in sys.stdin:
    print(str(line))

Third approach:

import sys

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    print line

I've also changed the script to initially open stdin from tty1 and just close it after the script is terminated, which makes sense, but doesn't change the outcome.


edit: unplugging the device, then plugging the device in again dmesg -w

[19557.527332] usb 1-1.3: USB disconnect, device number 4
[19565.156398] usb 1-1.3: new low-speed USB device number 5 using dwc_otg
[19565.298471] usb 1-1.3: New USB device found, idVendor=16c0, idProduct=27db, bcdDevice= 0.01
[19565.298491] usb 1-1.3: New USB device strings: Mfr=1, Product=0, SerialNumber=0
[19565.298504] usb 1-1.3: Manufacturer: HXGCoLtd
[19565.314868] input: HXGCoLtd Keyboard as /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3/1-1.3:1.0/0003:16C0:27DB.0002/input/input1
[19565.382012] hid-generic 0003:16C0:27DB.0002: input,hiddev96,hidraw0: USB HID v1.10 Keyboard [HXGCoLtd] on usb-3f980000.usb-1.3/input0

2 Answers 2

1

Why are you repeatedly opening and closing the port ? You could just open it once at the start of your program, wait for data and close it when you are done with it and when an exception occurs.

Otherwise I believe something like this could work too:

import sys

for line in sys.stdin:
   # do something

Alternatively you could use a dedicated library for serial communications like pyserial. The code would be like this (untested):

import serial
ser = serial.Serial('/dev/tty1', 9600)
ser.flushInput()

while True:
    try:
        ser_bytes = ser.readline()
        # do something with the bytes

    except:
        print("Keyboard Interrupt")
        break

Make sure you set the correct baud rate.

6
  • Hello, thanks for your input. I've changed my script to initially open and eventually close when I interrupt the script, the outcome doesn't change. I've tried both your suggestions with a respective print(str(line)) and print(str(ser_bytes)), but neither gives my any output. Commented Mar 1, 2020 at 9:37
  • Hmm are you sure your device uses /dev/tty1 ? I would expect ttyAMA0 or possibly ttyUSB0 or something like that. Note that it's not guaranteed to remain constant (for example if you plug in other devices). Run dmesg -w from the command line, then plug your reader and see how it's been named by the system. There should be no need to use stdin anyway. I also found some code that uses the pyrfid library which is yet another alternative.
    – Kate
    Commented Mar 1, 2020 at 13:38
  • I believe I've got the /dev/tty1 from syslog, but I've attached dmesg -w to the question. I have no ttyUSB0 and ttyAMA0 doesn't provide any output with the scripts mentioned in the question. Commented Mar 1, 2020 at 14:59
  • I've installed and tested pyrfid, but that doesn't seem to work in my case either. Commented Mar 1, 2020 at 15:08
  • The dmesg output indicates your reader does keyboard emulation (like a barcode reader would). So as said above, just read it like a keyboard. If you need to distinguish between the RFID reader and your regular keyboard using the evdev library is another possible option. I was expecting to see some sort of serial device, but it's a plain keyboard device you've got. Sorry for confusing you even more - there are really many ways of doing it..
    – Kate
    Commented Mar 1, 2020 at 15:15
1

/dev/tty1 is NOT a USB port.

This is the default console.

There should be no need to "open" it and certainly repeatedly opening and closing stdin is just going to cause character loss.

I suspect the (unspecified) RFID reader is designed to emulate a keyboard. Just read as you would a keyboard!

1
  • Thanks for your input! I've added the RFID readers name and a link. Commented Mar 1, 2020 at 9:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.