Skip to content

Commit 192fdf6

Browse files
committed
2 parents 3aca51b + 8ab5469 commit 192fdf6

2 files changed

Lines changed: 80 additions & 39 deletions

File tree

‎cri_lib/cri_controller.py‎

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from .cri_errors import CRICommandError, CRICommandTimeOutError, CRIConnectionError
1515
from .cri_protocol_parser import CRIProtocolParser
16-
from .robot_state import KinematicsState, RobotState
16+
from .robot_state import KinematicsState, ReplayMode, RobotState
1717

1818
logger = logging.getLogger(__name__)
1919

@@ -441,48 +441,52 @@ async def wait_for_kinematics_ready_async(self, timeout: float = 30) -> bool:
441441
async def get_board_temperatures_async(
442442
self,
443443
timeout: float | None = DEFAULT, # type: ignore
444-
) -> bool:
444+
) -> list[float]:
445445
"""Receive motor controller PCB temperatures and save in robot state
446446
447447
Parameters
448448
----------
449449
timeout: float | None
450450
timeout for waiting in seconds or None for infinite waiting
451+
452+
Returns
453+
-------
454+
list of motor controller PCB temperatures
451455
"""
452456
self._send_command("SYSTEM GetBoardTemp", True, "info_boardtemp")
453457
if (
454458
error_msg := await self._wait_for_answer_async(
455459
"info_boardtemp", timeout=timeout
456460
)
457461
) is not None:
458-
logger.debug("Error in GetBoardTemp command: %s", error_msg)
459-
return False
460-
else:
461-
return True
462+
raise CRICommandError(f"Error in GetBoardTemp command: {error_msg}")
463+
return list(self.robot_state.board_temps)
462464

463465
async def get_motor_temperatures_async(
464466
self,
465467
timeout: float | None = DEFAULT, # type: ignore
466-
) -> bool:
468+
) -> list[float]:
467469
"""Receive motor temperatures and save in robot state
468470
469471
Parameters
470472
----------
471473
timeout: float | None
472474
timeout for waiting in seconds or None for infinite waiting
475+
476+
Returns
477+
-------
478+
list of motor temperatures
473479
"""
474480
self._send_command("SYSTEM GetMotorTemp", True, "info_motortemp")
475481
if (
476482
error_msg := await self._wait_for_answer_async(
477483
"info_motortemp", timeout=timeout
478484
)
479485
) is not None:
480-
logger.debug("Error in GetMotorTemp command: %s", error_msg)
481-
return False
482-
else:
483-
return True
486+
raise CRICommandError(f"Error in GetMotorTemp command: {error_msg}")
487+
return list(self.robot_state.motor_temps)
484488

485-
async def list_files_async(self, target_directory: str = "Programs") -> bool:
489+
async def list_files_async(self, target_directory: str = "Programs") -> list[str]:
486490
"""Request a list of all files in the directory, which is relative to the /Data/ directory.
487491
488492
Parameters
@@ -492,28 +496,20 @@ async def list_files_async(self, target_directory: str = "Programs") -> bool:
492496
493497
Returns
494498
-------
495-
a list of files
499+
a list of file paths relative to `/Data`
496500
"""
497501

498502
command = f"CMD ListFiles {target_directory}"
499-
503+
self._send_command(
504+
command=command, register_answer=True, fixed_answer_name="info_filelist"
505+
)
500506
if (
501-
self._send_command(
502-
command=command, register_answer=True, fixed_answer_name="info_filelist"
503-
)
504-
is not None
505-
):
506-
if (
507-
error_msg := await self._wait_for_answer_async(
508-
"info_filelist", timeout=self.DEFAULT_ANSWER_TIMEOUT
509-
)
510-
) is not None:
511-
logger.debug("Error in ListFiles command: %s", error_msg)
512-
return False
513-
else:
514-
return True
515-
else:
516-
return False
507+
error_msg := await self._wait_for_answer_async("info_filelist")
508+
) is not None:
509+
raise CRICommandError(f"Error in ListFiles command: {error_msg}")
510+
# the obtained file list is cached in the parser
511+
with self.parser.file_list_lock:
512+
return list(self.parser.file_list)
517513

518514
def wait_for_status_update(self, timeout: float | None = None) -> None:
519515
"""Blocking wrapper around :func:`CRIClient.wait_for_status_update_async`."""
@@ -530,7 +526,7 @@ def wait_for_kinematics_ready(self, timeout: float = 30) -> bool:
530526
def get_board_temperatures(
531527
self,
532528
timeout: float | None = DEFAULT, # type: ignore
533-
) -> bool:
529+
) -> list[float]:
534530
"""Blocking wrapper around :func:`CRIClient.get_board_temperatures_async`."""
535531
return asyncio.get_event_loop().run_until_complete(
536532
self.get_board_temperatures_async(timeout=timeout)
@@ -539,13 +535,13 @@ def get_board_temperatures(
539535
def get_motor_temperatures(
540536
self,
541537
timeout: float | None = DEFAULT, # type: ignore
542-
) -> bool:
538+
) -> list[float]:
543539
"""Blocking wrapper around :func:`CRIClient.get_motor_temperatures_async`."""
544540
return asyncio.get_event_loop().run_until_complete(
545541
self.get_motor_temperatures_async(timeout=timeout)
546542
)
547543

548-
def list_files(self) -> bool:
544+
def list_files(self) -> list[str]:
549545
"""Blocking wrapper around :func:`CRIClient.list_files_async`."""
550546
return asyncio.get_event_loop().run_until_complete(self.list_files_async())
551547

@@ -1355,15 +1351,52 @@ async def load_logic_programm_async(self, program_name: str) -> bool:
13551351
else:
13561352
return True
13571353

1358-
async def start_programm_async(self) -> bool:
1359-
"""Start currently loaded Program
1354+
async def set_replay_mode_async(self, replay_mode: ReplayMode) -> None:
1355+
"""Set the main program replay mode.
1356+
1357+
Parameters
1358+
----------
1359+
replay_mode
1360+
Which mode to apply if the ``robot_state`` is not already in it.
1361+
1362+
Raises
1363+
------
1364+
CRICommandError
1365+
If the ``replay_mode`` could not be applied.
1366+
"""
1367+
while self.robot_state.main_replay_mode != replay_mode:
1368+
msg_id = self.send_command(
1369+
f"CMD ProgramReplayMode {replay_mode.value}", True
1370+
)
1371+
if (error_msg := await self._wait_for_answer_async(msg_id)) is not None:
1372+
raise CRICommandError(f"Could not set replay mode: {error_msg}")
1373+
await asyncio.sleep(0.05)
1374+
1375+
async def start_programm_async(
1376+
self, *, replay_mode: ReplayMode | None = None
1377+
) -> bool:
1378+
"""Start currently loaded Program.
1379+
1380+
Parameters
1381+
----------
1382+
replay_mode
1383+
Which replay mode to apply before starting.
1384+
If not provided, the currently set mode is kept.
13601385
13611386
Returns
13621387
-------
13631388
bool
13641389
`True` if request was successful
13651390
`False` if request was not successful
1391+
1392+
Raises
1393+
------
1394+
CRICommandError
1395+
If the ``replay_mode`` could not be applied.
13661396
"""
1397+
if replay_mode is not None:
1398+
await self.set_replay_mode_async(replay_mode)
1399+
13671400
command = "CMD StartProgram"
13681401

13691402
msg_id = self._send_command(command, True)
@@ -1785,9 +1818,11 @@ def load_logic_programm(self, program_name: str) -> bool:
17851818
self.load_logic_programm_async(program_name)
17861819
)
17871820

1788-
def start_programm(self) -> bool:
1821+
def start_programm(self, *, replay_mode: ReplayMode | None = None) -> bool:
17891822
"""Blocking wrapper around :func:`CRIController.start_programm_async`."""
1790-
return asyncio.get_event_loop().run_until_complete(self.start_programm_async())
1823+
return asyncio.get_event_loop().run_until_complete(
1824+
self.start_programm_async(replay_mode=replay_mode)
1825+
)
17911826

17921827
def stop_programm(self) -> bool:
17931828
"""Blocking wrapper around :func:`CRIController.stop_programm_async`."""

‎cri_lib/cri_protocol_parser.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,14 @@ def parse_message(
9595
if (answer := self._parse_info(parts[3:-1])) is not None:
9696
result = {"answer": answer}
9797

98-
case "EXECEND":
99-
result = {"answer": "EXECEND"}
98+
case "LOGMSG":
99+
# every received message is logged, so there's no need to log it again
100+
pass
101+
102+
case "EXECACK" | "EXECPAUSE" | "EXECEND":
103+
# the messages doesn't contain a command message ID,
104+
# therefore only the category can be subscribed to.
105+
result = {"answer": str(cmd_category)}
100106

101107
case "EXECERROR":
102108
result = self._parse_execerror(parts[3:-1])

0 commit comments

Comments
 (0)