Skip to content

Instantly share code, notes, and snippets.

@samthor
Last active September 23, 2021 03:59
Show Gist options
  • 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

Just wanted to say thanks for this, awesome work.

I had struggled with this as I’m pretty new to BLE, but this makes a bunch more sense now!

@samthor
Copy link
Author

samthor commented Apr 7, 2021

No worries @phindmarsh. I only (partially) bought these switches because I saw folks like you had posted code snippets, so I knew they could be controlled remotely somehow.

@ell249
Copy link

ell249 commented May 5, 2021

Just a sneaky tip @samthor and @phindmarsh as I have also been following this here and on the other discussion thread for some time. Even adapted the code you wrote to work on an ESP32 microcontroller to run my lights with Home Assistant. However - hot tip - if you have newish firmware and you push the button 12 times they go through a process which swaps them over to Zigbee. Push the button 3 times to put it in pairing mode, and they're detected by my non-Clipsal hub first go. Did the same on the other 5 or so in my house and all working. Good luck guys - see how it goes for you - and really appreciate your effort.

@phindmarsh
Copy link

@ell246 thanks so much for that, I had seen that zigbee was referenced in places but never worked out if the support was 'real'.

What hub do you use? I have a zigbee2mqtt hub running and it detects the dimmers but they aren't supported automatically. Also seems after pushing the button 12 times the manual control of the lights no longer works! Did you happen to have any docs on how the zigbee support works, or did you just stumble on the 12 button press thing?

In any case, this is definitely an excellent tip and will make integrating them into HA soooo much easier (once I can work out the support part!).

@ell249
Copy link

ell249 commented May 5, 2021

I have the Samsung SmartThings v2 hub - which I’ll admit probably wasn’t my first choice as HA integration requires a few things. Manual control definitely works on mine. It did take a minute or so for the switch to reconfigure after the first changeover before it worked again. I heard about it from a Clipsal rep but it’s also in the latest install leaflet on the website now that Clipsal have released their own Wiser Zigbee Hub.

@phindmarsh
Copy link

Do you know if there's a way to switch them back? I can't seem to get the one that I have converted to show up in the Wiser app anymore, and since I'm gonna need to do some integration work for zigbee2mqtt it would be good to be able to manually control it for now.

Seems like the factory reset doesn't restore it back to the non-zigbee firmware, or the restore procedure is different under the zigbee process.

Also found this which I haven't had time to pull apart yet on whether this will help with the integration: https://zigbeealliance.org/zigbee_products/wiser-40-300-series-module-switch-10a/

@samthor
Copy link
Author

samthor commented May 6, 2021

Also seems after pushing the button 12 times the manual control of the lights no longer works!

That's a bit concerning.

I'm super interested to hear y'all you go with Zigbee support, although I have built my own BLE solution using a PyBoard running a bunch of hacked up Python code. So I'm probably not going to switch. I also got all my CLP's for about $50 each off eBay so buying more at RRP of $150 isn't that appealing...

@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