usb automatic detection in python for linux env - python

I'm using polling command(glob('/dev/tty[A-Za-z]*')) in python to detect usb devices connected to my linux pc in regular interval for my application. Is there any way to detect usb devices connected automatically?

Here is a start. You can find your usb vendor here. You got to code yourself a current_list_usb, set a time interval to check so you can compare and see if a new device is attached or not. Some code to use when importing usb module:
import usb, usb.core, usb.util, usb.backend.libusb1
...snippet...
# usb.core.find()
# find our device
dev = usb.core.find(idVendor= ...., idProduct= ....)
#dev_1 = usb.util.find_descriptor(cfg, find_all =True)
# was it found?
if dev is None:
raise ValueError('Device not found')
#x = dev.set_configuration()
#print (dev)
#print (help(usb.core))
if usb.core.find(find_all=True, bDeviceClass=7) is None:
raise ValueError('No printer found')

The normal way to do this is to make a udev rule that tells your program a new tty exists.
A custom udev rule may look something like this(let's call it /etc/udev/rules.d/50-custom-tty.rules:
KERNEL=="ttyUSB[0-9]+", RUN+="/usr/bin/my-program"
Here's a good guide on writing udev rules.
In this case, the program /usr/bin/my-program will run whenever a new ttyUSB device is created in /dev; udev will set a bunch of environment variables to tell you exactly what was just plugged in. You can then notify your main program that a new ttyUSB exists, and it should use it. Note that whatever program you run should be small, as otherwise the udev daemon will kill it if it takes too long.

I'd suggest using libudev and creating a udev monitor object to detect hotplugged devices. Here is a starting point for you to learn about libudev and its monitor feature:
https://www.freedesktop.org/software/systemd/man/libudev.html
There might be a good Python library already that wraps udev so you can use its features without writing C code.

Related

Turn off specific USB port in windows with python

This is my first post, and I kind of have seen that the more specific the better, so I'll try to be super clear, and thanks in advance!
What I want:
I need to scan images from 2 or more scanners at the same time, these scanners are from the same brand and model, in this case Epson Perfection V600, I need different time intervals for at least 40 captures over a course of 20 hours.
My approach
I decided to use Windows, I already have a program in Python that does what I want with just one scanner, or with two from different models. But here is where you guys come in:
The problem
Windows always prints with the same scanner, Since they are from the same brand and model it always uses the same one, and I cannot use two different scanners because that will cause the images not to be comparable. Nevertheless, when I use two different scanners, I don't have such problem. I need to find a way to print with each scanner. I thought in buying a USB hub and control it with python as well, but apparently given libsub implementation in windows, I will not be able to control it. So I'm currently Looking for a way to disable an specific USB port so the program will only recognize one device, scan with it, disable that one, re-enable the other one, and so on.
What I have access to:
Right now I'm using Windows 10, 64 bits, python kernel 3 in a python 3.5 version inside a Conda environment, conda version (4.5.11).
Ubuntu 16.04, 64 bits, with pyinsane working, in a python 3.5 environment inside conda (don't have the conda version at hand).
One Epson perfection V600.
Two Canon Lide200, working only in windows, because drivers are not available in Ubuntu.
What I have also tried
Using Ubuntu,
I thought it was a good Idea, but the Epson drivers webpage fails to connect to the repository containing the rest of the Epson files, letting me only partially download the files, I already tried to contact the owner of the Docky repository, but he fails to contact me.
The error:
W: The repository 'http://ppa.launchpad.net/docky-core/ppa/ubuntu Xenial Release' does not have a Release file.
N: Data from such a repository can't be authenticated and is therefore potentially dangerous to use.
N: See apt-secure(8) manpage for repository creation and user configuration details.
E: Failed to fetch http://ppa.launchpad.net/docky-core/ppa/ubuntu/dists/xenial/main/binary-amd64/Packages 404 Not Found
E: Some index files failed to download. They have been ignored, or old ones used instead.
when I manually try to enter the site's repository I found that
All links to XENIAL drivers are down, actually the whole Xenial
Folder is missing.
Also then thought it was a good idea to ignore this message, but I
Need the Epwoka driver to run Epson scanners in Ubuntu, and that
a whole problem by itself. Aside from that, is not known if Epson
Perfection V600 is going to be possible to be controlled by the
PyInsane lib, since is marked as untested.
Using Windows
I thought in buying an USB hub and to controlled as shown in this thread, but apparently is not possible in windows.
I already installed libsub, usb.util, libusb1,USB (for the core functions) and usb1, but I don't know (I think is not possible) to disable and re-enable a specific USB port with them.
Can't disable the drivers since that mean all USB will be down to connect with the scanners.
Device manager is not helping, because of the inability of telling which device is which.
Cannot change the name of the scanner (yes, printers can have specific names) but scanners can't.
Can't buy another scanner, I'm stuck with Epson.
My code for Scanning
import pyinsane2
def Scan(Device, dpi):
pyinsane2.init()
try:
pyinsane2.set_scanner_opt(Device, 'resolution', [dpi])
pyinsane2.set_scanner_opt(Device, 'mode', ['Color'])
pyinsane2.maximize_scan_area(Device)
scan_session = Device.scan(multiple=False)
try:
while True:
scan_session.scan.read()
except EOFError:
pass
Image = scan_session.images[-1]
finally:
pyinsane2.exit()
return(Image)
devices = pyinsane2.get_devices()
image_a = Scan(devices[0], 75)
image_b = Scan(devices[1], 75)
a = devices[1]
b = devices[0]
a == b #Different
a.dev_type == b.dev_type
a.model == b.model
a.name == b.name #Different
a.nice_name == b.nice_name
a.options == b.options
a.reload_options == b.reload_options #Different
a.scan == b.scan #Different
a.srcs == b.srcs #Different
a.vendor == b.vendor
I put a sticki note inside each Scanner, one with an "a" the other one with a "b" and it always scans with the scanner that I plugged in first
This is what I would like to do (and doing it manually works): .
This is what I get when trying in python:
Any solution will help me, get creative! I was thinking on using a .bat file to disable an specific port and calling it with Python. But I couldn't find a way to make it.Keep in mind that doing it manually is not an option 'cause of the 20 to 40 hours of continuous image acquisition.
Thanks!
~Diego

Using python how to check if a module is loaded?

I'm currently working on a project that involves an Up-board running ubilinux connected to three usb devices. We have witnessed issues where the board sees the usb device disconnect. When the usb device reconnects, it loads the USBSerial and FTDI_sio module, which is an issue. Before the program can check for the presence of the connected devices I need to run
sudo /sbin/rmmod usbserial
sudo /sbin/rmmod ftdi_sio
I don't want the program to constantly perform those operations, so what I've done is created a thread that looks for a usb device being plugged in. I'm using pyudev to accomplish this.
My issue is that I don't always have to perform the rmmod for usbserial and ftdi_sio, as they don't always load when the usb device is attached. Is there some way to run a check, written in python, to determine if ftdi_sio and usbserial have loaded?
I've done a number of searches and I find a number of links that show how to do it as a bash script, but I'm trying to find out if I can do it in python. I also seem to get a large number of search results for loading python modules, which isn't very helpful.
Here's some Popen code to check if it's loaded using lsmod:
import subprocess
def module_loaded(module_name):
"""Checks if module is loaded"""
lsmod_proc = subprocess.Popen(['lsmod'], stdout=subprocess.PIPE)
grep_proc = subprocess.Popen(['grep', module_name], stdin=lsmod_proc.stdout)
grep_proc.communicate() # Block until finished
return grep_proc.returncode == 0
for module_name in ['usbserial', 'ftdi_sio']:
loaded = module_loaded(module_name)
print('Module {} {} loaded'.format(module_name, "is" if loaded else "isn't"))
The print is there just to prove it works; you can replace that with your rmmod code. Output:
Module usbserial isn't loaded
ftdi_sio 52791 0
Module ftdi_sio is loaded
I went with modinfo to begin with btw, but that didn't work as intended. modinfo would show the module info regardless of whether or not it was loaded. The lsmod approach appears to work well though.

How to check whether the device's display is turned on/off with Python?

I want to write a Python script that checks whether my device has a display and whether that display is turned on or off.
I googled it, there is a third-party library named "WMI", but it can only get some information like CPU/HDD/process/thread, so I am confused about it.
I am using Windows 10, in case that matters.
Is it possible to get that kind of low level hardware information via Python, and if it is, how can I do it?
It looks like Windows does not really have a way to tell you if the monitor is on or off. The WMI Win32_DesktopMonitor class has an 'Availability' property but this doesn't seem to be affected by changing the monitor state. I tested this using the following python script:
import wmi # pip install WMI
import win32gui, win32con
SC_MONITORPOWER = 0xF170
wmic = wmi.WMI()
def powersave():
# Put the monitor to Off.
win32gui.SendMessage(win32con.HWND_BROADCAST, win32con.WM_SYSCOMMAND, SC_MONITORPOWER, 2)
# Get the monitor states
print([monitor.Availability for monitor in wmic.Win32_DesktopMonitor()])
if __name__ == '__main__':
powersave()
The SC_MONITORPOWER arguments are documented here.
Unfortunately the result for my monitor is always 3 which means it is "on", even when it is actually powered down either in sleep mode or physically off.
Depending on your requirement, you might just want to send the broadcast message to assert the power state you want and not need to check the current state.

Detect when new USB device is connected (plug'n'play)

Using this answer, we are able to query all the USB devices connected at a precise moment.
I have a Python program running on Linux (Debian or RaspBian) that does a specific task, but I also want that this program listens if new USB device is connected, and when this happens, trigger a specific action.
I'm thinking about doing a new thread that does:
while True:
list_USB_devices() # using https://stackoverflow.com/a/8265634/1422096
see_if_new_devices_in_this_list()
time.sleep(2) # wait 2 seconds
but I don't find this solution very elegant.
What's a cleaner solution to detect in the background of a Python program if a new USB device is connected?
Example of application for my program: listen if a new USB-MIDI keyboard/device is connected, and if so, attach it with rtmidi-python "Plug and play!"
Look into the gio library (part of glib). You can attach watches and connect callbacks when devices are created. This way you don't have to poll at all. Set a watch on the devices directory, look for file creation. Filter out files not interested in.
You can probably also look at 'udev' system itself, and write a rule to execute something on apparition of a new usb device.

How to use FDTI chip in VCP mode?

I'm trying to get a SainSmart USB relay board based on the FT245RL chip working and having a terrible time. I was under the impression that I could control the relays from the command line with something like:
echo -e -n "\xFF\x1\x1" > /dev/ttyUSB1
While the device is mounted automatically and I think I've got the baud rate and permissions set up, nothing happens on my Debian squeeze or CentOS 5 machines. SainSmart's support is worthless.
I decided to try on windows, so I installed the drivers and wrote a small program in python:
import serial
ser = serial.Serial(2) #COM3
ser.write(chr(255) + chr(0) + chr(1))
ser.close
Still nothing. Perhaps it's a hardware problem so I install a provided windows program. It sees the device and works when I click on the relay buttons. Discouraged, I exit their program, look for bugs in mine (can't find any) but try it anyways, and it works! I write a much bigger program to do all sorts of cool things and cool things happen until I unplug the device. When I plug it back in, nothing works. I've got to run and exit the relay control program before my code will do anything.
I suspect that I've got to do something with d2xx drivers like FT_SetBitMode(). Is there any way to just use VCP mode? PyUSB won't install on my computer and isn't available for Linux.
All I want is a simple way to control a relay on Linux using python.
I had the same problem, I think you were right about FT_SetBitMode(). Eventually I got it to work by using ftd2xx (which you can get by pip). You will also need to install the D2XX drivers.
import ftd2xx
if ftd2xx.listDevices() < 1:
print "No relays found. Exiting..."
exit()
else: print "Initializing relays..."
relays = ftd2xx.open(0)
relays.setBitMode(255,1) # I think this uses FT_SetBitMode()
relays.write(b'\01\01') # relay one on
relays.write(b'\01\01') # relay two on
relays.write(b'\00\00') # all relays off
relays.close()
I would first suggest you to try out hyperterminal first.
From your code snippet it seems that you are missing the baudrate (assuming the rest are going to be the default values). And I don't really know if it matters but I always explicitly set the port as Serial('COM3'), one less possible point of failure this way :)
Probably you don't have a problem with Python, but with controlling the device as such.
You should try to find out if the the device has special requirements about the state of the control lines (DST, DTR etc.).
And, not to forget, the communication speed which Alex already mentions.
Using virtual com ports on Windows I found I had to use 115k baud

Categories