Skip to content

Summit/blink/skeleton #249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 14, 2025

Conversation

bessman
Copy link
Collaborator

@bessman bessman commented Mar 14, 2025

This provided a code skeleton for the PSLab Development 101 workshop at FOSSASIA Summit 2025.

It shall not be merged into main.

Summary by Sourcery

New Features:

  • Introduce blink functionality for the onboard RGB LED, with options for software and firmware implementations.

Copy link

sourcery-ai bot commented Mar 14, 2025

Reviewer's Guide by Sourcery

This pull request introduces a new exchange method to streamline communication with the PSLab device, refactors existing methods to use this new method, and adds functionality for blinking the onboard RGB LED using both software and firmware implementations. It also includes a new blink.py file containing the blink functionality and removes unused constants.

Sequence diagram for get_version method

sequenceDiagram
  participant Device as PSLab Device
  participant Connection as ConnectionHandler

  activate Device
  Device->>Connection: exchange(COMMON + GET_VERSION)
  activate Connection
  Connection->>Device: Header + Data
  Device-->>Connection: Status + Response
  deactivate Connection
  Device-->>Device: Decode version
  Device-->>Device: Return version
  deactivate Device
Loading

Sequence diagram for rgb_led method

sequenceDiagram
  participant ScienceLab
  participant ConnectionHandler

  ScienceLab->>ConnectionHandler: exchange(cmd, args)
  activate ConnectionHandler
  ConnectionHandler->>ScienceLab: Header + Data
  ScienceLab-->>ConnectionHandler: Status + Response
  deactivate ConnectionHandler
Loading

Updated class diagram for ConnectionHandler

classDiagram
  class ConnectionHandler {
    +write(data: bytes) int
    +read(size: int) bytes
    +exchange(cmd: bytes, data: bytes) bytes
    +get_byte() int
    +get_version() str
    +get_firmware_version() FirmwareVersion
  }
Loading

Class diagram for blink functions

classDiagram
  class blink {
    +blink(psl: pslab.ScienceLab, color: tuple[int, int, int], period: int) None
    +blink_c(psl: pslab.ScienceLab, color: tuple[int, int, int], period: int) None
  }
Loading

File-Level Changes

Change Details Files
Introduces a new exchange method to the ConnectionHandler class for simplified command and data exchange with the device.
  • Adds an exchange method to handle sending commands and data, and receiving responses.
  • Uses struct packing and unpacking for command and data handling.
  • Includes error handling for status codes and timeouts.
pslab/connection/connection.py
Refactors get_version and get_firmware_version methods in ConnectionHandler to use the new exchange method.
  • Replaces the manual sending of command bytes and reading of the response with a single exchange call in get_version.
  • Removes redundant code for handling version retrieval.
  • Simplifies get_firmware_version to use exchange for retrieving firmware version information.
pslab/connection/connection.py
Introduces a Header struct in protocol.py for packing and unpacking command headers.
  • Adds a struct definition for Header to handle command headers.
  • Removes unused constants related to NRFL01 radio module.
pslab/protocol.py
Modifies the rgb_led method in ScienceLab to use the exchange method for sending RGB LED commands.
  • Uses exchange to send the RGB LED command and data.
  • Simplifies the logic for setting RGB LED colors, especially for PSLab version 6.
  • Removes redundant calls to send_byte and get_ack.
pslab/sciencelab.py
Introduces a new blink.py file with functions for blinking the onboard RGB LED.
  • Adds blink and blink_c functions for controlling the RGB LED.
  • Implements blinking functionality using both software and firmware implementations.
  • Uses the exchange method to send commands for the firmware implementation.
pslab/blink.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@bessman bessman marked this pull request as ready for review March 14, 2025 17:05
@bessman bessman changed the base branch from main to summit/blink/skeleton March 14, 2025 17:06
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @bessman - I've reviewed your changes - here's some feedback:

Overall Comments:

  • The new exchange method looks useful; consider using it in more places to reduce code duplication.
  • It looks like the rgb_led function in sciencelab.py could be simplified by using the new exchange method.
Here's what I looked at during the review
  • 🟢 General issues: all looks good
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -70,6 +70,36 @@ def write(self, data: bytes) -> int:
"""
...

def exchange(self, cmd: bytes, data: bytes = b"") -> bytes:
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider refactoring the exchange method into smaller helper functions to separate the header processing and response validation steps, improving code modularity and readability without altering functionality .

The exchange method now does too many things in one go. Consider splitting up the responsibilities into separate helper functions. For example, separate out the header processing and response validation:

def _process_header(self) -> int:
    """Process header, raise exception on status error, and return expected response size."""
    status, response_size = CP.Header.unpack(self.read(CP.Header.size))
    if status:
        raise Exception(status)
    return response_size

def _validate_response(self, response: bytes, expected_size: int) -> bytes:
    """Ensure the full response was received, or raise TimeoutError."""
    if len(response) < expected_size:
        raise TimeoutError
    return response

Then update exchange to use these helpers while retaining functionality:

def exchange(self, cmd: bytes, data: bytes = b"") -> bytes:
    (cmd_int,) = CP.ShortInt.unpack(cmd)
    header = CP.Header.pack(cmd_int, len(data))
    self.write(header + data)
    response_size = self._process_header()
    response = self.read(response_size)
    return self._validate_response(response, response_size)

This refactoring maintains all functionality while reducing complexity in exchange.

@bessman
Copy link
Collaborator Author

bessman commented Mar 14, 2025

@sourcery-ai review

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @bessman - I've reviewed your changes - here's some feedback:

Overall Comments:

  • The new exchange method looks useful; consider using it in other places where you're sending commands and data.
  • It looks like you're using CP.COMMON + CP.GET_VERSION as a command. Consider defining a constant for this.
Here's what I looked at during the review
  • 🟡 General issues: 1 issue found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +98 to +99
if len(response) < response_size:
raise TimeoutError
Copy link

Choose a reason for hiding this comment

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

suggestion: Consider providing more context when raising TimeoutError.

Including details such as the expected response size and the actual number of bytes received would aid in debugging timeout issues.

Suggested change
if len(response) < response_size:
raise TimeoutError
if len(response) < response_size:
raise TimeoutError(f"Timeout error: expected {response_size} bytes but received {len(response)} bytes")

@bessman bessman merged commit 585796f into fossasia:summit/blink/skeleton Mar 14, 2025
2 checks passed
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