You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
6.7 KiB
229 lines
6.7 KiB
#!/usr/bin/env python3 |
|
import sys |
|
import os, math, random |
|
import time |
|
import socket |
|
import struct |
|
import select |
|
from threading import Thread |
|
import bluetooth |
|
import wiiboard |
|
|
|
known_boards = {'niklas': '00:26:59:34:C8:69', |
|
'kaka': '00:26:59:37:04:15', |
|
'michael': '00:24:44:65:5B:F8', |
|
'fed': '00:23:CC:23:5E:1D', |
|
} |
|
|
|
class StatusThread(Thread): |
|
def __init__(self, t1, t2): |
|
Thread.__init__(self) |
|
self.t1 = t1 |
|
self.t2 = t2 |
|
self.stop = False |
|
|
|
def run(self): |
|
t1 = self.t1 |
|
t2 = self.t2 |
|
colw = 50 |
|
batw = colw - len('Bat: 000% || ') |
|
while not self.stop: |
|
print('') |
|
print(('Left player - '+t1.addr).ljust(colw) + 'Right player - '+t2.addr) |
|
print('-'*2*colw) |
|
if t1.addr != 'dummy': |
|
if t1.connected: |
|
s1 = 'Connected' |
|
bat = t1.board.battery |
|
else: |
|
s1 = 'Connecting...' |
|
bat = -1 |
|
else: |
|
s1 = 'Dummy' |
|
bat = 0.42 |
|
px = 'Low ' if t1.pos_x is None else '%.3f'%t1.pos_x |
|
py = 'Low ' if t1.pos_y is None else '%.3f'%t1.pos_y |
|
p1 = 'Position: X: %s - Y: %s' % (px, py) |
|
if bat is not None: |
|
b1 = 'Bat: |%s| %03d%%' % (('='*int(batw*bat)).ljust(batw), int(bat*100)) |
|
else: |
|
b1 = 'Bat: |%s| ---%%' % ('?'*batw).ljust(batw) |
|
w1 = 'Weight: %.1f' % t1.weight |
|
|
|
if t2.addr != 'dummy': |
|
if t2.connected: |
|
s2 = 'Connected' |
|
bat = t2.board.battery |
|
else: |
|
s2 = 'Connecting...' |
|
bat = -1 |
|
else: |
|
s2 = 'Dummy' |
|
bat = 0.42 |
|
px = 'Low ' if t2.pos_x is None else '%.3f'%t2.pos_x |
|
py = 'Low ' if t2.pos_y is None else '%.3f'%t2.pos_y |
|
p2 = 'Position: X: %s - Y: %s' % (px, py) |
|
if bat is not None: |
|
b2 = 'Bat: |%s| %03d%%' % (('='*int(batw*bat)).ljust(batw), int(bat*100)) |
|
else: |
|
b2 = 'Bat: |%s| ---%%' % ('?'*batw).ljust(batw) |
|
w2 = 'Weight: %.1f' % t2.weight |
|
|
|
print(s1.ljust(colw) + s2) |
|
print(b1.ljust(colw) + b2) |
|
print(w1.ljust(colw) + w2) |
|
print(p1.ljust(colw) + p2) |
|
|
|
time.sleep(1) |
|
|
|
class WiiThread(Thread): |
|
def __init__(self, player, addr): |
|
Thread.__init__(self) |
|
self.addr = addr |
|
self.player = player |
|
self.stop = False |
|
self.connected = False |
|
self.board = None |
|
self.pos_x = None |
|
self.pos_y = None |
|
self.weight = 0 |
|
|
|
def run(self): |
|
if self.addr != 'dummy': |
|
while not self.stop: |
|
self.connected = False |
|
self.pos = 'C' |
|
self.board = wiiboard.Wiiboard() |
|
print('%s: Connecting to %s' % (self.player, self.addr)) |
|
try: |
|
self.board.connect(self.addr) |
|
except bluetooth.btcommon.BluetoothError: |
|
continue |
|
|
|
time.sleep(1) |
|
print('%s: Connected' % self.player) |
|
self.connected = True |
|
self.board.setLight(True) |
|
|
|
while not self.stop and self.board.status == 'Connected': |
|
self.weight = self.board.mass.totalWeight |
|
if self.board.mass.totalWeight > 15: |
|
m = self.board.mass |
|
x_balance = -(m.topLeft+m.bottomLeft) + (m.topRight+m.bottomRight) |
|
x_balance = x_balance/float(m.totalWeight) |
|
y_balance = -(m.bottomLeft+m.bottomRight) + (m.topLeft+m.topRight) |
|
y_balance = y_balance/float(m.totalWeight) |
|
self.pos_x = x_balance |
|
self.pos_y = y_balance |
|
else: |
|
self.pos_x = None |
|
self.pos_y = None |
|
|
|
time.sleep(0.1) |
|
|
|
self.board.disconnect() |
|
else: |
|
print('%s: Connected as DUMMY' % self.player) |
|
self.connected = True |
|
self.pos = 'D' |
|
|
|
wiis = [] |
|
if len(sys.argv) > 1: |
|
if sys.argv[1] in list(known_boards.keys()): |
|
addr = known_boards[sys.argv[1]] |
|
else: |
|
addr = sys.argv[1] |
|
t1 = WiiThread('L', addr) |
|
else: |
|
t1 = WiiThread('') |
|
|
|
t1.daemon = True |
|
t1.start() |
|
|
|
if len(sys.argv) > 2: |
|
if sys.argv[2] in list(known_boards.keys()): |
|
addr = known_boards[sys.argv[2]] |
|
else: |
|
addr = sys.argv[2] |
|
t2 = WiiThread('R', addr) |
|
else: |
|
t2 = WiiThread('') |
|
|
|
while not t1.connected: |
|
time.sleep(0.1) |
|
|
|
t2.daemon = True |
|
t2.start() |
|
|
|
while not t2.connected: |
|
time.sleep(0.1) |
|
|
|
tStatus = StatusThread(t1, t2) |
|
tStatus.daemon = True |
|
tStatus.start() |
|
|
|
wiis = [t1, t2] |
|
|
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
|
s.bind(('', 4711)) |
|
s.listen(1) |
|
|
|
try: |
|
conns = [] |
|
while True: |
|
rlist, wlist, xlist = select.select([s]+conns, [], conns) |
|
if s in rlist: |
|
conn, addr = s.accept() |
|
conns.append(conn) |
|
rlist.remove(s) |
|
|
|
for sock in xlist: |
|
conns.remove(sock) |
|
|
|
for sock in rlist: |
|
try: |
|
m = sock.recv(1) |
|
except Exception: |
|
conns.remove(sock) |
|
continue |
|
|
|
r = b'' |
|
for w in wiis: |
|
if m[0] == ord('w'): |
|
# Return weight |
|
v = 0 |
|
if w.weight is not None: |
|
v = round(w.weight) |
|
r += struct.pack('b', v) |
|
elif m[0] == ord('b'): |
|
# Return battery |
|
v = 0 |
|
if w.board.battery is not None: |
|
v = round(w.board.battery*100) |
|
r += struct.pack('b', v) |
|
else: |
|
# Return balance |
|
if w.pos_x is None: |
|
v = -128 |
|
else: |
|
v = int(round(w.pos_x*100)) |
|
r += struct.pack('b', v) |
|
if w.pos_y is None: |
|
v = -128 |
|
else: |
|
v = int(round(w.pos_y*100)) |
|
r += struct.pack('b', v) |
|
|
|
try: |
|
sock.send(r) |
|
except Exception: |
|
conns.remove(sock) |
|
continue |
|
|
|
except (KeyboardInterrupt, SystemExit): |
|
t1.stop = True |
|
t2.stop = True |
|
tStatus.stop = True |
|
sys.exit() |
|
|
|
|