Mercurial > ~darius > hgwebdir.cgi > ZigBee
view zbmux.py @ 13:729f2393f296
Auto increment frame ID when creating a TX packet.
author | darius@Inchoate |
---|---|
date | Sat, 17 Jan 2009 14:39:50 +1030 |
parents | a3ec3f2988ac |
children | ac60a9244bdf |
line wrap: on
line source
# # Mux the ZB module to TCP ports # # Copyright (c) 2009 # Daniel O'Connor <darius@dons.net.au>. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # from twisted.internet.serialport import SerialPort from twisted.internet.protocol import Protocol from twisted.protocols import basic from twisted.internet import protocol, reactor from twisted.python import log import sys, zb, logging, logging.handlers portname = '/dev/cuaU0' baudrate = 38400 lognamebase = '/tmp/zbmux-%d.log' baseport = 1080 zbids = [1, 2] class ZBClient(basic.LineReceiver): """Client for the TCP connection""" def connectionMade(self): log.msg("Got new client") self.factory.clients.append(self) if self.factory.lastline != None: self.message(self.factory.lastline) 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 message(self, message): """Called to write a mesage to our client""" self.transport.write(message) class ZBFactory(protocol.ServerFactory): """Factory for a ZB module Represents a remote ZB module and has zero or more clients and a log file. """ protocol = ZBClient def __init__(self, zbid, proto, lognamebase): self.zbid = zbid self.proto = proto self.clients = [] self.tmpline = "" self.lastline = None # Open logger self.logger = logging.getLogger('Zigbee-%d' % (zbid)) self.logger.setLevel(logging.DEBUG) # Add the log message handler to the logger handler = logging.handlers.RotatingFileHandler( lognamebase % (zbid), maxBytes = 20 * 1024, backupCount = 5) self.logger.addHandler(handler) def message(self, zbid, message): """Called when we get a message, check it's for us - if it is log it and write to our clients""" if zbid != self.zbid: return for c in self.clients: c.message(message) # Logger is line oriented, convert from packet oriented here self.tmpline = self.tmpline + message tmp = self.tmpline.split('\n') for l in tmp[0:-1]: self.lastline = l # Stores last seen line for new clients self.logger.debug(l.replace('\n', '')) self.tmpline = tmp[-1] class ZBProto(Protocol): """Protocol to handle packets from the ZB module on the serial port""" def __init__(self): self.pkts = zb.Packets() self.factories = [] def dataReceived(self, data): """Parses data from ZB module into packets, calls each factory if a RX packet is received""" #log.msg("Read data " + data) if self.pkts.processstr(data) > 0: while len(self.pkts.pktq) > 0: a = self.pkts.pktq.pop(0) #log.msg("type is " + str(type(a))) if type(a) == type(zb.RX_16_Bit()): #log.msg("Rx'd from %d => %s" % (a.sender, a.payloadstr)) for f in self.factories: f.message(a.sender, a.payloadstr) 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 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) # ZigBee serial protocol handler zbproto = ZBProto() SerialPort(zbproto, portname, reactor, baudrate = 38400) # Per-module TCP listener for id in zbids: zbfactory = ZBFactory(id, zbproto, lognamebase) zbproto.factories.append(zbfactory) reactor.listenTCP(baseport + id, zbfactory) reactor.run()