-
Notifications
You must be signed in to change notification settings - Fork 0
/
server-asyncio.py
executable file
·169 lines (131 loc) · 4.42 KB
/
server-asyncio.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#!/usr/bin/env python3
import xwiimote
from time import sleep
import struct
import asyncio
import functools
import websockets
import socket
import signal
import serverutils
# watched wiimotes
wiimotes = []
connections = []
udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def print_wiimote(dev):
print("syspath:" + dev.get_syspath())
fd = dev.get_fd()
print("fd:", fd)
def read_monitor(mon, wiimotes):
# For once this PC is too fast, can't open the interface until the device
# has settled
# 0 gives no error for open, events come through fine but no keys
# 1/4.0 gives 13 permission denied
# 1/2.0 works fine it seems, might want to crank it up incase of errors
sleep(1/2.0)
newmotes = []
wiimote_path = mon.poll()
while wiimote_path is not None:
try:
dev = xwiimote.iface(wiimote_path)
wiimotes.append(dev)
# enable rumble and IR
dev.open(dev.available() | xwiimote.IFACE_WRITABLE | xwiimote.IFACE_IR )
newmotes.append(dev)
except IOError as eo:
print("Fail on creating the wiimote (", eo, ")")
wiimote_path = mon.poll()
return newmotes
def remove_device(wiimotes, dev):
if dev in wiimotes:
wiimotes.remove(dev)
# Do i need to specify IR here?
dev.close(xwiimote.IFACE_WRITABLE | xwiimote.IFACE_IR )
handled_events = {
xwiimote.EVENT_IR,
xwiimote.EVENT_ACCEL,
xwiimote.EVENT_KEY,
xwiimote.EVENT_GONE
}
def send_udp(message):
for websocket in connections:
if websocket.open:
udpSock.sendto(message,(websocket.remote_address[0],9001))
def send_ws(message):
for websocket in connections:
if websocket.open:
asyncio.ensure_future(websocket.send(message))
def wiimote_event(dev):
event = xwiimote.event()
try:
dev.dispatch(event)
except BlockingIOError:
return
if event.type not in handled_events:
return
message = bytearray(struct.pack("<?i",False,dev.get_fd()))
message.extend(serverutils.xwiimote_event_to_bytearray(event))
message_bytes = bytes(message)
if event.type == xwiimote.EVENT_ACCEL or event.type == xwiimote.EVENT_MOTION_PLUS or event.type == xwiimote.EVENT_IR:
send_udp(message_bytes)
else:
send_ws(message_bytes)
if event.type == xwiimote.EVENT_GONE:
remove_device(wiimotes,dev)
def _wiimote_monitor_event(mon,loop):
newmotes = read_monitor(mon, wiimotes)
for dev in newmotes:
loop.add_reader(dev.get_fd(), functools.partial(wiimote_event, dev))
for websocket in connections:
asyncio.ensure_future(websocket.send(struct.pack("<?i",True,dev.get_fd())))
async def handle(websocket,path):
connections.append(websocket)
print("Client connected")
for dev in wiimotes:
asyncio.ensure_future(websocket.send(struct.pack("<?i",True,dev.get_fd())))
try:
while True:
message = await websocket.recv()
if type(message) == bytes:
message_type = struct.unpack("<i",message[:4])[0]
# rumble
if message_type == 1:
fd, state = struct.unpack_from("<ii",message[4:16])
for dev in wiimotes:
if dev.get_fd() == fd:
dev.rumble(state == 1)
elif message is str:
print("Got a s message" + message)
except websockets.exceptions.ConnectionClosed as e:
print("Client disconnected")
connections.remove(websocket)
try:
mon = xwiimote.monitor(True, True)
except SystemError as e:
print("ooops, cannot create monitor (", e, ")")
exit(1)
loop = asyncio.get_event_loop()
wiimote_monitor_event = functools.partial(_wiimote_monitor_event,mon,loop)
# get current wiimotes
wiimote_monitor_event()
print("Starting websocket server")
start_server = websockets.serve(handle, '', 9000)
server_task = loop.run_until_complete(start_server)
print("Websocket server started")
# def sigint_handler():
# print('Stopping')
#
# server_task.close()
#
# for task in asyncio.Task.all_tasks():
# task.cancel()
#
# loop.add_signal_handler(signal.SIGINT, sigint_handler)
print("Monitoring wiimote events")
loop.add_reader(mon.get_fd(False), wiimote_monitor_event)
print("Starting event loop")
loop.run_forever()
# cleaning
for dev in wiimotes:
remove_device(wiimotes, dev)
exit(0)