def consumer(self, callback, blocking=True, immortal=False, raw=False): """ When a position sentence is received, it will be passed to the callback function blocking: if true (default), runs forever, otherwise will return after one sentence You can still exit the loop, by raising StopIteration in the callback function immortal: When true, consumer will try to reconnect and stop propagation of Parse exceptions if false (default), consumer will return raw: when true, raw packet is passed to callback, otherwise the result from aprs.parse() """ if not self._connected: raise ConnectionError("not connected to a server") line = b'' while True: try: for line in self._socket_readlines(blocking): if line[0:1] != b'#': if raw: return line else: packet = self._parse(line) return packet else: self.logger.debug("Server: %s", line.decode('utf8')) except ParseError as exp: self.logger.log(11, "%s\n Packet: %s", exp.message, exp.packet) except UnknownFormat as exp: self.logger.log(9, "%s\n Packet: %s", exp.message, exp.packet) except LoginError as exp: self.logger.error("%s: %s", exp.__class__.__name__, exp.message) except (KeyboardInterrupt, SystemExit): raise except (ConnectionDrop, ConnectionError): self.close() if not immortal: raise else: self.connect(blocking=blocking) continue except GenericError: pass except StopIteration: break except: self.logger.error("APRS Packet: %s", line) raise if not blocking: break
def _connect(self): """ Attemps connection to the server """ self.logger.info("Attempting connection to %s:%s", self.server[0], self.server[1]) try: self._open_socket() peer = self.sock.getpeername() self.logger.info("Connected to %s", str(peer)) # 5 second timeout to receive server banner self.sock.setblocking(1) self.sock.settimeout(5) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) banner = self.sock.recv(512) if is_py3: banner = banner.decode('latin-1') if banner[0] == "#": self.logger.debug("Banner: %s", banner.rstrip()) else: raise ConnectionError("invalid banner from server") except ConnectionError as e: self.logger.error(str(e)) self.close() raise except (socket.error, socket.timeout) as e: self.close() self.logger.error("Socket error: %s" % str(e)) if str(e) == "timed out": raise ConnectionError("no banner from server") else: raise ConnectionError(e) self._connected = True
def sendall(self, line): """ Send a line, or multiple lines sperapted by '\\r\\n' """ if isinstance(line, APRSPacket): line = str(line) elif not isinstance(line, string_type): raise TypeError("Expected line to be str or APRSPacket, got %s", type(line)) if not self._connected: raise ConnectionError("not connected") if line == "": return line = line.rstrip("\r\n") + "\r\n" try: self.sock.setblocking(1) self.sock.settimeout(5) self._sendall(line) except socket.error as exp: self.close() raise ConnectionError(str(exp))