Recently I described basics of asynchronous file reading with Twisted framework. Using this approach is build my twistedinput library. Now I would like describe more this library and show you basic usage.
InputEvent objects
Before we can start using twistedinput, you have to understand of basic building block of this library.
If you read previous article, you should remember, that we simply printed out length of received data. Let me quickly describe these data.
When you press button on your input device, protocol from previous article actually received couple of input_event structures. This structure is defined in linux/input.h header file.
struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value; };
Time is another structure. It is composed of two fields – seconds and microseconds. Both are 64-bit long. Type and code are unsigned 16-bit values. Value field is signed 32-bit value.
Twistedinput knows this structure and has wrapper class InputEvent for it. See the basic usage.
>>> from twistedinput.event import InputEvent >>> event = InputEvent.buildInputEvent(1, 2, 3) >>> print unicode(event) time: 1379719268.6574370, type: 0x0001, code: 0x0002, value: 0x00000003 >>> event.time.seconds 1379719268 >>> event.type 1 >>> event.code 2 >>> event.value 3
Receiving events
Now you are familiar with InputEvent class. Lets write small script, which receives event from your input device. I'm using Genius gamepad with device file located at /dev/input/event15.
from twistedinput.device import EventDevice from twistedinput.protocol import EventProtocol from twistedinput.factory import InputEventFactory from twisted.internet import reactor import sys class GamepadProtocol(EventProtocol): def eventReceived(self, event): print unicode(event) gamepad = EventDevice( GamepadProtocol(InputEventFactory()), sys.argv[1]) gamepad.startReading() reactor.run()
Twistedinput has protocol for receiving events. Is simply receive data from input device and save them in buffer. When it has enough data for creating an event, it use factory (given as first argument) for building it and calls eventReceived method.
When I run this script and press and release buttons 1, 2, 3 and 4 respectively, I get following output
buben@debian:~$ python gamepad.py /dev/input/event15 time: 1379976614.640730, type: 0x0004, code: 0x0004, value: 0x00090001 time: 1379976614.640733, type: 0x0001, code: 0x0120, value: 0x00000001 time: 1379976614.640781, type: 0x0000, code: 0x0000, value: 0x00000000 time: 1379976614.712725, type: 0x0004, code: 0x0004, value: 0x00090001 time: 1379976614.712730, type: 0x0001, code: 0x0120, value: 0x00000000 time: 1379976614.712774, type: 0x0000, code: 0x0000, value: 0x00000000 time: 1379976614.888736, type: 0x0004, code: 0x0004, value: 0x00090002 time: 1379976614.888741, type: 0x0001, code: 0x0121, value: 0x00000001 time: 1379976614.888786, type: 0x0000, code: 0x0000, value: 0x00000000 time: 1379976614.944742, type: 0x0004, code: 0x0004, value: 0x00090002 time: 1379976614.944747, type: 0x0001, code: 0x0121, value: 0x00000000 time: 1379976614.944790, type: 0x0000, code: 0x0000, value: 0x00000000 time: 1379976615.192746, type: 0x0004, code: 0x0004, value: 0x00090003 time: 1379976615.192752, type: 0x0001, code: 0x0122, value: 0x00000001 time: 1379976615.192792, type: 0x0000, code: 0x0000, value: 0x00000000 time: 1379976615.272742, type: 0x0004, code: 0x0004, value: 0x00090003 time: 1379976615.272747, type: 0x0001, code: 0x0122, value: 0x00000000 time: 1379976615.272788, type: 0x0000, code: 0x0000, value: 0x00000000 time: 1379976615.632773, type: 0x0004, code: 0x0004, value: 0x00090004 time: 1379976615.632778, type: 0x0001, code: 0x0123, value: 0x00000001 time: 1379976615.632815, type: 0x0000, code: 0x0000, value: 0x00000000 time: 1379976615.712743, type: 0x0004, code: 0x0004, value: 0x00090004 time: 1379976615.712746, type: 0x0001, code: 0x0123, value: 0x00000000 time: 1379976615.712768, type: 0x0000, code: 0x0000, value: 0x00000000
There are 24 events in total. Four buttons has been pressed and released. There are three events for each physical event. In other words, when you press a button, three events is generated. Not all buttons generate three events, some generate only two.
Let's despite first three events which belongs to button 1.
time: 1379976614.640730, type: 0x0004, code: 0x0004, value: 0x00090001 time: 1379976614.640733, type: 0x0001, code: 0x0120, value: 0x00000001 time: 1379976614.640781, type: 0x0000, code: 0x0000, value: 0x00000000
First event has type 0x4 and code 0x4. These values corresponds to symbolic names EV_MSC and MSC_SCAN in linux/input.h header file. This sort of events are not important to us for now.
The second one has type 0x1 and code 0x120. Symbolic names are EV_KEY and BTN_TRIGGER. So type telling us that some button has been pressed. Code describing which button has been pressed. And finally value is value of this button. This is the most important event for us.
The last one is synchronization event. It is used as event separator. We can ignore it too.
Using Mapping
Now we can handle events in one eventReceived method. It's fine if you are interested in for few event types. But what if you are writing driver for keyboard. Your eventReceived should be composed from very long list of elif statemets for handling all different key. That's not good idea. In this case event mapping comes for your rescue.
Event mapping maps event into their handle routines. Everything what you have to do is implement only those routines, which you are interested in.
Instance of mapping is second optional argument for EventProtocol. If omnited, you have to override eventReceived method. If you provide mapping, simply implement methods defined by mapping and only those, which are interesting for you. Let's look at following example.
from twistedinput.device import EventDevice from twistedinput.protocol import EventProtocol from twistedinput.factory import InputEventFactory from twistedinput.mapping import GamepadEventMapping from twisted.internet import reactor import sys class GamepadProtocol(EventProtocol): def button1(self, event): print "button 1:", event.value def button2(self, event): print "button 2:", event.value def button3(self, event): print "button 3:", event.value def button4(self, event): print "button 4:", event.value def nonMappedEvent(self, event): print "not supported event:", unicode(event) gamepad = EventDevice( GamepadProtocol( InputEventFactory(), GamepadEventMapping()), sys.argv[1]) gamepad.startReading() reactor.run()
Lets run this script and see its output
buben@debian:~$ python gamepad.py /dev/input/event15 button 1: 1 button 1: 0 button 2: 1 button 2: 0 button 3: 1 button 3: 0 button 4: 1 button 4: 0
This is much better. If you don't implement method defined by mapping, nothing happened. If mapping doesn't map some event, nonMappedEvent method is called with this event as an argument.
Žádné komentáře:
Okomentovat