#!/usr/bin/env python import select import re import time import array import struct """*****************************************************""" """ """ """ Software Defines & Parmeters """ """ """ """*****************************************************""" SOFTWARE_VERSION = '1.0' RS232_BAUDRATE = 115200 SERVER_TCP_IP = '192.168.1.1' SERVER_TCP_PORT = 3081 SERVER_BUFFER_SIZE = 128 SERVER_TIMEOUT = 600 RETRIES = 3 """*****************************************************""" """ """ """ Numeriflash Xml Parser """ """ """ """*****************************************************""" from xml.dom import minidom class NumeriflashXmlParser: @staticmethod def getValueNode( node ): for nv in node.childNodes: if nv.nodeType == 1: ##Node.ELEMENT_NODE: if nv.nodeName == "value": return nv @staticmethod def parseCommandNode( node ): """ A command node should have the following form : XXXXX """ try: nv = NumeriflashXmlParser.getValueNode( node ) name = node.attributes.item(0).value try: type = nv.attributes.item(0).value except: type = None try: val = nv.childNodes[0].nodeValue except: val = None if type is None: return (name, val) elif type == "i" or type == "l": return (name, int( val )) elif type == "f" or type == "d": return (name, float( val )) else: return (name, val) except: return None @staticmethod def parse( data ): doc = minidom.parseString( data ) """ First, get Numeriflash Node """ node_Numeriflash = None for node in doc.childNodes: if node.nodeType == 1: ##Node.ELEMENT_NODE: if node.nodeName == "Numeriflash": node_Numeriflash = node break if node_Numeriflash is None: return None """ Then, get the command node(s) """ resList = [] for node in node_Numeriflash.childNodes: if node.nodeType == 1: ##Node.ELEMENT_NODE: if node.nodeName == "command": res = NumeriflashXmlParser.parseCommandNode( node ) if not res is None: resList.append( res ) return resList """*****************************************************""" """ """ """ Numeriflash Xml Server """ """ """ """*****************************************************""" import threading import socket class NumeriflashXmlServerThread( threading.Thread ): devLock = threading.Condition(threading.Lock()) watchdog = False buf = None def __init__(self, conn, ip, port, device=None, NumeriflashCompat=True, args=None): threading.Thread.__init__( self ) self.__conn = conn self.__ip = ip self.__port = port self.__compat = NumeriflashCompat self.__device = device self.__dargs = args self.Terminated = False print( 'Connected to ' + ip ) self.start() def stop(self): self.Terminated = True self.__conn.close() def __recoverSerial( self ): NumeriflashXmlServerThread.devLock.acquire() self.__device.close() NumeriflashXmlServerThread.devLock.release() def __listen( self ): while( True ): data = self.__conn.recv( SERVER_BUFFER_SIZE ) if not data: raise IOError( 'No data received' ) try: start = data.index( '' ) end = data.index( '', start ) res = data[ start:(end+14) ] #self.buf = data[ (end+14): ] return res except: pass def __send( self, msg ): msglen = len(msg) totalsent = 0 while totalsent < msglen: sent = self.__conn.send( msg[totalsent:] ) if sent == 0: print( 'socket connection broken' ) raise IOError( 'socket connection broken' ) totalsent = totalsent + sent def __parseRequest( self, data ): res = NumeriflashXmlParser.parse( data ) name = (res[0])[0] value = (res[0])[1] return ( ( name, value ), Samsung2Distec.S2D( name, value ) )[ self.__compat ] def __execute( self, name, value ): NumeriflashXmlServerThread.devLock.acquire() try: result = None if value is None: result = self.__device.cmd( name ) else: result = self.__device.cmd( name, value ) except: NumeriflashXmlServerThread.devLock.release() raise NumeriflashXmlServerThread.devLock.release() return result def __validate( self, name, value ): if ( name=='Power' and value==2 ) or ( name=='Power' and value==8 ) or ( name=='MainSourceInput' and value==1 ) or ( name=='MainSourceInput' and value==2 ): return False else: return True def run( self ): while not self.Terminated: cname = None cvalue = None resname = None resvalue = None res = None # I - Recive data from client try: data = self.__listen() except Exception, e: print "Unexpected error 0 :", e print( 'Socket Timeout => Connection closed by remote client' ) break # II - Parse request try: cname, cvalue = self.__parseRequest( data ) except Exception, e: print "Unexpected error:", e print( 'Failed to parse client request' ) try: self.__send( 'Invalid or malformed request' ) except: print( 'Socket Error => Connection closed by remote client' ) break continue # III - Execute command try: command = envbox_db.getCommandByName( cname ) # Avoid timeout for Numeriflash Compatibility if command is None: try: ( resname, resvalue ) = ( ( cname, cvalue ), Samsung2Distec.D2S( cname, cvalue ) )[ self.__compat ] self.__send( '' ) except Exception, e: print "Unexpected error:", e print( 'Socket Error => Connection closed by remote client' ) break continue if cname=='Power': if not cvalue is None: if cvalue == 0: try: self.__device.cmd( 'PowerOffType', 0 ) except: pass for i in range( 0, RETRIES ): try: res = self.__execute( cname, cvalue ) except: print( 'Serial IO Error' ) self.__recoverSerial() res = None if res is None: print( 'Serial port timeout' ) self.__recoverSerial() elif not self.__validate( cname, res ): print( 'Bug : Unexpected value returned by envbox (' + cname + '=' + str( res ) + ')' ) self.__recoverSerial() res=None else: break except: print( 'Serial IO Error' ) self.__recoverSerial() try: self.__send( 'error' ) except Exception, e: print "Unexpected error 2:", e print( 'Socket Error => Connection closed by remote client' ) break continue # IV - Build response try: ( resname, resvalue ) = ( ( cname, res ), Samsung2Distec.D2S( cname, res ) )[ self.__compat ] if not resvalue is None: msg = '' + str(resvalue) + '' else: msg = '' + 'error' + '' except: pass # V - Send response try: self.__send( msg ) except Exception, e: print "Unexpected error 3:", e print( 'Socket Error => Connection closed by remote client' ) break # VI - Tick watchdog NumeriflashXmlServerThread.watchdog = False # # End run function # print( 'Connection from ' + str(self.__ip) + ':' + str(self.__port) + ' closed' )