-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSkyMoteCommandResponseService.py
108 lines (93 loc) · 4.23 KB
/
SkyMoteCommandResponseService.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
# SkyMoteCommandResponseService - Handles the command/reponse side of comms.
from twisted.internet.protocol import Protocol, ServerFactory
from twisted.internet import defer
import os
import struct
class SkyMoteCommandResponseProtocol(Protocol):
# Twisted calls these functions
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):
"""
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])
else:
print "dataReceived: got data. length: %d" % len(data)
print "dataReceived: ",
print [ hex(ord(c)) for c in data ]
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()
elif data.lower().startswith("crh"):
# Close and re-open handleOnly
sleepTime = int(data[3])
self.factory.exchanger.closeAndReopenDevice(sleepTime, True)
elif data.lower().startswith("rst"):
# Close and re-open normally
sleepTime = int(data[3])
self.factory.exchanger.closeAndReopenDevice(sleepTime)
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
results = struct.pack("B" * len(data), *data)
print "responseReceived: len of packet", len(results)
print "type(self.transport)", type(self.transport), self.transport
self.transport.writeSomeData(results)
def closeConnection(self):
print "Connection # %s closing connection." % (self.connectionNumber)
os.close(self.transport.fileno())
return True
class SkyMoteCommandResponseFactory(ServerFactory):
protocol = SkyMoteCommandResponseProtocol
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)
def clientConnectionLost(self, connector, reason):
print "Lost connection: %s" % reason.getErrorMessage()