def subscribe_override(self, cmd_name, cmd_params): 'Implement the subscribe operation' # create a new notif session unless a notif session already exists token = self.login_token if self.notif_token: token = self.notif_token try: notif_filter = cmd_params['filter'] except KeyError: raise ApiException.APIError(ApiException.CommandError.TOO_FEW_FIELDS, "expected 'filter' parameter") # call the Manager API subscribe command try: log.info('Sending %s: %s' % (cmd_name, [token, notif_filter])) (self.notif_token, self.notif_port) = self.manager.subscribe(token, notif_filter) log.info('Received response %s: %s %s' % (cmd_name, self.notif_token, self.notif_port)) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) # create the notification thread if not self.notif_thread: self.notif_thread = NotifReader(self.connect_params['host'], int(self.notif_port), self.notif_token, use_ssl=self.connect_params['use_ssl'], notif_callback=self.handle_notif, disconnect_callback=self.handle_notif_disconnect) self.notif_thread.connect() self.notif_thread.daemon = True self.notif_thread.start() return {'notif_token': self.notif_token}
def subscribe_override(self, cmd_name, cmd_params): 'Implement the subscribe operation' # create a new notif session unless a notif session already exists token = self.login_token if self.notif_token: token = self.notif_token try: notif_filter = cmd_params['filter'] except KeyError: raise ApiException.APIError( ApiException.CommandError.TOO_FEW_FIELDS, "expected 'filter' parameter") # call the Manager API subscribe command try: log.info('Sending %s: %s' % (cmd_name, [token, notif_filter])) (self.notif_token, self.notif_port) = self.manager.subscribe(token, notif_filter) log.info('Received response %s: %s %s' % (cmd_name, self.notif_token, self.notif_port)) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) # create the notification thread if not self.notif_thread: self.notif_thread = NotifReader( self.connect_params['host'], int(self.notif_port), self.notif_token, use_ssl=self.connect_params['use_ssl'], notif_callback=self.handle_notif, disconnect_callback=self.handle_notif_disconnect) self.notif_thread.connect() self.notif_thread.daemon = True self.notif_thread.start() return {'notif_token': self.notif_token}
class HartMgrConnectorInternal(ApiConnector): '''\brief Connector object for WirelessHART Manager using the XML API ''' DEFAULT_HOST = '192.168.99.100' DEFAULT_PORT = 4445 DEFAULT_USER = '******' DEFAULT_PASS = '******' DEFAULT_CONNECT_PARAMS = {'host': DEFAULT_HOST, 'port': DEFAULT_PORT, 'user': DEFAULT_USER, 'password': DEFAULT_PASS, 'use_ssl': False, } def __init__(self): # TODO: init super? ApiConnector.__init__(self) # TODO: maxQSize self.apidef = HartMgrDefinition.HartMgrDefinition() self.manager = None self.login_token = None self.notif_token = None self.notif_thread = None def getApiDefinition(self): return self.apidef def _init_xmlrpc(self, host, port, use_ssl = False): scheme = 'http' if not use_ssl else 'https' xmlrpc_url = "%s://%s:%d" % (scheme, host, port) rpc_client = xmlrpclib.ServerProxy(xmlrpc_url) # xmlrpclib.Fault exceptions are passed up to the caller return rpc_client def connect(self, resource): # set up the connection parameters self.connect_params = copy.copy(self.DEFAULT_CONNECT_PARAMS) self.connect_params.update(resource) # TODO: allow HTTPS try: self.manager = self._init_xmlrpc(self.connect_params['host'], int(self.connect_params['port']), bool(self.connect_params['use_ssl'])) self.login(self.connect_params['user'], self.connect_params['password']) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.ConnectionError(str(ex)) log.info('Connected to %s' % self.connect_params['host']) ApiConnector.connect(self) def disconnect(self, reason = None): self.unsubscribe_override(['unsubscribe'], {}) self.logout() log.info('Disconnected from %s' % self.connect_params['host']) ApiConnector.disconnect(self, reason) def send(self, cmd_name, cmd_params): # ensure the application is connected if not self.login_token: raise ApiException.ConnectionError('not connected') # handle command overrides - replacement methods for processing a command cmd_metadata = self.apidef.getDefinition(self.apidef.COMMAND, cmd_name) if 'command_override' in cmd_metadata: cmd_override = getattr(self, cmd_metadata['command_override']) resp = cmd_override(cmd_name, cmd_params) return resp # construct the XML-RPC parameter list # validation happens automatically as part of serialization param_list = self.apidef.serialize(cmd_name, cmd_params) log.info('Sending %s: %s' % (cmd_name, param_list)) # call method by string name, params is a list of the parameters params = [self.login_token] + param_list cmd_id = self.apidef.nameToId(self.apidef.COMMAND, cmd_name) try: xmlrpc_resp = getattr(self.manager, cmd_id)(*params) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) log.info('Received response %s: %s' % (cmd_name, xmlrpc_resp)) # call deserialize to parse the response into a dict resp = self.apidef.deserialize(cmd_name, xmlrpc_resp) # call a command-specific post-processor method cmd_metadata = self.apidef.getDefinition(self.apidef.COMMAND, cmd_name) if 'post_processor' in cmd_metadata: post_processor = getattr(self, cmd_metadata['post_processor']) post_processor(resp) return resp def login(self, user = DEFAULT_USER, password = DEFAULT_PASS): # TODO: what if we need to reauthenticate? if not self.login_token: result = self.manager.login(user, password) # LATER: add some processing to detect faults self.login_token = result return self.login_token def logout(self): if self.login_token: try: result = self.manager.logout(self.login_token) except xmlrpclib.Fault: pass self.login_token = None # ---------------------------------------------------------------------- # notification management methods def subscribe_override(self, cmd_name, cmd_params): 'Implement the subscribe operation' # create a new notif session unless a notif session already exists token = self.login_token if self.notif_token: token = self.notif_token try: notif_filter = cmd_params['filter'] except KeyError: raise ApiException.APIError(ApiException.CommandError.TOO_FEW_FIELDS, "expected 'filter' parameter") # call the Manager API subscribe command try: log.info('Sending %s: %s' % (cmd_name, [token, notif_filter])) (self.notif_token, self.notif_port) = self.manager.subscribe(token, notif_filter) log.info('Received response %s: %s %s' % (cmd_name, self.notif_token, self.notif_port)) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) # create the notification thread if not self.notif_thread: self.notif_thread = NotifReader(self.connect_params['host'], int(self.notif_port), self.notif_token, use_ssl=self.connect_params['use_ssl'], notif_callback=self.handle_notif, disconnect_callback=self.handle_notif_disconnect) self.notif_thread.connect() self.notif_thread.daemon = True self.notif_thread.start() return {'notif_token': self.notif_token} def unsubscribe_override(self, cmd_name, cmd_params): 'Implement the unsubscribe operation' try: if self.notif_token: log.info('Sending %s: %s' % (cmd_name, self.notif_token)) resp = self.manager.unsubscribe(self.notif_token) log.info('Received response %s: %s' % (cmd_name, resp)) self.notif_thread.join() self.notif_thread = None self.notif_token = None return {'result': "OK"} except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) def handle_notif_disconnect(self, reason): 'Handle a disconnection from the notification channel' self.queue.putDisconnectNotification(reason) def handle_notif(self, notif_name, notif_str): 'Parse a notification' try: notif = self.apidef.parse_notif([notif_name], notif_str) log.info('Received notification %s: %s', notif_name, str(notif)) self.putNotification(notif) except ApiException.CommandError as ex: log.warn('Unknown notification type %s: %s', notif_name, notif_str)
class HartMgrConnectorInternal(ApiConnector): '''\brief Connector object for WirelessHART Manager using the XML API ''' DEFAULT_HOST = '192.168.99.100' DEFAULT_PORT = 4445 DEFAULT_USER = '******' DEFAULT_PASS = '******' DEFAULT_CONNECT_PARAMS = { 'host': DEFAULT_HOST, 'port': DEFAULT_PORT, 'user': DEFAULT_USER, 'password': DEFAULT_PASS, 'use_ssl': False, } def __init__(self): # TODO: init super? ApiConnector.__init__(self) # TODO: maxQSize self.apidef = HartMgrDefinition.HartMgrDefinition() self.manager = None self.login_token = None self.notif_token = None self.notif_thread = None def getApiDefinition(self): return self.apidef def _init_xmlrpc(self, host, port, use_ssl=False): scheme = 'http' if not use_ssl else 'https' xmlrpc_url = "%s://%s:%d" % (scheme, host, port) rpc_client = xmlrpclib.ServerProxy(xmlrpc_url) # xmlrpclib.Fault exceptions are passed up to the caller return rpc_client def connect(self, resource): # set up the connection parameters self.connect_params = copy.copy(self.DEFAULT_CONNECT_PARAMS) self.connect_params.update(resource) # TODO: allow HTTPS try: self.manager = self._init_xmlrpc( self.connect_params['host'], int(self.connect_params['port']), bool(self.connect_params['use_ssl'])) self.login(self.connect_params['user'], self.connect_params['password']) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.ConnectionError(str(ex)) log.info('Connected to %s' % self.connect_params['host']) ApiConnector.connect(self) def disconnect(self, reason=None): self.unsubscribe_override(['unsubscribe'], {}) self.logout() log.info('Disconnected from %s' % self.connect_params['host']) ApiConnector.disconnect(self, reason) def send(self, cmd_name, cmd_params): # ensure the application is connected if not self.login_token: raise ApiException.ConnectionError('not connected') # handle command overrides - replacement methods for processing a command cmd_metadata = self.apidef.getDefinition(self.apidef.COMMAND, cmd_name) if 'command_override' in cmd_metadata: cmd_override = getattr(self, cmd_metadata['command_override']) resp = cmd_override(cmd_name, cmd_params) return resp # construct the XML-RPC parameter list # validation happens automatically as part of serialization param_list = self.apidef.serialize(cmd_name, cmd_params) log.info('Sending %s: %s' % (cmd_name, param_list)) # call method by string name, params is a list of the parameters params = [self.login_token] + param_list cmd_id = self.apidef.nameToId(self.apidef.COMMAND, cmd_name) try: xmlrpc_resp = getattr(self.manager, cmd_id)(*params) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) log.info('Received response %s: %s' % (cmd_name, xmlrpc_resp)) # call deserialize to parse the response into a dict resp = self.apidef.deserialize(cmd_name, xmlrpc_resp) # call a command-specific post-processor method cmd_metadata = self.apidef.getDefinition(self.apidef.COMMAND, cmd_name) if 'post_processor' in cmd_metadata: post_processor = getattr(self, cmd_metadata['post_processor']) post_processor(resp) return resp def login(self, user=DEFAULT_USER, password=DEFAULT_PASS): # TODO: what if we need to reauthenticate? if not self.login_token: result = self.manager.login(user, password) # LATER: add some processing to detect faults self.login_token = result return self.login_token def logout(self): if self.login_token: try: result = self.manager.logout(self.login_token) except xmlrpclib.Fault: pass self.login_token = None # ---------------------------------------------------------------------- # notification management methods def subscribe_override(self, cmd_name, cmd_params): 'Implement the subscribe operation' # create a new notif session unless a notif session already exists token = self.login_token if self.notif_token: token = self.notif_token try: notif_filter = cmd_params['filter'] except KeyError: raise ApiException.APIError( ApiException.CommandError.TOO_FEW_FIELDS, "expected 'filter' parameter") # call the Manager API subscribe command try: log.info('Sending %s: %s' % (cmd_name, [token, notif_filter])) (self.notif_token, self.notif_port) = self.manager.subscribe(token, notif_filter) log.info('Received response %s: %s %s' % (cmd_name, self.notif_token, self.notif_port)) except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) # create the notification thread if not self.notif_thread: self.notif_thread = NotifReader( self.connect_params['host'], int(self.notif_port), self.notif_token, use_ssl=self.connect_params['use_ssl'], notif_callback=self.handle_notif, disconnect_callback=self.handle_notif_disconnect) self.notif_thread.connect() self.notif_thread.daemon = True self.notif_thread.start() return {'notif_token': self.notif_token} def unsubscribe_override(self, cmd_name, cmd_params): 'Implement the unsubscribe operation' try: if self.notif_token: log.info('Sending %s: %s' % (cmd_name, self.notif_token)) resp = self.manager.unsubscribe(self.notif_token) log.info('Received response %s: %s' % (cmd_name, resp)) self.notif_thread.join() self.notif_thread = None self.notif_token = None return {'result': "OK"} except xmlrpclib.Fault as ex: log.error(str(ex)) raise ApiException.APIError(cmd_name[0], str(ex)) def handle_notif_disconnect(self, reason): 'Handle a disconnection from the notification channel' self.queue.putDisconnectNotification(reason) def handle_notif(self, notif_name, notif_str): 'Parse a notification' try: notif = self.apidef.parse_notif([notif_name], notif_str) log.info('Received notification %s: %s', notif_name, str(notif)) self.putNotification(notif) except ApiException.CommandError as ex: log.warn('Unknown notification type %s: %s', notif_name, notif_str)