Open tcarroll2 opened 5 years ago
Unfortunately, the way usb-ser-mon is coded it relies on udev, which is only available under linux.
In order to determine which /dev/ttys your barcode scanner is connected to, try using this utility: https://github.com/dhylands/dotfiles/blob/master/bin/find_port.py
Run it with the -l option. It only uses python serial port and no depdendencies on udev. I designed it to be run from within shell scripts for find serial ports. It can search based on vendor name, PID, VID, and serial number.
I tried running the find_port.py script, but firstly I had to comment out the sys.exit(1) line near the bottom as Python was not liking it. I was reading the docs here, but I could see why that wouldn't work.
Anyway, I ran your script and it failed to detect my scanner on the ttys* port.
I can use pyusb along with libusb1 as the backend and it sees the device connected, but it does not tell me which ttys* port it is connected to, which I find strange. Here's the code I am using with pyusb:
import usb
import usb.backend.libusb1 as libusb1
import libusb1 as libusb
# find our device
dev = usb.core.find(idVendor=0xad93, idProduct=0x4002, backend=libusb1.get_backend())
print (dev)
This is the output when I run the above code:
DEVICE ID ad93:4002 on Bus 020 Address 001 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x110 USB 1.1
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x40 (64 bytes)
idVendor : 0xad93
idProduct : 0x4002
bcdDevice : 0x100 Device 1.0
iManufacturer : 0x1 YK
iProduct : 0x2 YK-2D PRODUCT HID KBW
iSerialNumber : 0x3 APP-000000000
bNumConfigurations : 0x1
CONFIGURATION 1: 200 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x22 (34 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0x80 Bus Powered
bMaxPower : 0x64 (200 mA)
INTERFACE 0: Human Interface Device ====================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x1
bInterfaceClass : 0x3 Human Interface Device
bInterfaceSubClass : 0x1
bInterfaceProtocol : 0x1
iInterface : 0x0
ENDPOINT 0x81: Interrupt IN ==========================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x3 Interrupt
wMaxPacketSize : 0x8 (8 bytes)
bInterval : 0x1
This would be all I need if only it would show the ttys port it is reading this information from. Would the ttys port be one of the 0x** codes above?
Thank you for your response and help.
It looks like your scanner is presenting itself as a HID device and not a USB Serial device (which is why it's not showing up with a tty. If it was showing up as a tty then you should be able to do
ls /dev/tty.*
On my Mac I see something like this with a usb serail device plugged in:
508 >ls /dev/tty.*
/dev/tty.Bluetooth-Incoming-Port /dev/tty.MALS /dev/tty.SOC /dev/tty.usbserial-1440
Notice the /dev/tty.usbserial-1440 on the far right (you'll probably need to scroll the display).
If I run your little python program then I see (The Digi dongle is using an FTDI USB-to-serial chip)
DEVICE ID 0403:6001 on Bus 020 Address 002 =================
bLength : 0x12 (18 bytes)
bDescriptorType : 0x1 Device
bcdUSB : 0x200 USB 2.0
bDeviceClass : 0x0 Specified at interface
bDeviceSubClass : 0x0
bDeviceProtocol : 0x0
bMaxPacketSize0 : 0x8 (8 bytes)
idVendor : 0x0403
idProduct : 0x6001
bcdDevice : 0x600 Device 6.0
iManufacturer : 0x1 Digi
iProduct : 0x2 XStick
iSerialNumber : 0x0
bNumConfigurations : 0x1
CONFIGURATION 1: 100 mA ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x20 (32 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0x80 Bus Powered
bMaxPower : 0x32 (100 mA)
INTERFACE 0: Vendor Specific ===========================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x2
bInterfaceClass : 0xff Vendor Specific
bInterfaceSubClass : 0xff
bInterfaceProtocol : 0xff
iInterface : 0x2 XStick
ENDPOINT 0x81: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x0
When my barcode scanner is plugged in, it comes up as ttys002 most of the time. It could change from that to ttys003 or another number at times, or if I plug it into my macbook it can be different. So that is why I am trying to figure out how to identify which /dev/ device it is being represented as.
Is there a way to poll HID devices since it is presenting itself as an HID device?
When I first got the scanner and plugged it in Mac OS recognized it as a keyboard and wanted me to hold down the shift key. I just canceled that setup process.
The scanner works, but I have to ensure my input field has focus, or it won't capture the barcode when I scan it. I would like to trap the code without having to have the input field having focus. But, for now, I can live with it until I need to do something. I have a thread set up to continuously read the /dev/ttys002 port, but it doesn't capture anything when a barcode is scanned. Here's my thread function:
def wait_for_qrcode():
global stopGame
checkWinEntry.delete(0, END)
checkWinEntry.focus_set()
f=open("/dev/ttys002")
while len(checkWinEntry.get()) == 0 and not stopGame:
qrcode = f.read()
time.sleep(1)
f.close
print (qrcode)
check_win(qrcode)
But this code would only work if I knew for certain the /dev/ttys002 was correct.
Again, thanks for your help.
Since its acting like a keyboard, then it makes sense that its coming up as a HID device.
I know under linux there are "input" drivers and you can setup your code to read from each individual input device (keyboard, mouse, etc), but I'm not that familiar with the Mac, so I'm not sure.
So went digging a little more with the HID info, and I found pyhid and libusb/hidapi. I installed it and I can see the device using their code:
import hid
# get list of HID devices connected to this computer
h=hid.enumerate()
print ("HID info=", h,"\n")
# get path of first item
item=0
path=h[item]['path']
vid=h[item]['vendor_id']
pid=h[item]['product_id']
print ("Path=%s Vid=%s Pid=%s" % (path, vid, pid) + "/n")
# open the device
try:
# using path works on raw, not non-raw
# d=hid.Device(path=path)
# print "Opened device=", path
d=hid.Device(vid=vid, pid=pid)
print ("Opened device=", vid, pid, "\n")
# -- TBD
#r=d.get_feature_report(1, 1024)
#print "Report=", r
# loop rading the keyboard....
done=0
while(done==0):
r=d.read(10)
for c in r:
x=ord(c)
print ("read=",x,"\n")
except Exception as e:
print ("Exception, e=", e)
print ("Done!")
Which results in a bunch of information, but here's the relevant entry for the barcode scanner:
{'path': b'IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/XHC1@14/XHC1@14000000/HS10@14600000/YK-2D PRODUCT HID KBW@14600000/IOUSBHostInterface@0/IOUSBHostHIDDevice@14600000,0', 'vendor_id': 44435, 'product_id': 16386, 'serial_number': 'APP-000000000', 'release_number': 256, 'manufacturer_string': 'YK', 'product_string': 'YK-2D PRODUCT HID KBW', 'usage_page': 1, 'usage': 6, 'interface_number': 0}
Path=b'IOService:/IOResources/IOBluetoothHCIController/AppleBroadcomBluetoothHostController/IOBluetoothDevice/IOBluetoothL2CAPChannel/AppleHSBluetoothDevice/Accelerometer@2/AppleHSBluetoothHIDDriver' Vid=76 Pid=617/n
Opened device= 76 617
Still doesn't give me the /dev/ttys path that it is. This time when I plugged it in, it is coming up as /dev/ttys003, I think.
As you can see from the directory listing, ttys001 through ttys003 are all active at nearly the same time.
crw--w---- 1 carroll tty 16, 0 Aug 29 23:04 /dev/ttys000
crw--w---- 1 carroll tty 16, 1 Aug 30 14:40 /dev/ttys001
crw--w---- 1 carroll tty 16, 2 Aug 30 14:03 /dev/ttys002
crw--w---- 1 carroll tty 16, 3 Aug 30 14:30 /dev/ttys003
crw-rw-rw- 1 root wheel 4, 49 Aug 27 23:14 /dev/ttys1
crw-rw-rw- 1 root wheel 4, 50 Aug 27 23:14 /dev/ttys2
crw-rw-rw- 1 root wheel 4, 51 Aug 27 23:14 /dev/ttys3
crw-rw-rw- 1 root wheel 4, 52 Aug 27 23:14 /dev/ttys4
crw-rw-rw- 1 root wheel 4, 53 Aug 27 23:14 /dev/ttys5
crw-rw-rw- 1 root wheel 4, 54 Aug 27 23:14 /dev/ttys6
crw-rw-rw- 1 root wheel 4, 55 Aug 27 23:14 /dev/ttys7
crw-rw-rw- 1 root wheel 4, 56 Aug 27 23:14 /dev/ttys8
crw-rw-rw- 1 root wheel 4, 57 Aug 27 23:14 /dev/ttys9
crw-rw-rw- 1 root wheel 4, 58 Aug 27 23:14 /dev/ttysa
crw-rw-rw- 1 root wheel 4, 59 Aug 27 23:14 /dev/ttysb
crw-rw-rw- 1 root wheel 4, 60 Aug 27 23:14 /dev/ttysc
crw-rw-rw- 1 root wheel 4, 61 Aug 27 23:14 /dev/ttysd
crw-rw-rw- 1 root wheel 4, 62 Aug 27 23:14 /dev/ttyse
crw-rw-rw- 1 root wheel 4, 63 Aug 27 23:14 /dev/ttysf
It looks like the /dev/ttysXXX are psuedo tty's. If you open a terminal window and type the tty
command then it will show you the /dev/ttysXXX entry that's been assigned to that particular terminal.
The command lsof | grep ttys0
(takes a few minutes) will tell you which processes have which /dev/ttysXXX assigned to them.
I suspect that if you knew the tty for the terminal that launched your "reader" process and that terminal had focus then it would get the characters from the scanner. But as soon as you change the focus away, it will stop receiving the scanner data.
I installed your package via pip and upon running I get this error:
Traceback (most recent call last): File "/Users/carroll/.vscode/extensions/ms-python.python-2019.8.30787/pythonFiles/ptvsd_launcher.py", line 43, in
main(ptvsdArgs)
File "/Users/carroll/.vscode/extensions/ms-python.python-2019.8.30787/pythonFiles/lib/python/ptvsd/main.py", line 432, in main
run()
File "/Users/carroll/.vscode/extensions/ms-python.python-2019.8.30787/pythonFiles/lib/python/ptvsd/main.py", line 316, in run_file
runpy.run_path(target, run_name='main')
File "/Users/carroll/.pyenv/versions/3.7.4/lib/python3.7/runpy.py", line 263, in run_path
pkg_name=pkg_name, script_name=fname)
File "/Users/carroll/.pyenv/versions/3.7.4/lib/python3.7/runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "/Users/carroll/.pyenv/versions/3.7.4/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/Shared/toms-music-bingo/test-tty.py", line 145, in
main()
File "/Users/Shared/toms-music-bingo/test-tty.py", line 136, in main
context = pyudev.Context()
File "/Users/carroll/.pyenv/versions/3.7.4/lib/python3.7/site-packages/pyudev/core.py", line 64, in init
self._libudev = load_ctypes_library('udev', SIGNATURES, ERROR_CHECKERS)
File "/Users/carroll/.pyenv/versions/3.7.4/lib/python3.7/site-packages/pyudev/_ctypeslib/utils.py", line 56, in load_ctypes_library
raise ImportError('No library named %s' % name)
ImportError: No library named udev
Exception ignored in: <function Context.del at 0x106b8e4d0>
Traceback (most recent call last):
File "/Users/carroll/.pyenv/versions/3.7.4/lib/python3.7/site-packages/pyudev/core.py", line 68, in del
self._libudev.udev_unref(self)
AttributeError: 'Context' object has no attribute '_libudev'
I am on Mac OS Mojave 10.14.6 using Python version 3.7.4. All I am trying to do is determine which /dev/ttys my barcode/qr code scanner is connected to.
Thank you!