Reading USB camera button press event - python

This is simple USB camera with a snapshot button.
When the device is plugged into a USB port, I get this information from "cat /proc/bus/input/devices" on the host running Armbian Ubuntu 16.04.3:
I: Bus=0003 Vendor=eb1a Product=2580 Version=0415
N: Name="UVC Camera (eb1a:2580)"
P: Phys=usb-sunxi-ehci-1/button
S: Sysfs=/devices/platform/sunxi-ehci.2/usb2/2-1/2-1:1.0/input/input2
U: Uniq=
H: Handlers=kbd event2
B: PROP=0
B: EV=3
B: KEY=100000 0 0 0 0 0 0
That lead me to try the input device /dev/input/event2 -- but all my effort using python-usb and python-evdev (with sample code found here on StackOverflow) have so far failed to receive any input event when the button is pressed.
Your insights are very much appreciated!

try to follow any step on http://python-evdev.readthedocs.io/en/latest/tutorial.html
Listing accessible event devices
import evdev
devices = [evdev.InputDevice(fn) for fn in evdev.list_devices()]
for device in devices:
print(device.fn, device.name, device.phys)
Listing device capabilities
import evdev
device = evdev.InputDevice('/dev/input/event0')
print(device)
.
.
.
to have all information like paths, which button is associated with which event ... from python

Related

psutil fails to run if no monitor plugged into PI

I have a raspberry pi that on reboot runs a pyudev and psutil script to look for a removable storage device. The script runs perfectly fine if there is a monitor plugged in. But as soon as I unplug the screen and reboot the PI, it doesn't load the psutil. I can't even find what the error is as the error output is:
>#>#>#>#>#>#>#>#>#>#>#
Here is my script:
def checkstorage():
context = pyudev.Context()
removable = [device for device in context.list_devices(subsystem='block', DEVTYPE='disk') if device.attributes.asstring('removable') == "1"]
for device in removable:
partitions = [device.device_node for device in context.list_devices(subsystem='block', DEVTYPE='partition', parent=device)]
print("All removable partitions: {}".format(", ".join(partitions)))
print("Mounted removable partitions:")
for p in psutil.disk_partitions():
if p.device in partitions:
print(" {}: {}".format(p.device, p.mountpoint))
if p.device == "/dev/sda1":
path = p.mountpoint
else:
path = 0
return path, True
It fails by:
for p in psutil.disk_partitions()
If there is no HDMI screen plugged in
The issue was that as soon as the monitor was unplugged the PI acted like a headless PI. This intern caused psutil to fail as there was no partition associated with the usb. I fixed this by manually mounting the usb to a specific path I chose.

Get RSSI of non connected bluetooth device

I am currently using raspberry pi and want to get RSSI of a non-connected Bluetooth address.
I am using
import bluetooth
result=bluetooth.lookup_name('XX:XX:XX:XX:XX:XX',timeout=5)
if(result !=None):
print("user near")
else:
print("user far")
but I want to be a little more precise and go to the else block in a closer distance and hence I need an RSSI value. Please help. I am new with raspberry and Python.
(I am working in python3)
Getting the RSSI value on a Raspberry Pi is supported by the BlueZ device API.
In the example below I have used pydbus as the library to access BlueZ's D-Bus API. This example scans for 60 seconds and writes the device address and RSSI value to a file. You could modify the code to take an action when a particular address and RSSI value is found.
from datetime import datetime
from pathlib import Path
import pydbus
from gi.repository import GLib
discovery_time = 60
log_file = Path('/home/pi/device.log')
def write_to_log(address, rssi):
"""Write device and rssi values to a log file"""
now = datetime.now()
current_time = now.strftime('%H:%M:%S')
with log_file.open('a') as dev_log:
dev_log.write(f'Device seen[{current_time}]: {address} # {rssi} dBm\n')
bus = pydbus.SystemBus()
mainloop = GLib.MainLoop()
class DeviceMonitor:
"""Class to represent remote bluetooth devices discovered"""
def __init__(self, path_obj):
self.device = bus.get('org.bluez', path_obj)
self.device.onPropertiesChanged = self.prop_changed
rssi = self.device.GetAll('org.bluez.Device1').get('RSSI')
if rssi:
print(f'Device added to monitor {self.device.Address} # {rssi} dBm')
else:
print(f'Device added to monitor {self.device.Address}')
def prop_changed(self, iface, props_changed, props_removed):
"""method to be called when a property value on a device changes"""
rssi = props_changed.get('RSSI', None)
if rssi is not None:
print(f'\tDevice Seen: {self.device.Address} # {rssi} dBm')
write_to_log(self.device.Address, rssi)
def end_discovery():
"""method called at the end of discovery scan"""
mainloop.quit()
adapter.StopDiscovery()
def new_iface(path, iface_props):
"""If a new dbus interfaces is a device, add it to be monitored"""
device_addr = iface_props.get('org.bluez.Device1', {}).get('Address')
if device_addr:
DeviceMonitor(path)
# BlueZ object manager
mngr = bus.get('org.bluez', '/')
mngr.onInterfacesAdded = new_iface
# Connect to the DBus api for the Bluetooth adapter
adapter = bus.get('org.bluez', '/org/bluez/hci0')
adapter.DuplicateData = False
# Iterate around already known devices and add to monitor
print('Adding already known device to monitor...')
mng_objs = mngr.GetManagedObjects()
for path in mng_objs:
device = mng_objs[path].get('org.bluez.Device1', {}).get('Address', [])
if device:
DeviceMonitor(path)
# Run discovery for discovery_time
adapter.StartDiscovery()
GLib.timeout_add_seconds(discovery_time, end_discovery)
print('Finding nearby devices...')
try:
mainloop.run()
except KeyboardInterrupt:
end_discovery()
If you need to install the gi.repository library then follow the "Installing the system provided PyGObject" for Debian instructions at: https://pygobject.readthedocs.io/en/latest/getting_started.html#ubuntu-getting-started
Bluepy library looks beneficial for RaspberryPI. Dont forget you should run like
"sudo python3 name.py" from terminal.
For more info: https://github.com/IanHarvey/bluepy/tree/master/docs
from bluepy.btle import Scanner
while True:
try:
#10.0 sec scanning
ble_list = Scanner().scan(10.0)
for dev in ble_list:
print("rssi: {} ; mac: {}".format(dev.rssi,dev.addr))
except:
raise Exception("Error occured")

Turtlebot subscriber pointcloud2 shows color in Gazebo simulator but not in robot

I am subscribing to topic "/camera/depth/points" and message PointCloud2 on a turtlebot (deep learning version) with ASUS Xtion PRO LIVE camera.
I have used the python script below under the gazebo simulator environment and i can receive x, y, z and rgb values successfully.
However, when i run it in the robot, the rgb values are missing.
Is this a problem of my turtlebot version, or camera or is it that i have to specify somewhere that i want to receive PointCloud2 type="XYZRGB"? or is it a sync problem? Any clues please thanks!
#!/usr/bin/env python
import rospy
import struct
import ctypes
import sensor_msgs.point_cloud2 as pc2
from sensor_msgs.msg import PointCloud2
file = open('workfile.txt', 'w')
def callback(msg):
data_out = pc2.read_points(msg, skip_nans=True)
loop = True
while loop:
try:
int_data = next(data_out)
s = struct.pack('>f' ,int_data[3])
i = struct.unpack('>l',s)[0]
pack = ctypes.c_uint32(i).value
r = (pack & 0x00FF0000)>> 16
g = (pack & 0x0000FF00)>> 8
b = (pack & 0x000000FF)
file.write(str(int_data[0])+","+str(int_data[1])+","+str(int_data[2])+","+str(r)+","+str(g)+","+str(b)+"\n")
except Exception as e:
rospy.loginfo(e.message)
loop = False
file.flush
file.close
def listener():
rospy.init_node('writeCloudsToFile', anonymous=True)
rospy.Subscriber("/camera/depth/points", PointCloud2, callback)
rospy.spin()
if __name__ == '__main__':
listener()
The contents of Published topics are determined by the software that provides them - i.e. the drivers for your camera. To fix this you therefore need to get the right driver and use the topic that it says contains the required information.
You can find recommended drivers for your cameras on the ROS wiki or on some community websites - like this. In your case, the ASUS devices should use openni2 and set depth_registration:=true - as documented here.
At this point, /camera/depth_registered/points should now show the combined xyz and RGB point cloud. To use it, your new listener() code should look something like this:
def listener():
rospy.init_node('writeCloudsToFile', anonymous=True)
# Note the change to the topic name
rospy.Subscriber("/camera/depth_registered/points", PointCloud2, callback)
rospy.spin()

Finding Bluetooth low energy with python

Is it possible for this code to be modified to include Bluetooth Low Energy devices as well? https://code.google.com/p/pybluez/source/browse/trunk/examples/advanced/inquiry-with-rssi.py?r=1
I can find devices like my phone and other bluetooth 4.0 devices, but not any BLE. If this cannot be modified, is it possible to run the hcitool lescan and pull the data from hci dump within python? I can use the tools to see the devices I am looking for and it gives an RSSI in hcidump, which is what my end goal is. To get a MAC address and RSSI from the BLE device.
Thanks!
As I said in the comment, that library won't work with BLE.
Here's some example code to do a simple BLE scan:
import sys
import os
import struct
from ctypes import (CDLL, get_errno)
from ctypes.util import find_library
from socket import (
socket,
AF_BLUETOOTH,
SOCK_RAW,
BTPROTO_HCI,
SOL_HCI,
HCI_FILTER,
)
if not os.geteuid() == 0:
sys.exit("script only works as root")
btlib = find_library("bluetooth")
if not btlib:
raise Exception(
"Can't find required bluetooth libraries"
" (need to install bluez)"
)
bluez = CDLL(btlib, use_errno=True)
dev_id = bluez.hci_get_route(None)
sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)
sock.bind((dev_id,))
err = bluez.hci_le_set_scan_parameters(sock.fileno(), 0, 0x10, 0x10, 0, 0, 1000);
if err < 0:
raise Exception("Set scan parameters failed")
# occurs when scanning is still enabled from previous call
# allows LE advertising events
hci_filter = struct.pack(
"<IQH",
0x00000010,
0x4000000000000000,
0
)
sock.setsockopt(SOL_HCI, HCI_FILTER, hci_filter)
err = bluez.hci_le_set_scan_enable(
sock.fileno(),
1, # 1 - turn on; 0 - turn off
0, # 0-filtering disabled, 1-filter out duplicates
1000 # timeout
)
if err < 0:
errnum = get_errno()
raise Exception("{} {}".format(
errno.errorcode[errnum],
os.strerror(errnum)
))
while True:
data = sock.recv(1024)
# print bluetooth address from LE Advert. packet
print(':'.join("{0:02x}".format(x) for x in data[12:6:-1]))
I had to piece all of that together by looking at the hcitool and gatttool source code that comes with Bluez. The code is completely dependent on libbluetooth-dev so you'll have to make sure you have that installed first.
A better way would be to use dbus to make calls to bluetoothd, but I haven't had a chance to research that yet. Also, the dbus interface is limited in what you can do with a BLE connection after you make one.
EDIT:
Martin Tramšak pointed out that in Python 2 you need to change the last line to print(':'.join("{0:02x}".format(ord(x)) for x in data[12:6:-1]))
You could also try pygattlib. It can be used to discover devices, and (currently) there is a basic support for reading/writing characteristics. No RSSI for now.
You could discover using the following snippet:
from gattlib import DiscoveryService
service = DiscoveryService("hci0")
devices = service.discover(2)
DiscoveryService accepts the name of the device, and the method discover accepts a timeout (in seconds) for waiting responses. devices is a dictionary, with BL address as keys, and names as values.
pygattlib is packaged for Debian (or Ubuntu), and also available as a pip package.

python script to detect hot-plug event

I'm trying to use python to detect mouse and keyboard event, and tolerant the hot-plug action during the detection. I write this script to automatically detect the keyboard and mouse plug-ins in run-time and output all the keyboard and mouse events. I use evdev and pyudev packages to realize this function. I have my scripts mostly working, including keyboard and mouse event detection and plug-in detection. However, whenever I plug-out the mouse, many weird things happen and my script could not work properly. I have several confusions here.
(1) Whenever the mouse is plugged into the system, there are two files generated in /dev/input/ folder, including ./mouseX and ./eventX. I try to cat to see the output from both source and there are indeed differences, but I do not understand why linux will have ./mouseX even if ./eventX already exists?
(2) Whenever I unplug my mouse, the ./mouseX unplug event comes first, which I did not use in evdev, and this leads to the failure of the script because ./eventX(where I read the data in the script) is unplugged simultaneously but I could only detect ./eventX in the next round. I use a trick(variable i in my script) to bypass this issue, but even though I could successfully delete the mouse device, the select.select() begins endless input reading even though I did not type anything to the keyboard.
The script is listed below(modified based on answers from previous post), thanks beforehand for your attention!
#!/usr/bin/env python
import pyudev
from evdev import InputDevice, list_devices, categorize
from select import select
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='input')
monitor.start()
devices = map(InputDevice, list_devices())
dev_paths = []
finalizers = []
for dev in devices:
if "keyboard" in dev.name.lower():
dev_paths.append(dev.fn)
elif "mouse" in dev.name.lower():
dev_paths.append(dev.fn)
devices = map(InputDevice, dev_paths)
devices = {dev.fd : dev for dev in devices}
devices[monitor.fileno()] = monitor
count = 1
while True:
r, w, x = select(devices, [], [])
if monitor.fileno() in r:
r.remove(monitor.fileno())
for udev in iter(functools.partial(monitor.poll, 0), None):
# we're only interested in devices that have a device node
# (e.g. /dev/input/eventX)
if not udev.device_node:
break
# find the device we're interested in and add it to fds
for name in (i['NAME'] for i in udev.ancestors if 'NAME' in i):
# I used a virtual input device for this test - you
# should adapt this to your needs
if 'mouse' in name.lower() and 'event' in udev.device_node:
if udev.action == 'add':
print('Device added: %s' % udev)
dev = InputDevice(udev.device_node)
devices[dev.fd] = dev
break
if udev.action == 'remove':
print('Device removed: %s' % udev)
finalizers.append(udev.device_node)
break
for path in finalizers:
for dev in devices.keys():
if dev != monitor.fileno() and devices[dev].fn == path:
print "delete the device from list"
del devices[dev]
for i in r:
if i in devices.keys() and count != 0:
count = -1
for event in devices[i].read():
count = count + 1
print(categorize(event))
The difference between mouseX and eventX is, generally speaking, is eventX is the evdev device, whereas mouseX is the "traditional" device (which, for example, doesn't support various evdev ioctls.)
I don't know what's wrong with the code you posted, but here is a code snippet which does the right thing.
#!/usr/bin/env python
import pyudev
import evdev
import select
import sys
import functools
import errno
context = pyudev.Context()
monitor = pyudev.Monitor.from_netlink(context)
monitor.filter_by(subsystem='input')
# NB: Start monitoring BEFORE we query evdev initially, so that if
# there is a plugin after we evdev.list_devices() we'll pick it up
monitor.start()
# Modify this predicate function for whatever you want to match against
def pred(d):
return "keyboard" in d.name.lower() or "mouse" in d.name.lower()
# Populate the "active devices" map, mapping from /dev/input/eventXX to
# InputDevice
devices = {}
for d in map(evdev.InputDevice, evdev.list_devices()):
if pred(d):
print d
devices[d.fn] = d
# "Special" monitor device
devices['monitor'] = monitor
while True:
rs, _, _ = select.select(devices.values(), [], [])
# Unconditionally ping monitor; if this is spurious this
# will no-op because we pass a zero timeout. Note that
# it takes some time for udev events to get to us.
for udev in iter(functools.partial(monitor.poll, 0), None):
if not udev.device_node: break
if udev.action == 'add':
if udev.device_node not in devices:
print "Device added: %s" % udev
try:
devices[udev.device_node] = evdev.InputDevice(udev.device_node)
except IOError, e:
# udev reports MORE devices than are accessible from
# evdev; a simple way to check is see if the devinfo
# ioctl fails
if e.errno != errno.ENOTTY: raise
pass
elif udev.action == 'remove':
# NB: This code path isn't exercised very frequently,
# because select() will trigger a read immediately when file
# descriptor goes away, whereas the udev event takes some
# time to propagate to us.
if udev.device_node in devices:
print "Device removed (udev): %s" % devices[udev.device_node]
del devices[udev.device_node]
for r in rs:
# You can't read from a monitor
if r.fileno() == monitor.fileno(): continue
if r.fn not in devices: continue
# Select will immediately return an fd for read if it will
# ENODEV. So be sure to handle that.
try:
for event in r.read():
pass
print evdev.categorize(event)
except IOError, e:
if e.errno != errno.ENODEV: raise
print "Device removed: %s" % r
del devices[r.fn]

Categories