def delete_log(cls, nodename, grpc_uri, auto_pw_request=False, user=None, pw=None):
        '''
        Deletes the log file associated with the given node.

        :param  str nodename: the name of the node (with name space)
        :param str grpc_uri: uri of the node manager daemon where to delete log
        :raise Exception: on errors while resolving host
        :see: :meth:`fkie_node_manager.is_local()`
        '''
        try:
            nm.nmd().screen.delete_log(grpc_uri, [nodename])
        except Exception as err:
            rospy.logwarn("delete log using SSH because of error: %s" % utf8(err))
            host = get_hostname(grpc_uri)
            if nm.is_local(host):
                screenLog = screen.get_logfile(node=nodename)
                pidFile = screen.get_pidfile(node=nodename)
                roslog = screen.get_ros_logfile(nodename)
                if os.path.isfile(screenLog):
                    os.remove(screenLog)
                if os.path.isfile(pidFile):
                    os.remove(pidFile)
                if os.path.isfile(roslog):
                    os.remove(roslog)
            else:
                try:
                    # output ignored: output, error, ok
                    _, stdout, _, ok = nm.ssh().ssh_exec(host, [nm.settings().start_remote_script, '--delete_logs', nodename], user, pw, auto_pw_request, close_stdin=True, close_stdout=False, close_stderr=True)
                    if ok:
                        stdout.readlines()
                        stdout.close()
                except nm.AuthenticationRequest as e:
                    raise nm.InteractionNeededError(e, cls.delete_log, {'nodename': nodename, 'grpc_uri': host, 'auto_pw_request': auto_pw_request, 'user': user, 'pw': pw})
Esempio n. 2
0
 def mastername(self, masteruri, address=None):
     with self.mutex:
         for m in self._masters:
             if m.masteruri == masteruri:
                 if address is not None:
                     if m.has_address(address):
                         return m.get_mastername()
                 else:
                     return m.get_mastername()
         return get_hostname(masteruri)
    def _prepareROSMaster(cls, masteruri):
        if masteruri is None:
            masteruri = masteruri_from_ros()
        # start roscore, if needed
        try:
            if not os.path.isdir(screen.LOG_PATH):
                os.makedirs(screen.LOG_PATH)
            socket.setdefaulttimeout(3)
            master = xmlrpcclient.ServerProxy(masteruri)
            master.getUri(rospy.get_name())
            # restart ROSCORE on different masteruri?, not now...
#      master_uri = master.getUri(rospy.get_name())
#      if masteruri != master_uri[2]:
#        # kill the local roscore...
#        raise
        except Exception:
            # run a roscore
            master_host = get_hostname(masteruri)
            if nm.is_local(master_host, True):
                master_port = get_port(masteruri)
                new_env = dict(os.environ)
                new_env['ROS_MASTER_URI'] = masteruri
                ros_hostname = nmdhost.get_ros_hostname(masteruri)
                if ros_hostname:
                    new_env['ROS_HOSTNAME'] = ros_hostname
                cmd_args = '%s roscore --port %d' % (screen.get_cmd('/roscore--%d' % master_port), master_port)
                for n in [1, 2, 3, 4]:
                    try:
                        if n == 1:
                            print("Launch ROS Master in screen  ... %s" % (cmd_args))
                            SupervisedPopen(shlex.split(cmd_args), env=new_env, object_id="ROSCORE", description="Start roscore")
                        elif n == 2:
                            print("ROS Master takes too long for start, wait for next 10 sec ...")
                        elif n == 3:
                            print("A really slow start, wait for last 10 sec ...")
                        # wait for roscore to avoid connection problems while init_node
                        result = -1
                        count = 1
                        while result == -1 and count < 11:
                            try:
                                master = xmlrpcclient.ServerProxy(masteruri)
                                result, _, _ = master.getUri(rospy.get_name())  # _:=uri, msg
                                return
                            except Exception:
                                time.sleep(1)
                                count += 1
                        if n == 4 and count >= 11:
                            raise StartException('Cannot connect to ROS-Master: %s\n--> please run "roscore" manually!' % utf8(masteruri))
                    except Exception as e:
                        raise Exception("Error while call '%s': %s" % (cmd_args, utf8(e)))
            else:
                raise Exception("ROS master '%s' is not reachable" % masteruri)
        finally:
            socket.setdefaulttimeout(None)
Esempio n. 4
0
 def _prepareROSMaster(cls, masteruri):
     if not masteruri:
         masteruri = masteruri_from_ros()
     # start roscore, if needed
     try:
         if not os.path.isdir(screen.LOG_PATH):
             os.makedirs(screen.LOG_PATH)
         socket.setdefaulttimeout(3)
         master = xmlrpcclient.ServerProxy(masteruri)
         master.getUri(rospy.get_name())
     except Exception:
         # run a roscore
         screen.test_screen()
         master_host = get_hostname(masteruri)
         if cls.is_local(master_host, True):
             print("Start ROS-Master with %s ..." % masteruri)
             master_port = get_port(masteruri)
             new_env = dict(os.environ)
             new_env['ROS_MASTER_URI'] = masteruri
             ros_hostname = nmdhost.get_ros_hostname(masteruri)
             if ros_hostname:
                 new_env['ROS_HOSTNAME'] = ros_hostname
             cmd_args = '%s roscore --port %d' % (screen.get_cmd(
                 '/roscore--%d' % master_port), master_port)
             try:
                 subprocess.Popen(shlex.split(cmd_args), env=new_env)
                 # wait for roscore to avoid connection problems while init_node
                 result = -1
                 count = 1
                 while result == -1 and count < 11:
                     try:
                         print("  retry connect to ROS master %d/10" %
                               count)
                         master = xmlrpcclient.ServerProxy(masteruri)
                         result, _, _ = master.getUri(
                             rospy.get_name())  # _:=uri, msg
                     except Exception:
                         time.sleep(1)
                         count += 1
                 if count >= 11:
                     raise StartException(
                         'Cannot connect to the ROS-Master: ' +
                         str(masteruri))
             except Exception as e:
                 import sys
                 sys.stderr.write("%s\n" % e)
                 raise
         else:
             raise Exception("ROS master '%s' is not reachable" % masteruri)
     finally:
         socket.setdefaulttimeout(None)
    def transfer_file_nmd(cls, grpc_url, path, auto_pw_request=False, user=None, pw=None):
        '''
        Copies the given file to the remote host. Uses caching of remote paths.

        :param str grpc_url: destination grpc server
        :param str path: file to transfer
        '''
        try:
            nm.nmd().file.copy(path, grpc_url)
        except Exception as err:
            host = get_hostname(grpc_url)
            _uri, path = nmdurl.split(path)
            rospy.logwarn("use SSH to transfer file '%s' to '%s', because of error: %s" % (path, host, utf8(err)))
            cls.transfer_files(host, path, auto_pw_request, user, pw)
 def _rosclean_wo(self, grpc_uri, auto_pw_request=False, user=None, pw=None):
     try:
         nm.nmd().screen.rosclean(grpc_uri)
     except Exception as err:
         host = get_hostname(grpc_uri)
         if nm.is_local(host):
             rospy.loginfo("rosclean purge on localhost!")
             cmd = nm.settings().terminal_cmd(['rosclean purge -y'], "rosclean")
             SupervisedPopen(shlex.split(cmd), object_id="rosclean", description="rosclean")
         else:
             rospy.logwarn("use SSH to run 'rosclean' because of error: %s" % utf8(err))
             # kill on a remote machine
             cmd = ['rosclean purge -y']
             _ = nm.ssh().ssh_x11_exec(host, cmd, 'rosclean purge on %s' % host, user)
Esempio n. 7
0
 def __gt__(self, item):
     if isstring(item):
         local = False
         try:
             local = nm.is_local(get_hostname(nm.nameres().masteruri(item)))
         except Exception:
             pass
         if self.local and not local:  # local hosts are at the top
             return False
         return self.master.name.lower() > item.lower()
     elif not (item is None):
         if self.local and not item.local:  # local hosts are at the top
             return False
         return self.master.name.lower() > item.master.name.lower()
     return False
Esempio n. 8
0
 def __init__(self):
     '''
     Creates a new instance. Find the topic of the master_discovery node using
     U{fkie_master_discovery.interface_finder.get_changes_topic()
     <http://docs.ros.org/api/fkie_master_discovery/html/modules.html#interface-finder-module>}.
     Also the parameter C{~ignore_hosts} will be analyzed to exclude hosts from sync.
     '''
     self.masters = {}
     # the connection to the local service master
     self.masteruri = masteruri_from_master()
     self.hostname = get_hostname(self.masteruri)
     self._localname = ''
     '''@ivar: the ROS master URI of the C{local} ROS master. '''
     self.__lock = threading.RLock()
     # load interface
     self._load_interface()
     # subscribe to changes notifier topics
     self._check_host = rospy.get_param('~check_host', True)
     topic_names = interface_finder.get_changes_topic(
         masteruri_from_master(), check_host=self._check_host)
     self.sub_changes = dict()
     '''@ivar: `dict` with topics {name: U{rospy.Subscriber<http://docs.ros.org/api/rospy/html/rospy.topics.Subscriber-class.html>}} publishes the changes of the discovered ROS masters.'''
     for topic_name in topic_names:
         rospy.loginfo("listen for updates on %s", topic_name)
         self.sub_changes[topic_name] = rospy.Subscriber(
             topic_name, MasterState, self._rosmsg_callback_master_state)
     self.__timestamp_local = None
     self.__own_state = None
     self.update_timer = None
     self.resync_timer = None
     self.own_state_getter = None
     self._timer_update_diagnostics = None
     self._join_threads = dict(
     )  # threads waiting for stopping the sync thread
     # initialize the ROS services
     rospy.Service('~get_sync_info', GetSyncInfo,
                   self._rosservice_get_sync_info)
     rospy.on_shutdown(self.finish)
     self._current_diagnistic_level = None
     self.pub_diag = rospy.Publisher("/diagnostics",
                                     DiagnosticArray,
                                     queue_size=10,
                                     latch=True)
     self.obtain_masters()
Esempio n. 9
0
    def __get_ip(self):
        try:
            # get the IP of the master uri
            result = getaddrinfo(get_hostname(self.master.uri), None)
            ips = []
            for r in result:
                if r[0] == AF_INET6:
                    (_family, _socktype, _proto, _canonname, (ip, _port, _flow, _scope)) = r
                else:
                    (_family, _socktype, _proto, _canonname, (ip, _port)) = r
                if self.master_ip is None and ip:
                    self.master_ip = ''
                if ip and ip not in ips:
                    self.master_ip = ' '.join([self.master_ip, ip])
                    ips.append(ip)
#      self.updateNameView(self.master, self.quality, self)
        except Exception:
            import traceback
            print(traceback.format_exc(1))
Esempio n. 10
0
    def updateMaster(self, master):
        '''
        Updates the information of the ros master. If the ROS master not exists, it
        will be added.

        @param master: the ROS master to update
        @type master: U{fkie_master_discovery.msg.ROSMaster<http://docs.ros.org/api/fkie_multimaster_msgs/html/msg/ROSMaster.html>}
        '''
        # remove master, if his name was changed but not the ROS master URI
        root = self.invisibleRootItem()
        for i in reversed(range(root.rowCount())):
            masterItem = root.child(i)
            if masterItem.master.uri == master.uri and masterItem.master.name != master.name:
                root.removeRow(i)
                try:
                    del self.pyqt_workaround[masterItem.master.name]
                except Exception:
                    pass
                break

        # update or add a the item
        root = self.invisibleRootItem()
        doAddItem = True
        is_local = nm.is_local(get_hostname(master.uri))
        for index in range(root.rowCount()):
            masterItem = root.child(index, self.COL_NAME)
            if (masterItem == master.name):
                # update item
                masterItem.master = master
                masterItem.updateMasterView(root)
                doAddItem = False
                break
            elif (masterItem > master.name):
                self.addRow(master, is_local, root, index)
                doAddItem = False
                break
        if doAddItem:
            self.addRow(master, is_local, root, -1)
Esempio n. 11
0
def init_globals(masteruri):
    '''
    :return: True if the masteruri referred to localhost
    :rtype: bool
    '''
    # initialize the global handler
    global _NMD_CLIENT
    global _SSH_HANDLER
    global _SCREEN_HANDLER
    global _START_HANDLER
    global _NAME_RESOLUTION
    global _HISTORY
    _NMD_CLIENT = NmdClient()
    # _NMD_CLIENT.start()
    _SSH_HANDLER = SSHhandler()
    _SCREEN_HANDLER = ScreenHandler()
    _START_HANDLER = StartHandler()
    _NAME_RESOLUTION = NameResolution()
    _HISTORY = History()

    # test where the roscore is running (local or remote)
    __is_local('localhost')  # fill cache
    return __is_local(get_hostname(masteruri))  # fill cache
Esempio n. 12
0
    def updateTypeView(cls, service, item):
        '''
        Updates the representation of the column contains the type of the service.

        :param service: the service data
        :type service: fkie_master_discovery.ServiceInfo<http://docs.ros.org/kinetic/api/fkie_master_discovery/html/modules.html#fkie_master_discovery.master_info.ServiceInfo>
        :param item: corresponding item in the model
        :type item: :class:`ServiceItem`
        '''
        try:
            if service.isLocal and service.type:
                service_class = service.get_service_class(
                    nm.is_local(get_hostname(service.uri)))
                item.setText(service_class._type)
            elif service.type:
                item.setText(service.type)
            else:
                item.setText('unknown type')
            # removed tooltip for clarity !!!
#      tooltip = ''
#      tooltip = ''.join([tooltip, '<h4>', service_class._type, '</h4>'])
#      tooltip = ''.join([tooltip, '<b><u>', 'Request', ':</u></b>'])
#      tooltip = ''.join([tooltip, '<dl><dt>', utf8(service_class._request_class.__slots__), '</dt></dl>'])
#
#      tooltip = ''.join([tooltip, '<b><u>', 'Response', ':</u></b>'])
#      tooltip = ''.join([tooltip, '<dl><dt>', utf8(service_class._response_class.__slots__), '</dt></dl>'])
#
#      item.setToolTip(''.join(['<div>', tooltip, '</div>']))
            item.setToolTip('')
        except Exception:
            if not service.isLocal:
                tooltip = ''.join([
                    '<h4>',
                    'Service type is not available due to he running on another host.',
                    '</h4>'
                ])
                item.setToolTip(''.join(['<div>', tooltip, '</div>']))
Esempio n. 13
0
 def address(self, masteruri):
     with self.mutex:
         for m in self._masters:
             if m.masteruri == masteruri or m.has_mastername(masteruri):
                 return m.get_address(prefer_hostname=False)
         return get_hostname(masteruri)
Esempio n. 14
0
    def on_load_profile_file(self, grpc_url):
        '''
        Load the profile file.

        :param str grpc_url: the path of the profile file.
        '''
        _url, path = nmdurl.split(grpc_url)
        rospy.loginfo("Load profile %s" % path)
        self.progressBar.setValue(0)
        self.setVisible(True)
        self.setWindowTitle("%s profile started" %
                            os.path.basename(path).rstrip('.nmprofile'))
        hasstart = False
        if path:
            try:
                with open(path, 'r') as f:
                    content = ruamel.yaml.load(f.read(),
                                               Loader=ruamel.yaml.Loader)
                    if not isinstance(content, dict):
                        raise Exception("Mailformed profile: %s" %
                                        os.path.basename(path))
                    for muri, master_dict in content.items():
                        local_hostname = get_hostname(
                            self._main_window.getMasteruri())
                        rmuri = muri.replace('$LOCAL$', local_hostname)
                        master = self._main_window.getMaster(rmuri)
                        running_nodes = master.get_nodes_runningIfLocal()
                        usr = None
                        self._current_profile[rmuri] = set()
                        if 'user' in master_dict:
                            usr = master_dict['user']
                        if master_dict['mastername'] and master_dict[
                                'mastername']:
                            nm.nameres().add_master_entry(
                                master.masteruri, master_dict['mastername'],
                                master_dict['address'])
                        hostname = master_dict['address'].replace(
                            '$LOCAL$', local_hostname)
                        if 'master_discovery' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_master_discovery',
                                'master_discovery',
                                usr,
                                cfg=master_dict['master_discovery'])
                            self._current_profile[rmuri].add(
                                '/master_discovery')
                        if 'master_sync' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_master_sync',
                                'master_sync',
                                usr,
                                cfg=master_dict['master_sync'])
                            self._current_profile[rmuri].add('/master_sync')
                        if 'zeroconf' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_master_discovery',
                                'zeroconf',
                                usr,
                                cfg=master_dict['zeroconf'])
                            self._current_profile[rmuri].add('/zeroconf')
                        if 'node_manager_daemon' in master_dict:
                            self._start_node_from_profile(
                                master,
                                hostname,
                                'fkie_node_manager_daemon',
                                'node_manager_daemon',
                                usr,
                                cfg=master_dict['node_manager_daemon'])
                            self._current_profile[rmuri].add(
                                '/node_manager_daemon')
                        try:
                            do_start = []
                            do_not_stop = {
                                '/rosout',
                                rospy.get_name(), '/node_manager',
                                '/master_discovery', '/master_sync',
                                '*default_cfg', '/zeroconf',
                                '/node_manager_daemon'
                            }
                            configs = master_dict['configs']
                            conf_set = set()
                            for cfg_name, cmdict in configs.items():
                                cfg_name = cfg_name.replace(
                                    '$LOCAL$', local_hostname)
                                if cfg_name.startswith("pkg://"):
                                    cfg_name = resolve_pkg(
                                        cfg_name, nmdurl.nmduri(rmuri))
                                conf_set.add(cfg_name)
                                reload_launch = True
                                args = {}
                                if 'args' in cmdict:
                                    if 'args' in cmdict:
                                        args = cmdict['args']
                                    # do we need to load to load/reload launch file
                                    if cfg_name in master.launchfiles:
                                        reload_launch = set(
                                            master.launchfiles[cfg_name].args.
                                            itervalues()) != set(
                                                args.itervalues())
                                if reload_launch:
                                    self._main_window.launch_dock.load_file(
                                        cfg_name, args, master.masteruri)
                                if 'nodes' in cmdict:
                                    self._current_profile[rmuri].update(
                                        cmdict['nodes'])
                                    force_start = True
                                    cfg = cfg_name
                                    if not reload_launch:
                                        force_start = False
                                        do_not_stop.update(set(
                                            cmdict['nodes']))
                                        do_start.append(
                                            (reload_launch, cfg,
                                             cmdict['nodes'], force_start))
                                    else:
                                        do_start.append(
                                            (reload_launch, cfg,
                                             cmdict['nodes'], force_start))
                            # close unused configurations
                            for lfile in set(
                                    master.launchfiles.keys()) - conf_set:
                                master._close_cfg(lfile)
                            master.stop_nodes_by_name(running_nodes.keys(),
                                                      True, do_not_stop)
                            for reload_launch, cfg, nodes, force_start in do_start:
                                if nodes:
                                    hasstart = True
                                if reload_launch:
                                    master.start_nodes_after_load_cfg(
                                        cfg, list(nodes), force_start)
                                else:
                                    master.start_nodes_by_name(
                                        list(nodes), cfg, force_start)
                        except Exception as ml:
                            import traceback
                            print(utf8(traceback.format_exc(1)))
                            rospy.logwarn(
                                "Can not load launch file for %s: %s" %
                                (muri, utf8(ml)))
            except Exception as e:
                import traceback
                print(traceback.format_exc(1))
                MessageBox.warning(self, "Load profile error",
                                   'Error while load profile', utf8(e))
            if not hasstart:
                self.update_progress()
            else:
                QTimer.singleShot(1000, self.update_progress)
Esempio n. 15
0
    def on_save_profile(self, masteruri='', path=None):
        '''
        Saves the current environment to a node manager profile.

        :param str masteruri: If not empty, save the profile only for given master
        :param str path: the path of file to save. If None :meth:`get_profile_file` is called to get a path.
        '''
        try:
            if path is None:
                path = self.get_profile_file()
                if path is None:
                    return
            rospy.loginfo("Save profile %s" % path)
            content = {}
            for muri, master in self._main_window.masters.items():
                if not masteruri or masteruri == muri:
                    running_nodes = master.get_nodes_runningIfLocal()
                    configs = {}
                    md_param = {}
                    ms_param = {}
                    zc_param = {}
                    nmd_param = {}
                    smuri = muri
                    addr = nm.nameres().address(smuri)
                    hostname = get_hostname(smuri)
                    mastername = ''
                    if nm.is_local(addr):
                        smuri = smuri.replace(hostname, '$LOCAL$')
                        addr = '$LOCAL$'
                    else:
                        mastername = nm.nameres().mastername(
                            smuri,
                            nm.nameres().address(smuri))
                    for node_name in running_nodes.keys():
                        node_items = master.getNode(node_name)
                        for node in node_items:
                            if node.is_running(
                            ) and node.launched_cfg is not None:  # node.has_launch_cfgs(node.cfgs):
                                # it is a loaded launch file, get the filename
                                cfg = to_pkg(node.launched_cfg)
                                if cfg not in configs:
                                    configs[cfg] = {'nodes': []}
                                configs[cfg]['nodes'].append(node_name)
                            elif node_name.endswith('master_discovery'):
                                md_param = get_rosparam(
                                    'master_discovery', muri)
                            elif node_name.endswith('master_sync'):
                                ms_param = get_rosparam('master_sync', muri)
                            elif node_name.endswith('zeroconf'):
                                zc_param = get_rosparam('zeroconf', muri)
                            elif node_name.endswith('node_manager_daemon'):
                                nmd_param = get_rosparam(
                                    'node_manager_daemon', muri)
                    # store arguments for launchfiles
                    for a, b in master.launchfiles.items():
                        resolved_a = to_pkg(a)
                        if resolved_a not in configs:
                            configs[resolved_a] = {}
                            configs[resolved_a]['default'] = False
                        configs[resolved_a]['args'] = b.args
                    # fill the configuration content for yaml as dictionary
                    content[smuri] = {
                        'mastername': mastername,
                        'address': addr,
                        'configs': configs
                    }
                    if md_param:
                        content[smuri]['master_discovery'] = md_param
                    if ms_param:
                        content[smuri]['master_sync'] = ms_param
                    if zc_param:
                        content[smuri]['zeroconf'] = zc_param
                    if nmd_param:
                        content[smuri]['node_manager_daemon'] = nmd_param
            buf = ruamel.yaml.compat.StringIO()
            ruamel.yaml.dump(content, buf, Dumper=ruamel.yaml.RoundTripDumper)
            with open(path, 'w+') as f:
                f.write(buf.getvalue())
        except Exception as e:
            import traceback
            print(utf8(traceback.format_exc(3)))
            MessageBox.warning(self, "Save profile Error",
                               'Error while save profile', utf8(e))
Esempio n. 16
0
    def __init__(self,
                 name,
                 uri,
                 discoverer_name,
                 monitoruri,
                 timestamp,
                 sync_on_demand=False,
                 callback_resync=None):
        '''
        Initialization method for the SyncThread.
        @param name: the name of the ROS master synchronized with.
        @type name:  C{str}
        @param uri: the URI of the ROS master synchronized with
        @type uri:  C{str}
        @param discoverer_name: the name of the discovery node running on ROS master synchronized with.
        @type discoverer_name:  C{str}
        @param monitoruri: The URI of RPC server of the discovery node to get the ROS master state by calling a method only once.
        @type monitoruri:  C{str}
        @param timestamp: The timestamp of the current state of the ROS master info.
        @type timestamp:  C{float64}
        @param sync_on_demand: Synchronize topics on demand
        @type sync_on_demand: bool
        '''
        self.name = name
        self.uri = uri
        self.discoverer_name = discoverer_name
        self.monitoruri = monitoruri
        self.timestamp = timestamp
        self.timestamp_local = 0.
        self.timestamp_remote = 0.
        self._online = True
        self._offline_ts = 0

        self.masteruri_local = masteruri_from_ros()
        self.hostname_local = get_hostname(self.masteruri_local)
        rospy.logdebug(
            "SyncThread[%s]: create this sync thread, discoverer_name: %s",
            self.name, self.discoverer_name)
        # synchronization variables
        self.__lock_info = threading.RLock()
        self.__lock_intern = threading.RLock()
        self._use_filtered_method = None
        self._use_md5check_topics = None
        self._md5warnings = {
        }  # ditionary of {(topicname, node, nodeuri) : (topictype, md5sum)}
        self._topic_type_warnings = {
        }  # ditionary of {(topicname, node, nodeuri) : remote topictype}
        # SyncMasterInfo with currently synchronized nodes, publisher (topic, node, nodeuri), subscriber(topic, node, nodeuri) and services
        self.__sync_info = None
        self.__unregistered = False
        # a list with published topics as a tuple of (topic name, node name, node URL)
        self.__publisher = []
        # a list with subscribed topics as a tuple of (topic name, node name, node URL)
        self.__subscriber = []
        # a list with services as a tuple of (service name, service URL, node name, node URL)
        self.__services = []
        # the state of the own ROS master is used if `sync_on_demand` is enabled or
        # to determine the type of topic subscribed remote with `Empty` type
        self.__own_state = None
        self.__callback_resync = callback_resync
        self.__has_remove_sync = False

        # setup the filter
        self._filter = FilterInterface()
        self._filter.load(
            self.name,
            [
                '/rosout', self.discoverer_name, '/master_discovery',
                '/master_sync', '/node_manager', '/node_manager_daemon',
                '/zeroconf', '/param_sync'
            ],
            [],
            [
                '/rosout', '/rosout_agg', '/master_discovery/*',
                '/master_sync/*', '/zeroconf/*'
            ],
            ['/'] if sync_on_demand else [],
            [
                '/*get_loggers', '/*set_logger_level', '/master_discovery/*',
                '/master_sync/*', '/node_manager_daemon/*', '/zeroconf/*'
            ],
            [],
            # do not sync the bond message of the nodelets!!
            [
                'bond/Status', 'fkie_multimaster_msgs/SyncTopicInfo',
                'fkie_multimaster_msgs/SyncServiceInfo',
                'fkie_multimaster_msgs/SyncMasterInfo',
                'fkie_multimaster_msgs/MasterState'
            ],
            [],
            [],
            [])

        # congestion avoidance: wait for random.random*2 sec. If an update request
        # is received try to cancel and restart the current timer. The timer can be
        # canceled for maximal MAX_UPDATE_DELAY times.
        self._update_timer = None
        self._delayed_update = 0
        self.__on_update = False