#!/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' )