Skip to content

Commit ea733fe

Browse files
committed
xdd: Implement option to load object dictionary from XDD file.
Signed-off-by: Taras Zaporozhets <[email protected]>
1 parent be9c56d commit ea733fe

File tree

8 files changed

+1914
-32
lines changed

8 files changed

+1914
-32
lines changed

canopen/objectdictionary/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def import_od(
7676
source: Union[str, TextIO, None],
7777
node_id: Optional[int] = None,
7878
) -> ObjectDictionary:
79-
"""Parse an EDS, DCF, or EPF file.
79+
"""Parse an EDS, DCF, EPF or XDD file.
8080
8181
:param source:
8282
The path to object dictionary file, a file like object, or an EPF XML tree.
@@ -106,9 +106,12 @@ def import_od(
106106
elif suffix == ".epf":
107107
from canopen.objectdictionary import epf
108108
return epf.import_epf(source)
109+
elif suffix == ".xdd":
110+
from canopen.objectdictionary import xdd
111+
return xdd.import_xdd(source, node_id)
109112
else:
110113
doc_type = suffix[1:]
111-
allowed = ", ".join(["eds", "dcf", "epf"])
114+
allowed = ", ".join(["eds", "dcf", "epf", "xdd"])
112115
raise ValueError(
113116
f"Cannot import from the {doc_type!r} format; "
114117
f"supported formats: {allowed}"

canopen/objectdictionary/eds.py

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from canopen import objectdictionary
1010
from canopen.objectdictionary import ObjectDictionary, datatypes
1111
from canopen.sdo import SdoClient
12+
from canopen.utils import signed_int_from_hex, calc_bit_length
1213

1314
if TYPE_CHECKING:
1415
import canopen.network
@@ -201,30 +202,6 @@ def import_from_node(node_id: int, network: canopen.network.Network):
201202
network.unsubscribe(0x580 + node_id)
202203
return od
203204

204-
205-
def _calc_bit_length(data_type):
206-
if data_type == datatypes.INTEGER8:
207-
return 8
208-
elif data_type == datatypes.INTEGER16:
209-
return 16
210-
elif data_type == datatypes.INTEGER32:
211-
return 32
212-
elif data_type == datatypes.INTEGER64:
213-
return 64
214-
else:
215-
raise ValueError(f"Invalid data_type '{data_type}', expecting a signed integer data_type.")
216-
217-
218-
def _signed_int_from_hex(hex_str, bit_length):
219-
number = int(hex_str, 0)
220-
max_value = (1 << (bit_length - 1)) - 1
221-
222-
if number > max_value:
223-
return number - (1 << bit_length)
224-
else:
225-
return number
226-
227-
228205
def _convert_variable(node_id, var_type, value):
229206
if var_type in (datatypes.OCTET_STRING, datatypes.DOMAIN):
230207
return bytes.fromhex(value)
@@ -288,7 +265,7 @@ def build_variable(eds, section, node_id, index, subindex=0):
288265
try:
289266
min_string = eds.get(section, "LowLimit")
290267
if var.data_type in datatypes.SIGNED_TYPES:
291-
var.min = _signed_int_from_hex(min_string, _calc_bit_length(var.data_type))
268+
var.min = signed_int_from_hex(min_string, calc_bit_length(var.data_type))
292269
else:
293270
var.min = int(min_string, 0)
294271
except ValueError:
@@ -297,7 +274,7 @@ def build_variable(eds, section, node_id, index, subindex=0):
297274
try:
298275
max_string = eds.get(section, "HighLimit")
299276
if var.data_type in datatypes.SIGNED_TYPES:
300-
var.max = _signed_int_from_hex(max_string, _calc_bit_length(var.data_type))
277+
var.max = signed_int_from_hex(max_string, calc_bit_length(var.data_type))
301278
else:
302279
var.max = int(max_string, 0)
303280
except ValueError:

0 commit comments

Comments
 (0)