Receiving data from HID game controller in Python - python

I am trying to communicate with a game controller Human Interface Device (HID) with a Python script, but I'm having trouble receiving data from the controller. I am using pywinusb 0.3.2 and Python 3.3. The game controller is a Logitech Gamepad F310.Link Here to pywinusb.
I have been able to get python to recognize the HID, but I am stuck as on where to go from there. My code for recognizing the controller is:
import pywinusb.hid as hid
target = hid.HidDeviceFilter(vendor_id = target_vendor_id, product_id = target_product_id)
allitems = target.get_devices()
device = allitems[0]
print(device)
This code returns something like this: HID device (vID=0x00a, pID=0xa000, v=0x0000); Logitech; Logitech Dual Action, Path: \(numbers and letters in a long sequence here)
I'm not sure if the approach here would work with a controller, or whether there is another library that is preferable to pywinusb. If I have to switch libraries, I would prefer to switch to one that is cross platform. The small amount of documentation in the examples section included was not enough for me to figure this out with.
My question is: How do I receive the data from the controller? Is there a command? I've worked with the Arduino a little bit and hooking it up to a Wii Nunchuk was a similar process. Will I have to be sending initialization sequences, similar to the Arduino? I need to know the x and y values of both sticks on the controller as well as whether the buttons are pressed.
My apologies if this is obvious or has already been answered. I have never worked with an HID in python before.

Take a look to how HID usages work (google around).
Use the show_hids.py example script to review if the device exposes standard usages.
If not, your only hope is to use raw reports handlers (check the example folders from the source, I recommend you to work with github's code).

Related

How does a program distinguish between real key presses and those sent by pyautogui, pywinauto etc.?

I've been trying to write a script that sends specific key presses to the game, however they just get "ignored", while the script can send the exact same key presses to any other window without a problem. I'm using WIN 10 x64, python 3.9 and pyautogui and pywinatuo.
Is there an easy way around this? Please consider my inexperience with coding when answering.
I had a similar problem and ended up sending the desired keystroke out to a serial port, using the 'serial' module the writing some code on a 'pro micro' using an arduino ide which would accept any character coming in on the serial port and would then output said character or string to a the usb. The neat thing about the pro micro is the serial port and the usb can be same physical connection. While I had to make exceptions for some special characters like \r and \n it works quite well. Where my application that would not recognize keyboard or mouse inputs from pyautogui or pywinauto, it now does recognize them when coming from the usb as it looks like any other piece of hardware. If you are interested I will send/post the code for the pro micro and some examples of how I used it.
For normal GUI apps there is no easy way to distinguish real clicks vs pywinauto's ones. If you set monitoring keyboard/mouse hooks, there is no such info in HOOK structures. So the answer is no.

Python Wifi Issue Connect to Mysterious Camera

I have been working with some drones and robotics projects using arduino and python. There was a kickstarter project for a neat little hex copter, that hasn't been managed well.
I was lucky, i got my copter and then some time later after some frustrated email exchanges, i finally recieved the camera as well. To this day, their forum has people still complaining. Their maker forum is now down and their wiki hasn't been updated with any specifics on the camera.
http://www.flexbot.cc/wiki/index.php?title=Main_Page#Hardware
Their app to accompany the drone still doesn't support the camera module. Not that it'd matter, as their code isn't very well documented or annotated.
https://github.com/HexAirbot
There are some tips on switching the camera on the comments page of their kickstarter campaign.
https://www.kickstarter.com/projects/1387330585/hex-a-copter-that-anyone-can-fly/posts/1093716
So, sob story over, i'm stuck with this neat little wifi camera that i am unsure on how to connect to. I know how to switch it on and it does have a micro-usb port on it.
What library in Python could i use to stream an image from this camera given that it is a wifi camera. If i wanted the video stream as a numpy matrix.
I need to interface with the camera, so i can connect and disconnect.
Then, be able to read images frame by frame with ffmpeg. I have some python modules that can detect and read from a camera, but how can my code ensure that the camera is connected?
Totally stuck. Any help would be appreciated.
Considering you are building for the android platform, you will more than likely need to use some sort of java/python driver/interface, unless you just use java.
Here is an article on java/python, and using python from within java.
Using Python from within Java

Duplicate device input events on unix (/dev/input/event)

I'm using linux/ubuntu, and I would like to play a little bit with my touchpad. I'm trying to use python-evdev to read events from /dev/input/events, for now just printing them:
import evdev
dev = evdev.InputDevice('/dev/input/event6')
import time
while True:
try:
for event in dev.read():
print event
except:
print " ~ "
time.sleep(.5)
If I do run that script in with root privilege in a virtual console (outside X, pressing ctrl+alt+F1), the script does print events when I touch the touchpad. Yet, if X is on screen and I run this in a gnome-terminal console, nothing is printed; I somehow guess this is normal, the inputs are intercepted by X. Yet I would like to get them anyway. Is there a way to duplicate whatever comes from /dev/input/event6 so thqt both X and my script can read all events ?
sorry, a bit late on the answer here.
Up until version 1.8, the xorg synaptics driver used the EVIOCGRAB ioctl to prevent events to be delivered to other clients. That's disabled now by default, you can still use the GrabEventDevice option to disable it on your machine for older versions (see man synaptics).
In short, nothing wrong with your script, it's the synaptics driver that's the problem here. You'll find that your script will work on other devices just fine (though the xorg wacom driver did also grab the device until recently).
upstream commit in synaptics:
http://cgit.freedesktop.org/xorg/driver/xf86-input-synaptics/commit/?id=f1948e08ee9894864254a18098e4f4fceb6e322f
So, your idea is, X got the data from your touchpad, so that your python code is blocked from receiving touchpad signal, right? Or, may I repeat your words as: at least for some specific kind of device, an application can't get /dev/input/event*, when another is reading from that device?
Theoritically, since linux make all devices as a file, you are accessing a file as read-only, while X is also read-only accessing the file.
I just did another experiment as: I have a infrared reciver on my archlinux, and I connected to the system in two ssh consoles. I use two ways to access IR, that is, two applications to read the file of /dev/input/event0 (event0 is the SF on my arch):
1, a piece of python code, with evdev;
2, a shell command as: sudo cat /dev/input/event0 | hexdump
You can look on the 2nd as working as your X. If you were reasoning correctly, they both should not receive data from the IR (event0) on the same time, when I sending signal from a IR remote controller, right? But, I really got date on the two ssh consoles(I wish I could post image, but I am new with too low reputation to do so).
So, I think it should not be the reason. I guess it might be because of your touchpad itself. You know, some devices can only work on a single application. e.g., keyboard can only enter characters on the active application, and some input method just make itself as active over other applications, and redirect after it processed. Also, say, if you had a VM running on your system, and you use only one mouse, what would happen if you are moving pointer on the host desktop? Will the pointer in VM move? Or vice versa?
So I need more info about your touchpad. If your TP works only with a single active applicatio, I am afraid you need somethink like a hook to get touchpad signal ahead of X, and redirec it to X and your python code, which might be beyond evdev.
You could create a kernel input handler based on evdev so that the device input is distributed both to the normal /dev/input/eventN and, let's say, /dev/input/copied_eventN
X would read from /dev/input/eventN but you would still be able to read from /dev/input/copied_eventN
Actually you could very easily create a kernel module by copy-pasting the code in drivers/input/evdev.c

PS3 controller driver -> uinput-> python? somehow?

I'm trying to read from a PS3 controller in python on Ubuntu and I'm not having much luck. I started with the ps3joy driver from Willow Garage (http://www.ros.org/wiki/ps3joy) which supposedly publishes all the important bits of the PS3 controller to something I had never heard of called "uinput". Apparently it's a linux feature that allows userspace drivers to provide system events. ...Why the WG driver requires root access given that it's supposedly a userspace driver is beyond me, but that's not my question.
Anyway, the current state of me trying to get it to work is that I've got the driver working, and I've verified that it responds to button presses on the controller, but I don't know how to pull any of that data out so I can use it.
My first guess was to use pygame to (hopefully) read from /dev/uinput (which I'm pretty sure is where the driver sends the data):
from pygame import joystick
if not joystick.get_init():
joystick.init()
js = joystick.Joystick(0) # there is only one joystick... even if the driver isn't running(!)
js.init()
print js.get_numbuttons() # perhaps coincidentally correctly prints 17 which is the number of buttons on a PS3 controller
for i in range(js.get_numaxes()):
print js.get_axis(i) # always prints 0, no matter what I'm doing with the controller
but it didn't work. The most telling part of the problem is that it does the same thing if I don't have the WG driver running at all.
I'm sure this is something easy, that I'm just not reading the right information, but googling has not helped me find what the right information is and I'm getting tired and desperate.
You don't need the driver. Assuming the controller exposes itself as a HID, you can use the event subsystem to read controller events directly from the device.
I know it's too late, but if anyone will ever need the code or is struggling with it, you can use mine. I've wrote a script in python that gets ps3 data from USB and sends it to specific a MAC address via PC's bluetooth (you can use ps3controller.py only for data).
This was made for my quadcopter project.
https://github.com/urbanzrim/ps3controller
Try
pygame.event.pump()
before you read the joystick. I needed it to work with the 360 controller
I believe you need the following at the very least:
from pygame import joystick, event, display
display.init()
joystick.init()
js=joystick.Joystick(0)
js.init()
...
for foo in bar:
event.pump()
...
if foo:
event.pump()
...
while bar:
event.pump()
...
I believe that display.init() has to be there because it is needed for event handling...
Also, you can skip a lot of that with
import pygame
pygame.init()
js=pygame.joystick.Joystick(0)
js.init()
...
for foo in bar:
pygame.event.pump()
...
if foo:
pygame.event.pump()
...
while bar:
pygame.event.pump()
....
I could be wrong, but I think your issues are:
A) No event.pump in your if/while/for clauses
B) No display.init()
Sources:
http://webcache.googleusercontent.com/search?q=cache:I56GyE7I4CkJ:iamtherockstar.com/archive/making-hid-devices-easier-using-pygame-joysticks/+&cd=1&hl=en&ct=clnk&gl=us
and
http://www.pygame.org/docs/ref/event.html
"The input queue is heavily dependent on the pygame display module."
Solving similar problem right now: communicate/receive data from PS3 bluetooth remote with python in GNU/Linux.
What i found helpful:
Debugging PS3 Controller http://www.pabr.org/sixlinux/sixlinux.en.html
Looks like working project, for PS3 Remote http://kitlaan.twinaxis.com/projects/bluez-ps3remote/ (it requires to patch bluez 1st) did not tested, yet.
pybluez BT wrapper http://code.google.com/p/pybluez/ (checking it right now)

Media Play/Pause Simulation

My keyboard contains a row of buttons for various non-standard keyboard tasks. These keys contain such functions as modifying the volume, playing or pausing, and skipping tracks. How can I simulate a basic play/pause with Python? I am on Windows, by the way.
I would use pywin32. Bundled with the installation is a large number of API-docs (usually placed at something like C:\Python32\Lib\site-packages.) It essentially wraps a lot of stuff in the Win32-library which is used for many low-levels tasks in Windows.
After installing it you could use the wrapper for keybd_event.
You could also use SendInput instead of keybd_event but it doesn't seem to be wrapped by PyWin32. SendMessage is also an option but more cumbersome.
You'll need to look up the virtual scan code for those special buttons, since I doubt the char-to-code mapping functions will help you here. You can find the reference here.
Then it is a simple matter of calling the function. The snippet below pauses Chuck Berry on my computer.
>>> import win32api
>>> VK_MEDIA_PLAY_PAUSE = 0xB3
>>> hwcode = win32api.MapVirtualKey(VK_MEDIA_PLAY_PAUSE, 0)
>>> hwcode
34
>>> win32api.keybd_event(VK_MEDIA_PLAY_PAUSE, hwcode)
MapVirtualKey gives us the hardware scan code which keybd_event needs (or more likely, the keyboard driver.)
Note that all this is snapped up by the keyboard driver, so you don't really have any control where the keystrokes are sent. With SendMessage you can send them to a specific window. It usually doesn't matter with media keys since those are intercepted by music players and such.
This was not working for me on Windows 10 64, all recent updates installed. I needed this (the 3rd parameter 2) before it'd work.
win32api.keybd_event(0xB3,0,2,0)
didn't bother looking into why it works, but threw it out there since this and other similar posts had me frustrated as for some reason not working on my PC.
This successfully paused/played Amazon Music on my PC.
You can use pyautogui. This library contains a lot of keyboard and mouse simulations.
To install run pip install pyautogui in cmd.
In order to simulate a play/pause keypress, you should use pyautogui.press("playpause").
Check out their docs at https://pyautogui.readthedocs.io/en/latest/keyboard.html to see the list of the supported keys and some other keyboard functions.

Categories

Resources