@@ -1761,12 +1761,48 @@ def Led_all_off():
17611761
17621762
17631763#~autogen
1764- #~autogen button-class classes.button>currentClass
17651764
1766- import fcntl
1767- import array
1765+ class ButtonBase (object ):
1766+ """
1767+ Abstract button interface.
1768+ """
1769+
1770+ on_change = None
1771+
1772+ _state = set ([])
1773+
1774+ @property
1775+ def any (self ):
1776+ """
1777+ Checks if any button is pressed.
1778+ """
1779+ return bool (self .buttons_pressed )
1780+
1781+ def check_buttons (self ,buttons = []):
1782+ """
1783+ Check if currently pressed buttons exactly match the given list.
1784+ """
1785+ return set (self .buttons_pressed ) == set (buttons )
1786+
1787+ def process (self ):
1788+ """
1789+ Check for currenly pressed buttons. If the new state differs from the
1790+ old state, call the appropriate button event handlers.
1791+ """
1792+ new_state = set (self .buttons_pressed )
1793+ old_state = self ._state
1794+ self ._state = new_state
17681795
1769- class Button (object ):
1796+ state_diff = new_state .symmetric_difference (old_state )
1797+ for button in state_diff :
1798+ handler = getattr (self , 'on_' + button )
1799+ if handler is not None : handler (button in new_state )
1800+
1801+ if self .on_change is not None and state_diff :
1802+ self .on_change ([(button , button in new_state ) for button in state_diff ])
1803+
1804+ #~autogen button-class classes.button>currentClass
1805+ class Button (ButtonBase ):
17701806
17711807 """
17721808 Provides a generic button reading mechanism that can be adapted
@@ -1805,31 +1841,30 @@ def _button_buffer(self, name):
18051841 self .buffer_cache [name ] = array .array ( 'B' , [0 ] * self .KEY_BUF_LEN )
18061842 return self .buffer_cache [name ]
18071843
1808- def read_buttons (self ):
1844+ @property
1845+ def buttons_pressed (self ):
18091846 for b in self .buffer_cache :
18101847 fcntl .ioctl (self .filehandle_cache [b ], self .EVIOCGKEY , self .buffer_cache [b ])
18111848
1812- @property
1813- def buttons_pressed (self ):
18141849 pressed = []
1815- self .read_buttons ()
18161850 for k ,v in self ._buttons .items ():
18171851 buf = self .buffer_cache [v ['name' ]]
18181852 bit = v ['value' ]
18191853 if not bool (buf [int (bit / 8 )] & 1 << bit % 8 ):
18201854 pressed += [k ]
18211855 return pressed
18221856
1823- @property
1824- def any (self ):
1825- return bool (self .buttons_pressed )
1826-
1827- def check_buttons (self ,buttons = []):
1828- return set (self .buttons_pressed ) == set (buttons )
1829-
18301857 if current_platform () == 'ev3' :
18311858#~autogen button-property platforms.ev3.button>currentClass
1832- _buttons = {
1859+
1860+ on_up = None
1861+ on_down = None
1862+ on_left = None
1863+ on_right = None
1864+ on_enter = None
1865+ on_backspace = None
1866+
1867+ _buttons = {
18331868 'up' : { 'name' : '/dev/input/by-path/platform-gpio-keys.0-event' , 'value' : 103 },
18341869 'down' : { 'name' : '/dev/input/by-path/platform-gpio-keys.0-event' , 'value' : 108 },
18351870 'left' : { 'name' : '/dev/input/by-path/platform-gpio-keys.0-event' , 'value' : 105 },
@@ -1864,6 +1899,97 @@ def backspace(self):
18641899
18651900
18661901#~autogen
1902+
1903+ #~autogen remote-control classes.infraredSensor.remoteControl>currentClass
1904+ class RemoteControl (ButtonBase ):
1905+ """
1906+ EV3 Remote Controller
1907+ """
1908+
1909+ _BUTTON_VALUES = {
1910+ 0 : [],
1911+ 1 : ['red_up' ],
1912+ 2 : ['red_down' ],
1913+ 3 : ['blue_up' ],
1914+ 4 : ['blue_down' ],
1915+ 5 : ['red_up' , 'blue_up' ],
1916+ 6 : ['red_up' , 'blue_down' ],
1917+ 7 : ['red_down' , 'blue_up' ],
1918+ 8 : ['red_down' , 'blue_down' ],
1919+ 9 : ['beacon' ],
1920+ 10 : ['red_up' , 'red_down' ],
1921+ 11 : ['blue_up' , 'blue_down' ]
1922+ }
1923+
1924+ on_red_up = None
1925+ on_red_down = None
1926+ on_blue_up = None
1927+ on_blue_down = None
1928+ on_beacon = None
1929+
1930+
1931+ @property
1932+ def red_up (self ):
1933+ """
1934+ Checks if `red_up` button is pressed.
1935+ """
1936+ return 'red_up' in self .buttons_pressed
1937+
1938+
1939+ @property
1940+ def red_down (self ):
1941+ """
1942+ Checks if `red_down` button is pressed.
1943+ """
1944+ return 'red_down' in self .buttons_pressed
1945+
1946+
1947+ @property
1948+ def blue_up (self ):
1949+ """
1950+ Checks if `blue_up` button is pressed.
1951+ """
1952+ return 'blue_up' in self .buttons_pressed
1953+
1954+
1955+ @property
1956+ def blue_down (self ):
1957+ """
1958+ Checks if `blue_down` button is pressed.
1959+ """
1960+ return 'blue_down' in self .buttons_pressed
1961+
1962+
1963+ @property
1964+ def beacon (self ):
1965+ """
1966+ Checks if `beacon` button is pressed.
1967+ """
1968+ return 'beacon' in self .buttons_pressed
1969+
1970+
1971+
1972+ #~autogen
1973+
1974+ def __init__ (self , sensor = None , channel = 1 ):
1975+ if sensor is None :
1976+ self ._sensor = InfraredSensor ()
1977+ else :
1978+ self ._sensor = sensor
1979+
1980+ self ._channel = max (1 , min (4 , channel )) - 1
1981+ self ._state = set ([])
1982+
1983+ if self ._sensor .connected :
1984+ self ._sensor .mode = 'IR-REMOTE'
1985+
1986+ @property
1987+ def buttons_pressed (self ):
1988+ """
1989+ Returns list of currently pressed buttons.
1990+ """
1991+ return RemoteControl ._BUTTON_VALUES .get (self ._sensor .value (self ._channel ), [])
1992+
18671993#~autogen generic-class classes.powerSupply>currentClass
18681994
18691995class PowerSupply (Device ):
@@ -2255,10 +2381,10 @@ def clear(self):
22552381 self ._draw .rectangle (((0 ,0 ), self .shape ), fill = "white" )
22562382
22572383 def _color565 (self , r , g , b ):
2258- """Convert red, green, blue components to a 16-bit 565 RGB value. Components
2259- should be values 0 to 255.
2260- """
2261- return (((r & 0xF8 ) << 8 ) | ((g & 0xFC ) << 3 ) | (b >> 3 ))
2384+ """Convert red, green, blue components to a 16-bit 565 RGB value. Components
2385+ should be values 0 to 255.
2386+ """
2387+ return (((r & 0xF8 ) << 8 ) | ((g & 0xFC ) << 3 ) | (b >> 3 ))
22622388
22632389 def _img_to_rgb565_bytes (self ):
22642390 pixels = [self ._color565 (r ,g ,b ) for (r ,g ,b ) in self ._img .getdata ()]
@@ -2275,3 +2401,4 @@ def update(self):
22752401 self .mmap [:] = self ._img_to_rgb565_bytes ()
22762402 else :
22772403 raise Exception ("Not supported" )
2404+
0 commit comments