Verison 1.0.3 Release
Based on Buildbotics 0.4.14
This commit is contained in:
218
src/py/inevent/EventStream.py
Normal file
218
src/py/inevent/EventStream.py
Normal file
@@ -0,0 +1,218 @@
|
||||
################################################################################
|
||||
# #
|
||||
# This file is part of the Buildbotics firmware. #
|
||||
# #
|
||||
# Copyright (c) 2015 - 2018, Buildbotics LLC #
|
||||
# All rights reserved. #
|
||||
# #
|
||||
# This file ("the software") is free software: you can redistribute it #
|
||||
# and/or modify it under the terms of the GNU General Public License, #
|
||||
# version 2 as published by the Free Software Foundation. You should #
|
||||
# have received a copy of the GNU General Public License, version 2 #
|
||||
# along with the software. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# The software is distributed in the hope that it will be useful, but #
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
|
||||
# Lesser General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU Lesser General Public #
|
||||
# License along with the software. If not, see #
|
||||
# <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
# For information regarding this software email: #
|
||||
# "Joseph Coffland" <joseph@buildbotics.com> #
|
||||
# #
|
||||
################################################################################
|
||||
|
||||
# The inevent Python module was adapted from pi3d.event from the pi3d
|
||||
# project.
|
||||
#
|
||||
# Copyright (c) 2016, Joseph Coffland, Cauldron Development LLC.
|
||||
# Copyright (c) 2015, Tim Skillman.
|
||||
# Copyright (c) 2015, Paddy Gaunt.
|
||||
# Copyright (c) 2015, Tom Ritchford.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person
|
||||
# obtaining a copy of this software and associated documentation files
|
||||
# (the "Software"), to deal in the Software without restriction,
|
||||
# including without limitation the rights to use, copy, modify, merge,
|
||||
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
# and to permit persons to whom the Software is furnished to do so,
|
||||
# subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import fcntl
|
||||
import os
|
||||
import select
|
||||
import logging
|
||||
|
||||
from inevent.Constants import *
|
||||
from inevent import ioctl
|
||||
from inevent.AbsAxisScaling import AbsAxisScaling
|
||||
from inevent import Event
|
||||
from inevent.EventState import EventState
|
||||
|
||||
|
||||
log = logging.getLogger('inevent')
|
||||
|
||||
EVIOCGRAB = ioctl._IOW(ord('E'), 0x90, "i") # Grab/Release device
|
||||
|
||||
|
||||
|
||||
class EventStream(object):
|
||||
"""
|
||||
encapsulates the event* file handling
|
||||
|
||||
Each device is represented by a file in /dev/input called eventN, where N is
|
||||
a small number. (Actually, a keybaord can be represented by two such files.)
|
||||
Instances of this class open one of these files and provide means to read
|
||||
events from them.
|
||||
|
||||
Class methods also exist to read from multiple files simultaneously, and
|
||||
also to grab and ungrab all instances of a given type.
|
||||
"""
|
||||
axisX = 0
|
||||
axisY = 1
|
||||
axisZ = 2
|
||||
axisRX = 3
|
||||
axisRY = 4
|
||||
axisRZ = 5
|
||||
axisHat0X = 6
|
||||
axisHat0Y = 7
|
||||
axisHat1X = 8
|
||||
axisHat1Y = 9
|
||||
axisHat2X = 10
|
||||
axisHat2Y = 11
|
||||
axisHat3X = 12
|
||||
axisHat3Y = 13
|
||||
axisThrottle = 14
|
||||
axisRudder = 15
|
||||
axisWheel = 16
|
||||
axisGas = 17
|
||||
axisBrake = 18
|
||||
axisPressure = 19
|
||||
axisDistance = 20
|
||||
axisTiltX = 21
|
||||
axisTiltY = 22
|
||||
axisToolWidth = 23
|
||||
numAxes = 24
|
||||
|
||||
axisToEvent = [
|
||||
ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ, ABS_HAT0X, ABS_HAT0Y,
|
||||
ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y, ABS_HAT3X, ABS_HAT3Y,
|
||||
ABS_THROTTLE, ABS_RUDDER, ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_PRESSURE,
|
||||
ABS_DISTANCE, ABS_TILT_X, ABS_TILT_Y, ABS_TOOL_WIDTH]
|
||||
|
||||
|
||||
def __init__(self, devIndex, devType, devName):
|
||||
"""
|
||||
Opens the given /dev/input/event file and grabs it.
|
||||
|
||||
Also adds it to a class-global list of all existing streams.
|
||||
"""
|
||||
self.devIndex = devIndex
|
||||
self.devType = devType
|
||||
self.devName = devName
|
||||
self.filename = "/dev/input/event" + str(devIndex)
|
||||
self.filehandle = os.open(self.filename, os.O_RDWR)
|
||||
self.state = EventState()
|
||||
self.grab(True)
|
||||
self.absInfo = [None] * ABS_MAX
|
||||
|
||||
if devType == "js":
|
||||
for axis in range(ABS_MAX):
|
||||
self.absInfo[axis] = AbsAxisScaling(self, axis)
|
||||
|
||||
|
||||
def scale(self, axis, value):
|
||||
"""
|
||||
Scale the given value according to the given axis.
|
||||
|
||||
acquire_abs_info must have been previously called to acquire the data to
|
||||
do the scaling.
|
||||
"""
|
||||
assert axis < ABS_MAX, "Axis number out of range"
|
||||
|
||||
if self.absInfo[axis]: return self.absInfo[axis].scale(value)
|
||||
else: return value
|
||||
|
||||
|
||||
def grab(self, grab = True):
|
||||
"""
|
||||
Grab (or release) exclusive access to all devices of the given type.
|
||||
|
||||
The devices are grabbed if grab is True and released if grab is False.
|
||||
|
||||
All devices are grabbed to begin with. We might want to ungrab the
|
||||
keyboard for example to use it for text entry. While not grabbed, all
|
||||
key-down and key-hold events are filtered out.
|
||||
"""
|
||||
fcntl.ioctl(self.filehandle, EVIOCGRAB, 1 if grab else 0)
|
||||
self.grabbed = grab
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
"""s
|
||||
Required to make this class an iterator
|
||||
"""
|
||||
return self
|
||||
|
||||
|
||||
def next(self): return self.__next__()
|
||||
|
||||
|
||||
def __next__(self):
|
||||
"""
|
||||
Returns the next waiting event.
|
||||
|
||||
If no event is waiting, returns None.
|
||||
"""
|
||||
ready = select.select([self.filehandle], [], [], 0)[0]
|
||||
if ready: return self.read()
|
||||
|
||||
|
||||
def read(self):
|
||||
"""
|
||||
Read and return the next waiting event.
|
||||
"""
|
||||
try:
|
||||
s = os.read(self.filehandle, Event.size)
|
||||
if s:
|
||||
event = Event.Event(self)
|
||||
event.decode(s)
|
||||
return event
|
||||
|
||||
except Exception as e:
|
||||
log.info('Reading event: %s' % e)
|
||||
|
||||
|
||||
def __enter__(self): return self
|
||||
|
||||
|
||||
def release(self):
|
||||
"Ungrabs the file and closes it."
|
||||
|
||||
try:
|
||||
self.grab(False)
|
||||
os.close(self.filehandle)
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
"Ungrabs the file and closes it."
|
||||
|
||||
self.release()
|
||||
Reference in New Issue
Block a user