blesleep/vibrate.py

197 lines
7.9 KiB
Python

import time
import random
import logging
# Notes:
# The miband4 does not (seem to) support different vibration intensities, rather the values sent (2-255)
# represent how long the vibration motor runs. A value of 30 roughly corresponds to 60ms of motor run time.
# Sending a value of 255 triggecd rs continuous vibration.
# Currently "continuous" mode doesn't work, as it doesn't turn off.
# This will be fixed shortly.
class Vibrate():
vibrate_band = None
vibration_log = None
heartrate_increase_pct = 0
def __init__(self, band):
self.vibrate_band = band
FORMAT = '%(asctime)-15s %(name)s (%(levelname)s) > %(message)s'
logging.basicConfig(format=FORMAT)
vibration_log_level = logging.INFO
self.vibration_log = logging.getLogger(__name__)
self.vibration_log.setLevel(vibration_log_level)
def heartrate_alarm(self, settings):
interval_minutes = settings['interval_minutes']
duration_seconds = settings['duration_seconds']
vibration_type = settings['type']
heartrate_alarm_pct = settings['heartrate_alarm_pct']
tick_time = time.time()
buzz_delay = interval_minutes * 60
buzz_timer = tick_time - buzz_delay
self.vibration_log.info("Starting heartrate alarm timer, alarming at {} percent for {} seconds with a {} minute interval".format(
heartrate_alarm_pct,
duration_seconds,
interval_minutes))
if vibration_type not in ['random', 'pattern', 'rolling', 'continuous']:
self.vibration_log.warn("Invalid or no vibration type specified: {}".format(type))
self.vibration_log.warn("Must be one of these: random, pattern, rolling, continuous")
return
while True:
elapsed_time = tick_time - buzz_timer
if elapsed_time >= buzz_delay and self.heartrate_increase_pct >= heartrate_alarm_pct:
self.vibration_log.info("Heartrate alarm triggered at {} percent, buzzing".format(self.heartrate_increase_pct))
if vibration_type == 'random':
self.vibrate_random(duration_seconds)
elif vibration_type == 'pattern':
self.vibrate_pattern(duration_seconds)
elif vibration_type == 'rolling':
self.vibrate_rolling(duration_seconds)
elif vibration_type == 'continuous':
self.vibrate_continuous(duration_seconds)
buzz_timer = tick_time
elif not elapsed_time >= buzz_delay and self.heartrate_increase_pct >= heartrate_alarm_pct:
self.vibration_log.info("Heartrate alarm threshold reached ({} percent) but timout not expired".format(self.heartrate_increase_pct))
else:
tick_time = time.time()
time.sleep(0.5)
def timed_vibration(self, settings):
interval_minutes = settings['interval_minutes']
duration_seconds = settings['duration_seconds']
type = settings['type']
buzz_timer = time.time()
tick_time = time.time()
buzz_delay = interval_minutes * 60
self.vibration_log.info("Starting vibration timer: {} minutes".format(interval_minutes))
if type not in ['random', 'pattern', 'rolling', 'continuous']:
self.vibration_log.warn("Invalid or no vibration type specified: {}".format(type))
self.vibration_log.warn("Must be one of these: random, pattern, rolling, continuous")
return
while True:
elapsed_time = tick_time - buzz_timer
if elapsed_time >= buzz_delay:
print("Buzz timer expired, buzzing")
if type == 'random':
self.vibrate_random(duration_seconds)
elif type == 'pattern':
self.vibrate_pattern(duration_seconds)
elif type == 'rolling':
self.vibrate_rolling(duration_seconds)
elif type == 'continuous':
self.vibrate_continuous(duration_seconds)
buzz_timer = tick_time
else:
tick_time = time.time()
time.sleep(0.5)
def generate_random_vibration_pattern(self, pulse_count):
#pulse_duration_range and pulse_interval_range_ms are arbitrary
pulse_duration_range = {
'low': 80,
'high': 120
}
pulse_interval_range_ms = {
'low': 100,
'high': 800
}
output_pulse_pattern = []
for _ in range(pulse_count):
pulse_duration = random.randrange(pulse_duration_range['low'], pulse_duration_range['high'])
pulse_interval = random.randrange(pulse_interval_range_ms['low'], pulse_interval_range_ms['high'])/1000
output_pulse_pattern.append([pulse_duration, pulse_interval])
return output_pulse_pattern
def vibrate_random(self, duration_seconds):
print("Sending random vibration...")
duration_start = time.time()
pattern_length = 20 #This value is arbitrary
pulse_pattern = self.generate_random_vibration_pattern(pattern_length)
while True:
if (time.time() - duration_start) >= duration_seconds:
print ("Stopping vibration")
self.vibrate_band.vibrate(0)
break
else:
for pattern in pulse_pattern:
if (time.time() - duration_start) >= duration_seconds:
break
vibrate_ms = pattern[0]
vibro_delay = pattern[1]
self.vibrate_band.vibrate(vibrate_ms)
time.sleep(vibro_delay)
def vibrate_pattern(self, duration_seconds):
print("Sending vibration...")
duration_start = time.time()
#This pattern is an example.
pulse_pattern = [[30, 0.01], [60, 0.01], [90, 0.01], [120, 0.01], [150, 0.01], [180, 0.01]]
while True:
if (time.time() - duration_start) >= duration_seconds:
print ("Stopping vibration")
self.vibrate_band.vibrate(0)
break
else:
for pattern in pulse_pattern:
if (time.time() - duration_start) >= duration_seconds:
break
vibrate_ms = pattern[0]
vibro_delay = pattern[1]
self.vibrate_band.vibrate(vibrate_ms)
time.sleep(vibro_delay)
def vibrate_rolling(self, duration_seconds):
print("Sending rolling vibration...")
duration_start = time.time()
while True:
if (time.time() - duration_start) >= duration_seconds:
print ("Stopping vibration")
self.vibrate_band.vibrate(0)
break
else:
for x in range(10):
for x in range(20, 40, 1):
self.vibrate_band.vibrate(x)
for x in range(40, 20, -1):
self.vibrate_band.vibrate(x)
def vibrate_continuous(self, duration_seconds):
#Currently broken, still working on this bit.
print("Sending continuous vibration...")
duration_start = time.time()
while True:
if (time.time() - duration_start) >= duration_seconds:
print ("Stopping vibration")
self.vibrate_band.vibrate(0)
break
else:
self.vibrate_band.vibrate(1)