FAQ - heros 0.8.1 documentation

Skip to content
Back to top
View this page

# FAQ

## Can I use private methods and attributes?

By default, private methods and attributes (name starting with a `_`) are not exposed to the remote side.

However, you can force private methods to be exposed by decorating them with `@heros.inspect.force_remote`.

For attributes there is currently no straight forward way to force this.

## I am observing timeouts in the HERO communication. What can I do?

If a timeout occurs, HEROS will print an error like

    2025-10-23 17:41:47,609 heros [heros.py:70 _query_selector]: Stream interrupted when querying peer EntityGlobalId { zid: 2554c3255fd4ff7dce726aba72afd04f, eid: 0 } with arguments ('@object/heros/*/_discover',) and {'target': QueryTarget.ALL, 'timeout': 2.0}: b'Timeout'. If this error persists, consult the HEROS documentation on 'debuging'.

to the terminal. This can occure if a peer is in an unresponsive state and takes to long to respond. To find out what is going on, the best way is to setup a zenoh router. Therefore download the newest “standalone” package for your system here and unpack it.

Note

It does not matter on which machine you are doing this as long as it is connected to the same network as the offending peer.

Move into the unpacked folder and run

    RUST_LOG=DEBUG ./zenohd

in a terminal. Now the router should connect to all peers it finds on the network. For each peer it prints a line like

    2025-10-23T15:47:22.218912Z DEBUG acc-0 ThreadId(04) zenoh_transport::unicast::establishment::accept: New transport link accepted from 2554c3255fd4ff7dce726aba72afd04f to 2890d320dce65ff47c7ea57b87954cc6: TransportLinkUnicast { link: Link { src: tcp/[::ffff:192.168.1.130]:7447, dst: tcp/[::ffff:192.168.1.130]:54838, mtu: 49152, is_reliable: true, is_streamed: true }, config: TransportLinkUnicastConfig { direction: Inbound, batch: BatchConfig { mtu: 49152, is_streamed: true, is_compression: false }, priorities: None, reliability: None } }

Now search for the connecting `zid` you obtained from the timeout error message, in this example `2554c3255fd4ff7dce726aba72afd04f`. The router knows which IP address this peer runs on, here `tcp/[::ffff:192.168.1.130]:7447`.

Sometimes it is enough to restart the blocking HERO, but in general it is a sign of a intermittent connection.

Note

If the endpoint timing out is not `_discover` but for example `_@object/heros/my_hero/slow_calc`, this indicates that your function slow_calc takes to long to execute. If you require this, set the timeout in the `RemoteHERO` calling this slow function in zenoh config as a temporary solution and write a feature request.

## Can I use Heros with ARTIQ without using Atomiq?

Yes, even if we do not recommend it an there is no real point in it other than for a temporary transitionary setup! Just install HEROS within your flake.nix (adapt the version to the latest):

    heros = pkgs.python3Packages.buildPythonPackage rec {
      name = "heros";
      pname = "heros";
      format = "pyproject";
      version = "0.5.0";
      nativeBuildInputs = [
        pkgs.autoPatchelfHook
        ];
      src = pkgs.python3Packages.fetchPypi {
        inherit pname version;
        sha256 = "lXvd8N1BnHRWidwESy42ZlRopEX/y/uLXv+NCnxPWwo=";
      };
      buildInputs = [ pkgs.python3Packages.cbor2 pkgs.python3Packages.hatchling pkgs.python3Packages.numpy pkgs.python3Packages.zenoh];
    };

and add `heros` to the python packages loaded on shell creation.

Note

If you are using Atomiq, this is all handled automatically and you can just add your HERO to the components DB with the `$` identifier.

To use a remote hero as a device in the device DB, you have to circumvent the device manager to be passed to the `RemoteHERO` class by creating a device like:

    class ArtiqRemoteHERO(RemoteHERO)
      def __new__(cls, dmgr, name: str, realm: str = "heros", *args, **kwargs):
          return RemoteHERO.__new__(cls, name,realm, *args, **kwargs)

      def __init__(self, dmgr,  name: str, realm: str="heros", *args, **kwargs):
          super().__init__(name, realm, *args, **kwargs)

and adding it to the device db:

    device_db["my_hero"] = {
       "type": "local",
       "module": "my.lib",
       "class":"ArtiqRemoteHERO",
       "arguments": {
           "name":"my_remote_hero"
           }
    }