modified system to work with threads
This commit is contained in:
parent
2190feafcc
commit
0517035110
|
@ -0,0 +1,197 @@
|
||||||
|
def inttouint32(v):
|
||||||
|
return chr(v&0xff)+chr((v>>8)&0xff)+chr((v>>16)&0xff)+chr((v>>24)&0xff)
|
||||||
|
|
||||||
|
def uint32toint(v):
|
||||||
|
return (ord(v[3])<< 24) + (ord(v[2])<<16) + (ord(v[1])<<8) + (ord(v[0]))
|
||||||
|
|
||||||
|
class Packet:
|
||||||
|
def __init__(self, command, id=None, ctr=None):
|
||||||
|
if id == None and ctr == None:
|
||||||
|
message = command
|
||||||
|
command = message[2]
|
||||||
|
id = uint32toint(message[3:7])
|
||||||
|
ctr = uint32toint(message[7:11])
|
||||||
|
self.length = 32
|
||||||
|
self.protocol = 'G'
|
||||||
|
self.command = command
|
||||||
|
self.id = id
|
||||||
|
self.ctr = ctr
|
||||||
|
|
||||||
|
def toMessage(self):
|
||||||
|
message = chr(self.length)
|
||||||
|
message += self.protocol
|
||||||
|
message += self.command
|
||||||
|
message += inttouint32(self.id)
|
||||||
|
message += inttouint32(self.ctr)
|
||||||
|
return message
|
||||||
|
|
||||||
|
def headerString(self):
|
||||||
|
return "id=%d, ctr=%d"%(self.id, self.ctr)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Packet with protocol=" + self.protocol
|
||||||
|
s += ", command=" + self.command
|
||||||
|
s += ", "+ self.headerString()
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Button(Packet):
|
||||||
|
def __init__(self, id, ctr=None, button=None):
|
||||||
|
if ctr != None and button!= None:
|
||||||
|
Packet.__init__(self, 'B', id, ctr)
|
||||||
|
else:
|
||||||
|
message = id
|
||||||
|
Packet.__init__(self, message)
|
||||||
|
button = ord(message[11])
|
||||||
|
self.button = button
|
||||||
|
|
||||||
|
def toMessage(self):
|
||||||
|
base = Packet.toMessage(self)
|
||||||
|
return base + chr(self.button) + '\x00'*18
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Button packet with " + self.headerString()
|
||||||
|
s += ", button=%d"%self.button
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Announce(Packet):
|
||||||
|
def __init__(self, id, ctr, gameMac, gameChannel, gameId, gameFlags, gameTitle):
|
||||||
|
Packet.__init__(self, 'A', id, ctr)
|
||||||
|
self.gameMac = gameMac
|
||||||
|
self.gameChannel = gameChannel
|
||||||
|
self.gameId = gameId
|
||||||
|
self.gameFlags = gameFlags
|
||||||
|
self.gameTitle = gameTitle[0:8]
|
||||||
|
|
||||||
|
def toMessage(self):
|
||||||
|
message = Packet.toMessage(self)
|
||||||
|
message += ''.join([chr(x) for x in self.gameMac])
|
||||||
|
message += chr(self.gameChannel)
|
||||||
|
message += inttouint32(self.gameId)
|
||||||
|
message += chr(self.gameFlags)
|
||||||
|
message += self.gameTitle
|
||||||
|
if len(self.gameTitle) < 8:
|
||||||
|
message += '\x00'*(8-len(self.gameTitle))
|
||||||
|
return message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Announce packet with " + self.headerString()
|
||||||
|
s += ", gameMac="+str(self.gameMac)
|
||||||
|
s += ", gameChannel=%d"%self.gameChannel
|
||||||
|
s += ", gameId=%d"%self.gameId
|
||||||
|
s += ", gameFlags=%d"%self.gameFlags
|
||||||
|
s += ", gameTitle="+self.gameTitle
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Join(Packet):
|
||||||
|
def __init__(self, id, ctr=None, gameId=None):
|
||||||
|
if ctr != None and gameId != None:
|
||||||
|
Packet.__init__(self, 'J', id, ctr)
|
||||||
|
else:
|
||||||
|
message = id
|
||||||
|
Packet.__init__(self, message)
|
||||||
|
gameId = uint32toint(message[11:15])
|
||||||
|
self.gameId = gameId
|
||||||
|
|
||||||
|
def toMessage(self):
|
||||||
|
message = Packet.toMessage(self)
|
||||||
|
message += inttouint32(self.gameId)
|
||||||
|
message += '\x00'*15
|
||||||
|
return message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Join packet with " + self.headerString()
|
||||||
|
s += ", gameId=%d"%self.gameId
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Ack(Packet):
|
||||||
|
def __init__(self, id, ctr=None, flags=None):
|
||||||
|
if ctr != None and flags != None:
|
||||||
|
Packet.__init__(self, 'a', id, ctr)
|
||||||
|
else:
|
||||||
|
message = id
|
||||||
|
Packet.__init__(self, message)
|
||||||
|
flags = ord(message[11])
|
||||||
|
self.flags = flags
|
||||||
|
|
||||||
|
def toMessage(self):
|
||||||
|
message = Packet.toMessage(self)
|
||||||
|
message += chr(self.flags)
|
||||||
|
message += '\x00'*18
|
||||||
|
return message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Ack packet with " + self.headerString()
|
||||||
|
s += ", flags=%d"%self.flags
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Nickrequest(Packet):
|
||||||
|
def __init__(self, id, ctr):
|
||||||
|
Packet.__init__(self, 'N', id, ctr)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Nickrequest packet with " + self.headerString()
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Nick(Packet):
|
||||||
|
def __init__(self, id, ctr=None, flags=None, nick=None):
|
||||||
|
if ctr != None and flags != None and nick != None:
|
||||||
|
Packet.__init__(self, 'n', id, ctr)
|
||||||
|
else:
|
||||||
|
message = id
|
||||||
|
Packet.__init__(self, message)
|
||||||
|
flags = ord(message[11])
|
||||||
|
nick = message[12:30].rstrip(' \t\r\n\0')
|
||||||
|
self.flags = flags
|
||||||
|
self.nick = nick
|
||||||
|
|
||||||
|
def toMessage(self):
|
||||||
|
message = Packet.toMessage(self)
|
||||||
|
message += chr(self.flags)
|
||||||
|
message += self.nick
|
||||||
|
if len(self.nick) < 18:
|
||||||
|
message += '\x00'*(18-len(self.nick))
|
||||||
|
return message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Nick packet with " + self.headerString()
|
||||||
|
s += ", flags=%d"%self.flags
|
||||||
|
s += ", nick="+self.nick
|
||||||
|
return s
|
||||||
|
|
||||||
|
class Text(Packet):
|
||||||
|
def __init__(self, id, ctr, x, y, flags, text):
|
||||||
|
Packet.__init__(self, 'T', id, ctr)
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self. flags = flags
|
||||||
|
self.text = text[0:16]
|
||||||
|
|
||||||
|
def toMessage(self):
|
||||||
|
message = Packet.toMessage(self)
|
||||||
|
message += chr(self.x)
|
||||||
|
message += chr(self.y)
|
||||||
|
message += chr(self.flags)
|
||||||
|
message += self.text
|
||||||
|
if len(self.text) < 16:
|
||||||
|
message += '\x00'*(16-len(self.text))
|
||||||
|
return message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
s = "Text packet with " + self.headerString()
|
||||||
|
s += ", x=%d"%self.x
|
||||||
|
s += ", y=%d"%self.y
|
||||||
|
s += ", flags=%d"%self.flags
|
||||||
|
s += ", text="+self.text
|
||||||
|
return s
|
||||||
|
|
||||||
|
def fromMessage(message):
|
||||||
|
if len(message) >= 30 and ord(message[0]) == 32 and message[1] == 'G':
|
||||||
|
if message[2] == 'B':
|
||||||
|
return Button(message)
|
||||||
|
if message[2] == 'n':
|
||||||
|
return Nick(message)
|
||||||
|
if message[2] == 'J':
|
||||||
|
return Join(message)
|
||||||
|
if message[2] == 'a':
|
||||||
|
return Ack(message)
|
||||||
|
return None
|
|
@ -1,25 +1,135 @@
|
||||||
import serialinterface
|
import serialinterface
|
||||||
import thread
|
|
||||||
import threading
|
import threading
|
||||||
import Queue
|
import Queue
|
||||||
import crcmod
|
import crcmod
|
||||||
|
import packets
|
||||||
|
|
||||||
class r0ket:
|
class QueuePacket:
|
||||||
|
def __init__(self, channel, mac, acked, packet):
|
||||||
|
self.channel = channel
|
||||||
|
self.mac = mac
|
||||||
|
self.acked = acked
|
||||||
|
self.packet = packet
|
||||||
|
self.priority = 5
|
||||||
|
self.retriesleft = 5
|
||||||
|
self.timeout = 0.1
|
||||||
|
self.timer = None
|
||||||
|
self.timedout = False
|
||||||
|
self.lock = threading.RLock()
|
||||||
|
self.isdone = False
|
||||||
|
|
||||||
|
def __cmp__(self, other):
|
||||||
|
if not isinstance(other,QueuePacket):
|
||||||
|
return 1
|
||||||
|
if self.priority < other.priority:
|
||||||
|
return -1
|
||||||
|
if self.priority > other.priority:
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def valid(self):
|
||||||
|
with self.lock:
|
||||||
|
return self.retriesleft > 0 and not self.acked
|
||||||
|
|
||||||
|
def sent(self, timeoutcallback):
|
||||||
|
with self.lock:
|
||||||
|
self.timedout = False
|
||||||
|
if self.acked:
|
||||||
|
self.timeoutcallback = timeoutcallback
|
||||||
|
self.timer = threading.Timer(self.timeout, self.timercallback)
|
||||||
|
self.timer.start()
|
||||||
|
|
||||||
|
def done(self):
|
||||||
|
with self.lock:
|
||||||
|
if self.timer != None:
|
||||||
|
self.timer.cancel()
|
||||||
|
self.timer = None
|
||||||
|
self.isdone = True
|
||||||
|
|
||||||
|
def timercallback(self):
|
||||||
|
with self.lock:
|
||||||
|
self.timedout = True
|
||||||
|
self.timeoutcallback(self)
|
||||||
|
|
||||||
|
class Bridge:
|
||||||
def __init__(self, path2device):
|
def __init__(self, path2device):
|
||||||
self.ser = serialinterface.SerialInterface(path2device, 115200, 0)
|
self.ser = serialinterface.SerialInterface(path2device, 115200, 0)
|
||||||
self.free = threading.Lock()
|
self.free = threading.Lock()
|
||||||
self.packets = Queue.Queue()
|
self.queueslock = threading.Lock()
|
||||||
thread.start_new_thread(self.readerThread,())
|
self.packets = Queue.PriorityQueue()
|
||||||
self.setPacketLength(0x20)
|
self.outpackets = Queue.Queue()
|
||||||
self.crc = crcmod.predefined.mkCrcFun('crc-ccitt-false')
|
self.crc = crcmod.predefined.mkCrcFun('crc-ccitt-false')
|
||||||
|
self.queues = {}
|
||||||
|
|
||||||
|
self.reader = threading.Thread(target = self.readerThread)
|
||||||
|
self.reader.daemon = True
|
||||||
|
|
||||||
|
self.writer = threading.Thread(target = self.writerThread)
|
||||||
|
self.writer.daemon = True
|
||||||
|
|
||||||
|
self.writer.start()
|
||||||
|
self.reader.start()
|
||||||
|
|
||||||
def writeCommand(self, command, data):
|
self.setPacketLength(0x20)
|
||||||
crc = self.crc(data)
|
self.setTxMAC((1,2,3,2,1))
|
||||||
data += chr(crc>>8);
|
self.setRxMAC((1,2,3,2,1))
|
||||||
data += chr(crc&0xFF);
|
self.setChannel(81)
|
||||||
self.free.acquire()
|
|
||||||
print 'sending command:', command, 'len:', len(data), 'data:', list(data)
|
def registerQueue(self, queue):
|
||||||
self.ser.writeMessage(command,data);
|
if queue not in self.queues:
|
||||||
|
self.queues[queue] = None
|
||||||
|
|
||||||
|
def putInQueue(self, queue, qp):
|
||||||
|
if queue in self.queues:
|
||||||
|
queue.put(qp);
|
||||||
|
self.checkQueues()
|
||||||
|
|
||||||
|
def processAck(self, ack):
|
||||||
|
#find the corresponding packet in the queues
|
||||||
|
found = False
|
||||||
|
for pq in self.queues.values():
|
||||||
|
if pq.packet.id == ack.id and pq.packet.ctr == ack.ctr:
|
||||||
|
#notify it
|
||||||
|
pq.done()
|
||||||
|
found = True
|
||||||
|
#notify the queue system
|
||||||
|
if found:
|
||||||
|
self.checkQueues()
|
||||||
|
else:
|
||||||
|
print "got an ack for an unknown packet"
|
||||||
|
|
||||||
|
def packetTimeout(self, qp):
|
||||||
|
self.checkQueues()
|
||||||
|
|
||||||
|
def checkQueues(self):
|
||||||
|
with self.queueslock:
|
||||||
|
for q in self.queues:
|
||||||
|
#check if a packet has to be resent
|
||||||
|
#remove it from the packet slot if it has been resent to often
|
||||||
|
qp = self.queues[q]
|
||||||
|
if qp != None:
|
||||||
|
if qp.valid():
|
||||||
|
self.queues[q] = None
|
||||||
|
elif qp.timedout:
|
||||||
|
print "packet timed out" + qp.packet
|
||||||
|
self.outpackets.put(qp)
|
||||||
|
#check if a idle queue has a new packet in line
|
||||||
|
qp = self.queues[q]
|
||||||
|
if qp == None and not q.empty():
|
||||||
|
qp = q.get()
|
||||||
|
self.queues[q] = qp
|
||||||
|
self.outpackets.put(qp)
|
||||||
|
|
||||||
|
def writerThread(self):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
#wait until we have packets to take care of
|
||||||
|
qp = self.outpackets.get()
|
||||||
|
#send it and notify the queuepacket
|
||||||
|
self.sendPacket(qp.packet)
|
||||||
|
qp.sent(self.packetTimeout)
|
||||||
|
except Exception as e:
|
||||||
|
print e
|
||||||
|
|
||||||
def readerThread(self):
|
def readerThread(self):
|
||||||
while True:
|
while True:
|
||||||
|
@ -36,8 +146,15 @@ class r0ket:
|
||||||
print e
|
print e
|
||||||
|
|
||||||
def newPacket(self, data):
|
def newPacket(self, data):
|
||||||
print "received:", list(data)
|
#print "received:", list(data)
|
||||||
self.packets.put(data)
|
crc = self.crc(data[:-2])
|
||||||
|
if data[-2:] == chr(crc>>8) + chr(crc&0xFF):
|
||||||
|
packet = packets.fromMessage(data)
|
||||||
|
print "received:", packet
|
||||||
|
if isinstance(packet,packets.Ack):
|
||||||
|
self.ProcessAck(packet)
|
||||||
|
else:
|
||||||
|
self.packets.put(packet)
|
||||||
|
|
||||||
def gotPacket(self):
|
def gotPacket(self):
|
||||||
return not self.packets.empty()
|
return not self.packets.empty()
|
||||||
|
@ -46,8 +163,28 @@ class r0ket:
|
||||||
return self.packets.get()
|
return self.packets.get()
|
||||||
|
|
||||||
def sendPacket(self, packet):
|
def sendPacket(self, packet):
|
||||||
self.writeCommand('1', packet)
|
print 'sending', packet
|
||||||
|
data = packet.toMessage()
|
||||||
|
crc = self.crc(data)
|
||||||
|
data += chr(crc>>8);
|
||||||
|
data += chr(crc&0xFF);
|
||||||
|
self.free.acquire()
|
||||||
|
#print 'sending packet: len:', len(data), 'data:', list(data)
|
||||||
|
self.ser.writeMessage('1',data);
|
||||||
|
|
||||||
def setPacketLength(self, length):
|
def setPacketLength(self, length):
|
||||||
self.free.acquire()
|
self.free.acquire()
|
||||||
self.ser.writeMessage('6', '%c'%length)
|
self.ser.writeMessage('6', '%c'%length)
|
||||||
|
|
||||||
|
def setTxMAC(self, mac):
|
||||||
|
self.free.acquire()
|
||||||
|
self.ser.writeMessage('3', ''.join([chr(x) for x in mac]))
|
||||||
|
|
||||||
|
def setRxMAC(self, mac):
|
||||||
|
self.free.acquire()
|
||||||
|
self.ser.writeMessage('4', ''.join([chr(x) for x in mac]))
|
||||||
|
|
||||||
|
def setChannel(self, channel):
|
||||||
|
self.free.acquire()
|
||||||
|
self.ser.writeMessage('5', '%c'%channel)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
import r0ketrem0te.rem0te
|
import r0ketrem0te.rem0te
|
||||||
|
import r0ketrem0te.packets
|
||||||
import time
|
import time
|
||||||
r = r0ketrem0te.rem0te.r0ket('/dev/ttyACM0')
|
import Queue
|
||||||
|
|
||||||
|
announcequeue = Queue.Queue()
|
||||||
|
r = r0ketrem0te.rem0te.Bridge('/dev/ttyACM0')
|
||||||
|
|
||||||
|
r.registerQueue(announcequeue)
|
||||||
|
|
||||||
|
a = r0ketrem0te.packets.Announce(0,2,(1,2,3,2,1), 81, 1, 0, "testgame")
|
||||||
|
aq = r0ketrem0te.rem0te.QueuePacket(81, (1,2,3,2,1), False, a)
|
||||||
|
aq.priority = 4
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
r.sendPacket("\x20GA\x00\x00\x00\x00\x01\x02\x03\x04\x01\x02\x03\x01\x02\x51\x01\x02\x03\x04\x00test\x00\x06\x07\x08")
|
r.putInQueue(announcequeue, aq)
|
||||||
time.sleep(1)
|
for i in range(1,1000):
|
||||||
#packet = r.getPacket()
|
if r.gotPacket():
|
||||||
#print list(packet)
|
packet = r.getPacket()
|
||||||
#r.sendPacket('12345678901234567890123456789012')
|
if isinstance(packet, r0ketrem0te.packets.Join):
|
||||||
|
r.sendPacket(r0ketrem0te.packets.Ack(packet.id, packet.ctr, 1))
|
||||||
|
time.sleep(.001)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue