diff --git a/canopen/objectdictionary/__init__.py b/canopen/objectdictionary/__init__.py index fa694c56..a44a963e 100644 --- a/canopen/objectdictionary/__init__.py +++ b/canopen/objectdictionary/__init__.py @@ -484,8 +484,8 @@ def decode_phys(self, value: int) -> Union[int, bool, float, str, bytes]: def encode_phys(self, value: Union[int, bool, float, str, bytes]) -> int: if self.data_type in INTEGER_TYPES: - value /= self.factor - value = int(round(value)) + if self.factor != 1: + value = round(value / self.factor) return value def decode_desc(self, value: int) -> str: diff --git a/test/test_od.py b/test/test_od.py index 9ab0e187..28d7637b 100644 --- a/test/test_od.py +++ b/test/test_od.py @@ -182,6 +182,35 @@ def test_phys(self): self.assertAlmostEqual(var.decode_phys(128), 12.8) self.assertEqual(var.encode_phys(-0.1), -1) + def test_phys_factor_1_int64_roundtrip(self): + """int64 values must survive encode_phys when factor is 1.""" + var = od.ODVariable("Test UNSIGNED64", 0x1000) + var.data_type = od.UNSIGNED64 + value = 0x55554444AAAABBBB + self.assertEqual(var.encode_phys(value), value) + + def test_phys_factor_1_preserves_int(self): + """encode_phys with factor=1 must not convert int to float.""" + var = od.ODVariable("Test INTEGER32", 0x1000) + var.data_type = od.INTEGER32 + self.assertIsInstance(var.encode_phys(42), int) + + def test_phys_factor_1000_rounds(self): + """Existing rounding behaviour with integer factor != 1 is preserved.""" + var = od.ODVariable("Test INTEGER32", 0x1000) + var.data_type = od.INTEGER32 + var.factor = 1000 + # 5555 / 1000 = 5.555 → round → 6 + self.assertEqual(var.encode_phys(5555), 6) + + def test_phys_float_factor(self): + """Float factor still works via float division + round.""" + var = od.ODVariable("Test INTEGER16", 0x1000) + var.data_type = od.INTEGER16 + var.factor = 0.5 + # 10 / 0.5 = 20 + self.assertEqual(var.encode_phys(10), 20) + def test_desc(self): var = od.ODVariable("Test UNSIGNED8", 0x1000) var.data_type = od.UNSIGNED8