Skip to content

Fix AWS brightness scaling and treat zero brightness as “off” #1132

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

Open
wants to merge 21 commits into
base: latest
Choose a base branch
from

Conversation

cybermancerr
Copy link

… cmd

Fixes problems with AWS brightness scaling and adds the capability to turn off the device if brightness is set to “0”. Currently, if a Govee device receives a brightness of “0” over AWS, LAN, or BLE it defaults to a brightness of “1” and never actually turns off. This code update corrects the scaling issues reported by other users and ensures the device truly powers off when brightness is reduced to zero.

Current situation

Right now in sendDeviceUpdate, the ‘brightness’ case always sends a brightness command—even when the incoming value is zero. Because AWS and BLE implementations rarely accept a zero-level brightness, they clamp it up to one, leaving the light on at its lowest level instead of off. In addition, older code was applying a scaling multiplier for AWS devices that caused non-linear or off-by-one brightness on some models.

      case 'brightness': {
        /*
          BRIGHTNESS
          <= INPUT params.value INT in range [0, 100]
          AWS needs { cmd: 'brightness', data: { val: INT[0, 254] } }
          BLE needs { cmd: 0x04, data: (based on) INT[0, 100] }
          LAN needs { cmd: 'brightness', data: { value: INT[0, 100] } }
        */
        data.awsParams = {
          cmd: 'brightness',
          data: {
            val: accessory.context.awsBrightnessNoScale
              ? params.value
              : Math.round(params.value * 2.54),
          },
        }
        data.bleParams = {
          cmd: 0x04,
          data: Math.floor(
            platformConsts.bleBrightnessNoScale.includes(accessory.context.gvModel)
              ? (params.value / 100) * 0x64
              : (params.value / 100) * 0xFF,
          ),
        }
        data.lanParams = {
          cmd: 'brightness',
          data: {
            value: params.value,
          },
        }
        break
      }

and

    /*
      BRIGHTNESS
    */
    if (params.state && hasProperty(params.state, 'brightness')) {
      if (params.source === 'LAN') {
        data.brightness = params.state.brightness
      } else if (params.source === 'AWS') {

        data.brightness = accessory.context.awsBrightnessNoScale
        ? params.state.brightness
        //   : Math.round(params.state.brightness / 2.54)
      }
    }

Users have reported:

  • Setting brightness to zero never actually powers the device off
  • Some AWS models mis-scale values (for example, sending 254 for a value of 100, or rounding errors at low values)

Proposed solution

  • Short-circuit brightness equals zero
    If the incoming value is zero, immediately send an off command to AWS, BLE and LAN, which properly powers the device off.

  • Simplify AWS scaling
    Always send the raw brightness value when greater than zero, rather than applying a hard-to-tune multiplier.

Replace the existing ‘brightness’ block with:

case 'brightness': {
        /*
          BRIGHTNESS
          <= INPUT params.value INT in range [0, 100]
          AWS needs { cmd: 'brightness', data: { value: INT[0, 100] } }
          BLE needs { cmd: 0x04, data: (based on) INT[0, 100] }
          LAN needs { cmd: 'brightness', data: { value: INT[0, 100] } }
        */
  // if they set brightness to 0, treat it as OFF
  if (params.value === 0) {
    data.awsParams = { cmd: 'turn', data: { val: 0 } }
    data.bleParams = { cmd: 0x01, data: 0x0 }
    data.lanParams = { cmd: 'turn', data: { value: 0 } }
    break
  }

  // otherwise, handle brightness normally
  data.awsParams = {
    cmd: 'brightness',
    data: { val: params.value },
  }
  data.bleParams = {
    cmd: 0x04,
    data: Math.floor(
      platformConsts.bleBrightnessNoScale.includes(accessory.context.gvModel)
        ? (params.value / 100) * 0x64
        : (params.value / 100) * 0xFF
    ),
  }
  data.lanParams = {
    cmd: 'brightness',
    data: { value: params.value },
  }
  break
}

and

    /*
      BRIGHTNESS
    */
    if (params.state && hasProperty(params.state, 'brightness')) {
      if (params.source === 'LAN') {
        data.brightness = params.state.brightness
      } else if (params.source === 'AWS') {
        data.brightness = params.state.brightness
        // data.brightness = accessory.context.awsBrightnessNoScale
        //   ? params.state.brightness
        //   : Math.round(params.state.brightness / 2.54)
      }
    }

Release Notes

  • Turning brightness to zero now reliably powers the device off on AWS, BLE and LAN
  • Fixed AWS brightness scaling so that values one through one hundred map linearly without unexpected rounding
  • No breaking changes: existing devices will continue to accept brightness values as before, except that zero now means off
  • Tested on Govee models: H6006, H6010, H7033, H6046, H605C, H6087

Additional Information

  • This change only touches the sendDeviceUpdate method in the main platform class
  • No other command handlers are affected
  • Verification was performed against all unique models found in user data (H6006, H6010, H7033, H6046, H605C and H6087) to ensure consistent off-at-zero behavior

Testing

  • Manual device test

    • On each model (H6006, H6010, H7033, H6046, H605C, H6087):
      • Set brightness to zero → device turns off
      • Set brightness to one, fifty, one hundred → device lights at correct levels
  • Automated mocks

    • Unit-test sendDeviceUpdate to verify that for a brightness value of zero you generate an off command rather than a brightness command
    • Edge cases: confirm that very high (one hundred) and very low (one) values send the correct AWS payload

Reviewer Nudging

  • Entry point: the case 'brightness' block in sendDeviceUpdate (around line 1400 in index.js or wherever that method lives)
  • Key diff: the new zero-value guard and simplified scaling
  • Model coverage: ensure each tested model’s branch (H6006, H6010, H7033, H6046, H605C, H6087) correctly falls into the zero-value off path
  • Feel free to test with a real Govee device or existing mocks for any additional models

Video of controling 12 H6010 after patching the plugin with the proposed changes leveraging DMXSmartLink Software:

https://youtu.be/6w97MaAxoMA

@bwp91
Copy link
Collaborator

bwp91 commented Jul 12, 2025

Hi @cybermancerr are you on discord at all? and if so, in the homebridge server?

@cybermancerr
Copy link
Author

Hi @cybermancerr are you on discord at all? and if so, in the homebridge server?

Yes and I just joined that server. My profile name is WhiteCrowSecurity. Also, I have discord server for https://whitecrowsecurity.com

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