[Release] Philips Wiz Color Light Driver v1.01

This driver allows you to control Philips (Signify) Wiz wifi color bulbs. Since the last version, I've done more digging -- version 1.0 now correctly polls the bulbs for status instead of relying on an external program. If you change light settings with the Wiz app, it will now be reflected on your HE within a few seconds.

You can turn the bulb on/off, control color and color temperature, select from a range of preprogrammed effects, and so forth. It is entirely LAN based. No connection to the Internet is needed for this driver to work. Once you set up the bulbs using the Wiz app, you can firewall them off, uninstall the app, and control them as you like (although you might want to keep the app around -- some configuration is available only via the cloud. See the readme.md for more details.)

I've also added my notes on the Wiz LAN protocol to the repository.

(v1.01 - fixed bug that broke dimming via rule machine)

3 Likes

This means that the bulb is going to send a LAN message to the hub every 5 seconds? So, if you have 10 bulbs, your hub is going to get 120 LAN messages every minute? That is going to be more than the hub is going to be able to handle.

Yeah, that's what i thought too. Thus the Python program, which maintains the last known state for all active bulbs, and allows the Hub to query at its leisure. I have very mixed feelings about these bulbs.

On the one hand, they're cheap, have a decent feature set and come in a lot of interesting form factors. On the other, they're tethered to a huge, intrusive cloud architecture, and they don't respect local bandwidth at all. Fill a house with these things, and your LAN will be um... busy. (This device handler of course, only generates traffic when you're actively working with the bulb. But if the bulbs have access to the Internet, they still periodically phone home.)

I've given a couple to a friend with a small office who wanted something to decorate his reception area. It's easy to configure, easy to run, and two bulbs in a commercial setting can't do much harm. But after I'm done playing, if it's possible, I'm going to flash mine to Tasmota or ESPHome. Don't want to get on the soapbox about this here but, I'm definitely not a fan of cloud dependency.

I would highly, HIGHLY doubt that Phillips is using an ESP module for their bulbs. They are most likely using a custom firmware with a chip that is not available off the shelf. They have no reason to pay the higher price for a Tuya module.

The teardown here:

Pwn the WIZ connected - LimitedResults

says it's an ESP-WROOM-02, which can be read/flashed with esptool. I've got a spare bulb that I'm going to open shortly. If nothing else, looking at the strings in the firmware may show a few more commands and parameters that aren't used by the app.

If you're going to flash it with custom firmware, why spend the money for a Wiz bulb and just buy a Tuya bulb instead?

You're right, of course. If I really wanted WiFi bulbs, Tuya is the better option.

I got these bulbs at Home Depot at the (quite low) introductory price. They're completely an experiment - my house is all Zigbee and custom devices of various flavors, and I wanted to see what a commercial WiFi smarthome product was like.

There have been a lot of them lately, and it seems like, despite the drawbacks, they're winning the battle for consumer attention. A Philips-backed product seemed a reasonable place to start. (Of course, Philips didn't develop the product, they just purchased the company. I'd expect better integration with the rest of their lineup over time, but at this point, it's a pretty standard Chinese LED bulb, for good or ill. )

I’ve got a driver in my GitHub repo that sends/receives raw UDP packets. 5s shouldn’t be bad, I’ve pushed mine to 1s before and, while data can get jumbled, it’s manageable by the hub for some time.

If you’d like, feel free to take a look :slight_smile: Those drivers are the WiOn/Woods ones.

Thanks for the info. I'm going try out the bulb.

So I can better understand them do you have a pointer to any documentation (official or otherwise) on the LAN protocol?

The problem with Tuya is that it's a challenge to ferret out the keys to use my own apps. Do you have a good way to open up Tuya devices short of reflashing?

All the documentation I've used or made is listed in the credits section of readme.md in the device handler's github repository.

As far as I know, there's nothing official yet. It's pretty much just source code, in a variety of languages.

The LAN protocol is clear text json over datagram, with commands sent over one port and a status heartbeat from the bulb sent over another. The cloud portion is probably mqtt, though since I have mine firewalled off from the internet, I haven't put much work into decrypting it.

I've installed it and it works. I did look at the documentation and appreciate the effort it took to ferret it out from the pieces here and there and I'm looking at your code. I was just hoping there was a simple documentation of the UDP packet formats in one place including what to listen for.

All that said, I'm pleased to see them moving from Zigbee to IP and, at least for now, at a lower price!

Here are my somewhat arbitrary notes on the protocol. Hope it helps -- I'm glad to answer any questions too!

To issue a command to the bulb, send a json packet to the bulb's command port (38899)
The bulb will immediately respond on the same port with a json packet confiming the command and
indicating success or failure.

The key pieces of the command packet are the "method" section, and the "params" section. "Methods" are
commands and "params" are arguments. Described below are the methods discovered thus far:


registration
"register" with the bulb so that it will send you status updates on port 38900
at about 1 per second for the next 20 seconds or so.
Example:
{"method": "registration", "id": 1, "params": {"phoneIp": "10.0.0.xxx", "register": true, "homeId": xxxxxx, "phoneMac": "macxxxxxx"}}

pulse
causes the light to "pulse" brightness by the specified amount over the specified number
of milliseconds.
Example:
{"method": "pulse", "id": 22, "params": {"delta": -30, "duration": 900}}

setPilot
Set bulb parameters - color, color temperature, state, preset, etc.
Example:
To turn the bulb "on"
{"method": "setPilot", "id": 24, "params": {"state": 1}}
(see source code for lots of "setPilot" examples)

To receive status heartbeat packets, issue a "registration" command via port 38899, and
listen on port 38900. After registering, the bulb will send you status updates for
about the next 20 seconds. To keep recieving updates, register again.

The status packets are json-formatted and may contain the following items:

method     - method will be "syncPilot" for heartbeat packets
id         - packet sequence number.  Far as I can tell, any integer will work
mac        - The MAC address of the bulb
rssi       - The bulb's WiFi signal strength
src        - The "source" of a command, "udp" or "hb" <purpose unknown>
mqttCd     - boolean <purpose unknown>
state      - boolean on/off state of the bulb
sceneId    - integer identifier for lighting preset
play       - boolean <purpose unknown>
speed      - animation speed for dynamic presets
r          - (0-255) red channel
g          - (0-255) green channel
b          - (0-255) blue channel
c          - (0-255) cool white channel? <not yet tested>
w          - (0-266) warm white channel? <not yet tested>
temp       - color temperature
dimming    - (0-100) brightness channel 
schdPsetId - preset schedule?   <not tested>
fwVersion  - firmware version number

A typical syncPilot packet looks like this:
{"method": "syncPilot", "id": 219, "env": "pro", "params":{ "mac": "bulbMac", "rssi": -72, "src": "hb", "mqttCd": 0, "state": true, "sceneId": 0, "temp": 3362, "dimming": 69, "schdPsetId": 5}}

Thanks! (Or I think thanks -- I don't really need another distraction and this makes it so tempting).

I know exactly what you mean!

I've just updated the driver to v1.0 -- was finally able to figure out how to properly poll status, so it will now stay consistent if people are changing settings with the Wiz app, no python daemon running on the inevitable always-on Linux box required! :slight_smile:

Thanks - I was just starting to give into temptation but if you're reporting status and I get notifications then there is little value for me to add. And it's a step ahead of the Philips Hu which will report a bulb as being on even if it's in my pocket.

Will update.

I got setPilot to work but when I send

 {"method":"registration","id":1,"params":{"phoneIp":"192.55.226.39","register":true,"homeId":"WizHome","phoneMac":"10:c3:7b:6b:d7:09"}}

I get

 {"method":"registration","id":1,"env":"pro","error":{"code":-32600,"message":"Invalid Request"}} ({"address":"192.55.227.200","family":"IPv4","port":38899,"size":96}

Thoughts?

A couple of thoughts...

First, the homeID isn't necessary for local control. You can leave it out. But it would be a large (6 or 7 digit) integer, assigned by the Wiz cloud at home creation time, not a string. I can't find a way to get the Wiz app to cough it up now, though I'd swear an earlier version displayed it. Certainly it shows up in packet captures.

Also, I don't know how good the address parser in the bulbs is, but I've been sending MAC addresses without the colons.

For reference, here's the registration packet I'm using in my Python test app:

{"params":{"phoneIp":"192.168.1.21","phoneMac":"0BADDEADBEEF","register":true},"id":10,"method":"registration"}                                              

(the order of the parameters doesn't seem to matter.)

Thanks! Eliminating the homeID and setting the MAC address to upper ace and removing the :'s did the track! At this point it is so trivial almost not worth making it npm module.

BTW, for Hubitat, any progress on getting the MakerAPI to send notifications as it does for other devices? For now I can work-around it by using my own app to listen.

Just remembered. If you don't want to mess around with registration and syncPilot packets, you can use the getPilot method. It immediately returns a packet with the bulb's current status. Check the protocol notes in the repository for a description -- the Wiz app doesn't use this method, so I didn't know it existed 'till a couple of days ago.