Skip to content

Possible fix for "Shade inoperable after charging" #31

Description

@safepay

Possible fix for "Shade inoperable after charging" — set shade time on connect

Heads up: I don't own any battery-powered shades myself, so I can't reproduce or test any of this. This is pure speculation based on the docs and the code already in the repo — posting it in case it's useful for someone with battery shades to pick up and verify.

What I think is going on

The Known Issue in the README ("shades require some re-initialization after charging; workaround is to operate the shade once using the vendor app") looks like it's actually a lost-clock problem, not a re-pairing problem.

Hunter Douglas's own troubleshooting docs spell it out:

"If the app is closed or the device is not local when the shades lose power (such as removal of the battery wand for replacement or charging), schedules will not run until a user connects to the affected shades. In this scenario, the user would need to open the PowerView App while in the home and activate Scenes that include all affected shade(s)."

"When a gateway is part of the Home, the gateway will automatically update every shade's clock at least once a day."

So when a battery wand is removed for charging, the shade's RTC stops, and on next boot it doesn't know what time it is. The vendor app silently pushes the current time when it next connects, and that's what restores schedule operation. We're not sending a time push.

Source: https://help.hunterdouglas.com/hc/en-us/articles/39415701588884-Troubleshoot-PowerView-Gen-3 and https://help.hunterdouglas.com/hc/en-us/articles/39320267982612-Why-aren-t-my-PowerView-schedules-working-with-the-app

Two clues already in the repo

  1. The advertisement decode in api.py already parses a resetClock flag (byte 8, bit 1) and a resetMode flag (byte 8, bit 0). They're populated but never used — no entity, no logic. The shade is literally announcing "my clock needs setting" and we're ignoring it.

  2. The emulator at emu/PV_BLE_cover/PV_BLE_cover.ino already has 0xFF77 documented as set shade time, with the exact payload layout:

    case 0xFF77:
      // set shade time
      Serial.printf("set time: %i-%i-%i %i:%i:%i\n",
        data_dec[4] | data_dec[5] << 8,  // year (LE u16)
        data_dec[6], data_dec[7],        // month, day
        data_dec[8], data_dec[9], data_dec[10]);  // h, m, s

    And 0xFF87 for sunrise/sunset (6 bytes: sunrise h/m/s + sunset h/m/s) — needed if the user has solar-tied schedules.

So the opcode appears to already be reverse-engineered, just not wired into the integration.

Suggested approach

Roughly, in order of usefulness:

  1. Send 0xFF77 with the current local time on every connect. Cheap, idempotent, and matches what HD says the app/gateway does. If resetClock == true in the latest advertisement, log it at INFO so users can see why a shade was unresponsive.
  2. Also send 0xFF87 with today's sunrise/sunset (Home Assistant exposes sun.sun attributes for this).
  3. As a stopgap before any of that, expose resetClock and resetMode as diagnostic binary sensors so users can at least see when a shade is in this state. (Already included in feat: hub-based architecture for automatic shade discovery #29)

As above, I can't test this — I don't have a battery shade. Flagging it here in case someone with the hardware wants to take a swing.

What's still unknown

  • Whether 0xFF77 alone is sufficient, or whether the app also re-pushes scenes (0xFA5A) and/or calls 0xFAEA "reset scene automations" as part of recovery.
  • The mystery 0xFF12 opcode that came up in PV_BLE_cover: unknown message #9 — possibly part of the same sequence.

A capture of the iOS app's traffic against an emulator that has just been re-powered would settle both questions, but the time-set fix is probably worth trying on its own first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions