diff --git a/SkyMoteCommandResponseService.py b/SkyMoteCommandResponseService.py index 4be36d4..63346d8 100644 --- a/SkyMoteCommandResponseService.py +++ b/SkyMoteCommandResponseService.py @@ -10,10 +10,18 @@ class SkyMoteCommandResponseProtocol(Protocol): def connectionMade(self): print "SkyMoteCommandResponseProtocol connectionMade: made connection" self.connectionNumber = self.factory.connectionNumber + self.factory.connectionNumber += 1 + self.queuedJobs = list() + if self.factory.inLockdown: + self.locked = True + else: + self.locked = False self.factory.connections[self.connectionNumber] = self def connectionLost(self, reason): print "SkyMoteCommandResponseProtocol connectionLost: reason: %s" % str(reason) + if self.factory.inLockdown and not self.locked: + self.factory.unlockEveryone() self.factory.connections.pop(self.connectionNumber) def dataReceived(self, data): @@ -21,14 +29,33 @@ def dataReceived(self, data): Twisted calls this function when we received data TODO: Check for fragments """ + if self.locked: + print "Locked connection got data. Stashing for later..." + d = defer.Deferred() + d.addCallback(self.responseReceived) + self.queuedJobs.append([data, d]) + + return True + print "dataReceived: got data. length: %d" % len(data) print "dataReceived: ", print [ hex(ord(c)) for c in data ] - d = defer.Deferred() - d.addCallback(self.responseReceived) - - readBytes = self.factory.writeRead(data, d) + if len(data.strip()) == 4: + data = data.strip() + print "Got special command:", data + if data.lower() == "lock": + # Prevent others from talking to this device + self.factory.lockout(self.connectionNumber) + elif data.lower() == "done": + # Allow others to talk to the device + self.factory.unlockEveryone() + else: + d = defer.Deferred() + d.addCallback(self.responseReceived) + + #self.factory.exchanger.newPacketEvent.set() + readBytes = self.factory.writeRead(data, d) def responseReceived(self, data): print "responseReceived: Got results:", data @@ -50,7 +77,24 @@ def __init__(self, exchanger): self.exchanger = exchanger self.connectionNumber = 0 self.connections = dict() + self.inLockdown = False + + def lockout(self, connectionNumber): + # Locks everyone except for one + print "Locking out everyone except ", connectionNumber + self.inLockdown = True + for n, c in self.connections.items(): + if n != connectionNumber: + c.locked = True + def unlockEveryone(self): + for c in self.connections.values(): + c.locked = False + while len(c.queuedJobs) != 0: + j = c.queuedJobs.pop() + self.writeRead(j[0], j[1]) + self.inLockdown = False + def writeRead(self, writeMessage, resultDeferred): return self.exchanger.writeRead(writeMessage, resultDeferred) diff --git a/SkyMoteExchanger.py b/SkyMoteExchanger.py index a02a092..5de130f 100644 --- a/SkyMoteExchanger.py +++ b/SkyMoteExchanger.py @@ -3,6 +3,10 @@ from Queue import Queue import Modbus +from datetime import datetime, timedelta + +BUSY_WAIT_TIME = timedelta(seconds = 0.2) + from twisted.internet import reactor from twisted.application import internet @@ -31,8 +35,9 @@ def __init__(self, device, commandResponsePort, spontaneousPort, serviceCollecti self.spontaneousService.setServiceParent(serviceCollection) self.deviceLost = deviceLostFnx - + self.running = True + self.lastCommandTime = datetime.now() reactor.callInThread(self.loopingRead) @@ -75,6 +80,17 @@ def sendSpontaneousData(self, data): def loopingRead(self): while self.running: + + # Busy wait just for a bit because we recently received a + # command. It's worth busy waiting to see if another will come. + while True: + sleep(0.002) + now = datetime.now() + if now - self.lastCommandTime > BUSY_WAIT_TIME: + break + if not self.commandQueue.empty(): + break + if not self.commandQueue.empty(): self.writeCommandsToDevice() @@ -90,8 +106,8 @@ def loopingRead(self): print "--------------------------------- Calling callback for transId = %s" % transId self.sentCommands[str(transId)].callback(packet) self.sentCommands.pop(str(transId)) - sleep(0.1) - + self.lastCommandTime = datetime.now() + else: #print "Got spontaneous data!" self.sendSpontaneousData(packet)