Skip to content

Conversation

jpcornil-git
Copy link
Contributor

@jpcornil-git jpcornil-git commented Oct 6, 2025

Log the contents of the indState message to the console Continuous reporting remains disabled by default and can be enabled by setting the AYAB_DEBUG environment variable

Summary by CodeRabbit

  • New Features

    • More detailed, human-readable status logs for device state with structured output and graceful handling when some fields are missing, improving troubleshooting and operator visibility.
    • Debug mode: set AYAB_DEBUG to force continuous reporting during sessions; default behavior unchanged when not set.
  • Refactor

    • Minor internal reorganization to integrate the enhanced logging path without affecting other functionality.

Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

Walkthrough

Adds Control.__log_indState to decode and emit structured logs for API6 IndState tokens and routes indState handling through it. Engine FSM change makes API6 start requests force continuous reporting when AYAB_DEBUG is set; otherwise preserves prior behavior.

Changes

Cohort / File(s) Summary of Changes
API6 IndState logging in Control
src/main/python/main/ayab/engine/control.py
Added import struct. Introduced private method __log_indState(self, msg: bytes) to decode IndState fields, map numeric codes to strings, handle optional parameters with an IndexError fallback, and emit a structured info log. check_serial_API6 now routes Token.indState payloads to this helper; local reorganization only.
API6 start request debug override
src/main/python/main/ayab/engine/engine_fsm.py
Added import os. In _API6_request_start, the third argument to control.com.req_start_API6 is now True when the AYAB_DEBUG env var is set; otherwise it passes control.continuous_reporting. No other functional changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant EngineFSM as EngineFSM
  participant Control as Control
  participant Comms as Comms

  Note over EngineFSM,Comms: API6 start request (debug override)
  User->>EngineFSM: initiate start
  EngineFSM->>EngineFSM: check AYAB_DEBUG env
  alt AYAB_DEBUG set
    EngineFSM->>Comms: req_start_API6(..., continuous_reporting=True)
  else AYAB_DEBUG not set
    EngineFSM->>Comms: req_start_API6(..., continuous_reporting=control.continuous_reporting)
  end
Loading
sequenceDiagram
  autonumber
  participant Serial as SerialPort
  participant Control as Control
  participant Logger as Logger

  Note over Serial,Control: API6 token processing for IndState
  Serial-->>Control: Token.indState + payload
  Control->>Control: __log_indState(payload)
  Control->>Logger: structured IndState info log (mapped fields)
  alt optional params missing
    Control->>Logger: reduced/fallback log format
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the primary change introduced by this pull request, namely adding support for continuous reporting via an environment variable, and it clearly conveys the feature enhancement without extraneous detail.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/python/main/ayab/engine/engine_fsm.py (1)

170-177: Keep status.active in sync with forced continuous reporting

When AYAB_DEBUG is set you now force continuous reporting on the wire, but status.active remains tied to control.continuous_reporting. That leaves the UI/engine believing reporting is off while the device streams continuously. Please derive a single effective_continuous_reporting value and use it for both status.active and the req_start_API6 call.

-                control.status.active = control.continuous_reporting
-                control.com.req_start_API6(
+                debug_reporting = bool(os.getenv("AYAB_DEBUG"))
+                effective_continuous_reporting = (
+                    True if debug_reporting else control.continuous_reporting
+                )
+                control.status.active = effective_continuous_reporting
+                control.com.req_start_API6(
                     control.pattern.knit_start_needle,
                     control.pattern.knit_end_needle - 1,
-                    True if os.getenv("AYAB_DEBUG") else control.continuous_reporting,
+                    effective_continuous_reporting,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6c62a69 and d90c637.

📒 Files selected for processing (2)
  • src/main/python/main/ayab/engine/control.py (2 hunks)
  • src/main/python/main/ayab/engine/engine_fsm.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/main/python/main/ayab/engine/engine_fsm.py (3)
src/main/python/main/ayab/engine/communication_mock.py (1)
  • req_start_API6 (97-103)
src/main/python/main/ayab/tests/test_communication_mock.py (2)
  • test_req_line_API6 (97-115)
  • test_req_start_API6 (44-56)
src/main/python/main/ayab/engine/communication.py (1)
  • req_start_API6 (137-156)
src/main/python/main/ayab/engine/control.py (2)
src/main/python/main/ayab/engine/communication.py (1)
  • Token (39-66)
src/main/python/main/ayab/signal_sender.py (1)
  • emit_hw_test_writer (102-103)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Create and upload Mac OSX build
  • GitHub Check: Create and upload Windows build

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/python/main/ayab/engine/control.py (1)

180-183: Consider defining mapping dictionaries as class constants.

The mapping dictionaries are recreated on every call to __log_indState. Moving them to class-level constants (e.g., _DIRECTION_MAP, _CARRIAGE_MAP, etc.) would avoid repeated allocation and improve readability by making these mappings more discoverable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d90c637 and 1a9f052.

📒 Files selected for processing (1)
  • src/main/python/main/ayab/engine/control.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/python/main/ayab/engine/control.py (3)
src/main/python/main/ayab/engine/communication.py (1)
  • Token (39-66)
src/main/python/main/ayab/signal_sender.py (1)
  • emit_hw_test_writer (102-103)
src/main/python/main/ayab/engine/status.py (1)
  • parse_device_state_API6 (177-211)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Create and upload Mac OSX build
  • GitHub Check: Create and upload Windows build
🔇 Additional comments (1)
src/main/python/main/ayab/engine/control.py (1)

189-189: Previous KeyError concerns addressed.

The use of .get() with hex fallbacks (e.g., f"0x{msg[7]:02x}?") successfully prevents KeyError exceptions for unexpected firmware codes, as requested in the previous review.

Also applies to: 191-191, 194-195

Log the contents of the indState message to the console
Continuous reporting remains disabled by default and can be enabled by
setting the AYAB_DEBUG environment variable
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3c57fd and 8d15874.

📒 Files selected for processing (2)
  • src/main/python/main/ayab/engine/control.py (2 hunks)
  • src/main/python/main/ayab/engine/engine_fsm.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/python/main/ayab/engine/engine_fsm.py
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/python/main/ayab/engine/control.py (3)
src/main/python/main/ayab/engine/communication.py (1)
  • Token (39-66)
src/main/python/main/ayab/signal_sender.py (1)
  • emit_hw_test_writer (102-103)
src/main/python/main/ayab/engine/status.py (1)
  • parse_device_state_API6 (177-211)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Create and upload Mac OSX build
  • GitHub Check: Create and upload Windows build
🔇 Additional comments (2)
src/main/python/main/ayab/engine/control.py (2)

42-42: LGTM!

The struct import is necessary for decoding binary fields in IndState messages and is properly placed with other imports.


173-173: LGTM!

The logging call is appropriately placed after state parsing and adds observability without altering the existing data flow.

Comment on lines 179 to 210
def __log_indState(self, msg: bytes) -> None:
try:
directionMap = {0x00: "Left ", 0x01: "Right", 0xFF: "?"}
machineSideMap = {0x00: "? ", 0x01: "Left", 2: "Right"}
beltShiftMap = {0x00: "?", 0x01: "Regular", 0x02: "Shifted"}
carriageMap = {0x00: "K", 0x01: "L", 0x02: "G", 0x03: "K270", 0xFF: "None"}

error = msg[1]
state = msg[2]
hallLeft = struct.unpack(">H", msg[3:5])[0]
hallRight = struct.unpack(">H", msg[5:7])[0]
carriage = carriageMap.get(msg[7], f"0x{msg[7]:02x}?")
position = msg[8]
direction = directionMap.get(msg[9], f"0x{msg[9]:02x}?")

try: # AyabAsync supplies additional parameters
hallActive = machineSideMap.get(msg[10], f"0x{msg[10]:02x}?")
beltShift = beltShiftMap.get(msg[11], f"0x{msg[11]:02x}?")
self.logger.info(
f"IndState: {error:1d} {state:1d} {position:3d}"
f" {carriage:5s} ({beltShift:11s},{direction:5s})"
f" Hall:{hallActive:5s} ({hallLeft:5d}, {hallRight:5d})"
)
except IndexError:
self.logger.info(
f"IndState: {error:1d} {state:1d} {position:3d}"
f" {carriage:5s} ({direction:5s})"
f" Hall:({hallLeft:5d}, {hallRight:5d})"
)
except (IndexError, struct.error) as e:
self.logger.warning(f"Unable to parse InState message: {e}")

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo in warning message.

The error handling and logging logic are well-structured with appropriate fallbacks for unknown codes and resilience against malformed messages. However, there's a typo in the warning message.

Apply this diff to correct the typo:

-        self.logger.warning(f"Unable to parse InState message: {e}")
+        self.logger.warning(f"Unable to parse IndState message: {e}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def __log_indState(self, msg: bytes) -> None:
try:
directionMap = {0x00: "Left ", 0x01: "Right", 0xFF: "?"}
machineSideMap = {0x00: "? ", 0x01: "Left", 2: "Right"}
beltShiftMap = {0x00: "?", 0x01: "Regular", 0x02: "Shifted"}
carriageMap = {0x00: "K", 0x01: "L", 0x02: "G", 0x03: "K270", 0xFF: "None"}
error = msg[1]
state = msg[2]
hallLeft = struct.unpack(">H", msg[3:5])[0]
hallRight = struct.unpack(">H", msg[5:7])[0]
carriage = carriageMap.get(msg[7], f"0x{msg[7]:02x}?")
position = msg[8]
direction = directionMap.get(msg[9], f"0x{msg[9]:02x}?")
try: # AyabAsync supplies additional parameters
hallActive = machineSideMap.get(msg[10], f"0x{msg[10]:02x}?")
beltShift = beltShiftMap.get(msg[11], f"0x{msg[11]:02x}?")
self.logger.info(
f"IndState: {error:1d} {state:1d} {position:3d}"
f" {carriage:5s} ({beltShift:11s},{direction:5s})"
f" Hall:{hallActive:5s} ({hallLeft:5d}, {hallRight:5d})"
)
except IndexError:
self.logger.info(
f"IndState: {error:1d} {state:1d} {position:3d}"
f" {carriage:5s} ({direction:5s})"
f" Hall:({hallLeft:5d}, {hallRight:5d})"
)
except (IndexError, struct.error) as e:
self.logger.warning(f"Unable to parse InState message: {e}")
def __log_indState(self, msg: bytes) -> None:
try:
directionMap = {0x00: "Left ", 0x01: "Right", 0xFF: "?"}
machineSideMap = {0x00: "? ", 0x01: "Left", 2: "Right"}
beltShiftMap = {0x00: "?", 0x01: "Regular", 0x02: "Shifted"}
carriageMap = {0x00: "K", 0x01: "L", 0x02: "G", 0x03: "K270", 0xFF: "None"}
error = msg[1]
state = msg[2]
hallLeft = struct.unpack(">H", msg[3:5])[0]
hallRight = struct.unpack(">H", msg[5:7])[0]
carriage = carriageMap.get(msg[7], f"0x{msg[7]:02x}?")
position = msg[8]
direction = directionMap.get(msg[9], f"0x{msg[9]:02x}?")
try: # AyabAsync supplies additional parameters
hallActive = machineSideMap.get(msg[10], f"0x{msg[10]:02x}?")
beltShift = beltShiftMap.get(msg[11], f"0x{msg[11]:02x}?")
self.logger.info(
f"IndState: {error:1d} {state:1d} {position:3d}"
f" {carriage:5s} ({beltShift:11s},{direction:5s})"
f" Hall:{hallActive:5s} ({hallLeft:5d}, {hallRight:5d})"
)
except IndexError:
self.logger.info(
f"IndState: {error:1d} {state:1d} {position:3d}"
f" {carriage:5s} ({direction:5s})"
f" Hall:({hallLeft:5d}, {hallRight:5d})"
)
except (IndexError, struct.error) as e:
self.logger.warning(f"Unable to parse IndState message: {e}")
🤖 Prompt for AI Agents
In src/main/python/main/ayab/engine/control.py around lines 179 to 210, the
exception warning string contains a typo ("InState") that should match the
logged message prefix ("IndState"); update the logger.warning call to use
"IndState" instead of "InState" so the warning reads f"Unable to parse IndState
message: {e}" (preserve the f-string and exception variable).

Copy link

sonarqubecloud bot commented Oct 8, 2025

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d15874 and 53db14e.

📒 Files selected for processing (1)
  • src/main/python/main/ayab/engine/control.py (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/main/python/main/ayab/engine/control.py (2)
src/main/python/main/ayab/engine/communication.py (1)
  • Token (39-66)
src/main/python/main/ayab/signal_sender.py (1)
  • emit_hw_test_writer (102-103)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Create and upload Linux AppImage release
  • GitHub Check: Create and upload Windows build
  • GitHub Check: Create and upload Mac OSX build

Comment on lines +208 to +209
except (IndexError, struct.error) as e:
self.logger.warning(f"Unable to parse indState message: {e}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix casing in the warning message.

The warning still prints indState, which makes log filtering inconsistent with the IndState prefix used elsewhere. Please match the casing.

-            self.logger.warning(f"Unable to parse indState message: {e}")
+            self.logger.warning(f"Unable to parse IndState message: {e}")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
except (IndexError, struct.error) as e:
self.logger.warning(f"Unable to parse indState message: {e}")
except (IndexError, struct.error) as e:
self.logger.warning(f"Unable to parse IndState message: {e}")
🤖 Prompt for AI Agents
In src/main/python/main/ayab/engine/control.py around lines 208-209, the warning
message prints "indState" with wrong casing; update the f-string to use
"IndState" (e.g. self.logger.warning(f"Unable to parse IndState message: {e}"))
so the log message matches the existing "IndState" prefix used elsewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant