Skip to content

Instantly share code, notes, and snippets.

@samthor
Last active September 23, 2021 03:59
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samthor/42f41372dfeb942b0e419e238d72f752 to your computer and use it in GitHub Desktop.
Save samthor/42f41372dfeb942b0e419e238d72f752 to your computer and use it in GitHub Desktop.
Read/write Clipsal smart switches

This is notes for anyone who is interacting with (in Australia at least) Clipsal-branded smart switches that operate over BLE. (They also come with a ZigBee certification document, but it seems like it was never enabled.)

They have a couple of interesting UUIDs (these are here for y'all searching for them):

  • Control service, 720a9080-9c7d-11e5-a7e3-0002a5d5c51b

    • State characteristic (i.e., switch on/off), 720a9081-9c7d-11e5-a7e3-0002a5d5c51b
    • Level characteristic (i.e., brightness), 720a9082-9c7d-11e5-a7e3-0002a5d5c51b
  • Command service, 720a7080-9c7d-11e5-a7e3-0002a5d5c51b

    • Request characteristic, 720a7081-9c7d-11e5-a7e3-0002a5d5c51b
    • Response characteristic, 720a7082-9c7d-11e5-a7e3-0002a5d5c51b

Set switch on/off and brightness the naïve way

For clarification, I have some CLP5010's which have on/off as well as brightness. I also have CLP5011's which I've yet to install (but are just switches, and do not have a level)—these seem more suitable for controlled loads or lights that cannot dim.

So, you can write 0x00 or 0x01 to the state characteristic to turn a switch on or off. You can also write to the level characteristic (as a 16-bit little-endian number, for some reason) which ranges from 0-10,000. (So the highest value will be 0x2710, written as "0x10 0x27" in LE).

The brightness isn't independent from the power state. If the light is off, brightness will be zero. For example: if you set the brightness to 600 on an off switch, the light will come on, and the opposite if you set brightness to zero. (Toggling on/off will restore the most recent brightness, or there's an option in their app to have it restore at a specific value always.)

Regardless, it seems as if these characteristics ONLY report the last state you wrote over BLE.

  • You cannot read the latest value if a person physically toggled the switch.
  • You can see the latest value if you're subscribed to the characteristic, but this requires holding a BLE connection open (not really ideal when you have lots of switches).

This is… strangely broken for real use if you're trying to include these switches in a home automation system.

BLE scanner way

You can read the current state of the light by having a BLE scanner run. The advertising data packet contains a "manufacturer specific" (i.e., 0xff) payload that announces on/off and level. Yes, this means sufficiently motivated neighbours could read the status of your lights—it's public. But they could probably tell if your windows are lit up anyway.

The packet has a bunch of stuff in it, but importantly:

  • data[5] contains the current settings generation (it updates whenever a setting changes)
  • data[6] reports on/off state (the Clipsal app masks it with & 15 but no other data ever appears here)
  • data[7] has the brightness from 0-255 (it's really internally 0-10,000), you can / 255.0 * 10000 to bring it in-range

I use these packets to update my code which eventually informs e.g., Google Assistant as to whether the lights are on.

(I find it really amusing that the Clipsal app does this discovery, but still makes you tap on a specific light to see whether it's currently on. It already knows and could show the statuses all at once!)

Request/Response way

There's also a way to make arbitrary requests and wait for responses. This is how the app gets state and writes settings.

There's two types of requests: read and write. The app refers to using these as reading and writing "registers". The read command looks like:

Byte Value Notes
0 0xff
1 0xff
2 0x06 Magic value
3 0xff
4 0x43 Magic value
5-6 register The register to read, in 2-byte big-endian
6-7 length / 2 The number of 2-byte values we expect in return (length is total bytes)

The write is pretty similar, but contains more data:

Byte Value Notes
0 0xff
1 0xff
2 length + 7 The number of bytes to write, plus seven
3 0xff
4 0x10 Magic value
5-6 register The register to write, in 2-byte big-endian
6-7 length / 2 The number of 2-byte values we're reading (length is total bytes)
8 length The total number of bytes being written
9+ your payload The payload to write

Length must always be even and seems to be minimum eight. If the payload you're writing is fewer bytes (many registers only take 2-byte BE values) then pad it on the right with zeros.

Once you've done a read or write request (well, you should do this before that) watch for notifications on the response characteristic. It has a bunch of values as a prefix, but the result tends to start at byte 8.

Registers

You can e.g., read the light's name by reading register 0x1002. If you happen to have access to the app's source code, you can find the descriptions of additional registers in a file called "ParametersMapCommon.xml".

Done

Write a comment if you're interested in more or just want to say thanks.

@phindmarsh
Copy link

That might have been a temporary state, I’ve got control back via the manual switch now, although there’s a permanently lit green LED in the bottom right quadrant of the dimmer button. I’m presuming thats some kind of indicator for the zigbee status but there’s not a lot of documentation online for the zigbee implementation in these units.

If I get time I’ll try unpack the compliance documentation linked above and see what I can work out from there. Main issue at the moment is it seems like the 12-pushes is a one way trip, and a factory reset doesn’t put it back into non-zigbee mode, at least I haven’t been able to do that. Also seems like once in zigbee mode they can’t be controlled via the Wiser app or the previous BLE interface anymore. I can’t remember if this switch I did this on was on the latest firmware or not before I did it, so gonna try work out how to get that paired again.

@ell249 if you have any links or experience that might help, I’m keen to get to the bottom of this!

@ell249
Copy link

ell249 commented May 6, 2021

@phindmarsh my understanding is it’s 12 presses to go back to BLE but it’s likely the process wipes existing pairings with BLE hosts so you need to re-pair. So delete from your paired device in your phone settings first. But I haven’t tried myself yet. I’ll try and send one back to BLE tonight and let you know. Mine also now are green in the bottom corner which I believe indicates zigbee status. I did take one apart to see the chipset and it’s based on the efr32mg13 SoC which might help you in the data sheet?

@ell249
Copy link

ell249 commented May 6, 2021

@phindmarsh ok so when I factory reset mine (2 quick then one 10+ sec hold) they go back to BLE mode. But had to delete the device from Bluetooth Settings before it would re-pair/connect in the “wiser by se” newer app. Then twelve presses switched them back over to Zigbee but then had to rejoin the hub. They only go green when the hub is scanning, or a new Zigbee device causes them all to scan. It goes away after that. It definitely takes a good few minutes for them to changeover to Zigbee. When you think it’s done it’s not and starts flashing again. 😊 so the no manual control you were experiencing I’d say was during the transition. Hope that helps!

@phindmarsh
Copy link

Ok so after some more tinkering I have them connected to Home Assistant using the ZHA integration (using an electro lama zzh! coordinator). I think the reason it wasn't working earlier was the coordinator I was using wasn't Zigbee 3.0.

I still haven't managed to get it back to "normal Bluetooth mode" even after a factory reset it seems to be in Zigbee mode still. But that's not really a problem because it's connected to the zigbee network now anyway. I'll play some more to work out if I can reset it, because it would still be handy to do OTA updates of the firmware etc via the Wiser app.

Thanks for the tip @ell249, seems like my main issue was an old Zigbee coordinator firmware!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment