#!/usr/bin/env python # # Based on simulated XIA PFCU-4 filter controller. # # For usage, see my printUsage function or run me with my -h option. # import getopt import asynchat import asyncore import os #import re import signal import socket import sys #import time DEFAULT_PORT = 31337 def main(args): (port, isDebugOutputEnabled) = parseCommandLineArgs(args) d = ConnectionDispatcher(port, isDebugOutputEnabled) asyncore.loop() def getProgramName(args=None): if args == None: args = sys.argv if len(args) == 0 or args[0] == "-c": return "PROGRAM_NAME" return os.path.basename(args[0]) def parseCommandLineArgs(args): (options, extra) = getopt.getopt(args[1:], "dp:h", ["debug", "port=", "help"]) port = DEFAULT_PORT isDebugOutputEnabled = False for eachOptName, eachOptValue in options: if eachOptName in ("-d", "--debug"): isDebugOutputEnabled = True elif eachOptName in ("-p", "--port"): port = int(eachOptValue) elif eachOptName in ("-h", "--help"): printUsage(sys.stdout) sys.exit(0) if len(extra) > 0: print >> sys.stderr, "Error: unexpected command line argument \"%s\"" % \ extra[0] printUsage(sys.stderr) sys.exit(1) return (port, isDebugOutputEnabled) def printUsage(outStream): print >> outStream, """\ Usage: %s [-dph] Options: -d,--debug Print debug messages to stderr -p,--port=NUMBER Listen on the specified port NUMBER for incoming connections (default: %d) -h,--help Print usage message and exit\ """ % (getProgramName(), DEFAULT_PORT) class ConnectionDispatcher(asyncore.dispatcher): def __init__(self, port, debugOutputEnabled=False): asyncore.dispatcher.__init__(self) self.port = port self.debugOutputEnabled = debugOutputEnabled # xia pfcu 4 example used 16 devices self.device = KevinRelay() self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind(("", port)) self.listen(5) def handle_accept(self): ConnectionSession(self.accept(), self.device, self.debugOutputEnabled) class ConnectionSession(asynchat.async_chat): ## regular expressions, if necessary, can go here def __init__(self, (conn, addr), device, debugOutputEnabled=False): asynchat.async_chat.__init__(self, conn) self.debugOutputEnabled = debugOutputEnabled self.set_terminator("\r") self.outputTerminator = "\r\n" self.device = device self.buffer = "" def collect_incoming_data(self, data): self.buffer = self.buffer + data def found_terminator(self): data = self.buffer self.buffer = "" if self.debugOutputEnabled: print >> sys.stderr, "< \"%s\"" % \ (data + self.get_terminator()).encode("string_escape") self.handleClientRequest(data) def handleClientRequest(self, request): request = request.strip() #print request ## handle actual commands here if len(request) >= 2: if request[0] == chr(254): ## NOTE chr(254) is 376 in octal if request[1] == chr(0): # turn off relay 1 print("Turn off relay 1") self.device.setRelayState(0, 0) elif request[1] == chr(1): # turn on relay 1 print("Turn on relay 1") self.device.setRelayState(0, 1) elif request[1] == chr(2): # turn off relay 2 print("Turn off relay 2") self.device.setRelayState(1, 0) elif request[1] == chr(3): # turn on relay 2 print("Turn on relay 2") self.device.setRelayState(1, 1) elif request[1] == chr(4): # get relay 1 status print("Get relay 1 status") status = self.device.getRelayState(0) self.sendClientResponse("%i" % status) elif request[1] == chr(5): # get relay 2 status print("Get relay 2 status") status = self.device.getRelayState(1) self.sendClientResponse("%i" % status) else: print("Other commands not implemented yet") else: print("First char wasn't the 254") else: print("Command wasn't at least two characters") ## return def sendClientResponse(self, response=""): data = response + self.outputTerminator self.push(data) if self.debugOutputEnabled: print >> sys.stderr, "> \"%s\"" % data.encode("string_escape") class KevinRelay: def __init__(self): self.relayStates = [0, 0] def getRelayState(self, relay): return self.relayStates[relay] def setRelayState(self, relay, state): self.relayStates[relay] = state if __name__ == '__main__': try: # command omitted main(sys.argv) except Exception, e: if isinstance(e, SystemExit): raise e else: print >> sys.stderr print >> sys.stderr, "Error: %s" % e sys.exit(1)