Module gonioimsoft.clientbase
Commond code for all client programs.
Functions
def run_client(client)
-
Runs the client from terminal without the main GonioImsoft program.
Classes
class ClientBase (host, port, running_index=0)
-
Base class for all clients.
The client offers a stable API for the main software (GonioImsoft) to use. The client internals and the server can be then more freely changed without causing havoc.
Attributes
host
:string
- The server IP (v4) address or a hostname
port
:int
- The server port number
local_server
:Popen obj
orNone
- None if no local server started by the client
Expand source code
class ClientBase: '''Base class for all clients. The client offers a stable API for the main software (GonioImsoft) to use. The client internals and the server can be then more freely changed without causing havoc. Attributes ---------- host : string The server IP (v4) address or a hostname port : int The server port number local_server : Popen obj or None None if no local server started by the client ''' def __init__(self, host, port, running_index=0): self.host = host self.port = port def send_command(self, command, listen=False, n_retry=60, retry_interval=1): '''Sends an arbitrary command to the server. Opens a connection to the server, send the command string and then optionally waits for the server's response. Arguments --------- command : string Format: "{command_name};{arg1}:{arg2}:..." Example 1: "ping;hello there" Example 2: "acquireSeries;0:0.1:0:5:label" listen : bool Wheter to wait and listen the server's response. If used incorrectly (listen=True but server says nothing, or listen=False and server says back), hangs either the client or the server. n_retry : int How many times to try to recontact the server if it cannot be reached (the server is off or the network is down etc.) Default is 60. retry_interval : int or float In seconds, how long to sleep between between the connection retries. Default is 1. ''' if not isinstance(command, str): typ = type(command) raise TypeError(f'command must be a string, not {typ}') tries = 0 host = self.host port = self.port with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as soc: while True: try: soc.connect((host, port)) break except ConnectionRefusedError: tries += 1 if tries > n_retry: raise ConnectionRefusedError( f'Cannot connect to {host}:{port}') print('Server connection unavailable, retrying...') time.sleep(retry_interval) soc.sendall(command.encode()) if listen: response = [] while True: data = soc.recv(1024) if not data: break response.append(data.decode()) response = ''.join(response) if ':' in response: response = response.split(':') return response def is_server_running(self): '''Returns True if the server responds to ping. ''' try: self.send_command( 'ping;Hello there!', n_retry=0) except ConnectionRefusedError: return False return True def set_save_directory(self, directory): '''For any data saving that the server can do, set the directory. ''' self.send_command(f'set_save_directory;{directory}') def start_server(self, name): '''Starts a local server if it is not running. Starts a new subprocess for the server. Arguments --------- name : string Name of the server. "camera" or "vio" ''' if name not in ['camera', 'vio']: raise ValueError( f'name has to be "camera" or "vio" not {name}') if self.is_server_running(): print(f'Local server on port {self.port} already runs') print('-> Not starting another') return print(f'Starting a local server on port {self.port}') self.local_server = subprocess.Popen( [ sys.executable, '-m', f'gonioimsoft.{name}_server', '--port', str(self.port), ], stdout=subprocess.DEVNULL) atexit.register(self.close_server) def close_server(self): '''Sens a closeure message for the server. If the server was started by this client (a local server), also waits the subprocess finish for 10 seconds unil terminates it. ''' try: self.send_command('exit;parakalo', n_retry=0) except ConnectionRefusedError: pass if self.local_server is None: return atexit.unregister(self.close_server) if self.local_server is not None: try: self.local_server.wait(10) except subprocess.TimeoutExpired: self.local_server.terminate() self.local_server = None
Subclasses
Methods
def close_server(self)
-
Sens a closeure message for the server.
If the server was started by this client (a local server), also waits the subprocess finish for 10 seconds unil terminates it.
def is_server_running(self)
-
Returns True if the server responds to ping.
def send_command(self, command, listen=False, n_retry=60, retry_interval=1)
-
Sends an arbitrary command to the server.
Opens a connection to the server, send the command string and then optionally waits for the server's response.
Arguments
command
:string
- Format: "{command_name};{arg1}:{arg2}:…" Example 1: "ping;hello there" Example 2: "acquireSeries;0:0.1:0:5:label"
listen
:bool
- Wheter to wait and listen the server's response. If used incorrectly (listen=True but server says nothing, or listen=False and server says back), hangs either the client or the server.
n_retry
:int
- How many times to try to recontact the server if it cannot be reached (the server is off or the network is down etc.) Default is 60.
retry_interval
:int
orfloat
- In seconds, how long to sleep between between the connection retries. Default is 1.
def set_save_directory(self, directory)
-
For any data saving that the server can do, set the directory.
def start_server(self, name)
-
Starts a local server if it is not running.
Starts a new subprocess for the server.
Arguments
name
:string
- Name of the server. "camera" or "vio"