My design decisions were:
- Power on indicator: Use the color cycling at a low brightness of the Dotstar to indicate that the Gemma is powered on.
- Move mouse 1/minute: Randomly choose -1 pixel or 1 pixel motion for each axis. The mouse will always move on screen edges, and will move 75% of the time in the corners.
- Indicate movement to user: Because the movement is only 1 pixel and easy to not notice, flash the Dotstar white at full brightness when moving the mouse.
Code: Select all
# Nudge the mouse once a minute to defeat timed lock using Gemma
# Using AdaFruit's "wheel" helper function to cycle colors on the on-board LED
import board
import time
import random
from analogio import AnalogIn
import adafruit_dotstar as dotstar
from adafruit_hid.mouse import Mouse
# Configuration variables
cycleBrightness = 0.1 # Brightness of LED during normal color cycling. Default = 0.1
nudgeBrightness = 1 # Brightness of LED for nudge flash. Default = 1
nudgeColor = [255, 255, 255] # Color of LED for nudge flash. Default = [255, 255, 255]
nudgeDistance = 1 # Distance to move mouse during the nudge. Default = 1
nudgeDelay = 60 # Interval between nudges (in whole seconds). Default = 60
nudgeFlashLength = 0.1 # Length of nudge flash. This is a blocking delay. Default = 0.1
# One pixel connected internally!
dot = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1)
# Analog input on A1
analogin = AnalogIn(board.A1)
# initialize random number generator
random.seed(analogin.value)
# HID mouse
m = Mouse()
# ######################## HELPERS ##############################
# Helper to nudge mouse randomly,
def nudge():
x = random.choice([(nudgeDistance * -1), nudgeDistance])
y = random.choice([(nudgeDistance * -1), nudgeDistance])
m.move(x, y, 0)
dot.brightness = nudgeBrightness
dot[0] = nudgeColor
time.sleep(0.1)
# Helper to give us a nice color swirl
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if (pos < 0):
return [0, 0, 0]
if (pos > 255):
return [0, 0, 0]
if (pos < 85):
return [int(pos * 3), int(255 - (pos*3)), 0]
elif (pos < 170):
pos -= 85
return [int(255 - pos*3), 0, int(pos*3)]
else:
pos -= 170
return [0, int(pos*3), int(255 - pos*3)]
# ######################## MAIN LOOP ##############################
i = 0
currentNudgeTimeCheck = 0
lastNudgeTimeCheck = 0
while True:
# spin internal LED around!
dot.brightness = cycleBrightness
dot[0] = wheel(i)
dot.show()
currentNudgeTimeCheck = time.monotonic() // 1 # round to 1 second accuracy
if (((currentNudgeTimeCheck % nudgeDelay) == 0) &
(currentNudgeTimeCheck != lastNudgeTimeCheck)):
nudge()
lastNudgeTimeCheck = currentNudgeTimeCheck
i = (i+1) % 256 # run from 0 to 255