/ Bluetooth_Restroom_Keys / code.py
code.py
1 # SPDX-FileCopyrightText: 2020 Anne Barela for Adafruit Industries 2 # 3 # SPDX-License-Identifier: MIT 4 5 """Bluetooth Key Tracker.""" 6 from adafruit_ble import BLERadio 7 from adafruit_led_animation.animation import Pulse, Solid 8 import adafruit_led_animation.color as color 9 from analogio import AnalogIn 10 from array import array 11 from audiobusio import I2SOut 12 from audiocore import RawSample, WaveFile 13 from board import BATTERY, D5, D6, D9, NEOPIXEL, RX, TX 14 from digitalio import DigitalInOut, Direction, Pull 15 from math import pi, sin 16 from neopixel import NeoPixel 17 from time import sleep 18 19 battery = AnalogIn(BATTERY) 20 21 ble = BLERadio() 22 hit_status = [color.RED, color.ORANGE, color.AMBER, color.GREEN] 23 24 pixel = NeoPixel(NEOPIXEL, 1) 25 pulse = Pulse(pixel, 26 speed=0.01, 27 color=color.PURPLE, # Use CYAN for Male Key 28 period=3, 29 min_intensity=0.0, 30 max_intensity=0.5) 31 32 solid = Solid(pixel, color.GREEN) 33 34 reed_switch = DigitalInOut(D5) 35 reed_switch.direction = Direction.INPUT 36 reed_switch.pull = Pull.UP 37 38 amp_enable = DigitalInOut(D6) 39 amp_enable.direction = Direction.OUTPUT 40 amp_enable.value = False 41 42 43 def play_tone(): 44 """Generate tone and transmit to I2S amp.""" 45 length = 4000 // 440 46 sine_wave = array("H", [0] * length) 47 for i in range(length): 48 sine_wave[i] = int(sin(pi * 2 * i / 18) * (2 ** 15) + 2 ** 15) 49 50 sample = RawSample(sine_wave, sample_rate=8000) 51 i2s = I2SOut(TX, RX, D9) 52 i2s.play(sample, loop=True) 53 sleep(1) 54 i2s.stop() 55 sample.deinit() 56 i2s.deinit() 57 58 59 def play_message(): 60 """Play recorded WAV message and transmit to I2S amp.""" 61 with open("d1.wav", "rb") as file: 62 wave = WaveFile(file) 63 i2s = I2SOut(TX, RX, D9) 64 i2s.play(wave) 65 while i2s.playing: 66 pass 67 wave.deinit() 68 i2s.deinit() 69 70 71 boundary_violations = 0 72 73 while True: 74 if reed_switch.value: # Not Docked 75 hits = 0 76 try: 77 advertisements = ble.start_scan(timeout=3) 78 for advertisement in advertisements: 79 addr = advertisement.address 80 if (advertisement.scan_response and 81 addr.type == addr.RANDOM_STATIC): 82 if advertisement.complete_name == '<Your 1st beacon name here>': 83 hits |= 0b001 84 elif advertisement.complete_name == '<Your 2nd beacon name here>': 85 hits |= 0b010 86 elif advertisement.complete_name == '<Your 3rd beacon name here>': 87 hits |= 0b100 88 except Exception as e: 89 print(repr(e)) 90 hit_count = len([ones for ones in bin(hits) if ones == '1']) 91 solid.color = hit_status[hit_count] 92 solid.animate() 93 sleep(1) 94 if hit_count == 0: 95 if boundary_violations % 60 == 0: # Play message every 60 cycles 96 amp_enable.value = True 97 sleep(1) 98 play_tone() 99 sleep(1) 100 play_message() 101 sleep(1) 102 amp_enable.value = False 103 boundary_violations += 1 104 else: 105 boundary_violations = 0 106 107 else: # Docked 108 boundary_violations = 0 109 voltage = battery.value * 3.3 / 65535 * 2 110 if voltage < 3.7: 111 pulse.period = 1 # Speed up LED pulse for low battery 112 else: 113 pulse.period = 3 114 pulse.animate()