Skip to content

Instantly share code, notes, and snippets.

@hexagon5un
Created January 11, 2023 16:42
Show Gist options
  • Save hexagon5un/8af6f6b52a429895094454bba40b1773 to your computer and use it in GitHub Desktop.
Save hexagon5un/8af6f6b52a429895094454bba40b1773 to your computer and use it in GitHub Desktop.
Quick and dirty Spacemouse test
#! /usr/bin/env python3
import serial
import subprocess
SENSITIVITY=250
PORT1="/dev/ttyUSB1"
DEBUG = False
DELAY = 0.25 ## seconds, prevents race
## commands all end with \r
def getSpacemouse(s):
"""Read a command. Think about how to do smartly/flush here"""
cmd = s.read_until(DELIM)
cmd = cmd.decode()
return cmd
validData = {"0":0, "A":1, "B":2, "3":3, "D":4, "5":5, "6":6, "G":7, "H":8,
"9":9, ":":10, "K":11, "<":12, "M":13, "N":14, "?":15}
def readNibble(byte):
try:
return validData[byte]
except KeyError():
return None
def buildWord(nibbleArray):
runningSum = 0
runningSum = runningSum + 4096 * nibbleArray.pop(0)
runningSum = runningSum + 256 * nibbleArray.pop(0)
runningSum = runningSum + 16 * nibbleArray.pop(0)
runningSum = runningSum + nibbleArray.pop(0)
runningSum = runningSum - 32768
return runningSum, nibbleArray
def parseDirection(cmd):
nibbleArray = [readNibble(x) for x in cmd]
values = []
while len(nibbleArray):
val, nibbleArray = buildWord(nibbleArray)
values.append(val)
return values
def parseKeys(cmd):
return cmd
def plotme(val):
spaces = int((val + 500)/10)
print( spaces*" " + "#" )
commands = {"d":parseDirection, "k":parseKeys}
def handleMouse(serialPort):
cmd = getSpacemouse(serialPort)
if cmd: ## returns '' if nothing on line
cmdType = cmd[0]
cmd = cmd[1:].strip()
try:
foo = commands[cmdType](cmd)
if DEBUG:
for f in foo:
plotme(f)
print
except:
print(len(cmd))
print(cmdType)
print(cmd)
serialPort.flush()
def scrollMouse(serialPort):
cmd = getSpacemouse(serialPort)
if cmd: ## returns '' if nothing on line
cmdType = cmd[0]
cmd = cmd[1:].strip()
try:
foo = commands[cmdType](cmd)
if DEBUG:
print(foo.decode())
xaxis = int(foo[0])
vertical = int(foo[1])
yaxis = int(foo[2])
pitch = int(foo[3])
yaw = int(foo[4])
roll = int(foo[5])
## Pitch = scrollwheel up/down
if pitch > 1:
for i in range(int(pitch/SENSITIVITY)+1):
subprocess.Popen(["xdotool", "click","5"])
if pitch < -1:
for i in range(int(-pitch/SENSITIVITY)+1):
subprocess.Popen(["xdotool", "click","4"])
## turn CW opens in new tab (middle mouse click)
if yaw < -30:
os.system("xdotool click 2")
time.sleep(DELAY)
## push down closes page
if vertical < -50:
os.system("xdotool type d")
time.sleep(DELAY)
## pull up undoes last close
if vertical > 50:
os.system("xdotool type u")
time.sleep(DELAY)
## shove left/right moves to prev/next tab
if xaxis < -50:
os.system("xdotool type K")
time.sleep(DELAY)
if xaxis > 50:
os.system("xdotool type J")
time.sleep(DELAY)
## rolling to right goes to forum next
if roll < -50:
os.system("xdotool type ]]")
time.sleep(DELAY)
## rolling to right follows link
# if roll < -50:
# os.system("xdotool click 1")
# time.sleep(DELAY)
## rolling to left goes backwards in history
if roll > 50:
os.system("xdotool type H")
time.sleep(DELAY)
except:
# handle keys
if cmd == "A00":
os.system("xdotool type bhad\n")
os.system("xdotool key Return")
elif cmd == "0B0": # left button
os.system("xdotool type [[")
elif cmd == "0D0": # right button
os.system("xdotool type ]]")
elif cmd == "0A0": # 5
os.system("xdotool type o")
os.system("xdotool key Escape")
elif cmd == "0H0": # 8
os.system("xdotool key Escape")
os.system("xdotool type ,p")
elif cmd == "000":
pass
else:
print("ERR0R: " + cmd)
serialPort.flushInput()
def writeout(serialport, seq):
"""writes out byte sequence to pass serial port"""
serialport.write(bytes(seq, encoding="ascii"))
if __name__ == "__main__":
TIMEOUT=0.1
DELIM="\r".encode("ascii")
import os
import time
import sys
if len(sys.argv) == 2:
PORT = sys.argv[1]
else:
PORT = PORT1
print("Trying " + PORT)
s = serial.Serial(baudrate=9600, stopbits=2, port=PORT, timeout=TIMEOUT)
time.sleep(0.1)
s.flush()
time.sleep(0.1)
print("Initializing...")
writeout(s,"vQ\r")
print(s.read(100).decode())
writeout(s,"mG\r") # both axes, dominant only mode
print(s.read(100).decode())
writeout(s,"nM\r") # default sensitivity radius -- rather large
print(s.read(100).decode())
writeout(s,"q00\r") # linear scaling for both translation and rotation
print(s.read(100).decode())
while(True):
# handleMouse(s)
scrollMouse(s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment