herosdevices.hardware.menlo.qwebchannel ======================================= .. py:module:: herosdevices.hardware.menlo.qwebchannel .. autoapi-nested-parse:: Client for Qt's WebChannel protocol over a plain websocket, without any Qt dependency. Some instruments (for example Menlo Systems frequency combs) expose their control/status tree via Qt's `QWebChannel `_ protocol. The protocol implementation itself is provided by the :mod:`pywebchannel` package, which has no Qt dependency. This module only supplies the websocket transport and the endpoint's authentication handshake on top of it. Module Contents --------------- .. py:data:: QWebChannel :value: None .. py:data:: QWEBCHANNEL_DEFAULT_PORT :value: 8002 .. py:class:: QWebChannelConnection(host: str, port: int = QWEBCHANNEL_DEFAULT_PORT, path: str = '/core/', user: str = 'guest', password: str = '', timeout: float = 5.0, reconnect_cooldown: float = 30.0) Manage a QWebChannel connection to a device over a plain websocket. :param host: Hostname or IP address of the websocket endpoint. :param port: Port the websocket endpoint listens on. :param path: Path component of the websocket URL. :param user: Username used for authentication. :param password: Password used for authentication. :param timeout: Seconds to wait for the connection to open and the channel to initialize. Also bounds how long the underlying socket connect may block, so an unresponsive (as opposed to actively refusing) endpoint fails within `timeout` too, instead of hanging on the OS's own connect timeout. :param reconnect_cooldown: Minimum seconds between two connection attempts. A :py:meth:`connect` call made before this has elapsed since the last attempt fails immediately without touching the network, so a caller that retries on every use (like :class:`OFC`) does not hammer a device that stays unreachable for an extended period. .. note:: There is no active reconnect-on-disconnect: a lost connection is only noticed and re-established the next time :py:meth:`connect` is called (which every read/write on :class:`OFC` does implicitly via its `_ensure_connected` helper). This keeps reconnection logic in one place, serialized by a lock, instead of racing an active retry from the websocket's own background thread against callers. .. py:attribute:: host .. py:attribute:: port :value: 8002 .. py:attribute:: path :value: '/core/' .. py:attribute:: user :value: 'guest' .. py:attribute:: password :value: '' .. py:attribute:: timeout :value: 5.0 .. py:attribute:: reconnect_cooldown :value: 30.0 .. py:attribute:: channel .. py:property:: root The root object exposed by the QWebChannel endpoint, or None if not connected yet. .. py:method:: is_ready() -> bool Whether the channel is initialized and :py:attr:`root` is available. .. py:method:: send(data: str) -> None Send raw data over the websocket. Called by :py:class:`pywebchannel.qwebchannel.QWebChannel`, not meant to be called directly. .. py:method:: connect() -> None Open the websocket connection and wait until the channel is initialized. Does nothing if a connection is already open and ready. Safe to call concurrently from multiple threads: only the first caller actually (re)connects, the others wait for it and then observe the result. :raises ConnectionError: The last attempt was less than `reconnect_cooldown` seconds ago; no new attempt was made. :raises TimeoutError: The connection could not be established within `timeout` seconds. .. py:method:: close() -> None Close the websocket connection.