from django.conf import settings import socket import configparser import abc import select import utils.Logger as L import time import os DEBUG_FILE = True ''' Generic object for the communication with all the devices ''' class DeviceController(): __metaclass__ = abc.ABCMeta logger = L.setupLogger("DeviceLogger", "Devices") name = "" config_file = "../config/socket_config.ini" config = None connected = False sock = None ip = None port = None def __init__(self, device_name): self.name = device_name self.getConfig() self.getConnection(device_name) self.connect() @abc.abstractmethod def set(self, command: str, *args): return @abc.abstractmethod def do(self, command: str, *args): return @abc.abstractmethod def get(self, command: str, *args): return @abc.abstractmethod def getStatus(self): return def sendMessage(self, message: str): if (not self.isConnected()): # (EP) NON, return 0 !!! #return (1) return False # (EP) Here we are still not sure that we are connected to the device (it may be down and we do not know) try: readable, writable, exceptional = select.select([], [self.sock], [self.sock], 0) if not (writable or exceptional): raise (Exception("Socket not writable")) self.sock.send(bytes(message, "UTF-8")) except Exception as e: if (settings.DEBUG): print("(ENV) Could not send message (on socket) to "+self.name+" : " + message + " -> " + str(e)) #EP TODO: bugfix: ce log ne fait rien du tout !! self.log(self.name, "Could not send message on socket : " + message + " -> " + str(e)) ret = self.reconnect() while not ret: ret = self.reconnect() # (EP) NON, 1 = true !!! #return (1) return False # (EP) NON, 0 = false !!! #return (0) return True def isError(self, message: str): #EP #if (message == "FAILED" or message == "NOT_SET" or message == "DISCONNECTED"): if (message == "FAILED" or message.startswith("NOT_SET") or message == "DISCONNECTED"): return (True) return (False) # MIND: Does not mean "is connected now" but "WAS connected once" def isConnected(self): if (not self.sock or not self.connected): # (EP) NON, c'est totalement illisible !!! on n'est plus en 1970 #if (self.connect()): return (False) print("something is wrong with this device, now trying to connect again...") if not self.connect(): return False #self.connected = True return True def readBytes(self, size) -> str: if (not self.isConnected()): return ("NOT_SET2") try: readable, writable, exceptional = select.select([self.sock], [], [self.sock], 0) if not (readable or exceptional): raise (Exception("Socket not readable")) ret = self.sock.recv(size).decode() if (not ret): if (settings.DEBUG): self.log(self.name, "Connection has been killed") self.connected = False return ("DISCONNECTED") except Exception as e: if (settings.DEBUG): self.log(self.name, "Socket not readable : " + str(e)) return ("FAILED") return (ret) def blockAndReadBytes(self, size) -> str: self.sock.setblocking(1) return (self.readBytes(size)) def blockAndReadMessage(self) -> str: return (self.blockAndReadBytes(1024)) def setBlocking(self, flag): if (not self.sock): return (1) self.sock.setblocking(flag) return (0) # TODO maybe read more than 1024 bytes ????? def readMessage(self) -> str: return self.readBytes(1024) def getConnection(self, device_name): self.ip = self.config.get(device_name, "ip") self.port = int(self.config.get(device_name, "port")) return (0) def getConfig(self): self.config = configparser.ConfigParser() self.config.read(self.config_file) return (0) def log(self, device_name: str, message: str): if DEBUG_FILE and settings.DEBUG: self.logger.info("From device : " + device_name + " -> " + message) return (0) def connect(self): if (self.ip is None or self.port is None): self.log(self.name, "Ip or Port not initialized") # (EP) It's a serious bug, so raise exception !!! #return (1) raise (Exception(self.name +"Controller has no ip or port to connect to")) try: # Create a TCP/IP socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connect the socket to the port on the server r = self.sock.connect_ex((self.ip, self.port)) if (r != 0): raise Exception("sock.connect_ex failed : " + os.strerror(r)) ''' Socket set to non blocking (by default, it is blocking) In non-blocking mode, if a recv() call doesn’t find any data, or if a send() call can’t immediately dispose of the data, an error exception is raised. (In blocking mode, the calls block until they can proceed) s.setblocking(0) is equivalent to s.settimeout(0.0); s.setblocking(1) is equivalent to s.settimeout(None). ''' self.sock.setblocking(0) except Exception as e: print(e) print("FAILED TO CONNECT TO DEVICE {}".format(self.name)) if (settings.DEBUG): #TODO: Bugfix: Ce log ne fait rien ! self.log(self.name, "Failed to connect to " + str(self.ip) + ":" + str(self.port) + " -> " + str(e)) # (EP) return TRUE??? (for python, 1=true !!!) #return (1) return False self.connected = True # (EP) return FALSE ??? (for python, 0=false !!!) #return (0) return True def reconnect(self): self.getConfig() self.getConnection(self.name) try: print("Trying to reconnect to " + str(self.name)) self.connect() return True except Exception as e: print(str(e)) time.sleep(1) return False