Source code for instrumentserver.client.core

import logging
import warnings
import zmq

from instrumentserver import DEFAULT_PORT, QtCore
from instrumentserver.base import send, recv
from instrumentserver.server.core import ServerResponse


logger = logging.getLogger(__name__)


# TODO: allow for the client to operate as context manager.


[docs]class BaseClient: """Simple client for the StationServer. When a timeout happens, a RunTimeError is being raised. This error is there just to warn the user that a timeout has occurred. After that the client will restart the socket to continue the normal work. :param host: The host address of the server, defaults to localhost. :param port: The port of the server, defaults to the value of DEFAULT_PORT. :param connect: If true, the server connects as it is being constructed, defaults to True. :param timeout: Amount of time that the client waits for an answer before declaring timeout in ms. Defaults to 5000. """ def __init__(self, host='localhost', port=DEFAULT_PORT, connect=True, timeout=5000): self.connected = False self.context = None self.socket = None self.host = host self.port = port self.addr = f"tcp://{host}:{port}" #: Timeout for server replies. self.recv_timeout = timeout if connect: self.connect() def __enter__(self): if not self.connected: self.connect() return self def __exit__(self, exc_type, exc_val, exc_tb): self.disconnect() def connect(self): logger.info(f"Connecting to {self.addr}") self.context = zmq.Context() self.socket = self.context.socket(zmq.REQ) self.socket.setsockopt(zmq.RCVTIMEO, self.recv_timeout) self.socket.connect(self.addr) self.connected = True def ask(self, message): if not self.connected: raise RuntimeError("No connection yet.") # try so that if timeout happens, the client remains usable try: send(self.socket, message) ret = recv(self.socket) logger.debug(f"Response received.") logger.debug(f"Response: {str(ret)}") if isinstance(ret, ServerResponse): err = ret.error if err is not None: if isinstance(err, str): logger.error(err) elif isinstance(err, Warning): warnings.warn(err) elif isinstance(err, Exception): raise err else: raise TypeError(f'Unknown Error Type: {str(err)}') return ret.message except zmq.error.Again as e: # if there is a timeout, close the socket and connect again self.socket.close() self.connect() raise RuntimeError(f'Server did not reply before timeout.') def disconnect(self): self.socket.close() self.connected = False
def sendRequest(message, host='localhost', port=DEFAULT_PORT): with BaseClient(host, port) as cli: ret = cli.ask(message) return ret