Mercurial > ~darius > hgwebdir.cgi > ZigBee
comparison zbmux.py @ 14:ac60a9244bdf
Use proper telnet protocol classes.
Means we use raw/character at a time stuff and don't get extra echos. Keeps
track of each line to log it to the file as well as printing the last seen
line on client connect.
author | darius@Inchoate |
---|---|
date | Sat, 17 Jan 2009 14:42:51 +1030 |
parents | a3ec3f2988ac |
children | a472d6eab97e |
comparison
equal
deleted
inserted
replaced
13:729f2393f296 | 14:ac60a9244bdf |
---|---|
26 # SUCH DAMAGE. | 26 # SUCH DAMAGE. |
27 # | 27 # |
28 | 28 |
29 from twisted.internet.serialport import SerialPort | 29 from twisted.internet.serialport import SerialPort |
30 from twisted.internet.protocol import Protocol | 30 from twisted.internet.protocol import Protocol |
31 from twisted.conch.telnet import TelnetTransport, TelnetBootstrapProtocol | |
32 from twisted.conch.insults import insults | |
31 from twisted.protocols import basic | 33 from twisted.protocols import basic |
32 from twisted.internet import protocol, reactor | 34 from twisted.internet import protocol, reactor |
33 from twisted.python import log | 35 from twisted.python import log |
34 import sys, zb, logging, logging.handlers | 36 import sys, zb, logging, logging.handlers, string |
35 | 37 |
36 portname = '/dev/cuaU0' | 38 portname = '/dev/cuaU0' |
37 baudrate = 38400 | 39 baudrate = 38400 |
38 lognamebase = '/tmp/zbmux-%d.log' | 40 lognamebase = '/tmp/zbmux-%d.log' |
39 baseport = 1080 | 41 baseport = 1080 |
40 zbids = [1, 2] | 42 zbids = [1, 2] |
41 | 43 |
42 class ZBClient(basic.LineReceiver): | 44 class ZBClient(insults.TerminalProtocol): |
43 """Client for the TCP connection""" | 45 """Client for the TCP connection""" |
44 | 46 #: Time to wait before sending pending data (seconds) |
47 QUEUE_TIME = 0.1 | |
48 | |
45 def connectionMade(self): | 49 def connectionMade(self): |
46 log.msg("Got new client") | 50 log.msg("Got new client") |
47 self.factory.clients.append(self) | 51 log.msg("Me - %s, terminal - %s" % (str(type(self)), str(type(self.terminal)))) |
52 self.terminal.eraseDisplay() | |
53 self.terminal.resetPrivateModes([]) | |
54 | |
55 # Send the last whole line we've seen out | |
48 if self.factory.lastline != None: | 56 if self.factory.lastline != None: |
49 self.message(self.factory.lastline) | 57 self.message(self.factory.lastline) |
58 | |
59 self.pending = "" | |
60 self.pendtimer = None | |
61 self.factory.clients.append(self) | |
50 | 62 |
51 def connectionLost(self, reason): | 63 def connectionLost(self, reason): |
52 log.msg("Lost a client") | 64 log.msg("Lost a client") |
53 self.factory.clients.remove(self) | 65 self.factory.clients.remove(self) |
54 | 66 |
55 def lineReceived(self, line): | 67 def keystrokeReceived(self, keyID, modifier): |
56 """Got a line - send it to our ZB module""" | 68 """Got some data, add it to the pending output queue""" |
57 #log.msg("Got line " + line) | 69 if modifier != None: |
58 self.factory.proto.sendData(self.factory.zbid, line + '\n') | 70 print "Received unhandled modifier: %s" % (str(modifier)) |
59 | 71 return |
72 #if keyID not in string.printable: | |
73 # print "Received unhandled keyID: %r" % (keyID,) | |
74 # return | |
75 #log.msg("Got key ->%s<-" % (keyID)) | |
76 self.pending = self.pending + keyID | |
77 if self.pendtimer == None: | |
78 self.pendtimer = reactor.callLater(self.QUEUE_TIME, self.sendData) | |
79 | |
80 def sendData(self): | |
81 """Send pending data to module""" | |
82 #log.msg("sending " + self.pending) | |
83 self.factory.zbproto.sendData(self.factory.zbid, self.pending) | |
84 self.pending = "" | |
85 self.pendtimer = None | |
86 | |
60 def message(self, message): | 87 def message(self, message): |
61 """Called to write a mesage to our client""" | 88 """Called to write a mesage to our client""" |
62 self.transport.write(message) | 89 self.terminal.write(message) |
63 | 90 |
64 class ZBFactory(protocol.ServerFactory): | 91 class ZBFactory(protocol.ServerFactory): |
65 """Factory for a ZB module | 92 """Factory for a ZB module |
66 | 93 |
67 Represents a remote ZB module and has zero or more clients and a log file. | 94 Represents a remote ZB module and has zero or more clients and a log file. |
68 """ | 95 """ |
69 protocol = ZBClient | 96 protocol = ZBClient |
70 | 97 |
71 def __init__(self, zbid, proto, lognamebase): | 98 def __init__(self, zbid, lognamebase): |
72 self.zbid = zbid | 99 self.zbid = zbid |
73 self.proto = proto | |
74 self.clients = [] | 100 self.clients = [] |
75 self.tmpline = "" | 101 self.tmpline = "" |
76 self.lastline = None | 102 self.lastline = None |
77 | 103 |
78 # Open logger | 104 # Open logger |
116 #log.msg("type is " + str(type(a))) | 142 #log.msg("type is " + str(type(a))) |
117 if type(a) == type(zb.RX_16_Bit()): | 143 if type(a) == type(zb.RX_16_Bit()): |
118 #log.msg("Rx'd from %d => %s" % (a.sender, a.payloadstr)) | 144 #log.msg("Rx'd from %d => %s" % (a.sender, a.payloadstr)) |
119 for f in self.factories: | 145 for f in self.factories: |
120 f.message(a.sender, a.payloadstr) | 146 f.message(a.sender, a.payloadstr) |
121 | 147 if type(a) == type(zb.TX_Status()): |
148 #log.msg("Tx status for frame %d is %s" % (a.frameid, a.statusMsg)) | |
149 pass | |
150 | |
122 def sendData(self, zbid, data): | 151 def sendData(self, zbid, data): |
123 """Sends a chunk of data to our ZB module""" | 152 """Sends a chunk of data to our ZB module""" |
124 #log.msg("%d <= %s" % (zbid, data)) | 153 #log.msg("%d <= %s" % (zbid, data)) |
125 | 154 |
126 # Chop up data into pieces the module can handle | 155 # Chop up data into pieces the module can handle |
127 maxsz = 10 | 156 maxsz = zb.TX_16_Bit.PKT_MAX_PAYLOAD |
128 #maxsz = zb.TX_16_Bit.PKT_MAX_PAYLOAD | |
129 for i, j in zip(range(0, len(data), maxsz), range(maxsz, len(data) + maxsz, maxsz)): | 157 for i, j in zip(range(0, len(data), maxsz), range(maxsz, len(data) + maxsz, maxsz)): |
130 p = zb.TX_16_Bit(zbid, data[i:j]) | 158 p = zb.TX_16_Bit(zbid, data[i:j]) |
131 self.transport.write(p.Pack()) | 159 self.transport.write(p.Pack()) |
132 #log.msg("sent " + str(p)) | 160 #log.msg("sent " + str(p)) |
133 | 161 |
134 if __name__ == '__main__': | 162 if __name__ == '__main__': |
135 logFile = sys.stdout | 163 logFile = sys.stdout |
136 log.startLogging(logFile) | 164 log.startLogging(logFile) |
137 | 165 |
138 # ZigBee serial protocol handler | 166 # ZigBee serial protocol handler |
139 zbproto = ZBProto() | 167 zbproto = ZBProto() |
140 SerialPort(zbproto, portname, reactor, baudrate = 38400) | 168 SerialPort(zbproto, portname, reactor, baudrate = 38400) |
141 | 169 |
142 # Per-module TCP listener | 170 # Per-module TCP listener |
143 for id in zbids: | 171 for id in zbids: |
144 zbfactory = ZBFactory(id, zbproto, lognamebase) | 172 f = ZBFactory(id, lognamebase) |
145 zbproto.factories.append(zbfactory) | 173 f.zbproto = zbproto |
146 reactor.listenTCP(baseport + id, zbfactory) | 174 f.protocol = lambda: TelnetTransport(TelnetBootstrapProtocol, |
175 insults.ServerProtocol, | |
176 ZBClient) | |
177 zbproto.factories.append(f) | |
178 reactor.listenTCP(baseport + id, f) | |
147 | 179 |
148 reactor.run() | 180 reactor.run() |