def __init__(self, port): """ Your init sequence and add webserver declaration. """ #Your specific code......... #Add lines : self._wsPort = port self._log = None self.serverUI = BroadcastServer(self._wsPort, self.cb_ServerWS, self._log) # Starting Websocket server
class YourFooPlugin(threading.Thread): """ Your classic declaration domogik plugin class. """ def __init__(self, port): """ Your init sequence and add webserver declaration. """ #Your specific code......... #Add lines : self._wsPort = port self._log = None self.serverUI = BroadcastServer(self._wsPort, self.cb_ServerWS, self._log) # Starting Websocket server # @ param self._wsPort : Port network, which must be opened for external access. # You could get it by plugin configuration : self._wsPort = int(self._configPlug.query('fooplugin', 'wsportserver')) # Port number must be unique for all WsServer instances in all domogik plugins. If port already exist an exception is raised. # So it is the user to be careful. # @ param self.cb_ServerWS : Callback function that must manage messages, see below. If not present or None server don't dispatch messages to plugin # @ param self._log : It can be log instance like self.log object of XplPlugin class or other log déclaration # if present or not None server log some infos, debug and error in this instance. #......Your specific code......... def cb_ServerWS(self, message): """ Callback to handle messages from server Websocket, principaly UI. Messages type resquest with or without Ack required. This an example you can develop it as you want !. You have just tu respect header ack message, see end function. """ blockAck = False # Using if it necessary to block Ack message for any reason. report = {'error': 'message not handle'} # Reporting structure for data to report in message, It's better having an error key to handle it in UI. ackMsg = {} # Ack structure, for particulars params print "Handle a Requesting Call Back from UI" , message # debug code if message['header']['type'] in ('req', 'req-ack'): # check if a message type is a request. if message['request'] == 'foorequest1' : # here manage your own functions. report = self.foofunction1(message['fooparam']) # Call your function, possibly with the parameters retrieved from the message. # Attribute resulte in report structure JSON with error key empty if no error. # example : {'error':"", 'fookey': "that you want", ...... } if not report['footest'] : blockAck = True # Possibly add blocking ack for example. elif message['request'] == 'foorequest2' : report = self.foofunction2() ackMsg['fooparam'] = message['yourparticularparam'] # If you need to recover a particular parameter in ack message you can assigned here. elif message['request'] == 'foorequest3' : if message.has_key('fooparam2'): # put all tests you want. report = self.foofunction3(message['fooparam1'], message['fooparam2']) else : report = {'error': 'Invalide foo param2 format.'} # handle error key in local callback. else : report['error'] ='unknown request' # handle unknown request case. print "unknown request" # debug code if message['header']['type'] == 'req-ack' and not blockAck : # check and prepare ack message ackMsg['header'] = {'type': 'ack', 'idws' : message['header']['idws'], 'idmsg' : message['header']['idmsg'], 'ip' : message['header']['ip'] , 'timestamp' : long(time.time()*100)} # header composition keys : # - 'type': here must be 'ack'. # - 'idws' : recover orignal header key (message['header']['idws']), it's identify resquesting client. # - 'idmsg: recover orignal header key (message['header']['idmsg']), it's identify the individual resquet. # - 'ip' : recover orignal header key (message['header']['ip']), it's identify resquesting IP client. # - 'timestamp' : must be updated to give a reference time. ackMsg['request'] = message['request'] if 'error' in report : # put error in ack structure if necessary ackMsg['error'] = report['error'] else : ackMsg['error'] = '' ackMsg['data'] = report # put values reportin data key self.serverUI.sendAck(ackMsg) # call server send function with parameters Ack structure def stop(self): """ Standard domogik stop function. """ # Your specific code .... self.serverUI.close() # just call server closing def foofunction1(self, param): return {'error': "", 'footest': True} def foofunction2(self): retval = {'error': ""} retval.update(RespD) return retval def foofunction3(self, param1, param2): return {'error': "Example error generated"} def anyFunction(self): """ Example to implement a publishing message """ # Your specific code .... # call broadcastMessage function with your JSON data as you want :) # server will dispatch 'pub' message to all client with good header :) self.serverUI.broadcastMessage({'fookey1': 'foovalue', 'fookeyx': {'anotherdic':'values'}, 'footab' : [1, 5, 10]})
class YourFooPlugin(threading.Thread): """ Your classic declaration domogik plugin class. """ def __init__(self, port): """ Your init sequence and add webserver declaration. """ #Your specific code......... #Add lines : self._wsPort = port self._log = None self.serverUI = BroadcastServer(self._wsPort, self.cb_ServerWS, self._log) # Starting Websocket server # @ param self._wsPort : Port network, which must be opened for external access. # You could get it by plugin configuration : self._wsPort = int(self._configPlug.query('fooplugin', 'wsportserver')) # Port number must be unique for all WsServer instances in all domogik plugins. If port already exist an exception is raised. # So it is the user to be careful. # @ param self.cb_ServerWS : Callback function that must manage messages, see below. If not present or None server don't dispatch messages to plugin # @ param self._log : It can be log instance like self.log object of XplPlugin class or other log déclaration # if present or not None server log some infos, debug and error in this instance. #......Your specific code......... def cb_ServerWS(self, message): """ Callback to handle messages from server Websocket, principaly UI. Messages type resquest with or without Ack required. This an example you can develop it as you want !. You have just tu respect header ack message, see end function. """ blockAck = False # Using if it necessary to block Ack message for any reason. report = { 'error': 'message not handle' } # Reporting structure for data to report in message, It's better having an error key to handle it in UI. ackMsg = {} # Ack structure, for particulars params print "Handle a Requesting Call Back from UI", message # debug code if message['header']['type'] in ( 'req', 'req-ack'): # check if a message type is a request. if message[ 'request'] == 'foorequest1': # here manage your own functions. report = self.foofunction1( message['fooparam'] ) # Call your function, possibly with the parameters retrieved from the message. # Attribute resulte in report structure JSON with error key empty if no error. # example : {'error':"", 'fookey': "that you want", ...... } if not report['footest']: blockAck = True # Possibly add blocking ack for example. elif message['request'] == 'foorequest2': report = self.foofunction2() ackMsg['fooparam'] = message[ 'yourparticularparam'] # If you need to recover a particular parameter in ack message you can assigned here. elif message['request'] == 'foorequest3': if message.has_key('fooparam2'): # put all tests you want. report = self.foofunction3(message['fooparam1'], message['fooparam2']) else: report = { 'error': 'Invalide foo param2 format.' } # handle error key in local callback. else: report[ 'error'] = 'unknown request' # handle unknown request case. print "unknown request" # debug code if message['header'][ 'type'] == 'req-ack' and not blockAck: # check and prepare ack message ackMsg['header'] = { 'type': 'ack', 'idws': message['header']['idws'], 'idmsg': message['header']['idmsg'], 'ip': message['header']['ip'], 'timestamp': long(time.time() * 100) } # header composition keys : # - 'type': here must be 'ack'. # - 'idws' : recover orignal header key (message['header']['idws']), it's identify resquesting client. # - 'idmsg: recover orignal header key (message['header']['idmsg']), it's identify the individual resquet. # - 'ip' : recover orignal header key (message['header']['ip']), it's identify resquesting IP client. # - 'timestamp' : must be updated to give a reference time. ackMsg['request'] = message['request'] if 'error' in report: # put error in ack structure if necessary ackMsg['error'] = report['error'] else: ackMsg['error'] = '' ackMsg['data'] = report # put values reportin data key self.serverUI.sendAck( ackMsg ) # call server send function with parameters Ack structure def stop(self): """ Standard domogik stop function. """ # Your specific code .... self.serverUI.close() # just call server closing def foofunction1(self, param): return {'error': "", 'footest': True} def foofunction2(self): retval = {'error': ""} retval.update(RespD) return retval def foofunction3(self, param1, param2): return {'error': "Example error generated"} def anyFunction(self): """ Example to implement a publishing message """ # Your specific code .... # call broadcastMessage function with your JSON data as you want :) # server will dispatch 'pub' message to all client with good header :) self.serverUI.broadcastMessage({ 'fookey1': 'foovalue', 'fookeyx': { 'anotherdic': 'values' }, 'footab': [1, 5, 10] })