def Receive(self, size=1): """Receives N bytes. It blocks at most timeout seconds. Args: size: number of bytes to receive. 0 means receiving what already in the input buffer. Returns: Received N bytes. Raises: SerialTimeoutException if it fails to receive N bytes. """ start_time = time.time() if size == 0: size = self._serial.inWaiting() response = self._serial.read(size) if len(response) == size: if self.log: duration = time.time() - start_time logging.info('Successfully received %r. Took %.3f seconds', response, duration) return response else: error_message = 'Receive %d bytes timeout after %.2f seconds' % ( size, self._serial.getTimeout()) if self.log: logging.warning(error_message) raise serial.SerialTimeoutException(error_message)
def _process_request(self, request: bytes, skip=0): """ :param request: request that is sent to the monoprice :param skip: number of bytes to skip for end of transmission decoding :return: ascii string returned by monoprice """ _LOGGER.debug('Sending "%s"', request) # clear self._port.reset_output_buffer() self._port.reset_input_buffer() # send self._port.write(request) self._port.flush() # receive result = bytearray() while True: c = self._port.read(1) if not c: raise serial.SerialTimeoutException( 'Connection timed out! Last received bytes {}'.format( [hex(a) for a in result])) result += c if len(result) > skip and result[-LEN_EOL:] == EOL: break ret = bytes(result) _LOGGER.debug('Received "%s"', ret) return ret.decode('ascii')
def Send(self, command, flush=True): """Sends a command. It blocks at most write_timeout seconds. Args: command: command to send. flush: call flush() after write(). Default True. Raises: SerialTimeoutException if it is timeout and fails to send the command. SerialException if it is disconnected during sending. """ try: start_time = time.time() self._serial.write(command) if flush: self._serial.flush() if self.log: duration = time.time() - start_time logging.info('Successfully sent %r. Took %.3f seconds', command, duration) except serial.SerialTimeoutException: error_message = 'Send %r timeout after %.2f seconds' % ( command, self._serial.getWriteTimeout()) if self.log: logging.warning(error_message) raise serial.SerialTimeoutException(error_message) except serial.SerialException: raise serial.SerialException('Serial disconnected')
def readSerial(self): cnt = 0 # read pack head while (True): tmp = self.ser.read() #print(tmp) if (tmp == b'\xaa'): tmp = self.ser.read() if (tmp == b'\x77'): break cnt += 1 if (50 == cnt): raise serial.SerialTimeoutException() # from here data is to be returned tmp = self.ser.read(3) ret = [0xaa, 0x77, tmp[0], tmp[1], tmp[2]] tmp = self.ser.read(ret[4] + 2) for d in tmp: ret.append(d) crc = self.CRC16_MODBUS(ret[0:-2]) if ((crc & 0xff == ret[-2]) and ((crc >> 8) & 0xff == ret[-1])): return ret[2:-2] else: # print(ret) raise serial.SerialException("data corrupted")
def _recv_once(self): """Receive once, filter output and update switch state by parsing prompt""" # First, call self.readlines(). # It reads from serial port and gets a list with one line per list item. # In each of the list's item, remove any \r or \n, but only at end of line (right strip) # For each line of the output, give it to _filter # This will filter out switch comments and put them into a separated list # Finally, use filter(None, list) to remove empty elements coms = [] try: out = filter(None, [ self._filter(l.rstrip("\r\n"), coms) for l in self.sock.readlines() ]) except serial.SerialException: logger.error("The switch port seems to be busy. Aborting") raise # out should never be empty. Otherwise it means we have a problem... if not out: raise serial.SerialTimeoutException("The read timed out.") # However, out may become empty after prompt parsing (prompt will be removed) self.state = self._parse_prompt(out) if self.state: logger.debug("Switch state is: '%s'", self.state.name) else: logger.error("Switch state is unknown") return (out, coms)
def _process_request(self, request: str): """ Send data to serial :param request: request that is sent ot the Nuvo :return: ascii string returned by Nuvo """ # clear the port self._port.reset_output_buffer() self._port.reset_input_buffer() # send request #format and send output command lineout = "*" + request + "\r" self._port.write(lineout.encode()) self._port.flush() _LOGGER.debug('Sending "%s"', lineout) # receive response result = bytearray() while True: c = self._port.read(1) if c is None: break if not c: raise serial.SerialTimeoutException( 'Connection timed out! Last received bytes {}'.format([hex(a) for a in result])) result += c if result [-LEN_EOL:] == EOL: break ret = bytes (result) _LOGGER.debug('Received "%s"', ret) return ret.decode('ascii')
def Send(self, command): """Sends a command. It blocks at most write_timeout seconds. Args: command: command to send. Raises: SerialTimeoutException if it is timeout and fails to send the command. SerialException if it is disconnected during sending. """ try: self._serial.write(command) self._serial.flush() if self.log: logging.info('Successfully sent %r', command) except serial.SerialTimeoutException: error_message = 'Send %r timeout after %.2f seconds' % ( command, self._serial.getWriteTimeout()) if self.log: logging.warning(error_message) raise serial.SerialTimeoutException(error_message) except serial.SerialException: raise serial.SerialException('Serial disconnected')
def _recv_command(self): """Reads a full line from the microcontroller We expect to complete a read when this is invoked, so don't invoke unless you expect to get data from the microcontroller. we raise a timeout if we cannot read a command in the alloted timeout interval.""" # we rely on the passed-in timeout while True: c = self._serial.read(1) if not c: raise serial.SerialTimeoutException( "Couldn't recv command in %d seconds" % self.IO_TIMEOUT_SEC) # finished reading an entire COBS structure if c == '\x00': # grab the data and reset the buffer data = self._read_buf[0:self._read_buf_pos] self._reset_read_buf() # return decoded data return cobs.decode(str(bytearray(data))) # still got reading to do else: self._read_buf[self._read_buf_pos] = c self._read_buf_pos += 1 # ugh. buffer overflow. wat do? if self._read_buf_pos == len(self._read_buf): # resetting the buffer likely means the next recv will fail, too (we lost the start bits) self._reset_read_buf() raise RuntimeError("IO read buffer overflow :(")
def isReady(self): self.ser.write(serial.to_bytes(self.setAddrBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = struct.unpack("!7B", rcv) if (self.checkChecksum(unpacked)): return True else: raise serial.SerialTimeoutException("Timeout setting address")
def readCurrent(self): self.ser.write(serial.to_bytes(self.readCurrentBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpaked = struct.unpack("!7B", rcv) if (self.checkChecksum(unpacked)): current = unpacket[2] + unpacked[3] / 100.0 else: raise serial.SerialTimeoutException("Timeout reading current")
def _send_command_raw(self, command, opt=''): """ Description: The TV doesn't handle long running connections very well, so we open a new connection every time. There might be a better way to do this, but it's pretty quick and resilient. Returns: If a value is being requested ( opt2 is "?" ), then the return value is returned. If a value is being set, it returns True for "OK" or False for "ERR" """ # According to the documentation: # http://files.sharpusa.com/Downloads/ForHome/ # HomeEntertainment/LCDTVs/Manuals/tel_man_LC40_46_52_60LE830U.pdf # Page 58 - Communication conditions for IP # The connection could be lost (but not only after 3 minutes), # so we need to the remote commands to be sure about states # clear self._port.reset_output_buffer() self._port.reset_input_buffer() # Send command if opt != '': command += str(opt) command = command.ljust(8)+'\r\n' command = command.encode('utf-8') _LOGGER.debug('*Sending "%s"', command) self._port.write(command) self._port.flush() # receive result = bytearray() while True: char = self._port.read(1) if char is None: break if not char: raise serial.SerialTimeoutException( 'Connection timed out! Last received bytes {}' .format([hex(a) for a in result])) result += char if result and result[-1:] == b'\r': break status = bytes(result).strip().decode("utf-8") _LOGGER.debug('*Received "%s"', status) if "OK" in status: return True if "ERR" in status: return False try: return int(status) except ValueError: return status
def readVoltage(self): self.ser.write(serial.to_bytes(self.readVoltageBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = struct.unpack("!7B", rcv) if (self.checkChecksum(unpacked)): tension = unpacked[2] + unpacked[3] / 10.0 return tension else: raise serial.SerialTimeoutException("Timeout reading tension")
def readPower(self): self.ser.write(serial.to_bytes(self.readPowerBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = struct.unpack("!7B", rcv) if (self.checkChecksum(unpacked)): power = unpacked[1] * 256 + unpacked[2] return power else: raise serial.SerialTimeoutException("Timeout reading power")
def waitForSync(): """ Waits for the SYNC character from Sparki arguments: none returns: nothing """ global serial_conn global serial_is_connected if not serial_is_connected: printDebug("Sparki is not connected - use init()", DEBUG_CRITICAL) raise RuntimeError( "Attempt to listen for message from Sparki without initialization") serial_conn.flushInput() # get rid of any waiting bytes start_time = time.time() inByte = -1 loop_wait = 0 if platform.system( ) == "Darwin": # Macs seem to be extremely likely to timeout -- this is attempting to deal with that quickly retries = 1 # the number of times to retry connecting in the case of a timeout loop_wait = 0 # pause this long each time through the loop else: retries = 5 # the number of times to retry connecting in the case of a timeout loop_wait = .01 # pause this long each time through the loop while inByte != SYNC.encode( ): # loop, doing nothing substantive, while we wait for SYNC if time.time() > start_time + (CONN_TIMEOUT * retries): if platform.system( ) == "Darwin": # Macs seem to be extremely likely to timeout -- so we report at a different debug level printDebug( "In waitForSync, unable to sync with Sparki (this may not be due to power saving settings)", DEBUG_INFO) else: printDebug("In waitForSync, unable to sync with Sparki", DEBUG_ERROR) raise serial.SerialTimeoutException( "Unable to sync with Sparki -- may be temporary error due to power saving" ) try: inByte = serial_conn.read() except serial.SerialTimeoutException: printDebug( "SerialTimeoutException caught in waitForSync, unable to sync with Sparki", DEBUG_ERROR) raise time.sleep(loop_wait)
def readEnergy(self): self.ser.write(serial.to_bytes(self.readEnergyBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = struct.unpack("!7B", rcv) if (self.checkChecksum(unpacked)): energy = unpacked[1] * 256 * 256 + unpacked[ 2] * 256 + unpacked[3] return energy else: raise serial.SerialTimeoutException( "Timeout reading registered power")
def _recv_once_retry(self): """Try to receive once, and retries with increasing timeout if it fails""" for _ in range(config.READ_RETRIES + 1): try: return self._recv_once() except serial.SerialTimeoutException: logger.error("Read failed with timeout %fs. Will retry...", self.sock.timeout) self.sock.timeout = self.sock.timeout * 2 msg = "All read attempts timed out. Is the switch dead or the port already busy?" logger.error(msg) raise serial.SerialTimeoutException(msg)
def readAll(self): """Returns all values (voltage, current, wattage, watt hours) Raises: serial.SerialTimeoutException: Timeout on PZEM connection Returns: tuple: All values (voltage, current, wattage, watt hours) """ if self.isReady(): return (self.readVoltage(), self.readCurrent(), self.readWattage(), self.readWattHours()) raise serial.SerialTimeoutException("Timeout reading registered power")
def _query(self, cmd): """tx/rx to/from PS""" self._debug("PPS <- %s<CR>\n" % cmd) self._serial.write((cmd + "\r").encode()) b = [] self._debug("PPS -> ") while True: b.append(self._serial.read(1)) self._debug(b[-1].replace(b"\r", b"<CR>").decode()) if b[-1] == "": raise serial.SerialTimeoutException() if b"".join(b[-3:]) == b"OK\r": break self._debug("\n") return (b"".join(b[:-4])).decode()
def _read(self, skip=0): result = bytearray() while True: c = self._port.read(1) if not c: raise serial.SerialTimeoutException( 'Connection timed out! Last received bytes {}'.format( [hex(a) for a in result])) result += c if len(result) > skip and result[-LEN_EOL:] == EOL: result = result[:-LEN_EOL] # strip off end of line break ret = bytes(result).decode(ENCODING) LOG.debug(f"Received: {ret}") return ret
def _process_request(self, request: bytes, skip=0): """ Send data to socket :param request: request that is sent to the blackbird :param skip: number of bytes to skip for end of transmission decoding :return: ascii string returned by blackbird """ _LOGGER.debug('Sending "%s"', request) if use_serial: # clear self._port.reset_output_buffer() self._port.reset_input_buffer() # send self._port.write(request) self._port.flush() # receive result = bytearray() while True: c = self._port.read(1) if c is None: break if not c: raise serial.SerialTimeoutException( 'Connection timed out! Last received bytes {}'. format([hex(a) for a in result])) result += c if len(result) > skip and result[-LEN_EOL:] == EOL: break ret = bytes(result) _LOGGER.debug('Received "%s"', ret) return ret.decode('ascii') else: self.socket.send(request) response = '' while True: data = self.socket.recv(SOCKET_RECV) response += data.decode('ascii') if EOL in data and len(response) > skip: break return response
def _query(self, cmd): """ tx/rx to/from PS """ if self._debug: _pps_debug("PPS <- %s<CR>\n" % cmd) self._Serial.write((cmd + "\r").encode()) b = [] if self._debug: _pps_debug("PPS -> ") while True: b.append(self._Serial.read(1)) if self._debug: _pps_debug(b[-1].replace(b'\r', b'<CR>').decode()) if b[-1] == "": raise serial.SerialTimeoutException() if b[-3:] == [bytes(c, encoding="ASCII") for c in "OK\r"]: break if self._debug: _pps_debug('\n') return (b"".join(b[:-4])).decode()
def isReady(self): """Checks whether the PZEM is ready to return data Raises: serial.SerialTimeoutException: Timeout on PZEM connection Returns: bool: Whether the PZEM is ready or not """ self.ser.write(serial.to_bytes(self.setAddrBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = unpack("!7B", rcv) if self.checkChecksum(unpacked): return True raise serial.SerialTimeoutException("Timeout setting address")
def recv_command(): global receive_pos while True: c = serial_port.read(1) if not c: raise serial.SerialTimeoutException( "Couldn't recv command in %d seconds" % IO_TIMEOUT_SEC) if c == '\r': # End of packet. data = str(bytearray(receive_buf[0:receive_pos])) reset_receive_buf() # Ignore short packets. if len(data) <= 8: print "Short packet" continue # Verify checksum. sum = data[-8:] data = data[:-8] checksum = binascii.crc32(data) & 0xFFFFFFFF if sum[0] != chr(97 + (checksum >> 28 & 0xf)) or \ sum[1] != chr(97 + (checksum >> 24 & 0xf)) or \ sum[2] != chr(97 + (checksum >> 20 & 0xf)) or \ sum[3] != chr(97 + (checksum >> 16 & 0xf)) or \ sum[4] != chr(97 + (checksum >> 12 & 0xf)) or \ sum[5] != chr(97 + (checksum >> 8 & 0xf)) or \ sum[6] != chr(97 + (checksum >> 4 & 0xf)) or \ sum[7] != chr(97 + (checksum & 0xf)): print "Bad checksum:", sum continue # Return received data. #print repr(data) return data #print "'" + c + "'" receive_buf[receive_pos] = c receive_pos += 1 if receive_pos == len(receive_buf): # Buffer overflow. reset_receive_buf() raise RuntimeError("IO read buffer overflow")
def SendReceive(self, command, size=1, retry=0, interval_secs=None, suppress_log=False): """Sends a command and returns a N bytes response. Args: command: command to send size: number of bytes to receive. 0 means receiving what already in the input buffer. retry: number of retry. interval_secs: #seconds to wait between send and receive. If specified, overrides self.send_receive_interval_secs. suppress_log: True to disable log regardless of self.log value. Returns: Received N bytes. Raises: SerialTimeoutException if it fails to receive N bytes. """ for nth_run in range(retry + 1): self.FlushBuffer() try: self.Send(command) if interval_secs is None: time.sleep(self.send_receive_interval_secs) else: time.sleep(interval_secs) response = self.Receive(size) if not suppress_log and self.log: logging.info('Successfully sent %r and received %r', command, response) return response except serial.SerialTimeoutException: if nth_run < retry: time.sleep(self.retry_interval_secs) error_message = 'Timeout receiving %d bytes for command %r' % (size, command) if not suppress_log and self.log: logging.warning(error_message) raise serial.SerialTimeoutException(error_message)
def wait_for(self, msg, timeout=0) -> str: """ Wait for a specific message response for a specific amount of time. msg: String message to wait for (potentially as part of larger output). timeout: int number of seconds to wait for. Returns full received buffer as a str. """ start = time.time() buffer = '' if timeout == 0: timeout = self.default_timeout while time.time() - start < timeout: if self.cnxn.in_waiting > 0: buffer += self.cnxn.read().decode(self.encoding) if msg in buffer: return buffer raise serial.SerialTimeoutException( 'Device timed out waiting for msg: {!r}'.format(msg))
def readVoltage(self): """Read the voltage from the PZEM Raises: serial.SerialTimeoutException: Timeout on PZEM connection Returns: float: Voltage (V) as float """ self.ser.write(serial.to_bytes(self.readVoltageBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = unpack("!7B", rcv) if self.checkChecksum(unpacked): tension = unpacked[2] + unpacked[3] / 10.0 return tension raise serial.SerialTimeoutException("Timeout reading tension")
def readCurrent(self): """Read the current from the PZEM Raises: serial.SerialTimeoutException: Timeout on PZEM connection Returns: float: Current (A) as float """ self.ser.write(serial.to_bytes(self.readCurrentBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = unpack("!7B", rcv) if self.checkChecksum(unpacked): current = unpacked[2] + unpacked[3] / 100.0 return current raise serial.SerialTimeoutException("Timeout reading current")
def readWattage(self): """Read the wattage from the PZEM Raises: serial.SerialTimeoutException: Timeout on PZEM connection Returns: int: Wattage (W) as int """ self.ser.write(serial.to_bytes(self.readWattageBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = unpack("!7B", rcv) if self.checkChecksum(unpacked): power = unpacked[1] * 256 + unpacked[2] return power raise serial.SerialTimeoutException("Timeout reading power")
def _query(self, cmd): """ tx/rx to/from PS """ if self._debug: _pps_debug("PPS <- %s<CR>\n" % cmd) self._Serial.write((cmd + '\r').encode()) b = [] if self._debug: _pps_debug("PPS -> ") while True: b.append(self._Serial.read(1).decode('utf-8')) if self._debug: _pps_debug(b[-1].replace('\r', '<CR>')) if b[-1] == "": raise serial.SerialTimeoutException() if b[-3:] == list("OK\r"): break if self._debug: _pps_debug('\n') return "".join(b[:-4])
def readWattHours(self): """Reads the stored watt hours from the PZEM Raises: serial.SerialTimeoutException: Timeout on PZEM connection Returns: int: Watt Hours (Wh) as int """ self.ser.write(serial.to_bytes(self.readWattHourBytes)) rcv = self.ser.read(7) if len(rcv) == 7: unpacked = unpack("!7B", rcv) if self.checkChecksum(unpacked): regPower = unpacked[1] * 256 * 256 + unpacked[ 2] * 256 + unpacked[3] return regPower raise serial.SerialTimeoutException("Timeout reading registered power")