Skip to content

Conversation

@stc1988
Copy link
Owner

@stc1988 stc1988 commented Dec 28, 2025

No description provided.

@gemini-code-assist
Copy link

Summary of Changes

Hello @stc1988, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces comprehensive support for addressable LEDs within the stackchan firmware. It provides a new Led class that encapsulates common LED operations and effects, and seamlessly integrates these capabilities into the Robot class, enabling easy control of LED strips through the robot's API. This enhancement allows for dynamic visual feedback and expressive lighting patterns, complete with platform-specific driver management and a dedicated test suite.

Highlights

  • New LED Module: Introduced a new Led class based on NeoStrand for controlling addressable LEDs (WS2812B compatible), providing methods for on, off, blink, and rainbow effects.
  • Robot Class Integration: Integrated LED control into the Robot class, allowing Robot instances to manage multiple named LED strips and expose public methods (lightOn, lightOff, lightBlink, lightRainbow) for easy control.
  • Platform-Specific LED Handling: Implemented platform-specific handling for neopixel drivers, including stubs for non-ESP32 environments (mac, lin, win) to ensure broader compatibility during development, while utilizing the actual driver for ESP32.
  • Dedicated Test Suite: Added a new test suite specifically for the LED functionality, demonstrating various lighting effects and operations.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for controlling LEDs, which is a great new feature. The implementation includes a new Led class to manage effects like on, off, blink, and rainbow, along with integration into the main Robot class. My review focuses on improving the robustness and correctness of the new Led class by ensuring that different effects don't conflict with each other. I've also pointed out a couple of areas where type safety and documentation can be improved.

Comment on lines 34 to 46
on(r: number, g: number, b: number, duration?: number, index?: number, count?: number) {
const _index = index ?? 0
const _count = count ?? this.length - _index
this._fill(this.makeRGB(r, g, b), _index, _count)

this.update()
if (duration) {
Timer.set(() => {
this._fill(this.makeRGB(0, 0, 0), _index, _count)
this.update()
}, duration)
}
}

Choose a reason for hiding this comment

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

high

The on() method does not stop currently running effects like blink() or rainbow(). This can lead to unexpected behavior where the LED color is immediately overridden by the active effect's timer. To ensure on() sets a static color, you should stop all other effects at the beginning of this method. Consider extracting this cleanup logic into a private helper method to be reused across on, blink, and rainbow to avoid code duplication.

  on(r: number, g: number, b: number, duration?: number, index?: number, count?: number) {
    this._blinking = false
    if (this._blinkTimer !== undefined) {
      Timer.clear(this._blinkTimer)
      this._blinkTimer = undefined
    }
    if (this._effect) {
      this.stop()
      this._effect = undefined
    }
    const _index = index ?? 0
    const _count = count ?? this.length - _index
    this._fill(this.makeRGB(r, g, b), _index, _count)

    this.update()
    if (duration) {
      Timer.set(() => {
        this._fill(this.makeRGB(0, 0, 0), _index, _count)
        this.update()
      }, duration)
    }
  }

Comment on lines 63 to 81
blink(r: number, g: number, b: number, interval: number, index?: number, count?: number) {
const _index = index ?? 0
const _count = count ?? this.length - _index
if (this._blinking) return
this._blinking = true
this._blinkState = false

const step = () => {
if (!this._blinking) return
this._blinkState = !this._blinkState
if (this._blinkState) {
this._fill(this.makeRGB(r, g, b), _index, _count)
} else {
this._fill(this.makeRGB(0, 0, 0), _index, _count)
}
this.update()
}
this._blinkTimer = Timer.repeat(step, interval)
}

Choose a reason for hiding this comment

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

high

The blink() method should cancel any other running effects (like rainbow) when called. Additionally, the if (this._blinking) return prevents updating an existing blink with new parameters. It's better to stop the current blink and any other effects, then start a new one. This ensures predictable behavior and allows for dynamic changes to the blink effect.

  blink(r: number, g: number, b: number, interval: number, index?: number, count?: number) {
    this._blinking = false
    if (this._blinkTimer !== undefined) {
      Timer.clear(this._blinkTimer)
      this._blinkTimer = undefined
    }
    if (this._effect) {
      this.stop()
      this._effect = undefined
    }

    const _index = index ?? 0
    const _count = count ?? this.length - _index
    this._blinking = true
    this._blinkState = false

    const step = () => {
      if (!this._blinking) return
      this._blinkState = !this._blinkState
      if (this._blinkState) {
        this._fill(this.makeRGB(r, g, b), _index, _count)
      } else {
        this._fill(this.makeRGB(0, 0, 0), _index, _count)
      }
      this.update()
    }
    this._blinkTimer = Timer.repeat(step, interval)
  }

Comment on lines 82 to 90
rainbow(index?: number, count?: number) {
const _index = index ?? 0
const _count = count ?? this.length - _index
if (this._effect) return

this._effect = new NeoStrand.HueSpan({ strand: this, start: _index, end: _count })
this.setScheme([this._effect])
this.start(50)
}

Choose a reason for hiding this comment

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

high

Similar to the other effect methods, rainbow() should cancel any previously running effects like blink(). The if (this._effect) return also prevents restarting the effect. It's better to always clear previous state before starting a new effect.

  rainbow(index?: number, count?: number) {
    this._blinking = false
    if (this._blinkTimer !== undefined) {
      Timer.clear(this._blinkTimer)
      this._blinkTimer = undefined
    }
    if (this._effect) {
      this.stop()
      this._effect = undefined
    }

    const _index = index ?? 0
    const _count = count ?? this.length - _index

    this._effect = new NeoStrand.HueSpan({ strand: this, start: _index, end: _count })
    this.setScheme([this._effect])
    this.start(50)
  }

const led = Object.fromEntries(
Object.entries(configLed).map(([key, config]) => [
key,
new Led(config as { pin: number; length?: number; order?: string }),

Choose a reason for hiding this comment

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

medium

Using a type assertion with as bypasses type-checking and can hide potential bugs if the config object from preferences doesn't match the expected shape. This could lead to runtime errors. For better type safety, consider adding a type guard function to validate the config object's structure before creating a new Led instance. This would make your code more robust against invalid configurations.

Copy link
Owner Author

@stc1988 stc1988 Dec 28, 2025

Choose a reason for hiding this comment

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

@gemini-code-assist 例えばどんな対策をしたらいい?

stc1988 and others added 3 commits December 28, 2025 12:04
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@stc1988
Copy link
Owner Author

stc1988 commented Dec 28, 2025

@gemini-code-assist review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for controlling LEDs, including effects like blinking and rainbow. The implementation is well-structured within a new led module and integrated into the existing Robot class. I've identified a critical bug in the rainbow effect, a high-severity performance issue in the blink effect, and a minor typing issue in a stub file. Addressing these points will significantly improve the correctness and performance of this new feature.

const newColor = value < half ? this.rgbOn : this.rgbOff
const currentColor = this.strand.getPixel(this.start)
if (newColor !== currentColor) {
for (let i = this.start; i < this.end; i++) this.strand.set(i, newColor, this.start, this.end)

Choose a reason for hiding this comment

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

high

The current implementation for setting pixel colors within the Blink effect is inefficient and contains a bug. The for loop calls this.strand.set() on each iteration, which in neostrand triggers an update of the LED strand. This leads to multiple, unnecessary updates within a single animation frame. Furthermore, the last argument to set() is this.end (an index), where a count is expected.

A more efficient and correct approach is to use the fill() method to update the pixel buffer for the entire segment at once. The animation timeline will then handle calling update() once per frame.

Suggested change
for (let i = this.start; i < this.end; i++) this.strand.set(i, newColor, this.start, this.end)
this.strand.fill(newColor, this.start, this.size)

stc1988 and others added 2 commits December 28, 2025 21:37
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@stc1988 stc1988 closed this Dec 28, 2025
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.

2 participants