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:
BlitzCityDIY 2020-05-10 15:34:26 -04:00
parent d2f4fb1dae
commit 7d59b0e2bf

179
BLE_Buzzy_Box/code.py Normal file
View 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