def base_st_connect(self): """ Sends a confirmation message to Base Station to acknowledge connection. If it receives and ACK from Base Station, starts up the Sensor_thread. """ self.tried = 0 while(self.tried<=5): LOGMSG("Checking if base station is responding...") self.tried += 1 msg = pack('8sBBB','SLIPCC11',kelvin.DISPATCH,kelvin.CMD | kelvin.CONN_REQ, 0) self.write(msg) time.sleep(2) rsp = self.read() if(rsp != b''): break if(self.tried > 5): LOGMSG("Base station currently unreachable. Please try later.") LOGMSG("The server will now close...") self.close() else: LOGMSG("Connected to base station.") #Start a thread which will handle all sensor data extraction self.sensor = Sensor(self) self.sensor.start()
class Serial_conn: """ Serial communication class. Provides connection and message transmission functionalities. """ def __init__(self): """ Initializes the SComms module. """ self.supports_base64 = False LOGMSG ("Server starting") self.start() def get_port(self): """ Specified the port number to be opened. Scans all available ports, and prompts the user to select a port number to be opened @rtype: number @return: the port number to be opened """ ports = self.scan_for_ports() while(ports == []): LOGMSG("Base station is not connected to any serial port. Please connect base station before proceeding. Press ENTER to try again, or type EXIT to quit") msg = input() if(msg==''): ports = self.scan_for_ports() elif(msg=='exit'): exit() elif(msg=='break'): break else: LOGMSG('Invalid command!Please try again') msg = "Serial connections detected at the following ports:" i = 0 while(i<len(ports)): msg += " COMM%d" %ports[i] i += 1 LOGMSG(msg) self.port = int(input("Please select a PORT number: ")) while((self.port<1) | (self.port>10)): self.port = int(input("Invalid PORT number! Please enter a valid PORT number: ")) return self.port def get_baud(self, msg="Please enter the baudrate of the connection, or press ENTER to skip this step (the baudrate will be set to default value 38400): "): """ Prompts the user for a baudrate value. If none selected, a default value is chosen. @type msg: string @param msg: the prompt message to be displayed to the user. @rtype: number @return: the baudrate value """ self.baud = (input(msg)) if(self.baud==''): self.baud = 38400 return int(self.baud) def get_timeout(self, msg="Please enter the connection timeout (in seconds), or press ENTER to skip this step (the timeout will be set to default value 1): "): """ Prompts the user for a timeout value. If none selected, a default value is chosen. @type msg: string @param msg: the prompt message to be displayed to the user. @rtype: number @return: the timeout value """ self._timeout = (input(msg)) if(self._timeout==''): self._timeout = 1 return int(self._timeout) def close(self,status=0): """ Terminates the serial communication and closes the the sensor_thread instance @type status: number @param status: the close status value """ try: self.sensor.close() except: if(self.serial != None and self.serial.isOpen()): self.serial.close() def start(self): """ Starts the SComms module. Prompts the user for a port number, baudrate and timeout values, and connects to the Base Station using these values. """ self.port = self.get_port() self.baud = self.get_baud() self._timeout = self.get_timeout() # Establish serial port connection self.connect(self.port-1, self.baud, self._timeout) # Connect to base station self.base_st_connect() def base_st_connect(self): """ Sends a confirmation message to Base Station to acknowledge connection. If it receives and ACK from Base Station, starts up the Sensor_thread. """ self.tried = 0 while(self.tried<=5): LOGMSG("Checking if base station is responding...") self.tried += 1 msg = pack('8sBBB','SLIPCC11',kelvin.DISPATCH,kelvin.CMD | kelvin.CONN_REQ, 0) self.write(msg) time.sleep(2) rsp = self.read() if(rsp != b''): break if(self.tried > 5): LOGMSG("Base station currently unreachable. Please try later.") LOGMSG("The server will now close...") self.close() else: LOGMSG("Connected to base station.") #Start a thread which will handle all sensor data extraction self.sensor = Sensor(self) self.sensor.start() def connect(self, port , baud = 38400 , _timeout = 1): """ Tries to connected to specified port, using given baudrate and timeout values @type port: number @param port: the port to be opened @type baud: number @param baud: the specified baudrate @type _timeout: number @param _timeout: the specified timeout value """ LOGMSG("Connecting to base station ...") try: self.serial = Serial(port,baud, timeout = _timeout) except serialutil.SerialException: LOGMSG ("Could not open port %d." %self.port) LOGMSG ("Retrying to reconnect in 5 seconds..." ) time.sleep(5) LOGMSG("Reconnecting...") try: self.serial = Serial(port,baud, timeout = _timeout) except serialutil.SerialException: LOGMSG("Could not open port %d." %self.port) self.port = self.get_port("Maybe the PORT number is wrong? Please enter PORT number again: "); LOGMSG("Reconnecting...") try: self.serial = Serial(port,baud, timeout= _timeout) except serialutil.SerialException: LOGMSG ("Could not open port %d. " %self.port) LOGMSG("Please check you configurations and PORT connections!") self.close(1) LOGMSG("Serial connection established on port %d. Using baudrate %d and timeout %d" %(self.port, self.baud, self._timeout)) def scan_for_ports(self): """ Scans the system for open ports @rtype: array @return: an array of available ports """ result=[] ports = scan() if (len(ports) >0): i = 1 while(i<len(ports)): result.append(ports[i][0]+1) i+=1 return result ################################################## Serial functions ############################################ def _process_line(self, line): """ Process line and return. - Checks if the other end responds in Base64 and changes operating mode. - Removes trailing \r\n """ if line is not None and len(line) > 0: line = line.rstrip(b'\r\n') if line[:1] == b'!': self.supports_base64 = True try: line = b''.join([b64decode(part) for part in line.split(b'!')[1:]]) except: DEBUG("Could not decode!") return line def read( self ): """ Calls _process_line to read incoming messages """ return self._process_line(self.serial.readline()) def write( self, string ): """ Only responds in Base64 if a previously received line was Base64. Adds \r\n """ if self.supports_base64: string = b'!' + b64encode(string) self.serial.write( string + b'\r\n' ) def __iter__(self): self._current_iter = iter(self.serial) return self def __next__(self): return self._process_line(self._current_iter.__next__()) def set_color(self, col): self.writeline(b"s "+str(col)) def flash(self): i = 0 for i in range(100): self.set_color(randint(0,7)) time.sleep(randint(1,7)/20) ################################### DEPRECATED ############################################ def pause(self): """ Pauses the sensor_thread - Deprecated """ if(self.sensor != None): if(self.sensor.closed != 1): if(self.sensor.paused != 1): self.sensor.paused = 1 DEBUG("Flow paused") else: DEBUG("Already paused!") def resume(self): """ Resumes the sensor_thread - Deprecated """ if(self.sensor != None): if(self.sensor.closed != 1): if(self.sensor.paused == 1): self.sensor.paused = 0 DEBUG("Flow resumed") else: DEBUG("Flow not paused!")