Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions armctl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,24 +39,30 @@
__author__ = "Michael Gross"


# Loggers to suppress/enable: armctl package and its dependencies
_LOGGERS_TO_MANAGE = ["armctl", "rtde"]


class Logger:
"""Global logger utility for armctl."""

@staticmethod
def disable():
"""Disables logging."""
"""Disables logging for armctl and its dependencies."""
import logging

# Disable all logging at and below the CRITICAL level
logging.disable(logging.CRITICAL)
# Suppress armctl and dependency loggers by setting level above CRITICAL
for logger_name in _LOGGERS_TO_MANAGE:
logging.getLogger(logger_name).setLevel(logging.CRITICAL + 1)

@staticmethod
def enable():
"""Enables logging."""
"""Enables logging for armctl and its dependencies."""
import logging

# Re-enable logging to its previous state
logging.disable(logging.NOTSET)
# Re-enable armctl and dependency loggers
for logger_name in _LOGGERS_TO_MANAGE:
logging.getLogger(logger_name).setLevel(logging.NOTSET)


import os
Expand Down
39 changes: 21 additions & 18 deletions armctl/universal_robots/protocols/rtde.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

from rtde import RTDE as _RTDE
from rtde.rtde_config import ConfigFile
from ctypes import c_uint32

UINT32 = NewType("UINT32", int)
u32 = NewType("u32", c_uint32)


class RTDE:
Expand Down Expand Up @@ -73,25 +74,27 @@ def robot_status(self) -> dict[str, bool]:
- **`Bit 10`**: Is stopped due to safety
"""
data = self._get_data()
rsb: UINT32 = data.robot_status_bits
ssb: UINT32 = data.safety_status_bits
rsb: u32 = data.robot_status_bits
ssb: u32 = data.safety_status_bits

bit = lambda data, n: bool(data & (1 << n))

return {
# Robot status bits
"Power On": bool(rsb & 1),
"Program Running": bool(rsb & 2),
"Teach Button": bool(rsb & 4),
"Power Button": bool(rsb & 8),
"Power On": bit(rsb, 0),
"Program Running": bit(rsb, 1),
"Teach Button": bit(rsb, 2),
"Power Button": bit(rsb, 3),
# Safety status bits
"Normal Mode": bool(ssb & 1),
"Reduced Mode": bool(ssb & 2),
"Protective Stop": bool(ssb & 4),
"Recovery Mode": bool(ssb & 8),
"Safeguard Stopped": bool(ssb & 16),
"System Emergency Stopped": bool(ssb & 32),
"Robot Emergency Stopped": bool(ssb & 64),
"Emergency Stopped": bool(ssb & 128),
"Violation": bool(ssb & 256),
"Fault": bool(ssb & 512),
"Stopped Due to Safety": bool(ssb & 1024),
"Normal Mode": bit(ssb, 0),
"Reduced Mode": bit(ssb, 1),
"Protective Stop": bit(ssb, 2),
"Recovery Mode": bit(ssb, 3),
"Safeguard Stopped": bit(ssb, 4),
"System Emergency Stopped": bit(ssb, 5),
"Robot Emergency Stopped": bit(ssb, 6),
"Emergency Stopped": bit(ssb, 7),
"Violation": bit(ssb, 8),
"Fault": bit(ssb, 9),
"Stopped Due to Safety": bit(ssb, 10),
}
56 changes: 54 additions & 2 deletions tests/test_logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,63 @@ def test_logger_receive_logs_message(caplog):


def test_logger_verbosity_and_enable_disable(caplog):
armctl_logger = logging.getLogger("armctl.test")
with caplog.at_level(logging.INFO):
Logger.enable() # Make sure logging is enabled
logging.info("This should appear")
armctl_logger.info("This should appear")
assert "This should appear" in caplog.text
Logger.disable()
logging.info("This should NOT appear")
armctl_logger.info("This should NOT appear")
assert "This should NOT appear" not in caplog.text
Logger.enable() # Re-enable for other tests


def test_rtde_logger_suppression(caplog):
"""Test that the RTDE logger is suppressed when Logger.disable() is called."""
rtde_logger = logging.getLogger("rtde")

# Enable logging first
Logger.enable()
with caplog.at_level(logging.INFO):
rtde_logger.info("RTDE message when enabled")
assert "RTDE message when enabled" in caplog.text

# Clear captured logs
caplog.clear()

# Disable logging and test that RTDE logger is suppressed
Logger.disable()
with caplog.at_level(logging.INFO):
rtde_logger.info("RTDE message when disabled")
assert "RTDE message when disabled" not in caplog.text

# Re-enable for other tests
Logger.enable()


def test_other_loggers_not_affected(caplog):
"""Test that non-armctl loggers are NOT affected by Logger.disable()."""
armctl_logger = logging.getLogger("armctl.test2")
other_logger = logging.getLogger("some.other.library")

Logger.enable()
with caplog.at_level(logging.INFO):
armctl_logger.info("Armctl message when enabled")
other_logger.info("Other library message when enabled")
assert "Armctl message when enabled" in caplog.text
assert "Other library message when enabled" in caplog.text

caplog.clear()

# Disable armctl logging - should NOT affect other loggers
Logger.disable()
with caplog.at_level(logging.INFO):
armctl_logger.info("Armctl message when disabled")
other_logger.info("Other library message when disabled")
# Armctl logger should be suppressed
assert "Armctl message when disabled" not in caplog.text
# Other library logger should still work
assert "Other library message when disabled" in caplog.text

Logger.enable()