def _cmd(self, command, byte0=None, byte1=None): std_cmd = True # Set the first two command bytes; use defaults in most cases if not byte0: std_cmd = False byte0 = self.byte0 if not byte1: std_cmd = False byte1 = self.byte1 # Convery first two bytes to hex if isinstance(byte0, int): byte0 = hex(byte0)[2:].zfill(2) if isinstance(byte1, int): byte1 = hex(byte1)[2:].zfill(2) cmd = [byte0, byte1] # Each command has a category code. code = command[0] if isinstance(code, int): code = hex(code)[2:].zfill(2) # Each command has a length (of its data) associated with it. # N.B. this length INCLUDES the checksum value! length = command[1] if isinstance(length, int): length = hex(length)[2:].zfill(2) required_length = int(length, 16) # Add the category code and length to the command cmd.extend([code, length]) # The actual command data. Include the checksum for length calculation data = command[2:] newdata = [] for d in data: if isinstance(d, int): d = hex(d)[2:].zfill(2) newdata.append(d) data = newdata data_length = len(data) + 1 # If issuing TV commands and the lengths don't match, zero-pad value if std_cmd and data_length != required_length: missing_data_length = required_length - data_length zero_pad = ['00' for x in range(missing_data_length)] data = zero_pad + data # Add the data to the command cmd.extend(data) # Calculate the checksum and add it to the command checksum = self._chksum(cmd) cmd.append(checksum) # Add a carriage return? Required? Probably not. #cmd.append('0D') # Uncomment for debugging; what is the whole command? #print "FINAL COMMAND:", cmd # Hex-encode the command for transmission try: enccmd = hexencode(''.join(cmd)) except TypeError: raise EncodeError("Cannot encode command: '%s'" % command) # Write the command to the serial port connection self.__conn.write(enccmd) self.__conn.flushOutput() # Command responses are always going to be 3 (hex) bytes: # 0x70 (header), 0xXX (response code), 0xXX (checksum) response = self.__conn.read(6) # Wait longer to read the response if nothing was returned if len(response) is 0: #self.__conn.timeout = 0.1 response = self.__conn.read(3) #self.__conn.timeout = self.command_interval # Zero-length responses are an error if len(response) is 0: raise ResponseError("No response received for command '%s'" % cmd) # Decode the hexadecimal response dec_response = hexdecode(response) # Extract the response (discard header and checksum) try: response_code = self._nsplit(dec_response)[1] except IndexError: raise ResponseError("Garbled response: '%s'" % response) # Raise exceptions if abnormal termination if response_code == '01': raise LimitOverError("Value overrun (exceeds maximum limit)") elif response_code == '02': raise LimitUnderError("Value underrun (below minimum limit)") elif response_code == '03': raise CommandCancelled("Invalid data/length (command cancelled)") elif response_code == '04': raise ParseError("Invalid command (parser error)") return response_code
def serialize(self, sw, pyobj, name=None, attrtext='', **kw): String.serialize(self, sw, hexencode(pyobj).upper(), orig=pyobj, **kw)
def _cmd(self, command, byte0=None, byte1=None): std_cmd = True # Set the first two command bytes; use defaults in most cases if not byte0: std_cmd = False byte0 = self.byte0 if not byte1: std_cmd = False byte1 = self.byte1 # Convert first two bytes to hex if isinstance(byte0, int): byte0 = hex(byte0)[2:].zfill(2) if isinstance(byte1, int): byte1 = hex(byte1)[2:].zfill(2) cmd = [byte0, byte1] # Each command has a category code. code = command[0] if isinstance(code, int): code = hex(code)[2:].zfill(2) # Each command has a length (of its data) associated with it. # N.B. this length INCLUDES the checksum value! length = command[1] if isinstance(length, int): length = hex(length)[2:].zfill(2) required_length = int(length, 16) # Add the category code and length to the command cmd.extend([code, length]) # The actual command data. Include the checksum for length calculation data = command[2:] newdata = [] for d in data: if isinstance(d, int): d = hex(d)[2:].zfill(2) newdata.append(d) data = newdata data_length = len(data) + 1 # If issuing TV commands and the lengths don't match, zero-pad value if std_cmd and data_length != required_length: missing_data_length = required_length - data_length zero_pad = ['00' for x in range(missing_data_length)] data = zero_pad + data # Add the data to the command cmd.extend(data) # Calculate the checksum and add it to the command checksum = self._chksum(cmd) cmd.append(checksum) # Add a carriage return? Required? Probably not. # cmd.append('0D') # Hex-encode the command for transmission try: enccmd = hexencode(''.join(cmd)) except TypeError: raise EncodeError("Cannot encode command: '%s'" % command) # Write the command to the serial port connection self.__conn.write(enccmd) self.__conn.flushOutput() # Command responses are always going to be 3 (hex) bytes: # 0x70 (header), 0xXX (response code), 0xXX (checksum) response = self.__conn.read(6) # Wait longer to read the response if nothing was returned if len(response) is 0: # self.__conn.timeout = 0.1 response = self.__conn.read(3) # self.__conn.timeout = self.command_interval # Zero-length responses are an error if len(response) is 0: raise ResponseError("No response received for command '%s'" % cmd) # Decode the hexadecimal response dec_response = hexdecode(response) # Extract the response (discard header and checksum) try: response_code = self._nsplit(dec_response)[1] response_int = int(response_code, 16) except IndexError: raise ResponseError("Garbled response: '%s'" % response) # Raise exceptions if abnormal termination if response_int == 1: raise LimitOverError("Value overrun (exceeds maximum limit)") elif response_int == 2: raise LimitUnderError("Value underrun (below minimum limit)") elif response_int == 3: raise CommandCancelled("Invalid data/length (command cancelled)") elif response_int == 4: raise ParseError("Invalid command (parser error)") return response_int