Listing details of USB drives using python and udisk2 - python

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

Related

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)

Filtering packets by src mac in scapy

When I filter the packets using this filter in wireshark:
wlan.sa == 04.b1.67.14.bd.64
All goes perfect.
However, I'm trying to do it with the following python script using scapy, but it never filter by the source mac:
from scapy.all import *
from datetime import datetime
import traceback
# import MySQLdb
def getAverageSSI():
global ssiFinal
return ssiFinal
def setParams():
global window
global timestamp
global SSID
global datetime
global iterator1
window = 1
timestamp = datetime.now()
SSID='DefaultName'
iterator1 = 0
global ssiArray
ssiArray = []
def myPacketHandler(pkt) :
global SSID
global timestamp
global iterator1
global ssiArray
try :
if pkt.haslayer(Dot11) :
ssiNew = -(256-ord(pkt.notdecoded[-4:-3]))
ssiArray.append(ssiNew)
diffT=(datetime.now()-timestamp).seconds
if diffT>window:
print 'With MAC dst = %s with SSI Power= %s' %(pkt.addr1, sum(ssiArray)/len(ssiArray))
print ssiArray
ssiArray = []
timestamp=datetime.now()
except Exception as e:
print 'Exception'
print e
traceback.print_exc()
sys.exit(0)
setParams()
try:
sniff(iface="wlan1", filter="ether src 04:b1:67:14:bd:64", prn = myPacketHandler, store=0)
except Exception as e:
print e
print "Sniff AP1 Off"
I have also tried to remove the filter in sniff, and put an if like the following:
if pkt.addr1 == '04:b1:67:14:bd:64' : # mac xiaomi mi a1
# SSID = pkt.info;
ssiNew = -(256-ord(pkt.notdecoded[-4:-3]))
ssiArray.append(ssiNew)
diffT=(datetime.now()-timestamp).seconds
if diffT>window:
# query = "START TRANSACTION;"
# queryBack=cur.execute(query)
# query = "INSERT INTO RSSI VALUES(%d,\"AP1\",%d);"%(iterator1,ssiNew)
# queryBack = cur.execute(query)
print 'MAC = %s with SSI Power= %s' %(pkt.addr1, sum(ssiArray)/len(ssiArray))
ssiArray = []
# Conexion.commit()
# iterator1+=1
timestamp=datetime.now()
But it is only filtering by destination mac.
Do you know how to properly filter by mac like in the following wireshark image? (it needs to be exactly the same behaviour than in the wireshark filter):
Your second method should be working well, if you used addr2 instead of addr1
Here is how it works in 802.11 (yes it’s really messy)
Also, you should update to the github scapy version, which has support for RSSI directly (so you don’t have to parse notdecoded)
See https://github.com/secdev/scapy/archive/master.zip

How to invoke C-STORE when trying to query from SCP

I've been using the following code, which is from the pynetdicom library to query and store some images from a remote server SCP, on my machine(SCU).
"""
Query/Retrieve SCU AE example.
This demonstrates a simple application entity that support the Patient
Root Find and Move SOP Classes as SCU. In order to receive retrieved
datasets, this application entity must support the CT Image Storage
SOP Class as SCP as well. For this example to work, there must be an
SCP listening on the specified host and port.
For help on usage,
python qrscu.py -h
"""
import argparse
from netdicom.applicationentity import AE
from netdicom.SOPclass import *
from dicom.dataset import Dataset, FileDataset
from dicom.UID import ExplicitVRLittleEndian, ImplicitVRLittleEndian, \
ExplicitVRBigEndian
import netdicom
# netdicom.debug(True)
import tempfile
# parse commandline
parser = argparse.ArgumentParser(description='storage SCU example')
parser.add_argument('remotehost')
parser.add_argument('remoteport', type=int)
parser.add_argument('searchstring')
parser.add_argument('-p', help='local server port', type=int, default=9999)
parser.add_argument('-aet', help='calling AE title', default='PYNETDICOM')
parser.add_argument('-aec', help='called AE title', default='REMOTESCU')
parser.add_argument('-implicit', action='store_true',
help='negociate implicit transfer syntax only',
default=False)
parser.add_argument('-explicit', action='store_true',
help='negociate explicit transfer syntax only',
default=False)
args = parser.parse_args()
if args.implicit:
ts = [ImplicitVRLittleEndian]
elif args.explicit:
ts = [ExplicitVRLittleEndian]
else:
ts = [
ExplicitVRLittleEndian,
ImplicitVRLittleEndian,
ExplicitVRBigEndian
]
# call back
def OnAssociateResponse(association):
print "Association response received"
def OnAssociateRequest(association):
print "Association resquested"
return True
def OnReceiveStore(SOPClass, DS):
print("FINALLY ENTERED")
print "Received C-STORE", DS.PatientName
try:
# do something with dataset. For instance, store it.
file_meta = Dataset()
file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2'
# !! Need valid UID here
file_meta.MediaStorageSOPInstanceUID = "1.2.3"
# !!! Need valid UIDs here
file_meta.ImplementationClassUID = "1.2.3.4"
filename = '%s/%s.dcm' % (tempfile.gettempdir(), DS.SOPInstanceUID)
ds = FileDataset(filename, {},
file_meta=file_meta, preamble="\0" * 128)
ds.update(DS)
#ds.is_little_endian = True
#ds.is_implicit_VR = True
ds.save_as(filename)
print "File %s written" % filename
except:
pass
# must return appropriate status
return SOPClass.Success
# create application entity
MyAE = AE(args.aet, args.p, [PatientRootFindSOPClass,
PatientRootMoveSOPClass,
VerificationSOPClass], [StorageSOPClass], ts)
MyAE.OnAssociateResponse = OnAssociateResponse
MyAE.OnAssociateRequest = OnAssociateRequest
MyAE.OnReceiveStore = OnReceiveStore
MyAE.start()
# remote application entity
RemoteAE = dict(Address=args.remotehost, Port=args.remoteport, AET=args.aec)
# create association with remote AE
print "Request association"
assoc = MyAE.RequestAssociation(RemoteAE)
# perform a DICOM ECHO
print "DICOM Echo ... ",
st = assoc.VerificationSOPClass.SCU(1)
print 'done with status "%s"' % st
print "DICOM FindSCU ... ",
d = Dataset()
d.PatientsName = args.searchstring
d.QueryRetrieveLevel = "PATIENT"
d.PatientID = "*"
st = assoc.PatientRootFindSOPClass.SCU(d, 1)
print 'done with status "%s"' % st
for ss in st:
if not ss[1]:
continue
# print ss[1]
try:
d.PatientID = ss[1].PatientID
except:
continue
print "Moving"
print d
assoc2 = MyAE.RequestAssociation(RemoteAE)
gen = assoc2.PatientRootMoveSOPClass.SCU(d, 'SAMTEST', 1)
for gg in gen:
print
print gg
assoc2.Release(0)
print "QWEQWE"
print "Release association"
assoc.Release(0)
# done
MyAE.Quit()
Running the program, I get the following output:
Request association
Association response received
DICOM Echo ... done with status "Success "
DICOM FindSCU ... done with status "<generator object SCU at 0x106014c30>"
Moving
(0008, 0052) Query/Retrieve Level CS: 'PATIENT'
(0010, 0010) Patient's Name PN: 'P*'
(0010, 0020) Patient ID LO: 'Pat00001563'
Association response received
QWEQWE
Moving
(0008, 0052) Query/Retrieve Level CS: 'PATIENT'
(0010, 0010) Patient's Name PN: 'P*'
(0010, 0020) Patient ID LO: 'Pat00002021'
Association response received
QWEQWE
Release association
Echo works so I know my associations are working and I am able to query and see the files on the server as suggested by the output. As you can see however, OnReceiveStore does not seem to be called. I am pretty new to DICOM and I was wondering what might be the case. Correct me if I am wrong but I think the line gen = assoc2.PatientRootMoveSOPClass.SCU(d, 'SAMTEST', 1) is supposed to invoke OnReceiveStore. If not, some insight on how C-STORE should be called is appreciated.
DICOM C-MOVE is a complicated operation, if You are not very familiar with DICOM.
You are not calling OnReceiveStore Yourself, it's called when the SCP starts sending instances to Your application. You issue a C-MOVE command to the SCP with Your own AE title, where You want to receive the images. In Your case SAMTEST. Since this is the only parameter for the C-MOVE command, then the SCP needs to be configured before-hand to know the IP and port of the SAMTEST AE. Have You done this?
I don't know, why the code is not outputting responses from the SCP to the C-MOVE command. It looks like it should. These could give a good indication, what is happening. You can also check the logs on the SCP side, to see, what's happening.
Also, here is some quite good reading about C-MOVE operation.

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.

Filtering USB HID Columns in 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.

Categories