#!/usr/bin/env python3 """Socket Client (abstract) To be used as a base class (interface) for any concrete socket client class """ # Standard library imports import os # Third party imports # None # Local application imports from src.logpyros import LogPyros ##from device_controller.logs import * ''' def printd(*args, **kwargs): if os.environ.get('PYROS_DEBUG', '0')=='1': print(*args, **kwargs) ''' ##class SocketClientAbstract(): class ClientChannel(): my_channel = None buf = 1024 #def __init__(self, server_host:str="localhost", server_port:int=11110, PROTOCOL:str="SOCKET-TCP", buffer_size=1024, DEBUG=False): def __init__(self, server_host:str="localhost", server_port:int=11110, PROTOCOL:str="SOCKET-TCP", buffer_size=1024): ''' :param server_host: server IP or hostname :param server_port: server port :param PROTOCOL: "SOCKET-TCP" or "SOCKET-UDP" or "SERIAL" or "USB" (to be continued...) ''' self.DEBUG_MODE = os.environ.get('PYROS_DEBUG', '0') == '1' self.HOST = server_host self.PORT = server_port self.PROTOCOL = PROTOCOL self.buf = buffer_size self.log = LogPyros(self.__class__.__name__) # Logger configuration #self.set_logger() ##set_logger(DEBUG) self.printd("\n**************************") ##log_d("Client CHANNEL instanciated") self.printd("Client CHANNEL instanciated") # So that we can use this with the "with" statement (context manager) def __enter__(self): return self def __exit__(self, type, value, traceback): self.close() #printd("Client channel killed") print("Client channel killed") # LOG methods def print(self, *args, **kwargs): self.log.print(*args, **kwargs) def printd(self, *args, **kwargs): self.log.printd(*args, **kwargs) def send_data(self, data:str): ##data_encapsulated = self.encapsulate_data_to_send(data) self._send_data(data) ''' #data_to_send = bytes(data_to_send + "\n", "utf-8") #data_to_send = bytes(data_to_send + "\x00", "utf-8") ##data_to_send = bytes(data_to_send, "utf-8") data_to_send_bytes = data_to_send.encode("utf-8") #data_to_send_bytes = data_to_send.encode() if self.PROTOCOL=="SOCKET-TCP": # Unlike send(), this method sendall() continues to send data from bytes until either all data has been sent or an error occurs. # None is returned on success. # On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent nb_bytes_sent = self.mysock.sendall(data_to_send_bytes) else: # SOCKET-UDP nb_bytes_sent = self.mysock.sendto(data_to_send_bytes, (self.HOST, self.PORT)) log_i(f'Sent: {data_to_send_bytes}') log_i(f"Sent {nb_bytes_sent} bytes") ''' #@abstract def _send_data(self, data_to_send:str): pass def receive_data(self)->str: data_received = self._receive_data() ##data_received_bytes = self.mysock.recv(self.buf) #printd("Received (all data): {}".format(data_received)) #printd("data in bytes: "+str(bytes(data_received, "utf-8"))) ##data_received_uncaped = self.uncap_received_data(data_received) #log_i("RECEIVED (useful data): {}".format(data_received)) return data_received #@abstract def _receive_data(self)->bytes: pass ''' data_received = self.mysock.recv(self.buf) #printd("data type is "+str(type(data_received))) log_i(f"RECEIVED (ALL BYTES): {data_received}") #return str(data_received, "utf-8") return data_received ''' #@abstract def _connect_to_server(self): pass # Close socket def close(self): self.mysock.close() ''' put(), read(), put_read() commands ''' def put(self, data:str): self.send_data(data) def read(self)->str: return self.receive_data() def put_read(self, data:str)->str: # send command self.put(data) # receive answer (or ack) return self.read()