Unable to update Black Switch firmware using Hubitat

I figured it out! It smelled like an off-by-one error, and indeed that’s what was happening. There’s a bug in the hubitat firmware update tool that is only triggered when the size of the firmware file is one byte larger than an even multiple of the fragment size. I fixed the bug and now it works.

Here’s what I figured out:

  • The firmware size of the LZW30 1.22 “beta” firmware as reported by the legacy firmware update tool is “firmware total bytes: 93601”
  • The max fragment size is 40 bytes.
  • 2340 * 40 = 93600, so the last fragment in the 1.22 firmware should be fragment 2341, with the last 1 byte of data in it.
  • The firmware size of the LZW30 1.20 “production” firmware is 93600 bytes
  • I was able to successfully flash the 1.20 firmware using the legacy firmware updater tool.

The bug is present in both versions of the firmware updater, in the void zwaveEvent(hubitat.zwave.commands.firmwareupdatemdv3.FirmwareUpdateMdGet cmd) method, where it’s trying to figure out if it’s sending the last fragment.

    if (lastByte >= byteBuffer.size()-1) {
        lastReport=true
        lastByte = byteBuffer.size()
    }

This stood out to me because generally you use if (foo > bar.size()-1) OR if (foo >= bar.size()) as a stopping condition when foo is zero-indexed and .size is one-indexed. Indeed, in this case, the code incorrectly sets lastReport=true for report 2340.

The next part is my inference, not what I can actually see, but I think it’s pretty likely what’s happening. Because the zwave command for the last fragment is a little different, setting lastReport=true for fragment 2340 results in a command that has a different header than what the switch is expecting (since the switch knows to expect 93601 bytes, which require 2341 fragments). So the switch doesn’t acknowledge it, and the firmware updater retransmits after 12 seconds. When that fails 10 times in a row, it times out.

The fix is simple: remove the -1 from that condition. Once I did that I was able to upload firmware 1.22 without problems. I’ll open a github PR for it.

This is my absolute favorite thing about open source software. There was a bug, and I could find and fix it myself by looking at the code. I love it when this happens.

3 Likes