def test_checksum_func_incomplete(self): """Check that the compute_checksum function fails when the "byte_seq" argument is incomplete (len(byte_seq) < 3).""" byte_seq = (0x01, 0x02) # incomplete packet with self.assertRaises(ValueError): pk.compute_checksum(byte_seq)
def test_checksum_func_wrong_id_byte(self): """Check that the compute_checksum function fails when the "id" byte of the "byte_seq" argument has a wrong value (too high value).""" byte_seq = (0xff,) # wrong id byte_seq += (4,) # length byte_seq += (0x02, 0x2b, 0x01) # read the temperature of the dynamixel with self.assertRaises(ValueError): pk.compute_checksum(byte_seq)
def test_checksum_func_wrong_byte_type(self): """Check that the compute_checksum function fails when an item of the "byte_seq" argument has a wrong type (float).""" # Check with None byte_seq = (0x01, None, 0x02, 0x2b, 0x01) # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with float byte_seq = (0x01, 1.0, 0x02, 0x2b, 0x01) # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with string byte_seq = (0x01, "hi", 0x02, 0x2b, 0x01) # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with tuple byte_seq = (0x01, (), 0x02, 0x2b, 0x01) # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq)
def test_checksum_func_wrong_byte_value(self): """Check that the compute_checksum function fails when an item of the "byte_seq" argument has a wrong value (too low or too high).""" # Too low value byte_seq = (0x01, -1, 0x02, 0x2b, 0x01) # wrong value with self.assertRaises(ValueError): pk.compute_checksum(byte_seq) # Too high value byte_seq = (0x01, 0xffff, 0x02, 0x2b, 0x01) # wrong value with self.assertRaises(ValueError): pk.compute_checksum(byte_seq)
def test_checksum_func_wrong_length_byte(self): """Check that the compute_checksum function fails when the "length" byte of the "byte_seq" argument has a wrong value (too low or too high). """ # Too low value byte_seq = (1,) # id byte_seq += (1,) # wrong length byte_seq += (0x02, 0x2b, 0x01) # read the temperature of the dynamixel with self.assertRaises(ValueError): pk.compute_checksum(byte_seq) # Too high value byte_seq = (1,) # id byte_seq += (9,) # wrong length byte_seq += (0x02, 0x2b, 0x01) # read the temperature of the dynamixel with self.assertRaises(ValueError): pk.compute_checksum(byte_seq)
def test_checksum_func_example1(self): """Check the "compute_checksum" function using the example 2 of the Dynamixel user guide: "Reading the internal temperature of the Dynamixel actuator with an ID of 1" (p.20).""" byte_seq = (1,) # id byte_seq += (4,) # length byte_seq += (0x02, 0x2b, 0x01) # read the temperature of the dynamixel checksum_byte = pk.compute_checksum(byte_seq) expected_checksum_byte = 0xcc self.assertEqual(checksum_byte, expected_checksum_byte)
def test_checksum_func_good_arg_type(self): """Check the "compute_checksum" function using the example 2 of the Dynamixel user guide: "Reading the internal temperature of the Dynamixel actuator with an ID of 1" (p.20).""" # Check with a tuple byte_seq = (0x01, 0x04, 0x02, 0x2b, 0x01) checksum_byte = pk.compute_checksum(byte_seq) expected_checksum_byte = 0xcc self.assertEqual(checksum_byte, expected_checksum_byte) # Check with a list byte_seq = [0x01, 0x04, 0x02, 0x2b, 0x01] checksum_byte = pk.compute_checksum(byte_seq) expected_checksum_byte = 0xcc self.assertEqual(checksum_byte, expected_checksum_byte) # Check with a bytes string byte_seq = bytes((0x01, 0x04, 0x02, 0x2b, 0x01)) checksum_byte = pk.compute_checksum(byte_seq) expected_checksum_byte = 0xcc self.assertEqual(checksum_byte, expected_checksum_byte) # Check with a bytearray byte_seq = bytearray((0x01, 0x04, 0x02, 0x2b, 0x01)) checksum_byte = pk.compute_checksum(byte_seq) expected_checksum_byte = 0xcc self.assertEqual(checksum_byte, expected_checksum_byte)
def __init__(self, packet): # Check the argument and convert it to "bytes" if necessary. # Assert "packet" items are in range (0, 0xff). # "TypeError" and "ValueError" are sent by the "bytes" constructor if # necessary. # The statement "tuple(packet)" implicitely rejects integers (and all # non-iterable objects) to compensate the fact that the bytes # constructor doesn't reject them: bytes(6) is valid and returns # b'\x00\x00\x00'. self._bytes = bytes(tuple(packet)) # Assert the argument is a sequence with at least 6 items. if len(self._bytes) < 6: raise ValueError("Incomplete packet.") # Check the header bytes. # Should be tested before the length and checksum because if the header # is wrong then the length and the checksum are wrong too (thus testing # the header first gives a more relevant information when its value is # wrong). if bytes(self.header) != b'\xff\xff': raise ValueError("Wrong header (should be b'\xff\xff').") # Check length (length = num_params + 2 = full_packet_length - 4). # Should be tested before the checksum because if the length is wrong # then the checksum is wrong too (thus testing the length first gives a # more relevant information when its value is wrong). if self.length != len(self._bytes) - 4: raise ValueError('Wrong length byte.') # Verify the checksum. computed_checksum = pk.compute_checksum(self._bytes[2:-1]) if computed_checksum != self.checksum: raise StatusChecksumError('Wrong checksum.') # Check error bit flags. if self.instruction_error: raise InstructionError() if self.overload_error: raise OverloadError() if self.checksum_error: raise InstructionChecksumError() if self.range_error: raise RangeError() if self.overheating_error: raise OverheatingError() if self.angle_limit_error: raise AngleLimitError() if self.input_voltage_error: raise InputVoltageError() # Check the ID byte if not(0x00 <= self.dynamixel_id <= 0xfd): msg = "Wrong dynamixel_id, a value in range (0, 0xFD) is required." raise ValueError(msg)
def __init__(self, dynamixel_id, instruction, parameters=None): # Check the parameters byte. # "TypeError" and "ValueError" are raised by the "bytes" constructor if # necessary. # The statement "tuple(parameters)" implicitely rejects integers (and # all non-iterable objects) to compensate the fact that the bytes # constructor doesn't reject them: bytes(3) is valid and returns # b'\x00\x00\x00'. if parameters is None: parameters = bytes() else: parameters = bytes(tuple(parameters)) # Add the header bytes. self._bytes = bytearray((0xff, 0xff)) # Check and add the Dynamixel ID byte. # "TypeError" and "ValueError" are raised by the "bytearray.append()" # if necessary. if 0x00 <= dynamixel_id <= 0xfe: self._bytes.append(dynamixel_id) else: if isinstance(dynamixel_id, int): msg = ("Wrong dynamixel_id value, " "an integer in range(0x00, 0xfe) is required.") raise ValueError(msg) else: raise TypeError("Wrong dynamixel_id type (integer required).") # Add the length byte. self._bytes.append(len(parameters) + 2) # Check and add the instruction byte. # "TypeError" and "ValueError" are raised by the "bytearray.append()" # if necessary. if instruction in INSTRUCTIONS: self._bytes.append(instruction) else: if isinstance(instruction, int): msg = "Wrong instruction, should be in ({})." instructions_str = utils.pretty_hex_str(INSTRUCTIONS) raise ValueError(msg.format(instructions_str)) else: raise TypeError("Wrong instruction type (integer required).") # Check and add the parameter bytes. nb_param_min = NUMBER_OF_PARAMETERS[self.instruction]['min'] nb_param_max = NUMBER_OF_PARAMETERS[self.instruction]['max'] if nb_param_min <= len(parameters) <= nb_param_max: self._bytes.extend(parameters) else: msg = ("Wrong number of parameters: {} parameters " "(min expected={}; max expected={}).") nb_param = len(parameters) raise ValueError(msg.format(nb_param, nb_param_min, nb_param_max)) # Add the checksum byte. computed_checksum = pk.compute_checksum(self._bytes[2:]) self._bytes.append(computed_checksum)
def test_checksum_func_wrong_arg_type(self): """Check that the compute_checksum function fails when the "byte_seq" argument has a wrong type.""" # Check with None byte_seq = None # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with an integer byte_seq = 0 # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with an integer byte_seq = 1 # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with an integer byte_seq = 3 # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with a float byte_seq = 1.0 # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq) # Check with a string byte_seq = "hello" # wrong type with self.assertRaises(TypeError): pk.compute_checksum(byte_seq)