Skip to content

Commit 3585837

Browse files
Correct signed_int_from_hex implementation (#394)
* fixed signed_int_from_hex method and eds tests. added full unit tests for method. * Fixed testdata, missing import and hex-prefix in string conversion.
1 parent 2d5d6d3 commit 3585837

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

canopen/objectdictionary/eds.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,10 @@ def _calc_bit_length(data_type):
211211

212212
def _signed_int_from_hex(hex_str, bit_length):
213213
number = int(hex_str, 0)
214-
limit = ((1 << bit_length - 1) - 1)
215-
if number > limit:
216-
return limit - number
214+
max_value = (1 << (bit_length - 1)) - 1
215+
216+
if number > max_value:
217+
return number - (1 << bit_length)
217218
else:
218219
return number
219220

test/sample.eds

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,8 @@ ParameterName=INTEGER32 only negative values
926926
ObjectType=0x7
927927
DataType=0x04
928928
AccessType=rw
929-
HighLimit=0x00000000
930-
LowLimit=0xFFFFFFFF
929+
HighLimit=0xFFFFFFFF
930+
LowLimit=0x80000000
931931
PDOMapping=0
932932

933933
[3040]
@@ -936,10 +936,9 @@ ObjectType=0x7
936936
DataType=0x15
937937
AccessType=rw
938938
HighLimit=0x000000000000000A
939-
LowLimit=0x8000000000000009
939+
LowLimit=0xFFFFFFFFFFFFFFF6
940940
PDOMapping=0
941941

942-
943942
[3050]
944943
ParameterName=EDS file extensions
945944
SubNumber=0x7

test/test_eds.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,44 @@
11
import os
22
import unittest
33
import canopen
4+
from canopen.objectdictionary.eds import _signed_int_from_hex
45

56
EDS_PATH = os.path.join(os.path.dirname(__file__), 'sample.eds')
67

78

89
class TestEDS(unittest.TestCase):
910

11+
test_data = {
12+
"int8": [
13+
{"hex_str": "7F", "bit_length": 8, "expected": 127},
14+
{"hex_str": "80", "bit_length": 8, "expected": -128},
15+
{"hex_str": "FF", "bit_length": 8, "expected": -1},
16+
{"hex_str": "00", "bit_length": 8, "expected": 0},
17+
{"hex_str": "01", "bit_length": 8, "expected": 1}
18+
],
19+
"int16": [
20+
{"hex_str": "7FFF", "bit_length": 16, "expected": 32767},
21+
{"hex_str": "8000", "bit_length": 16, "expected": -32768},
22+
{"hex_str": "FFFF", "bit_length": 16, "expected": -1},
23+
{"hex_str": "0000", "bit_length": 16, "expected": 0},
24+
{"hex_str": "0001", "bit_length": 16, "expected": 1}
25+
],
26+
"int32": [
27+
{"hex_str": "7FFFFFFF", "bit_length": 32, "expected": 2147483647},
28+
{"hex_str": "80000000", "bit_length": 32, "expected": -2147483648},
29+
{"hex_str": "FFFFFFFF", "bit_length": 32, "expected": -1},
30+
{"hex_str": "00000000", "bit_length": 32, "expected": 0},
31+
{"hex_str": "00000001", "bit_length": 32, "expected": 1}
32+
],
33+
"int64": [
34+
{"hex_str": "7FFFFFFFFFFFFFFF", "bit_length": 64, "expected": 9223372036854775807},
35+
{"hex_str": "8000000000000000", "bit_length": 64, "expected": -9223372036854775808},
36+
{"hex_str": "FFFFFFFFFFFFFFFF", "bit_length": 64, "expected": -1},
37+
{"hex_str": "0000000000000000", "bit_length": 64, "expected": 0},
38+
{"hex_str": "0000000000000001", "bit_length": 64, "expected": 1}
39+
]
40+
}
41+
1042
def setUp(self):
1143
self.od = canopen.import_od(EDS_PATH, 2)
1244

@@ -58,11 +90,18 @@ def test_record_with_limits(self):
5890
self.assertEqual(uint8.max, 10)
5991
int32 = self.od[0x3030]
6092
self.assertEqual(int32.min, -2147483648)
61-
self.assertEqual(int32.max, 0)
93+
self.assertEqual(int32.max, -1)
6294
int64 = self.od[0x3040]
6395
self.assertEqual(int64.min, -10)
6496
self.assertEqual(int64.max, +10)
6597

98+
def test_signed_int_from_hex(self):
99+
for data_type, test_cases in self.test_data.items():
100+
for test_case in test_cases:
101+
with self.subTest(data_type=data_type, test_case=test_case):
102+
result = _signed_int_from_hex('0x' + test_case["hex_str"], test_case["bit_length"])
103+
self.assertEqual(result, test_case["expected"])
104+
66105
def test_array_compact_subobj(self):
67106
array = self.od[0x1003]
68107
self.assertIsInstance(array, canopen.objectdictionary.Array)

0 commit comments

Comments
 (0)