Skip to content

Commit 258bb62

Browse files
authored
Merge pull request #16 from todbot/add_actions
Add actions to notifications
2 parents 6343719 + 78e3a12 commit 258bb62

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

adafruit_ble_apple_notification_center.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def __get__(self, notification, cls):
7070
"BusinessAndFinance",
7171
"Location",
7272
"Entertainment",
73+
"ActiveCall",
7374
)
7475

7576

@@ -140,6 +141,22 @@ def __init__(
140141
self.control_point = control_point
141142
self.data_source = data_source
142143

144+
def send_positive_action(self):
145+
"""Sends positive action on this notification. For example, to accept an IncomingCall."""
146+
cmd = 2 # ANCS_CMD_PERFORM_NOTIFICATION_ACTION,
147+
uid = self.id
148+
action_id = 0 # ANCS_ACTION_POSITIVE
149+
buffer = struct.pack("<BIB", cmd, uid, action_id)
150+
self.control_point.write(buffer)
151+
152+
def send_negative_action(self):
153+
"""Sends negative action on this notification. For example, to decline an IncomingCall."""
154+
cmd = 2 # ANCS_CMD_PERFORM_NOTIFICATION_ACTION,
155+
uid = self.id
156+
action_id = 1 # ANCS_ACTION_NEGATIVE
157+
buffer = struct.pack("<BIB", cmd, uid, action_id)
158+
self.control_point.write(buffer)
159+
143160
def update(self, event_flags, category_id, category_count):
144161
"""Update the notification and clear the attribute cache."""
145162
self.category_id = category_id
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# SPDX-FileCopyrightText: 2022 Tod Kurt for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
"""
5+
This example solicits notifications from Apple devices paired with it,
6+
detecting specifically the IncomingCall and ActiveCall notification categories
7+
and sending back Positive Actions to accept calls or Negative Actions to
8+
decline or hang up calls. It also shows initiating pairing, prints existing
9+
notifications and prints any new ones as they arrive.
10+
"""
11+
12+
import time
13+
import board
14+
import digitalio
15+
import neopixel
16+
import adafruit_ble
17+
from adafruit_ble.advertising.standard import SolicitServicesAdvertisement
18+
import adafruit_ble_apple_notification_center as ancs
19+
20+
# Circuit Playground Bluefruit buttons and LED setup
21+
butA = digitalio.DigitalInOut(board.D4) # CPB "A" button
22+
butB = digitalio.DigitalInOut(board.D5) # CPB "B" button
23+
butA.switch_to_input(digitalio.Pull.DOWN) # buttons are active HIGH
24+
butB.switch_to_input(digitalio.Pull.DOWN)
25+
26+
leds = neopixel.NeoPixel(board.D8, 10, brightness=0.1)
27+
28+
(coff, cred, cgrn, cblu, cgra) = (0x000000, 0xFF0000, 0x00FF00, 0x0000FF, 0x111111)
29+
leds_off = (coff, coff, coff, coff, coff, coff, coff, coff, coff, coff)
30+
leds_idle = (cgra, cgra, cgra, cgra, cgra, cgra, cgra, cgra, cgra, cgra)
31+
leds_incoming_call = (coff, cgrn, cgrn, cgrn, coff, coff, cred, cred, cred, coff)
32+
leds_active_call = (cgrn, coff, coff, coff, cgrn, cgrn, cred, cred, cred, cgrn)
33+
34+
print("starting...")
35+
radio = adafruit_ble.BLERadio() # pylint: disable=no-member
36+
a = SolicitServicesAdvertisement()
37+
# a.complete_name = "CIRPYCALLHANDLER" # this crashes things?
38+
a.solicited_services.append(ancs.AppleNotificationCenterService)
39+
radio.start_advertising(a)
40+
41+
last_display_time = time.monotonic()
42+
43+
while True:
44+
while not radio.connected:
45+
print("not connected")
46+
time.sleep(1)
47+
48+
for connection in radio.connections:
49+
if not connection.paired:
50+
connection.pair()
51+
print("paired")
52+
53+
ans = connection[ancs.AppleNotificationCenterService]
54+
55+
for notification in ans.wait_for_new_notifications():
56+
print("New Notification:\n- ", notification)
57+
58+
leds[:] = leds_idle
59+
60+
for notification in ans.active_notifications.values():
61+
# incoming call category, has positive & negative actions
62+
if notification.category_id == 1:
63+
leds[:] = leds_incoming_call
64+
if butA.value:
65+
print("Action: accepting call")
66+
notification.send_positive_action()
67+
time.sleep(1) # simple debounce
68+
if butB.value:
69+
print("Action: declining call")
70+
notification.send_negative_action()
71+
time.sleep(1) # simple debounce
72+
# active call category, only has negative action
73+
if notification.category_id == 12:
74+
leds[:] = leds_active_call
75+
if butB.value:
76+
print("Action: hanging up call")
77+
notification.send_negative_action()
78+
time.sleep(1) # simple debounce
79+
80+
if time.monotonic() - last_display_time > 3.0:
81+
last_display_time = time.monotonic()
82+
print(
83+
"Current Notifications:",
84+
len(ans.active_notifications),
85+
time.monotonic(),
86+
)
87+
for nid, n in ans.active_notifications.items():
88+
print(
89+
"- uid:",
90+
n.id,
91+
"catid:",
92+
n.category_id,
93+
"title:",
94+
n.title,
95+
"msg:",
96+
n.message,
97+
)

0 commit comments

Comments
 (0)