Adding code for BLE Buzzy Box
Code for BLE Buzzy Box Learn Guide. Feather NRF52840 with a DRV2605 haptic motor driver. When a notification arrives from ANCS it vibrates & onboard NeoPixel flashes. Also vibrates and flashes on the hour for mindfulness reminder
This commit is contained in:
parent
d2f4fb1dae
commit
7d59b0e2bf
1 changed files with 179 additions and 0 deletions
179
BLE_Buzzy_Box/code.py
Normal file
179
BLE_Buzzy_Box/code.py
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
import time
|
||||||
|
import board
|
||||||
|
import busio
|
||||||
|
import neopixel
|
||||||
|
import adafruit_drv2605
|
||||||
|
import adafruit_ble
|
||||||
|
from adafruit_ble.advertising.standard import SolicitServicesAdvertisement
|
||||||
|
from adafruit_ble.services.standard import CurrentTimeService
|
||||||
|
from adafruit_ble_apple_notification_center import AppleNotificationCenterService
|
||||||
|
from digitalio import DigitalInOut, Direction
|
||||||
|
|
||||||
|
# setup for onboard NeoPixel
|
||||||
|
pixel_pin = board.NEOPIXEL
|
||||||
|
num_pixels = 1
|
||||||
|
|
||||||
|
pixel = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.3, auto_write=False)
|
||||||
|
|
||||||
|
# setup for haptic motor driver
|
||||||
|
i2c = busio.I2C(board.SCL, board.SDA)
|
||||||
|
drv = adafruit_drv2605.DRV2605(i2c)
|
||||||
|
|
||||||
|
# onboard blue LED
|
||||||
|
blue_led = DigitalInOut(board.BLUE_LED)
|
||||||
|
blue_led.direction = Direction.OUTPUT
|
||||||
|
|
||||||
|
# setup for BLE
|
||||||
|
ble = adafruit_ble.BLERadio()
|
||||||
|
if ble.connected:
|
||||||
|
for c in ble.connections:
|
||||||
|
c.disconnect()
|
||||||
|
|
||||||
|
advertisement = SolicitServicesAdvertisement()
|
||||||
|
|
||||||
|
# adds ANCS and current time services for BLE to advertise
|
||||||
|
advertisement.solicited_services.append(AppleNotificationCenterService)
|
||||||
|
advertisement.solicited_services.append(CurrentTimeService)
|
||||||
|
|
||||||
|
# state machines
|
||||||
|
current_notification = None # tracks the current notification from ANCS
|
||||||
|
current_notifications = {} # array to hold all current notifications from ANCS
|
||||||
|
cleared = False # state to track if notifications have been cleared from ANCS
|
||||||
|
notification_service = None # holds the array of active notifications from ANCS
|
||||||
|
all_ids = [] # array to hold all of the ids from ANCS
|
||||||
|
hour = 0 # used to track when it is on the hour for the mindfulness reminder
|
||||||
|
mindful = False # state used to track if it is time for mindfulness
|
||||||
|
vibration = 16 # vibration effect being used for the haptic motor
|
||||||
|
blue = (0, 0, 255) # color blue for the NeoPixel
|
||||||
|
purple = (255, 0, 255) # color purple for the NeoPixel
|
||||||
|
red = (255, 0, 0) # color red for the NeoPixel
|
||||||
|
clear = (0, 0, 0) # allows for NeoPixel to be turned 'off'
|
||||||
|
|
||||||
|
# function for blinking NeoPixel
|
||||||
|
# blinks: # of blinks
|
||||||
|
# speed: how fast/slow blinks
|
||||||
|
# color1: first color
|
||||||
|
# color2: second color
|
||||||
|
def blink_pixel(blinks, speed, color1, color2):
|
||||||
|
for _ in range(0, blinks):
|
||||||
|
pixel.fill(color1)
|
||||||
|
pixel.show()
|
||||||
|
time.sleep(speed)
|
||||||
|
pixel.fill(color2)
|
||||||
|
pixel.show()
|
||||||
|
time.sleep(speed)
|
||||||
|
|
||||||
|
# function for haptic motor vibration
|
||||||
|
# num_zzz: # of times vibrates
|
||||||
|
# effect: type of vibration
|
||||||
|
# delay: time between vibrations
|
||||||
|
def vibe(num_zzz, effect, delay):
|
||||||
|
drv.sequence[0] = adafruit_drv2605.Effect(effect)
|
||||||
|
for _ in range(0, num_zzz):
|
||||||
|
drv.play() # play the effect
|
||||||
|
time.sleep(delay) # for 0.5 seconds
|
||||||
|
drv.stop()
|
||||||
|
|
||||||
|
# start BLE
|
||||||
|
ble.start_advertising(advertisement)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
blue_led.value = False
|
||||||
|
print("Waiting for connection")
|
||||||
|
|
||||||
|
# NeoPixel is red when not connected to BLE
|
||||||
|
while not ble.connected:
|
||||||
|
blue_led.value = False
|
||||||
|
pixel.fill(red)
|
||||||
|
pixel.show()
|
||||||
|
|
||||||
|
print("Connected")
|
||||||
|
|
||||||
|
while ble.connected:
|
||||||
|
blue_led.value = True # blue LED is on when connected
|
||||||
|
all_ids.clear()
|
||||||
|
for connection in ble.connections:
|
||||||
|
if not connection.paired:
|
||||||
|
# pairs to phone
|
||||||
|
connection.pair()
|
||||||
|
print("paired")
|
||||||
|
# allows connection to CurrentTimeService
|
||||||
|
cts = connection[CurrentTimeService]
|
||||||
|
notification_service = connection[AppleNotificationCenterService]
|
||||||
|
# grabs notifications from ANCS
|
||||||
|
current_notifications = notification_service.active_notifications
|
||||||
|
|
||||||
|
for notif_id in current_notifications:
|
||||||
|
# adds notifications into array
|
||||||
|
notification = current_notifications[notif_id]
|
||||||
|
all_ids.append(notif_id)
|
||||||
|
|
||||||
|
if current_notification and current_notification.removed:
|
||||||
|
# Stop showing the latest and show that there are no new notifications.
|
||||||
|
current_notification = None
|
||||||
|
pixel.fill(clear)
|
||||||
|
pixel.show()
|
||||||
|
|
||||||
|
if not current_notification and not all_ids and not cleared:
|
||||||
|
# updates cleared state for notification
|
||||||
|
cleared = True
|
||||||
|
# turns off NeoPixel when notifications are clear
|
||||||
|
pixel.fill(clear)
|
||||||
|
pixel.show()
|
||||||
|
|
||||||
|
elif all_ids:
|
||||||
|
cleared = False
|
||||||
|
if current_notification and current_notification.id in all_ids:
|
||||||
|
index = all_ids.index(current_notification.id)
|
||||||
|
else:
|
||||||
|
index = len(all_ids) - 1
|
||||||
|
notif_id = all_ids[index]
|
||||||
|
# if there is a notification:
|
||||||
|
if not current_notification or current_notification.id != notif_id:
|
||||||
|
current_notification = current_notifications[notif_id]
|
||||||
|
# parses notification info into a string
|
||||||
|
category = str(notification).split(" ", 1)[0]
|
||||||
|
# haptic motor vibrates
|
||||||
|
vibe(2, vibration, 0.5)
|
||||||
|
# all info for notification is printed to REPL
|
||||||
|
print('-'*36)
|
||||||
|
print("Msg #%d - Category %s" % (notification.id, category))
|
||||||
|
print("From app:", notification.app_id)
|
||||||
|
if notification.title:
|
||||||
|
print("Title:", notification.title)
|
||||||
|
if notification.subtitle:
|
||||||
|
print("Subtitle:", notification.subtitle)
|
||||||
|
if notification.message:
|
||||||
|
print("Message:", notification.message)
|
||||||
|
# NeoPixel blinks and then stays on until cleared
|
||||||
|
blink_pixel(2, 0.5, purple, clear)
|
||||||
|
pixel.fill(purple)
|
||||||
|
pixel.show()
|
||||||
|
# if it's on the hour:
|
||||||
|
if cts.current_time[4] == hour and not mindful:
|
||||||
|
print(cts.current_time[4])
|
||||||
|
print("mindful time")
|
||||||
|
# haptic motor vibrates
|
||||||
|
vibe(5, vibration, 1)
|
||||||
|
# NeoPixel blinks and then stays on
|
||||||
|
blink_pixel(5, 1, blue, clear)
|
||||||
|
mindful = True
|
||||||
|
pixel.fill(blue)
|
||||||
|
pixel.show()
|
||||||
|
print("hour = ", hour)
|
||||||
|
# if it's no longer on the hour:
|
||||||
|
if cts.current_time[4] == (hour + 1) and mindful:
|
||||||
|
# NeoPixel turns off
|
||||||
|
mindful = False
|
||||||
|
pixel.fill(clear)
|
||||||
|
pixel.show()
|
||||||
|
print("mindful time over")
|
||||||
|
|
||||||
|
# if BLE becomes disconnected then blue LED turns off
|
||||||
|
# and BLE begins advertising again to reconnect
|
||||||
|
print("Disconnected")
|
||||||
|
blue_led.value = False
|
||||||
|
print()
|
||||||
|
ble.start_advertising(advertisement)
|
||||||
|
notification_service = None
|
||||||
Loading…
Reference in a new issue