Skip to content

Commit 858d244

Browse files
committed
code for BLE vibration bracelet
Adding code for BLE vibration bracelet Learn Guide
1 parent 0a4612d commit 858d244

File tree

1 file changed

+205
-0
lines changed

1 file changed

+205
-0
lines changed

BLE_Vibration_Bracelet/code.py.py

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
import time
2+
import board
3+
import busio
4+
import neopixel
5+
import adafruit_drv2605
6+
from digitalio import DigitalInOut, Direction
7+
import adafruit_ble
8+
from adafruit_ble.advertising.standard import SolicitServicesAdvertisement
9+
from adafruit_ble.services.standard import CurrentTimeService
10+
from adafruit_ble_apple_notification_center import AppleNotificationCenterService
11+
12+
# setup for onboard NeoPixel
13+
pixel_pin = board.NEOPIXEL
14+
num_pixels = 1
15+
16+
pixel = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3, auto_write=False)
17+
18+
# setup for haptic motor driver
19+
i2c = busio.I2C(board.SCL, board.SDA)
20+
drv = adafruit_drv2605.DRV2605(i2c)
21+
22+
# onboard blue LED
23+
blue_led = DigitalInOut(board.BLUE_LED)
24+
blue_led.direction = Direction.OUTPUT
25+
26+
# setup for BLE
27+
ble = adafruit_ble.BLERadio()
28+
if ble.connected:
29+
for c in ble.connections:
30+
c.disconnect()
31+
32+
advertisement = SolicitServicesAdvertisement()
33+
34+
# adds ANCS and current time services for BLE to advertise
35+
advertisement.solicited_services.append(AppleNotificationCenterService)
36+
advertisement.solicited_services.append(CurrentTimeService)
37+
38+
# state machines
39+
current_notification = None # tracks the current notification from ANCS
40+
current_notifications = {} # array to hold all current notifications from ANCS
41+
cleared = False # state to track if notifications have been cleared from ANCS
42+
notification_service = None # holds the array of active notifications from ANCS
43+
all_ids = [] # array to hold all of the ids from ANCS
44+
hour = 0 # used to track when it is on the hour for the mindfulness reminder
45+
mindful = False # state used to track if it is time for mindfulness
46+
vibration = 16 # vibration effect being used for the haptic motor
47+
BLUE = (0, 0, 255) # color blue for the NeoPixel
48+
PURPLE = (255, 0, 255) # color purple for the NeoPixel
49+
RED = (255, 0, 0) # color red for the NeoPixel
50+
ORANGE = (255, 255, 0) # color orange
51+
YELLOW = (255, 150, 0) # color yellow
52+
GREEN = (0, 255, 0) # color green
53+
CYAN = (0, 255, 255) # color cyan
54+
PINK = (255, 0, 127) # color pink
55+
WHITE = (255, 255, 255) # color white
56+
clear = (0, 0, 0) # allows for NeoPixel to be turned 'off'
57+
58+
APP_COLORS = {
59+
"com.basecamp.bc3-ios": YELLOW, # Basecamp
60+
"com.apple.MobileSMS": GREEN, # Texts
61+
"com.hammerandchisel.discord": PURPLE, # Discord
62+
"com.apple.mobilecal": CYAN, # Calendar
63+
"com.apple.mobilephone": GREEN, # Phone
64+
"com.google.ios.youtube": ORANGE, # YouTube
65+
"com.burbn.instagram": PINK, # Instagram
66+
"com.apple.mobilemail": CYAN # Apple Email
67+
}
68+
69+
# function for blinking NeoPixel
70+
# blinks: # of blinks
71+
# speed: how fast/slow blinks
72+
# color1: first color
73+
# color2: second color
74+
def blink_pixel(blinks, speed, color1, color2):
75+
for _ in range(0, blinks):
76+
pixel.fill(color1)
77+
pixel.show()
78+
time.sleep(speed)
79+
pixel.fill(color2)
80+
pixel.show()
81+
time.sleep(speed)
82+
83+
# function for haptic motor vibration
84+
# num_zzz: # of times vibrates
85+
# effect: type of vibration
86+
# delay: time between vibrations
87+
def vibe(num_zzz, effect, delay):
88+
drv.sequence[0] = adafruit_drv2605.Effect(effect)
89+
for _ in range(0, num_zzz):
90+
drv.play() # play the effect
91+
time.sleep(delay) # for 0.5 seconds
92+
drv.stop()
93+
94+
# start BLE
95+
ble.start_advertising(advertisement)
96+
97+
while True:
98+
99+
blue_led.value = False
100+
print("Waiting for connection")
101+
102+
# NeoPixel is red when not connected to BLE
103+
while not ble.connected:
104+
blue_led.value = False
105+
pixel.fill(RED)
106+
pixel.show()
107+
print("Connected")
108+
109+
while ble.connected:
110+
blue_led.value = True # blue LED is on when connected
111+
all_ids.clear()
112+
for connection in ble.connections:
113+
if not connection.paired:
114+
# pairs to phone
115+
connection.pair()
116+
print("paired")
117+
# allows connection to CurrentTimeService
118+
cts = connection[CurrentTimeService]
119+
notification_service = connection[AppleNotificationCenterService]
120+
# grabs notifications from ANCS
121+
current_notifications = notification_service.active_notifications
122+
123+
for notif_id in current_notifications:
124+
# adds notifications into array
125+
notification = current_notifications[notif_id]
126+
all_ids.append(notif_id)
127+
128+
# all_ids.sort(key=lambda x: current_notifications[x]._raw_date)
129+
130+
if current_notification and current_notification.removed:
131+
# Stop showing the latest and show that there are no new notifications.
132+
current_notification = None
133+
pixel.fill(clear)
134+
pixel.show()
135+
136+
if not current_notification and not all_ids and not cleared:
137+
# updates cleared state for notification
138+
cleared = True
139+
# turns off NeoPixel when notifications are clear
140+
pixel.fill(clear)
141+
pixel.show()
142+
143+
elif all_ids:
144+
cleared = False
145+
if current_notification and current_notification.id in all_ids:
146+
index = all_ids.index(current_notification.id)
147+
else:
148+
index = len(all_ids) - 1
149+
notif_id = all_ids[index]
150+
# if there is a notification:
151+
if not current_notification or current_notification.id != notif_id:
152+
current_notification = current_notifications[notif_id]
153+
# if the notification is from an app that is not
154+
# defined in APP_COLORS then the NeoPixel will be white
155+
if current_notification.app_id not in APP_COLORS:
156+
notif_color = WHITE
157+
# if the notification is from an app defined in
158+
# APP_COLORS then the assigned color will show
159+
else:
160+
notif_color = APP_COLORS[current_notification.app_id]
161+
# parses notification info into a string
162+
category = str(notification).split(" ", 1)[0]
163+
# haptic motor vibrates
164+
vibe(2, vibration, 0.5)
165+
# all info for notification is printed to REPL
166+
print('-'*36)
167+
print("Msg #%d - Category %s" % (notification.id, category))
168+
print("From app:", notification.app_id)
169+
if notification.title:
170+
print("Title:", notification.title)
171+
if notification.subtitle:
172+
print("Subtitle:", notification.subtitle)
173+
if notification.message:
174+
print("Message:", notification.message)
175+
# NeoPixel blinks and then stays on until cleared
176+
blink_pixel(2, 0.5, notif_color, clear)
177+
pixel.fill(notif_color)
178+
pixel.show()
179+
# if it's on the hour:
180+
if cts.current_time[4] == hour and not mindful:
181+
print(cts.current_time[4])
182+
print("mindful time")
183+
# haptic motor vibrates
184+
vibe(5, vibration, 1)
185+
# NeoPixel blinks and then stays on
186+
blink_pixel(5, 1, BLUE, clear)
187+
mindful = True
188+
pixel.fill(BLUE)
189+
pixel.show()
190+
print("hour = ", hour)
191+
# if it's no longer on the hour:
192+
if cts.current_time[4] == (hour + 1) and mindful:
193+
# NeoPixel turns off
194+
mindful = False
195+
pixel.fill(clear)
196+
pixel.show()
197+
print("mindful time over")
198+
199+
# if BLE becomes disconnected then blue LED turns off
200+
# and BLE begins advertising again to reconnect
201+
print("Disconnected")
202+
blue_led.value = False
203+
print()
204+
ble.start_advertising(advertisement)
205+
notification_service = None

0 commit comments

Comments
 (0)