# HG changeset patch # User darius@Inchoate # Date 1232165571 -37800 # Node ID ac60a9244bdf76e3e4355631ee8db090e68afd54 # Parent 729f2393f29672a846e3546cc7ebf789a95e3139 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. diff -r 729f2393f296 -r ac60a9244bdf zbmux.py --- a/zbmux.py Sat Jan 17 14:39:50 2009 +1030 +++ b/zbmux.py Sat Jan 17 14:42:51 2009 +1030 @@ -28,10 +28,12 @@ from twisted.internet.serialport import SerialPort from twisted.internet.protocol import Protocol +from twisted.conch.telnet import TelnetTransport, TelnetBootstrapProtocol +from twisted.conch.insults import insults from twisted.protocols import basic from twisted.internet import protocol, reactor from twisted.python import log -import sys, zb, logging, logging.handlers +import sys, zb, logging, logging.handlers, string portname = '/dev/cuaU0' baudrate = 38400 @@ -39,27 +41,52 @@ baseport = 1080 zbids = [1, 2] -class ZBClient(basic.LineReceiver): +class ZBClient(insults.TerminalProtocol): """Client for the TCP connection""" - + #: Time to wait before sending pending data (seconds) + QUEUE_TIME = 0.1 + def connectionMade(self): log.msg("Got new client") - self.factory.clients.append(self) + log.msg("Me - %s, terminal - %s" % (str(type(self)), str(type(self.terminal)))) + self.terminal.eraseDisplay() + self.terminal.resetPrivateModes([]) + + # Send the last whole line we've seen out if self.factory.lastline != None: self.message(self.factory.lastline) + + self.pending = "" + self.pendtimer = None + self.factory.clients.append(self) def connectionLost(self, reason): log.msg("Lost a client") self.factory.clients.remove(self) - - def lineReceived(self, line): - """Got a line - send it to our ZB module""" - #log.msg("Got line " + line) - self.factory.proto.sendData(self.factory.zbid, line + '\n') - + + def keystrokeReceived(self, keyID, modifier): + """Got some data, add it to the pending output queue""" + if modifier != None: + print "Received unhandled modifier: %s" % (str(modifier)) + return + #if keyID not in string.printable: + # print "Received unhandled keyID: %r" % (keyID,) + # return + #log.msg("Got key ->%s<-" % (keyID)) + self.pending = self.pending + keyID + if self.pendtimer == None: + self.pendtimer = reactor.callLater(self.QUEUE_TIME, self.sendData) + + def sendData(self): + """Send pending data to module""" + #log.msg("sending " + self.pending) + self.factory.zbproto.sendData(self.factory.zbid, self.pending) + self.pending = "" + self.pendtimer = None + def message(self, message): """Called to write a mesage to our client""" - self.transport.write(message) + self.terminal.write(message) class ZBFactory(protocol.ServerFactory): """Factory for a ZB module @@ -68,9 +95,8 @@ """ protocol = ZBClient - def __init__(self, zbid, proto, lognamebase): + def __init__(self, zbid, lognamebase): self.zbid = zbid - self.proto = proto self.clients = [] self.tmpline = "" self.lastline = None @@ -118,19 +144,21 @@ #log.msg("Rx'd from %d => %s" % (a.sender, a.payloadstr)) for f in self.factories: f.message(a.sender, a.payloadstr) - + if type(a) == type(zb.TX_Status()): + #log.msg("Tx status for frame %d is %s" % (a.frameid, a.statusMsg)) + pass + def sendData(self, zbid, data): """Sends a chunk of data to our ZB module""" #log.msg("%d <= %s" % (zbid, data)) - + # Chop up data into pieces the module can handle - maxsz = 10 - #maxsz = zb.TX_16_Bit.PKT_MAX_PAYLOAD + maxsz = zb.TX_16_Bit.PKT_MAX_PAYLOAD for i, j in zip(range(0, len(data), maxsz), range(maxsz, len(data) + maxsz, maxsz)): p = zb.TX_16_Bit(zbid, data[i:j]) self.transport.write(p.Pack()) #log.msg("sent " + str(p)) - + if __name__ == '__main__': logFile = sys.stdout log.startLogging(logFile) @@ -141,8 +169,12 @@ # Per-module TCP listener for id in zbids: - zbfactory = ZBFactory(id, zbproto, lognamebase) - zbproto.factories.append(zbfactory) - reactor.listenTCP(baseport + id, zbfactory) + f = ZBFactory(id, lognamebase) + f.zbproto = zbproto + f.protocol = lambda: TelnetTransport(TelnetBootstrapProtocol, + insults.ServerProtocol, + ZBClient) + zbproto.factories.append(f) + reactor.listenTCP(baseport + id, f) reactor.run()