def __init__(self, host=None, port=None): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # find BrewPi's via mdns lookup self.host=host self.port=port self.retries=10 # max reconnect attempts to try when doing a read or write operation self.retryCount=0 # count of reconnect attempts performed BrewPiUtil.logMessage("Connecting to BrewPi " + host + " on port " + str(port)) self.open() self.setTimeout(0.5) # self.timeout=self.sock.gettimeout() self.name=host + ':' + str(port) return
def create(self): """ Creates a socket socket based on the settings in the member variables and assigns it to self.sock This function deletes old sockets for file sockets, so do not use it to connect to a socket that is in use. """ if self.type == 'i': # Internet socket self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind((self.host, self.port)) util.logMessage('Bound to TCP socket on port %d ' % self.port) else: if os.path.exists(self.file): # if socket already exists, remove it. This prevents errors when the socket is corrupt after a crash. os.remove(self.file) self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind(self.file) # Bind BEERSOCKET # set all permissions for socket os.chmod(self.file, 0777)
def connect(self): """ Connect to the socket represented by BrewPiSocket. Returns a new connected socket object. This function should be called when the socket is created by a different instance of brewpi. """ sock = socket.socket try: if self.type == 'i': # Internet socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) util.logMessage('Bound to existing TCP socket on port %d ' % self.port) sock.connect((self.host, self.port)) else: sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.connect(self.file) except socket.error: sock = False finally: return sock
def read(self, size=1): #Returns: Bytes read from the port. #Read size bytes from the serial port. If a timeout is set it may return less characters as requested. With no timeout it will block until the requested number of bytes is read. bytes=None try: bytes=self.sock.recv(size) except socket.timeout: # timeout on receive just means there is nothing in the buffer. This is not an error return None except socket.error: # other socket errors probably mean we lost our connection. try to recover it. if self.retryCount < self.retries: self.retryCount=self.retryCount+1 BrewPiUtil.logMessage("Lost connection to controller on read. Attempting to reconnect.") self.sock.close() self.open() bytes=self.read(size) else: self.sock.close() BrewPiUtil.logMessage("Lost connection to controller on read. Exiting.") sys.exit(1) # return None if bytes is not None: if self.retryCount > 0: BrewPiUtil.logMessage("Successfully reconnected to controller on read.") self.retryCount = 0 return bytes
def detect_port(bootLoader=False, my_port=None): """ :return: first detected serial port as tuple: (port, name) :rtype: """ if my_port == "auto": my_port = None port = (None, None) ports = find_compatible_serial_ports(bootLoader=bootLoader, my_port=my_port) try: port = next(ports) except StopIteration: return port try: another_port = next(ports) BrewPiUtil.logMessage("Warning: Multiple compatible ports.") except StopIteration: pass return port
def write(self, data): #Returns: Number of bytes written. #Raises SerialTimeoutException: # In case a write timeout is configured for the port and the time is exceeded. #Write the string data to the port. try: bytes=self.sock.sendall(data) except socket.timeout: # A write timeout is probably a connection issue if self.retryCount < self.retries: self.retryCount=self.retryCount+1 BrewPiUtil.logMessage("Lost connection to controller on write. Attempting to reconnect.") self.sock.close() self.open() bytes=self.write(data) else: self.sock.close() BrewPiUtil.logMessage("Lost connection to controller on write. Exiting.") sys.exit(1) # return -1 except socket.error: # general errors are most likely to be a timeout disconnect from BrewPi, so try to recover. if self.retryCount < self.retries: BrewPiUtil.logMessage("Lost connection to controller on write. Attempting to reconnect.") self.retryCount=self.retryCount+1 self.sock.close() self.open() bytes=self.write(data) else: self.sock.close() BrewPiUtil.logMessage("Lost connection to controller on write, with socket.error. Exiting.") sys.exit(1) # return -1 if bytes>=0: if self.retryCount > 0: BrewPiUtil.logMessage("Successfully reconnected to controller on write.") self.retryCount = 0 return bytes
def open(self): mdnsLocator.locate_brewpi_services() # This causes all the BrewPi devices to resend their mDNS info try: self.sock.connect((self.host, self.port)) BrewPiUtil.logMessage("Successfully connected to controller.") except socket.gaierror as e: BrewPiUtil.logMessage("Unable to connect to BrewPi " + self.host + " on port " + str(self.port) + ". Exiting.") sys.exit(1) except socket.error as e: # Catches "bad file descriptor" error BrewPiUtil.logMessage("Unable to connect to BrewPi " + self.host + " on port " + str(self.port) + ". Exiting.") sys.exit(1)