Skip to content

Commit 5631a03

Browse files
committed
Adding support for reading PDO map from OD
1 parent 1be9102 commit 5631a03

File tree

1 file changed

+76
-74
lines changed

1 file changed

+76
-74
lines changed

canopen/pdo/base.py

Lines changed: 76 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,26 @@ def __getitem__(self, key) -> PdoBase:
5555
def __len__(self):
5656
return len(self.map)
5757

58-
def read(self):
58+
def read(self, from_od=False):
5959
"""Read PDO configuration from node using SDO."""
6060
for pdo_map in self.map.values():
61-
pdo_map.read()
61+
pdo_map.read(from_od=from_od)
6262

63-
async def aread(self):
64-
"""Read PDO configuration from node using SDO."""
63+
async def aread(self, from_od=False):
64+
"""Read PDO configuration from node using SDO, async variant."""
6565
for pdo_map in self.map.values():
66-
await pdo_map.aread()
66+
await pdo_map.aread(from_od=from_od)
6767

6868
def save(self):
6969
"""Save PDO configuration to node using SDO."""
7070
for pdo_map in self.map.values():
7171
pdo_map.save()
7272

73+
async def asave(self):
74+
"""Save PDO configuration to node using SDO, async variant."""
75+
for pdo_map in self.map.values():
76+
await pdo_map.asave()
77+
7378
def subscribe(self):
7479
"""Register the node's PDOs for reception on the network.
7580
@@ -341,43 +346,43 @@ def add_callback(self, callback: Callable[["Map"], None]) -> None:
341346
"""
342347
self.callbacks.append(callback)
343348

344-
def read(self) -> None:
345-
"""Read PDO configuration for this map using SDO."""
346-
cob_id = self.com_record[1].get_raw()
349+
def read_generator(self):
350+
"""Read PDO configuration for this map."""
351+
cob_id = yield self.com_record[1]
347352
self.cob_id = cob_id & 0x1FFFFFFF
348353
logger.info("COB-ID is 0x%X", self.cob_id)
349354
self.enabled = cob_id & PDO_NOT_VALID == 0
350355
logger.info("PDO is %s", "enabled" if self.enabled else "disabled")
351356
self.rtr_allowed = cob_id & RTR_NOT_ALLOWED == 0
352357
logger.info("RTR is %s", "allowed" if self.rtr_allowed else "not allowed")
353-
self.trans_type = self.com_record[2].get_raw()
358+
self.trans_type = yield self.com_record[2]
354359
logger.info("Transmission type is %d", self.trans_type)
355360
if self.trans_type >= 254:
356361
try:
357-
self.inhibit_time = self.com_record[3].get_raw()
362+
self.inhibit_time = yield self.com_record[3]
358363
except (KeyError, SdoAbortedError) as e:
359364
logger.info("Could not read inhibit time (%s)", e)
360365
else:
361366
logger.info("Inhibit time is set to %d ms", self.inhibit_time)
362367

363368
try:
364-
self.event_timer = self.com_record[5].get_raw()
369+
self.event_timer = yield self.com_record[5]
365370
except (KeyError, SdoAbortedError) as e:
366371
logger.info("Could not read event timer (%s)", e)
367372
else:
368373
logger.info("Event timer is set to %d ms", self.event_timer)
369374

370375
try:
371-
self.sync_start_value = self.com_record[6].get_raw()
376+
self.sync_start_value = yield self.com_record[6]
372377
except (KeyError, SdoAbortedError) as e:
373378
logger.info("Could not read SYNC start value (%s)", e)
374379
else:
375380
logger.info("SYNC start value is set to %d ms", self.sync_start_value)
376381

377382
self.clear()
378-
nof_entries = self.map_array[0].get_raw()
383+
nof_entries = yield self.map_array[0]
379384
for subindex in range(1, nof_entries + 1):
380-
value = self.map_array[subindex].get_raw()
385+
value = yield self.map_array[subindex]
381386
index = value >> 16
382387
subindex = (value >> 8) & 0xFF
383388
size = value & 0xFF
@@ -390,97 +395,84 @@ def read(self) -> None:
390395

391396
self.subscribe()
392397

393-
async def aread(self) -> None:
394-
"""Read PDO configuration for this map using SDO."""
395-
cob_id = await self.com_record[1].aget_raw()
396-
self.cob_id = cob_id & 0x1FFFFFFF
397-
logger.info("COB-ID is 0x%X", self.cob_id)
398-
self.enabled = cob_id & PDO_NOT_VALID == 0
399-
logger.info("PDO is %s", "enabled" if self.enabled else "disabled")
400-
self.rtr_allowed = cob_id & RTR_NOT_ALLOWED == 0
401-
logger.info("RTR is %s", "allowed" if self.rtr_allowed else "not allowed")
402-
self.trans_type = await self.com_record[2].aget_raw()
403-
logger.info("Transmission type is %d", self.trans_type)
404-
if self.trans_type >= 254:
405-
try:
406-
self.inhibit_time = await self.com_record[3].aget_raw()
407-
except (KeyError, SdoAbortedError) as e:
408-
logger.info("Could not read inhibit time (%s)", e)
398+
def read(self, from_od=False) -> None:
399+
"""Read PDO configuration for this map using SDO or from OD."""
400+
gen = self.read_generator()
401+
var = next(gen)
402+
while var:
403+
if from_od:
404+
# Use default value from OD
405+
value = var.od.default
409406
else:
410-
logger.info("Inhibit time is set to %d ms", self.inhibit_time)
411-
407+
# Get value from SDO
408+
value = var.get_raw()
412409
try:
413-
self.event_timer = await self.com_record[5].aget_raw()
414-
except (KeyError, SdoAbortedError) as e:
415-
logger.info("Could not read event timer (%s)", e)
410+
# Deliver value into read_generator and wait for next object
411+
var = gen.send(value)
412+
except StopIteration:
413+
break
414+
415+
async def aread(self, from_od=False) -> None:
416+
"""Read PDO configuration for this map using SDO, async variant."""
417+
gen = self.read_generator()
418+
var = next(gen)
419+
while var:
420+
if from_od:
421+
# Use default value from OD
422+
value = var.od.default
416423
else:
417-
logger.info("Event timer is set to %d ms", self.event_timer)
418-
424+
# Get value from SDO
425+
value = await var.aget_raw()
426+
pass
419427
try:
420-
self.sync_start_value = await self.com_record[6].aget_raw()
421-
except (KeyError, SdoAbortedError) as e:
422-
logger.info("Could not read SYNC start value (%s)", e)
423-
else:
424-
logger.info("SYNC start value is set to %d ms", self.sync_start_value)
428+
var = gen.send(value)
429+
except StopIteration:
430+
break
425431

426-
self.clear()
427-
nof_entries = await self.map_array[0].aget_raw()
428-
for subindex in range(1, nof_entries + 1):
429-
value = await self.map_array[subindex].aget_raw()
430-
index = value >> 16
431-
subindex = (value >> 8) & 0xFF
432-
size = value & 0xFF
433-
if hasattr(self.pdo_node.node, "curtis_hack") and self.pdo_node.node.curtis_hack: # Curtis HACK: mixed up field order
434-
index = value & 0xFFFF
435-
subindex = (value >> 16) & 0xFF
436-
size = (value >> 24) & 0xFF
437-
if index and size:
438-
self.add_variable(index, subindex, size)
439-
440-
self.subscribe()
441-
442-
def save(self) -> None:
443-
"""Save PDO configuration for this map using SDO."""
432+
def save_generator(self):
433+
"""Save PDO configuration for this map."""
444434
logger.info("Setting COB-ID 0x%X and temporarily disabling PDO",
445435
self.cob_id)
446-
self.com_record[1].set_raw(self.cob_id | PDO_NOT_VALID | (RTR_NOT_ALLOWED if not self.rtr_allowed else 0x0))
436+
yield self.com_record[1], self.cob_id | PDO_NOT_VALID | (RTR_NOT_ALLOWED if not self.rtr_allowed else 0x0)
447437
if self.trans_type is not None:
448438
logger.info("Setting transmission type to %d", self.trans_type)
449-
self.com_record[2].set_raw(self.trans_type)
439+
yield self.com_record[2], self.trans_type
450440
if self.inhibit_time is not None:
451441
logger.info("Setting inhibit time to %d us", (self.inhibit_time * 100))
452-
self.com_record[3].set_raw(self.inhibit_time)
442+
yield self.com_record[3], self.inhibit_time
453443
if self.event_timer is not None:
454444
logger.info("Setting event timer to %d ms", self.event_timer)
455-
self.com_record[5].set_raw(self.event_timer)
445+
yield self.com_record[5], self.event_timer
456446
if self.sync_start_value is not None:
457447
logger.info("Setting SYNC start value to %d", self.sync_start_value)
458-
self.com_record[6].set_raw(self.sync_start_value)
448+
yield self.com_record[6], self.sync_start_value
459449

460450
if self.map is not None:
461451
try:
462-
self.map_array[0].set_raw(0)
452+
yield self.map_array[0], 0
463453
except SdoAbortedError:
464454
# WORKAROUND for broken implementations: If the array has a
465455
# fixed number of entries (count not writable), generate dummy
466456
# mappings for an invalid object 0x0000:00 to overwrite any
467457
# excess entries with all-zeros.
458+
459+
# FIXME: This is a blocking call which might be called from async
468460
self._fill_map(self.map_array[0].get_raw())
469461
subindex = 1
470462
for var in self.map:
471463
logger.info("Writing %s (0x%X:%d, %d bits) to PDO map",
472464
var.name, var.index, var.subindex, var.length)
473465
if hasattr(self.pdo_node.node, "curtis_hack") and self.pdo_node.node.curtis_hack: # Curtis HACK: mixed up field order
474-
self.map_array[subindex].set_raw(var.index |
475-
var.subindex << 16 |
476-
var.length << 24)
466+
yield self.map_array[subindex], (var.index |
467+
var.subindex << 16 |
468+
var.length << 24)
477469
else:
478-
self.map_array[subindex].set_raw(var.index << 16 |
479-
var.subindex << 8 |
480-
var.length)
470+
yield self.map_array[subindex], (var.index << 16 |
471+
var.subindex << 8 |
472+
var.length)
481473
subindex += 1
482474
try:
483-
self.map_array[0].set_raw(len(self.map))
475+
yield self.map_array[0], len(self.map)
484476
except SdoAbortedError as e:
485477
# WORKAROUND for broken implementations: If the array
486478
# number-of-entries parameter is not writable, we have already
@@ -492,9 +484,19 @@ def save(self) -> None:
492484
self._update_data_size()
493485

494486
if self.enabled:
495-
self.com_record[1].set_raw(self.cob_id | (RTR_NOT_ALLOWED if not self.rtr_allowed else 0x0))
487+
yield self.com_record[1], self.cob_id | (RTR_NOT_ALLOWED if not self.rtr_allowed else 0x0)
496488
self.subscribe()
497489

490+
def save(self) -> None:
491+
"""Read PDO configuration for this map using SDO."""
492+
for sdo, value in self.save_generator():
493+
sdo.set_raw(value)
494+
495+
async def asave(self) -> None:
496+
"""Read PDO configuration for this map using SDO, async variant."""
497+
for sdo, value in self.save_generator():
498+
await sdo.aset_raw(value)
499+
498500
def subscribe(self) -> None:
499501
"""Register the PDO for reception on the network.
500502

0 commit comments

Comments
 (0)