Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
TurnTouch Python Library
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Anton Sarukhanov
TurnTouch Python Library
Commits
66210139
Commit
66210139
authored
6 years ago
by
Anton Sarukhanov
Browse files
Options
Downloads
Patches
Plain Diff
Implement de-bouncing.
Fixes #2.
parent
5a22ab13
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
README.md
+2
-2
2 additions, 2 deletions
README.md
turntouch/turntouch.py
+268
-88
268 additions, 88 deletions
turntouch/turntouch.py
with
270 additions
and
90 deletions
README.md
+
2
−
2
View file @
66210139
...
@@ -60,7 +60,7 @@ class MyHandler(DefaultActionHandler):
...
@@ -60,7 +60,7 @@ class MyHandler(DefaultActionHandler):
print
(
"
Down button held.
"
)
print
(
"
Down button held.
"
)
tt
=
TurnTouch
(
'
c0:ff:ee:c0:ff:ee
'
)
tt
=
TurnTouch
(
'
c0:ff:ee:c0:ff:ee
'
)
tt
.
set_
handler
(
MyHandler
()
)
tt
.
handler
=
MyHandler
()
tt
.
listen_forever
()
tt
.
listen_forever
()
# One-liner alternative (same as listen_forever)
# One-liner alternative (same as listen_forever)
...
@@ -107,7 +107,7 @@ while not devices:
...
@@ -107,7 +107,7 @@ while not devices:
tt
=
devices
[
0
]
tt
=
devices
[
0
]
# Assign the handler to your device.
# Assign the handler to your device.
tt
.
set_
handler
(
my_handler
)
tt
.
handler
=
my_handler
tt
.
listen_forever
()
tt
.
listen_forever
()
```
```
...
...
This diff is collapsed.
Click to expand it.
turntouch/turntouch.py
+
268
−
88
View file @
66210139
"""
Classes related to the Turn Touch remote.
"""
"""
Classes related to the Turn Touch remote.
"""
from
concurrent.futures
import
ThreadPoolExecutor
import
time
import
logging
import
logging
from
bluepy
import
btle
from
bluepy
import
btle
from
typing
import
Union
from
typing
import
List
,
Union
logger
=
logging
.
getLogger
(
'
TurnTouch
'
)
logger
=
logging
.
getLogger
(
'
TurnTouch
'
)
class
Button
:
"""
A button on the Turn Touch remote.
"""
def
__init__
(
self
,
label
:
str
,
name
:
str
):
"""
Define a button.
:param label str: Human-readable name for the button
:param name str: Machine name for the button
"""
if
not
name
.
isidentifier
():
raise
TurnTouchException
(
"
Button name must be a valid identifier.
"
)
self
.
label
=
label
self
.
name
=
name
def
__str__
(
self
):
return
self
.
label
def
__repr__
(
self
):
return
'
<Button name=
"
{name}
"
>
'
.
format
(
name
=
self
.
name
)
class
PressType
:
"""
A type of button press.
"""
def
__init__
(
self
,
label
:
str
,
name
:
str
):
"""
Define a button.
:param label str: Human-readable name for the button
:param name str: Machine name for the button
"""
if
not
name
.
isidentifier
():
raise
TurnTouchException
(
"
Press name must be a valid identifier.
"
)
self
.
label
=
label
self
.
name
=
name
def
__str__
(
self
):
return
self
.
label
def
__repr__
(
self
):
return
'
<PressType name=
"
{name}
"
>
'
.
format
(
name
=
self
.
name
)
class
Action
:
class
Action
:
"""
A type of button press.
"""
"""
A type of button press.
"""
def
__init__
(
self
,
data
:
bytes
,
label
:
str
,
name
:
str
,
def
__init__
(
self
,
data
:
bytes
,
label
:
str
,
name
:
str
,
multi
:
bool
=
False
):
buttons
:
List
[
Button
],
press_type
:
PressType
):
"""
Define an action type.
:param data bytes: Byte representation of this event
:param label str: Human-readable name of this event
:param name str: Machine name for this event
:param buttons List[Button]: Machine name for this event
:param press_type PressType: Type of press (single, double, hold)
"""
if
not
name
.
isidentifier
():
if
not
name
.
isidentifier
():
raise
TurnTouchException
(
"
Press name must be a valid identifier.
"
)
raise
TurnTouchException
(
"
Press name must be a valid identifier.
"
)
self
.
data
=
data
self
.
data
=
data
self
.
label
=
label
self
.
label
=
label
self
.
name
=
name
self
.
name
=
name
self
.
multi
=
multi
self
.
buttons
=
frozenset
(
buttons
)
self
.
press_type
=
press_type
def
__eq__
(
self
,
other
):
return
self
.
data
==
other
.
data
def
__str__
(
self
):
return
self
.
label
def
__repr__
(
self
):
def
__repr__
(
self
):
return
'
<Action name=
"
{name}
"
>
'
.
format
(
name
=
self
.
name
)
return
'
<Action name=
"
{name}
"
>
'
.
format
(
name
=
self
.
name
)
def
__hash__
(
self
):
return
self
.
data
@property
def
is_multi
(
self
):
return
len
(
self
.
buttons
)
>
1
@property
def
is_off
(
self
):
return
self
.
press_type
==
TurnTouch
.
PRESS_NONE
@property
def
is_combo
(
self
):
return
self
.
press_type
in
(
TurnTouch
.
PRESS_DOUBLE
,
TurnTouch
.
PRESS_HOLD
)
class
TurnTouchException
(
Exception
):
class
TurnTouchException
(
Exception
):
"""
An error related to the Turn Touch bluetooth smart home remote.
"""
"""
An error related to the Turn Touch bluetooth smart home remote.
"""
...
@@ -31,55 +98,55 @@ class DefaultActionHandler:
...
@@ -31,55 +98,55 @@ class DefaultActionHandler:
"""
A callback handler class for button press events.
"""
A callback handler class for button press events.
Create a subclass of this class to define your button press behavior.
"""
Create a subclass of this class to define your button press behavior.
"""
def
butt
on_any
(
self
,
action
:
Action
=
None
):
pass
def
acti
on_any
(
self
,
action
:
Action
=
None
):
pass
def
butt
on_off
(
self
):
pass
def
acti
on_off
(
self
):
pass
def
butt
on_north
(
self
):
pass
def
acti
on_north
(
self
):
pass
def
butt
on_north_double_tap
(
self
):
pass
def
acti
on_north_double_tap
(
self
):
pass
def
butt
on_north_hold
(
self
):
pass
def
acti
on_north_hold
(
self
):
pass
def
butt
on_east
(
self
):
pass
def
acti
on_east
(
self
):
pass
def
butt
on_east_double_tap
(
self
):
pass
def
acti
on_east_double_tap
(
self
):
pass
def
butt
on_east_hold
(
self
):
pass
def
acti
on_east_hold
(
self
):
pass
def
butt
on_west
(
self
):
pass
def
acti
on_west
(
self
):
pass
def
butt
on_west_double_tap
(
self
):
pass
def
acti
on_west_double_tap
(
self
):
pass
def
butt
on_west_hold
(
self
):
pass
def
acti
on_west_hold
(
self
):
pass
def
butt
on_south
(
self
):
pass
def
acti
on_south
(
self
):
pass
def
butt
on_south_double_tap
(
self
):
pass
def
acti
on_south_double_tap
(
self
):
pass
def
butt
on_south_hold
(
self
):
pass
def
acti
on_south_hold
(
self
):
pass
def
butt
on_multi_north_east
(
self
):
pass
def
acti
on_multi_north_east
(
self
):
pass
def
butt
on_multi_north_west
(
self
):
pass
def
acti
on_multi_north_west
(
self
):
pass
def
butt
on_multi_north_south
(
self
):
pass
def
acti
on_multi_north_south
(
self
):
pass
def
butt
on_multi_east_west
(
self
):
pass
def
acti
on_multi_east_west
(
self
):
pass
def
butt
on_multi_east_south
(
self
):
pass
def
acti
on_multi_east_south
(
self
):
pass
def
butt
on_multi_west_south
(
self
):
pass
def
acti
on_multi_west_south
(
self
):
pass
def
butt
on_multi_north_east_west
(
self
):
pass
def
acti
on_multi_north_east_west
(
self
):
pass
def
butt
on_multi_north_east_south
(
self
):
pass
def
acti
on_multi_north_east_south
(
self
):
pass
def
butt
on_multi_north_west_south
(
self
):
pass
def
acti
on_multi_north_west_south
(
self
):
pass
def
butt
on_multi_east_west_south
(
self
):
pass
def
acti
on_multi_east_west_south
(
self
):
pass
def
butt
on_multi_north_east_west_south
(
self
):
pass
def
acti
on_multi_north_east_west_south
(
self
):
pass
class
TurnTouch
(
btle
.
Peripheral
):
class
TurnTouch
(
btle
.
Peripheral
):
...
@@ -89,62 +156,93 @@ class TurnTouch(btle.Peripheral):
...
@@ -89,62 +156,93 @@ class TurnTouch(btle.Peripheral):
BATTERY_LEVEL_CHARACTERISTIC_UUID
=
'
2a19
'
BATTERY_LEVEL_CHARACTERISTIC_UUID
=
'
2a19
'
DEVICE_NAME_CHARACTERISTIC_UUID
=
'
99c31526-dc4f-41b1-bb04-4e4deb81fadd
'
DEVICE_NAME_CHARACTERISTIC_UUID
=
'
99c31526-dc4f-41b1-bb04-4e4deb81fadd
'
DEVICE_NAME_LENGTH
=
32
DEVICE_NAME_LENGTH
=
32
PRESS_TYPES
=
{
MAX_DELAY
=
0.75
0xFF00
:
Action
(
0xFF00
,
'
Off
'
,
'
button_off
'
),
LISTEN_TIMEOUT
=
0.1
BUTTON_NORTH
=
Button
(
'
North
'
,
'
north
'
)
0xFE00
:
Action
(
0xFE00
,
'
North
'
,
'
button_north
'
),
BUTTON_EAST
=
Button
(
'
East
'
,
'
east
'
)
0xEF00
:
Action
(
0xEF00
,
'
North double tap
'
,
BUTTON_WEST
=
Button
(
'
West
'
,
'
west
'
)
'
button_north_double_tap
'
),
BUTTON_SOUTH
=
Button
(
'
South
'
,
'
south
'
)
0xFEFF
:
Action
(
0xFEFF
,
'
North hold
'
,
'
button_north_hold
'
),
PRESS_NONE
=
PressType
(
'
None (off)
'
,
'
none
'
)
PRESS_SINGLE
=
PressType
(
'
Single
'
,
'
single
'
)
0xFD00
:
Action
(
0xFD00
,
'
East
'
,
'
button_east
'
),
PRESS_DOUBLE
=
PressType
(
'
Double
'
,
'
double
'
)
0xDF00
:
Action
(
0xDF00
,
'
East double tap
'
,
'
button_east_double_tap
'
),
PRESS_HOLD
=
PressType
(
'
Hold
'
,
'
hold
'
)
0xFDFF
:
Action
(
0xFDFF
,
'
East hold
'
,
'
button_east_hold
'
),
ACTIONS
=
{
0xFF00
:
Action
(
0xFF00
,
'
Off
'
,
'
action_off
'
,
[],
PRESS_NONE
),
0xFB00
:
Action
(
0xFB00
,
'
West
'
,
'
button_west
'
),
0xBF00
:
Action
(
0xBF00
,
'
West double tap
'
,
'
button_west_double_tap
'
),
0xFE00
:
Action
(
0xFE00
,
'
North
'
,
'
action_north
'
,
[
BUTTON_NORTH
],
0xFBFF
:
Action
(
0xFBFF
,
'
West hold
'
,
'
button_west_hold
'
),
PRESS_SINGLE
),
0xEF00
:
Action
(
0xEF00
,
'
North double tap
'
,
'
action_north_double_tap
'
,
0xF700
:
Action
(
0xF700
,
'
South
'
,
'
button_south
'
),
[
BUTTON_NORTH
],
PRESS_DOUBLE
),
0x7F00
:
Action
(
0x7F00
,
'
South double tap
'
,
0xFEFF
:
Action
(
0xFEFF
,
'
North hold
'
,
'
action_north_hold
'
,
'
button_south_double_tap
'
),
[
BUTTON_NORTH
],
PRESS_HOLD
),
0xF7FF
:
Action
(
0xF7FF
,
'
South hold
'
,
'
button_south_hold
'
),
0xFD00
:
Action
(
0xFD00
,
'
East
'
,
'
action_east
'
,
[
BUTTON_EAST
],
0xFC00
:
Action
(
0xFC00
,
'
Multi North East
'
,
PRESS_SINGLE
),
'
button_multi_north_east
'
,
True
),
0xDF00
:
Action
(
0xDF00
,
'
East double tap
'
,
'
action_east_double_tap
'
,
0xFA00
:
Action
(
0xFA00
,
'
Multi North West
'
,
[
BUTTON_EAST
],
PRESS_DOUBLE
),
'
button_multi_north_west
'
,
True
),
0xFDFF
:
Action
(
0xFDFF
,
'
East hold
'
,
'
action_east_hold
'
,
[
BUTTON_EAST
],
0xF600
:
Action
(
0xF600
,
'
Multi North South
'
,
PRESS_HOLD
),
'
button_multi_north_south
'
,
True
),
0xF900
:
Action
(
0xF900
,
'
Multi East West
'
,
0xFB00
:
Action
(
0xFB00
,
'
West
'
,
'
action_west
'
,
[
BUTTON_WEST
],
'
button_multi_east_west
'
,
True
),
PRESS_SINGLE
),
0xF500
:
Action
(
0xF500
,
'
Multi East South
'
,
0xBF00
:
Action
(
0xBF00
,
'
West double tap
'
,
'
action_west_double_tap
'
,
'
button_multi_east_south
'
,
True
),
[
BUTTON_WEST
],
PRESS_DOUBLE
),
0xF300
:
Action
(
0xF300
,
'
Multi West South
'
,
0xFBFF
:
Action
(
0xFBFF
,
'
West hold
'
,
'
action_west_hold
'
,
[
BUTTON_WEST
],
'
button_multi_west_south
'
,
True
),
PRESS_HOLD
),
0xF700
:
Action
(
0xF700
,
'
South
'
,
'
action_south
'
,
[
BUTTON_SOUTH
],
PRESS_SINGLE
),
0x7F00
:
Action
(
0x7F00
,
'
South double tap
'
,
'
action_south_double_tap
'
,
[
BUTTON_SOUTH
],
PRESS_DOUBLE
),
0xF7FF
:
Action
(
0xF7FF
,
'
South hold
'
,
'
action_south_hold
'
,
[
BUTTON_SOUTH
],
PRESS_HOLD
),
0xFC00
:
Action
(
0xFC00
,
'
Multi North East
'
,
'
action_multi_north_east
'
,
[
BUTTON_NORTH
,
BUTTON_EAST
],
PRESS_SINGLE
),
0xFA00
:
Action
(
0xFA00
,
'
Multi North West
'
,
'
action_multi_north_west
'
,
[
BUTTON_NORTH
,
BUTTON_WEST
],
PRESS_SINGLE
),
0xF600
:
Action
(
0xF600
,
'
Multi North South
'
,
'
action_multi_north_south
'
,
[
BUTTON_NORTH
,
BUTTON_SOUTH
],
PRESS_SINGLE
),
0xF900
:
Action
(
0xF900
,
'
Multi East West
'
,
'
action_multi_east_west
'
,
[
BUTTON_EAST
,
BUTTON_WEST
],
PRESS_SINGLE
),
0xF500
:
Action
(
0xF500
,
'
Multi East South
'
,
'
action_multi_east_south
'
,
[
BUTTON_EAST
,
BUTTON_SOUTH
],
PRESS_SINGLE
),
0xF300
:
Action
(
0xF300
,
'
Multi West South
'
,
'
action_multi_west_south
'
,
[
BUTTON_WEST
,
BUTTON_SOUTH
],
PRESS_SINGLE
),
0xF800
:
Action
(
0xF800
,
'
Multi North East West
'
,
0xF800
:
Action
(
0xF800
,
'
Multi North East West
'
,
'
button_multi_north_east_west
'
,
True
),
'
action_multi_north_east_west
'
,
[
BUTTON_NORTH
,
BUTTON_EAST
,
BUTTON_WEST
],
PRESS_SINGLE
),
0xF400
:
Action
(
0xF400
,
'
Multi North East South
'
,
0xF400
:
Action
(
0xF400
,
'
Multi North East South
'
,
'
button_multi_north_east_south
'
,
True
),
'
action_multi_north_east_south
'
,
[
BUTTON_NORTH
,
BUTTON_EAST
,
BUTTON_SOUTH
],
PRESS_SINGLE
),
0xF200
:
Action
(
0xF200
,
'
Multi North West South
'
,
0xF200
:
Action
(
0xF200
,
'
Multi North West South
'
,
'
button_multi_north_west_south
'
,
True
),
'
action_multi_north_west_south
'
,
[
BUTTON_NORTH
,
BUTTON_WEST
,
BUTTON_SOUTH
],
PRESS_SINGLE
),
0xF100
:
Action
(
0xF100
,
'
Multi East West South
'
,
0xF100
:
Action
(
0xF100
,
'
Multi East West South
'
,
'
button_multi_east_west_south
'
,
True
),
'
action_multi_east_west_south
'
,
[
BUTTON_EAST
,
BUTTON_WEST
,
BUTTON_SOUTH
],
PRESS_SINGLE
),
0xF000
:
Action
(
0xF000
,
'
Multi North East West South
'
,
0xF000
:
Action
(
0xF000
,
'
Multi North East West South
'
,
'
button_multi_north_east_west_south
'
,
True
),
'
action_multi_north_east_west_south
'
,
[
BUTTON_NORTH
,
BUTTON_EAST
,
BUTTON_WEST
,
BUTTON_SOUTH
],
PRESS_SINGLE
),
}
}
def
__init__
(
self
,
def
__init__
(
self
,
address
:
Union
[
str
,
btle
.
ScanEntry
],
address
:
Union
[
str
,
btle
.
ScanEntry
],
handler
:
DefaultActionHandler
=
None
,
handler
:
DefaultActionHandler
=
None
,
debounce
:
bool
=
True
,
listen
:
bool
=
False
,
listen
:
bool
=
False
,
interface
:
int
=
None
):
interface
:
int
=
None
):
"""
Connect to the Turn Touch remote.
"""
Connect to the Turn Touch remote.
Set appropriate address type (overriding btle default).
Set appropriate address type (overriding btle default).
:param address Union[str, btle.ScanEntry]:
:param address Union[str, btle.ScanEntry]:
MAC address (or btle.ScanEntry object) of this device
MAC address (or btle.ScanEntry object) of this device
:param debounce bool:
Suppress single presses during a hold, double-tap or multi-press.
:param listen bool: Start listening for button presses
:param listen bool: Start listening for button presses
:param interface int: Index of the bluetooth device (eg. 0 for hci0)
"""
:param interface int: Index of the bluetooth device (eg. 0 for hci0)
"""
try
:
try
:
...
@@ -158,7 +256,8 @@ class TurnTouch(btle.Peripheral):
...
@@ -158,7 +256,8 @@ class TurnTouch(btle.Peripheral):
raise
TurnTouchException
(
"
Failed to connect to device {address}
"
raise
TurnTouchException
(
"
Failed to connect to device {address}
"
.
format
(
address
=
address
))
.
format
(
address
=
address
))
self
.
withDelegate
(
self
.
NotificationDelegate
(
turn_touch
=
self
))
self
.
withDelegate
(
self
.
NotificationDelegate
(
turn_touch
=
self
))
self
.
set_handler
(
handler
)
self
.
handler
=
handler
or
DefaultActionHandler
self
.
_combo_action
=
set
()
if
listen
:
if
listen
:
self
.
listen_forever
()
self
.
listen_forever
()
...
@@ -184,25 +283,26 @@ class TurnTouch(btle.Peripheral):
...
@@ -184,25 +283,26 @@ class TurnTouch(btle.Peripheral):
logger
.
debug
(
"
Set name for device {address} to
'
{name}
'"
.
format
(
logger
.
debug
(
"
Set name for device {address} to
'
{name}
'"
.
format
(
address
=
self
.
addr
,
name
=
name_bytes
))
address
=
self
.
addr
,
name
=
name_bytes
))
def
set_handler
(
self
,
handler
:
DefaultActionHandler
=
None
):
def
listen_forever
(
self
):
"""
Set the
button press
handler class for this remote
.
"""
"""
Listen for
button press
events indefinitely
.
"""
self
.
_handler
=
handler
or
DefaultActionHandler
self
.
listen
(
only_one
=
False
)
def
listen
(
self
,
timeout
:
int
=
0
,
only_one
:
bool
=
True
):
def
listen
(
self
,
only_one
:
bool
=
True
):
"""
Listen for a button press event.
"""
Listen for a button press event.
Will listen indefinitely if `only_one` is False.
"""
Will listen indefinitely if `only_one` is False.
"""
self
.
_enable_notifications
()
self
.
_enable_notifications
()
if
only_one
:
if
self
.
debounce
:
self
.
waitForNotifications
(
timeout
)
self
.
executor
=
ThreadPoolExecutor
(
5
)
else
:
try
:
while
True
:
if
only_one
:
self
.
waitForNotifications
(
timeout
)
self
.
waitForNotifications
(
0
)
else
:
while
True
:
self
.
waitForNotifications
(
0
)
except
btle
.
BTLEException
as
e
:
raise
TurnTouchException
(
e
)
self
.
_enable_notifications
(
enable
=
False
)
self
.
_enable_notifications
(
enable
=
False
)
def
listen_forever
(
self
):
"""
Listen for button press events indefinitely.
"""
self
.
listen
(
only_one
=
False
)
def
_enable_notifications
(
self
,
enabled
=
True
):
def
_enable_notifications
(
self
,
enabled
=
True
):
"""
Tell the remote to start sending button press notifications.
"""
"""
Tell the remote to start sending button press notifications.
"""
notification_handle
=
self
.
getCharacteristics
(
notification_handle
=
self
.
getCharacteristics
(
...
@@ -217,19 +317,99 @@ class TurnTouch(btle.Peripheral):
...
@@ -217,19 +317,99 @@ class TurnTouch(btle.Peripheral):
action
=
"
enabled
"
if
enabled
else
"
disabled
"
,
address
=
self
.
addr
))
action
=
"
enabled
"
if
enabled
else
"
disabled
"
,
address
=
self
.
addr
))
class
NotificationDelegate
(
btle
.
DefaultDelegate
):
class
NotificationDelegate
(
btle
.
DefaultDelegate
):
"""
Handle callbacks for notifications from the device.
"""
"""
Handle callbacks for notifications from the device.
This is an internal-use class. To handle button presses, you should
subclass DefaultActionHandler, not this class.
"""
def
__init__
(
self
,
turn_touch
):
def
__init__
(
self
,
turn_touch
):
"""
Retain a reference to the
calling
object.
"""
"""
Retain a reference to the
parent TurnTouch
object.
"""
self
.
turn_touch
=
turn_touch
self
.
turn_touch
=
turn_touch
def
_handle_combo
(
self
,
action
):
"""
Handle an action immediately.
This action may be the end of a complex press (double-tap or hold),
so we record that. See _handle_single for the other side.
"""
self
.
turn_touch
.
_combo_action
.
add
(
action
)
self
.
handle_action
(
action
)
time
.
sleep
(
self
.
turn_touch
.
MAX_DELAY
)
self
.
turn_touch
.
_combo_action
.
remove
(
action
)
def
_handle_multi
(
self
,
action
):
"""
Handle a multi-button action.
Occurs immediately, but we need to debounce because it can fire
more than once.
"""
for
combo_action
in
self
.
turn_touch
.
_combo_action
:
if
combo_action
.
buttons
.
issuperset
(
action
.
buttons
):
# This was already handled
logger
.
debug
(
"
Debounce Multi: ignoring action {action}.
"
.
format
(
action
=
action
))
return
# Not a duplicate; proceed
self
.
turn_touch
.
_combo_action
.
add
(
action
)
self
.
handle_action
(
action
)
time
.
sleep
(
self
.
turn_touch
.
MAX_DELAY
)
self
.
turn_touch
.
_combo_action
.
remove
(
action
)
def
_handle_off
(
self
,
action
):
"""
Handle the
"
Off
'
action
Occurs with a delay, and we need to debounce because it can fire
more than once.
"""
if
action
in
self
.
turn_touch
.
_combo_action
:
logger
.
debug
(
"
Debounce Off: ignoring action {action}.
"
.
format
(
action
=
action
))
return
# Not a duplicate; proceed
self
.
turn_touch
.
_combo_action
.
add
(
action
)
time
.
sleep
(
self
.
turn_touch
.
MAX_DELAY
)
self
.
handle_action
(
action
)
self
.
turn_touch
.
_combo_action
.
remove
(
action
)
def
_handle_single
(
self
,
action
):
"""
Handle an action which may be the beginning of a complex press
(double tap, or hold). Wait for further actions before handling.
"""
time
.
sleep
(
self
.
turn_touch
.
MAX_DELAY
)
for
combo_action
in
self
.
turn_touch
.
_combo_action
:
if
combo_action
.
buttons
.
issuperset
(
action
.
buttons
):
# This button press was part of a combo; ignore it.
logger
.
debug
(
"
Debounce: ignoring action {action}.
"
.
format
(
action
=
action
))
return
# Apparently there was no combo, so handle the original action
self
.
handle_action
(
action
)
def
handle_action
(
self
,
action
):
"""
Actually invoke the handlers for this action.
"""
# Call the generic (any button) callback.
self
.
turn_touch
.
handler
.
action_any
(
action
)
# Call the button-specific callback
getattr
(
self
.
turn_touch
.
handler
,
action
.
name
)()
def
handleNotification
(
self
,
cHandle
,
data
):
def
handleNotification
(
self
,
cHandle
,
data
):
"""
Call the appropriate button press handler method(s).
"""
"""
Call the appropriate button press handler method(s).
"""
logger
.
debug
(
"
Got notification {notification}
"
.
format
(
logger
.
debug
(
"
Got notification {notification}
"
.
format
(
notification
=
data
))
notification
=
data
))
type_int
=
int
.
from_bytes
(
data
,
byteorder
=
'
big
'
)
type_int
=
int
.
from_bytes
(
data
,
byteorder
=
'
big
'
)
# Call the generic (any button) callback.
try
:
self
.
turn_touch
.
_handler
.
button_any
(
action
=
self
.
turn_touch
.
ACTIONS
[
type_int
]
self
.
turn_touch
.
PRESS_TYPES
.
get
(
type_int
))
except
IndexError
:
# Call the button-specific callback
raise
TurnTouchException
(
'
Unknown notification received: {}
'
getattr
(
self
.
turn_touch
.
_handler
,
.
format
(
data
))
self
.
turn_touch
.
PRESS_TYPES
.
get
(
type_int
).
name
)()
if
self
.
turn_touch
.
debounce
:
if
action
.
is_combo
:
self
.
_handle_combo
(
action
)
elif
action
.
is_multi
:
logger
.
debug
(
"
Debounce: delaying action {action}.
"
.
format
(
action
=
action
))
self
.
turn_touch
.
executor
.
submit
(
self
.
_handle_multi
,
(
action
))
elif
action
.
is_off
:
logger
.
debug
(
"
Debounce: delaying action {action}.
"
.
format
(
action
=
action
))
self
.
turn_touch
.
executor
.
submit
(
self
.
_handle_off
,
(
action
))
else
:
logger
.
debug
(
"
Debounce: delaying action {action}.
"
.
format
(
action
=
action
))
self
.
turn_touch
.
executor
.
submit
(
self
.
_handle_single
,
(
action
))
else
:
self
.
handle_action
(
action
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment