Filtering USB HID Columns in Python - python

Something I can't seem to find the answer for. Please bare in mind I am not an expert so I may be missing simple, perhaps how I'm printing the device I want.
I am trying to store a device version number (dvm from herein), off a USB device. The problem is the USB device has two columns for reporting, feature and output.
So when I print the device I receive two sets of print statements.
#
def device(target_usage, target_vendor_id):
hidDevice = False
all_devices = hid.HidDeviceFilter(vendor_id = target_vendor_id).get_devices()
print "\n", all_devices
if len(all_devices) == 0:
# Exit if no devices found, report error.
hidDevice = False
time.sleep(0.2)
print "No devices can be detected, please check device is connected."
sys.exit(1)
return
elif len(all_devices) > 2:
# announce there are more than 1 device connected to prevent conflicting upgrades
hidDevice = True
time.sleep(0.2)
print "Too many devices connected, ensure the only device connected is the device needed to test."
sys.exit(1)
else:
# loop through all devices
for device in all_devices:
try:
device.open()
# print device details
device_name = unicode("=== INFO: Found %s %s (vID=[%04x], pID=[%04x], version number [%04x]) ===" % \
(device.vendor_name, device.product_name, device.vendor_id, device.product_id, device.version_number))
dvm = unicode("%04x" % \
(device.version_number))
print dvm;
print device_name;
finally:
device.close()
hidDevice = True
return hidDevice
#
When this function is called it will print all devices but I end up with the following result (Modified pids/vids etc for privacy issues.)
[HID device (vID=0x0000, pID=0x0000, v=0x0000); Make; Model, Path: \?\hid#vid_0000&pid_0000&col01#7&00000000&1&0000#{00000000-0000-0000-0000-000000000000}, HID device (vID=0x0000, pID=0x0000, v=0x0000); Make; Model, Path: \?\hid#vid_0000&pid_0000&col02#7&00000000&1&0000#{00000000-0000-0000-0000-000000000000}
The important part is the col01 and col02.
How can I filter that second enumerated HID device out?

Included the following code.
for report in device.find_output_reports():
if target_usage in report:
# add to target list
Targets.append(device)
finally:
device.close()
for item in Targets:
try:
item.open(output_only = True)
dvm = unicode("%04x" % \
(device.version_number))
print dvm
finally:
item.close()
Problem resolved.

Related

Reading More Than One Slave Sequentially With Pymodbus

2 slaves(devices) are working. I use slave units #2 and #5. MPR_46S in #5, Thermometer in #2. Slave addresses are not read sequentially, so I need to read an empty slave address that i named 'Slave jump'
NSlave=[2,5]
Clientnames=["client0","client1","client2","client3",]
def Find_Device(NSlave,Clientnames):
i=0
print("searching devices")
Devices=[]
S_Slave=[]
for i in range(len(NSlave)):
Clientnames[i].connect()
# check MPR_46S
result = Clientnames[i].read_holding_registers(address=0xEC00,count=1,unit=NSlave[i])
if not result.isError():
if result.registers==[41223]:
Devices.append("MPR_46S")
S_Slave.append(NSlave[i])
print("device found , Energy-Meter( MPR_46S) ")
else:
print("unsuccessful, meter")
else:
print('Errory >>>> {}' , format(result) )
Clientnames[i].close()
####################################### slave_jump
Clientnames[i].connect()
result = Clientnames[i].read_holding_registers(address=0x0003,count=1,unit=200)
Clientnames[i].close()
####################################### slave_jump
result = Clientnames[i].read_holding_registers(address=0x0003,count=1,unit=NSlave[i])
Clientnames[i].connect()
print(Clientnames[i].connect())
# check Term
if not result.isError():
if result.registers == [1]:
Devices.append("Term")
S_Slave.append(NSlave[i])
print("device found ,term")
else:
print("unsuccessful,term")
else:
print('Errory >>>> {}' , format(result))
Clientnames[i].close()
####################################### slave_jump
Clientnames[i].connect()
result = Clientnames[i].read_holding_registers(address=0x0003,count=1,unit=201)
Clientnames[i].close()
####################################### slave_jump
i+=1
result.registers=[]
print(Devices)
print(S_Slave)
return (Devices,S_Slave)
I wonder the reason for this. I would like to use if there is a better method

List available cameras OpenCV/Python

I have multiple webcams connected to my PC and I would like to select one camera based on its info (name, resolution etc.). Is there a way to list all the cameras available on a PC, instead of trying all the indices in cv2.VideoCapture()?
To answer the title of your question, you can use a while loop:
import cv2
def list_ports():
"""
Test the ports and returns a tuple with the available ports and the ones that are working.
"""
is_working = True
dev_port = 0
working_ports = []
available_ports = []
while is_working:
camera = cv2.VideoCapture(dev_port)
if not camera.isOpened():
is_working = False
print("Port %s is not working." %dev_port)
else:
is_reading, img = camera.read()
w = camera.get(3)
h = camera.get(4)
if is_reading:
print("Port %s is working and reads images (%s x %s)" %(dev_port,h,w))
working_ports.append(dev_port)
else:
print("Port %s for camera ( %s x %s) is present but does not reads." %(dev_port,h,w))
available_ports.append(dev_port)
dev_port +=1
return available_ports,working_ports
It's quite easy solution to implement on your code.
Version 2
As #ketza noticed, there might be cases in which the working ports are not sequential, this version will test at least 5 non working ports before exiting the while loop:
import cv2
def list_ports():
"""
Test the ports and returns a tuple with the available ports and the ones that are working.
"""
non_working_ports = []
dev_port = 0
working_ports = []
available_ports = []
while len(non_working_ports) < 6: # if there are more than 5 non working ports stop the testing.
camera = cv2.VideoCapture(dev_port)
if not camera.isOpened():
non_working_ports.append(dev_port)
print("Port %s is not working." %dev_port)
else:
is_reading, img = camera.read()
w = camera.get(3)
h = camera.get(4)
if is_reading:
print("Port %s is working and reads images (%s x %s)" %(dev_port,h,w))
working_ports.append(dev_port)
else:
print("Port %s for camera ( %s x %s) is present but does not reads." %(dev_port,h,w))
available_ports.append(dev_port)
dev_port +=1
return available_ports,working_ports,non_working_ports
The answer is negative. OpenCV doesn't have a method for listing the available video capture devices on your system. If you look at the code you see how currently OpenCV handles invalid device indices that don't exist. For instance for MacOS here is the code:
if ( cameraNum < 0 || devices.count <= NSUInteger(cameraNum) ) {
fprintf(stderr, "OpenCV: out device of bound (0-%ld): %d\n", devices.count-1, cameraNum);
[localpool drain];
return 0;
}
You see devices.count returns the number of available devices but OpenCV doesn't have a method to return that to the user.
The relevant code for Windows is here:
if ((unsigned)m_deviceID >= m_devices.Get()->Size)
{
OutputDebugStringA("Video::initGrabber - no video device found\n");
return false;
}
Again there is no function for returning m_devices.Get()->Size to the user. The Linux code is a bit more complex.
If you're building OpenCV from code you could add a function that returns the number of available devices. Or even better submit a pull request to OpenCV with your patch.
first install package :
pip install pygrabber==0.1
code #
from pygrabber.dshow_graph import FilterGraph
graph = FilterGraph()
print(graph.get_input_devices())# list of camera device
try:
device =graph.get_input_devices().index("name camera that I want to use it ")
except ValueError as e:
device = graph.get_input_devices().index("Integrated Webcam")#use default camera if the name of the camera that I want to use is not in my list
vid=cv2.VideoCapture(device)

Listing details of USB drives using python and udisk2

I have developed an application which uses udisks version 1 to find and list details of connected USB drives. The details include device (/dev/sdb1...etc), mount point, and free space. However, I found that modern distros has udisks2 installed by default. Here is the little code found on the other SO thread:-
#!/usr/bin/python2.7
import dbus
bus = dbus.SystemBus()
ud_manager_obj = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2')
om = dbus.Interface(ud_manager_obj, 'org.freedesktop.DBus.ObjectManager')
for k,v in om.GetManagedObjects().iteritems():
drive_info = v.get('org.freedesktop.UDisks2.Drive', {})
if drive_info.get('ConnectionBus') == 'usb' and drive_info.get('Removable'):
if drive_info['MediaRemovable']:
print("Device Path: %s" % k)
It produces:-
[sundar#arch ~]$ ./udisk2.py
Device Path: /org/freedesktop/UDisks2/drives/JetFlash_Transcend_8GB_GLFK4LYSFG3HZZ48
The above result is fine but how can I connect org.freedesktop.UDisks2.Block and get properties of the devices?
http://udisks.freedesktop.org/docs/latest/gdbus-org.freedesktop.UDisks2.Block.html
After lot of hit and trial, I could get what I wanted. Just posting it so that some one can benefit in the future. Here is the code:-
#!/usr/bin/python2.7
# coding: utf-8
import dbus
def get_usb():
devices = []
bus = dbus.SystemBus()
ud_manager_obj = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2')
om = dbus.Interface(ud_manager_obj, 'org.freedesktop.DBus.ObjectManager')
try:
for k,v in om.GetManagedObjects().iteritems():
drive_info = v.get('org.freedesktop.UDisks2.Block', {})
if drive_info.get('IdUsage') == "filesystem" and not drive_info.get('HintSystem') and not drive_info.get('ReadOnly'):
device = drive_info.get('Device')
device = bytearray(device).replace(b'\x00', b'').decode('utf-8')
devices.append(device)
except:
print "No device found..."
return devices
def usb_details(device):
bus = dbus.SystemBus()
bd = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2/block_devices%s'%device[4:])
try:
device = bd.Get('org.freedesktop.UDisks2.Block', 'Device', dbus_interface='org.freedesktop.DBus.Properties')
device = bytearray(device).replace(b'\x00', b'').decode('utf-8')
print "printing " + device
label = bd.Get('org.freedesktop.UDisks2.Block', 'IdLabel', dbus_interface='org.freedesktop.DBus.Properties')
print 'Name od partition is %s'%label
uuid = bd.Get('org.freedesktop.UDisks2.Block', 'IdUUID', dbus_interface='org.freedesktop.DBus.Properties')
print 'UUID is %s'%uuid
size = bd.Get('org.freedesktop.UDisks2.Block', 'Size', dbus_interface='org.freedesktop.DBus.Properties')
print 'Size is %s'%uuid
file_system = bd.Get('org.freedesktop.UDisks2.Block', 'IdType', dbus_interface='org.freedesktop.DBus.Properties')
print 'Filesystem is %s'%file_system
except:
print "Error detecting USB details..."
The complete block device properties can be found here http://udisks.freedesktop.org/docs/latest/gdbus-org.freedesktop.UDisks2.Block.html
Edit
Note that the Block object does not have ConnectionBus or Removable properties. You will have to change the code to remove references to Drive object properties for the code to work.
/Edit
If you want to connect to Block, not Drive, then instead of
drive_info = v.get('org.freedesktop.UDisks2.Drive', {})
try
drive_info = v.get('org.freedesktop.UDisks2.Block', {})
Then you can iterate through drive_info and output it's properties. For example, to get the Id property, you could:
print("Id: %s" % drive_info['Id'])
I'm sure that there is a nice pythonic way to iterate through all the property key/value pairs and display the values, but I'll leave that to you. Key being 'Id' and value being the string stored in drive_info['Id']. Good luck

pywinusb send a LED OFF_HOOK (0x17) on HID

I have the following definitions:
Telephony Device Page: 0x0B,
TELEPHONY HEADSET: 0x05,
LED Page: 0x08,
LED OFF_HOOK: 0x17
I want to send a "LED OFF_HOOK = 0x17" using pywinusb-0.3 example "simple send" below but am getting this error "The target device was found, but the requested usage does not exist!". I will appriciate any help. Thanks
import pywinusb.hid as hid
def click_signal(target_usage, target_vendor_id):
all_devices = hid.HidDeviceFilter(vendor_id = target_vendor_id).get_devices()
if not all_devices:
print("Can't find target device (vendor_id = 0x%04x)!" % target_vendor_id)
else:
for device in all_devices:
try:
device.open()
DD = device.find_output_reports()
for report in DD:
c = target_usage in report
if target_usage in report:
report[target_usage] = 1 # yes, changing values is that easy
report.send()
report[target_usage] = 0
report.send()
print("\nUsage clicked!\n")
return
finally:
device.close()
print("The target device was found, but the requested usage does not exist!\n")
#
if __name__ == '__main__':
target_vendor_id = 0x1395 # just an example, change it to the actual vendor_id
target_usage = hid.get_full_usage_id(0x0B, 0x17) # generic vendor page, usage_id = 2
click_signal(target_usage, target_vendor_id)
LED OFF_HOOK is expected to be a signal 'back' to the host.
In order to change the state, you'd need to issue a change in the HOOK_SWITCH usage on telephony page.

Alternative to tuntap

I'm trying to transmit TCP/IP over a radio that is connected to my computer (specifically, the USRP). Right now, it's done very simply using Tun/Tap to set up a new network interface. Here's the code:
from gnuradio import gr, gru, modulation_utils
from gnuradio import usrp
from gnuradio import eng_notation
from gnuradio.eng_option import eng_option
from optparse import OptionParser
import random
import time
import struct
import sys
import os
# from current dir
from transmit_path import transmit_path
from receive_path import receive_path
import fusb_options
#print os.getpid()
#raw_input('Attach and press enter')
# Linux specific...
# TUNSETIFF ifr flags from <linux/tun_if.h>
IFF_TUN = 0x0001 # tunnel IP packets
IFF_TAP = 0x0002 # tunnel ethernet frames
IFF_NO_PI = 0x1000 # don't pass extra packet info
IFF_ONE_QUEUE = 0x2000 # beats me ;)
def open_tun_interface(tun_device_filename):
from fcntl import ioctl
mode = IFF_TAP | IFF_NO_PI
TUNSETIFF = 0x400454ca
tun = os.open(tun_device_filename, os.O_RDWR)
ifs = ioctl(tun, TUNSETIFF, struct.pack("16sH", "gr%d", mode))
ifname = ifs[:16].strip("\x00")
return (tun, ifname)
# /////////////////////////////////////////////////////////////////////////////
# the flow graph
# /////////////////////////////////////////////////////////////////////////////
class my_top_block(gr.top_block):
def __init__(self, mod_class, demod_class,
rx_callback, options):
gr.top_block.__init__(self)
self.txpath = transmit_path(mod_class, options)
self.rxpath = receive_path(demod_class, rx_callback, options)
self.connect(self.txpath);
self.connect(self.rxpath);
def send_pkt(self, payload='', eof=False):
return self.txpath.send_pkt(payload, eof)
def carrier_sensed(self):
"""
Return True if the receive path thinks there's carrier
"""
return self.rxpath.carrier_sensed()
# /////////////////////////////////////////////////////////////////////////////
# Carrier Sense MAC
# /////////////////////////////////////////////////////////////////////////////
class cs_mac(object):
"""
Prototype carrier sense MAC
Reads packets from the TUN/TAP interface, and sends them to the PHY.
Receives packets from the PHY via phy_rx_callback, and sends them
into the TUN/TAP interface.
Of course, we're not restricted to getting packets via TUN/TAP, this
is just an example.
"""
def __init__(self, tun_fd, verbose=False):
self.tun_fd = tun_fd # file descriptor for TUN/TAP interface
self.verbose = verbose
self.tb = None # top block (access to PHY)
def set_top_block(self, tb):
self.tb = tb
def phy_rx_callback(self, ok, payload):
"""
Invoked by thread associated with PHY to pass received packet up.
#param ok: bool indicating whether payload CRC was OK
#param payload: contents of the packet (string)
"""
if self.verbose:
print "Rx: ok = %r len(payload) = %4d" % (ok, len(payload))
if ok:
os.write(self.tun_fd, payload)
def main_loop(self):
"""
Main loop for MAC.
Only returns if we get an error reading from TUN.
FIXME: may want to check for EINTR and EAGAIN and reissue read
"""
min_delay = 0.001 # seconds
while 1:
payload = os.read(self.tun_fd, 10*1024)
if not payload:
self.tb.send_pkt(eof=True)
break
if self.verbose:
print "Tx: len(payload) = %4d" % (len(payload),)
delay = min_delay
while self.tb.carrier_sensed():
sys.stderr.write('B')
time.sleep(delay)
if delay < 0.050:
delay = delay * 2 # exponential back-off
self.tb.send_pkt(payload)
# /////////////////////////////////////////////////////////////////////////////
# main
# /////////////////////////////////////////////////////////////////////////////
def main():
mods = modulation_utils.type_1_mods()
demods = modulation_utils.type_1_demods()
parser = OptionParser (option_class=eng_option, conflict_handler="resolve")
expert_grp = parser.add_option_group("Expert")
parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(),
default='gmsk',
help="Select modulation from: %s [default=%%default]"
% (', '.join(mods.keys()),))
parser.add_option("-v","--verbose", action="store_true", default=False)
expert_grp.add_option("-c", "--carrier-threshold", type="eng_float", default=30,
help="set carrier detect threshold (dB) [default=%default]")
expert_grp.add_option("","--tun-device-filename", default="/dev/net/tun",
help="path to tun device file [default=%default]")
transmit_path.add_options(parser, expert_grp)
receive_path.add_options(parser, expert_grp)
for mod in mods.values():
mod.add_options(expert_grp)
for demod in demods.values():
demod.add_options(expert_grp)
fusb_options.add_options(expert_grp)
(options, args) = parser.parse_args ()
if len(args) != 0:
parser.print_help(sys.stderr)
sys.exit(1)
if options.rx_freq is None or options.tx_freq is None:
sys.stderr.write("You must specify -f FREQ or --freq FREQ\n")
parser.print_help(sys.stderr)
sys.exit(1)
# open the TUN/TAP interface
(tun_fd, tun_ifname) = open_tun_interface(options.tun_device_filename)
# Attempt to enable realtime scheduling
r = gr.enable_realtime_scheduling()
if r == gr.RT_OK:
realtime = True
else:
realtime = False
print "Note: failed to enable realtime scheduling"
# If the user hasn't set the fusb_* parameters on the command line,
# pick some values that will reduce latency.
if options.fusb_block_size == 0 and options.fusb_nblocks == 0:
if realtime: # be more aggressive
options.fusb_block_size = gr.prefs().get_long('fusb', 'rt_block_size', 1024)
options.fusb_nblocks = gr.prefs().get_long('fusb', 'rt_nblocks', 16)
else:
options.fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096)
options.fusb_nblocks = gr.prefs().get_long('fusb', 'nblocks', 16)
#print "fusb_block_size =", options.fusb_block_size
#print "fusb_nblocks =", options.fusb_nblocks
# instantiate the MAC
mac = cs_mac(tun_fd, verbose=True)
# build the graph (PHY)
tb = my_top_block(mods[options.modulation],
demods[options.modulation],
mac.phy_rx_callback,
options)
mac.set_top_block(tb) # give the MAC a handle for the PHY
if tb.txpath.bitrate() != tb.rxpath.bitrate():
print "WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % (
eng_notation.num_to_str(tb.txpath.bitrate()),
eng_notation.num_to_str(tb.rxpath.bitrate()))
print "modulation: %s" % (options.modulation,)
print "freq: %s" % (eng_notation.num_to_str(options.tx_freq))
print "bitrate: %sb/sec" % (eng_notation.num_to_str(tb.txpath.bitrate()),)
print "samples/symbol: %3d" % (tb.txpath.samples_per_symbol(),)
#print "interp: %3d" % (tb.txpath.interp(),)
#print "decim: %3d" % (tb.rxpath.decim(),)
tb.rxpath.set_carrier_threshold(options.carrier_threshold)
print "Carrier sense threshold:", options.carrier_threshold, "dB"
print
print "Allocated virtual ethernet interface: %s" % (tun_ifname,)
print "You must now use ifconfig to set its IP address. E.g.,"
print
print " $ sudo ifconfig %s 192.168.200.1" % (tun_ifname,)
print
print "Be sure to use a different address in the same subnet for each machine."
print
tb.start() # Start executing the flow graph (runs in separate threads)
mac.main_loop() # don't expect this to return...
tb.stop() # but if it does, tell flow graph to stop.
tb.wait() # wait for it to finish
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
pass
(Anyone familiar with GNU Radio will recognize this as tunnel.py)
My question is, is there a better way to move packets to and from the kernel than tun/tap? I've been looking at ipip or maybe using sockets, but I'm pretty sure those won't be very fast. Speed is what I'm most concerned with.
Remember that tunnel.py is a really, really rough example, and hasn't been updated in a while. It's not really meant to be a basis for other code, so be careful of how much you rely on the code.
Also, remember that TCP over unreliable radio links has significant issues:
http://en.wikipedia.org/wiki/Transmission_Control_Protocol#TCP_over_wireless_networks

Categories