plasticrake / homebridge-tplink-smarthome

TP-Link Smarthome Plugin for Homebridge
MIT License
480 stars 69 forks source link

[LB120] Trying to set "color", fails with "No response" #32

Closed marinasundstrom closed 7 years ago

marinasundstrom commented 7 years ago

I've recently got a LB120. I configured and tried to set the "color" (actually the color temperature) in the Home app. It failed and I got "No response", and this is what my log says happened:

Oct 08 11:48:38 raspberrypi homebridge[3923]: [2017-10-8 11:48:38] [TP-Link] { ResponseError:  {"err_code":-10000,"err_msg":"Invalid input argument"}
Oct 08 11:48:38 raspberrypi homebridge[3923]: at processResponse (/usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:230:11)
Oct 08 11:48:38 raspberrypi homebridge[3923]: at /usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:59:21
Oct 08 11:48:38 raspberrypi homebridge[3923]: at Generator.next (<anonymous>)
Oct 08 11:48:38 raspberrypi homebridge[3923]: at step (/usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:3:191)
Oct 08 11:48:38 raspberrypi homebridge[3923]: at /usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:3:361
Oct 08 11:48:38 raspberrypi homebridge[3923]: at <anonymous>
Oct 08 11:48:38 raspberrypi homebridge[3923]: at process._tickCallback (internal/process/next_tick.js:188:7)
Oct 08 11:48:38 raspberrypi homebridge[3923]: name: 'ResponseError',
Oct 08 11:48:38 raspberrypi homebridge[3923]: response: { err_code: -10000, err_msg: 'Invalid input argument' } }
marinasundstrom commented 7 years ago

Some more from the logs:

Oct 08 16:04:50 raspberrypi homebridge[30066]: { transition_light_state: { ignore_default: 1, transition_period: 0, color_temp: 400 } } }
Oct 08 16:04:50 raspberrypi homebridge[30066]: [2017-10-8 16:04:50] [TP-Link] [Sovrumslampa] setLightState
Oct 08 16:04:50 raspberrypi homebridge[30066]: [2017-10-8 16:04:50] [TP-Link] { ResponseError:  {"err_code":-10000,"err_msg":"Invalid input argument"}
Oct 08 16:04:50 raspberrypi homebridge[30066]: at processResponse (/usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:233:11)
Oct 08 16:04:50 raspberrypi homebridge[30066]: at /usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:60:21
Oct 08 16:04:50 raspberrypi homebridge[30066]: at Generator.next (<anonymous>)
Oct 08 16:04:50 raspberrypi homebridge[30066]: at step (/usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:3:191)
Oct 08 16:04:50 raspberrypi homebridge[30066]: at /usr/lib/node_modules/homebridge-hs100/node_modules/hs100-api/lib/device.js:3:361
Oct 08 16:04:50 raspberrypi homebridge[30066]: at <anonymous>
Oct 08 16:04:50 raspberrypi homebridge[30066]: at process._tickCallback (internal/process/next_tick.js:188:7)
Oct 08 16:04:50 raspberrypi homebridge[30066]: name: 'ResponseError',
Oct 08 16:04:50 raspberrypi homebridge[30066]: response: { err_code: -10000, err_msg: 'Invalid input argument' } }
Oct 08 16:04:50 raspberrypi homebridge[30066]: Sun, 08 Oct 2017 16:04:50 GMT Accessory [Homebridge] Error setting Characteristic "Color Temperature" to v...rgument"}
Oct 08 16:04:50 raspberrypi homebridge[30066]: Sun, 08 Oct 2017 16:04:50 GMT EventedHTTPServer [::ffff:192.168.1.65] HTTP Response is finished

I'm currently debugging the code.

marinasundstrom commented 7 years ago

The problem is that the bulb expects a value in Kelvin (K) within the range 2700K-6500K, but HomeKit handles values in reciprocal Mega Kelvins, or the mirek scale.

Conversion of color temperature from mirek to Kelvin is required before sending to the bulb, and the reverse when getting the values from the device.

http://www.tp-link.com/us/products/details/cat-5609_LB120.html

marinasundstrom commented 7 years ago

My hack (temporary)

In "device.js" (hs100-api):

const mired = require('mired');

... // Omitted code

setLightState(options) {
    var _this2 = this;

    return _asyncToGenerator(function* () {
      let state = {};
      state.ignore_default = options.ignore_default || 1;
      state.transition_period = options.transition_period || 0;
      if (options.on_off !== undefined) state.on_off = options.on_off;
      if (options.mode !== undefined) state.mode = options.mode;
      if (options.hue !== undefined) state.hue = options.hue; // hue: 0-360
      if (options.saturation !== undefined) state.saturation = options.saturation; // saturation: 0-100
      if (options.brightness !== undefined) state.brightness = options.brightness; // brightness: 0-100
      if (options.color_temp !== undefined) state.color_temp = 
Math.round(mired.miredToKelvin(options.color_temp)); // temperture: 0-7000

The color palett in the Home app allows for choosing values that, when converted, are out of range (outside 2700K-6500K).

plasticrake commented 7 years ago

Thanks for the info, I'll take a look at this further and update!

plasticrake commented 7 years ago

I made some updates in 3.5.0 to use mired. Please reopen a new issue if you're still having problems. Thanks!

marinasundstrom commented 7 years ago

Thanks, @plasticrake ! It works much better than my hack. :)

Just to warn you: I'll have to file another bug for RGB LEDs. They do not behave well in the Home app using the color picker. I'm going to investigate it further while reading the spec.

plasticrake commented 7 years ago

What behavior are you seeing? As far as I can tell the Hue (0-360) and Saturation (0-100) values should match up with HomeKit. The only thing about HomeKit is each parameter is sent separately (at least Homebridge provides them separately to the plugin), so when you change the color it changes Hue, then it sends a separate request for Saturation (not sure the order). I'd like to change this to queue the events when they are close together only send one command to the bulb with both parameters. I don't have a bulb to test so I'm not sure if that behavior is an problem.

Note that you can see the actual commands sent to the bulb if you start homebridge in debug mode homebridge -D. You can also use the hs100-api command line tool to send raw commands to the bulb to test. If you can figure anything out I'd love to be able to fix!

marinasundstrom commented 7 years ago

OK. The color picker does not work anyway. Only the temperature picker does.

I’m going to look into it this weekend.

marinasundstrom commented 7 years ago

@plasticrake, In the HAP spec (8.107 Color Temperature):

If this characteristic (Color Temperature) is included in the Lightbulb (page 217), Hue (page 151) and Saturation (page 159) must not be included as optional characteristics in Lightbulb (page 217). This characteristic must not be used for lamps which support color. This characteristic requires iOS 10.3.

plasticrake commented 7 years ago

Yeah I read some discussion about that and I heard its okay for them to coexist if you do it right. I just did some testing with my simulator; one thing I'm not sure about is if you send hue/saturation to the LB130 do you have to zero out the color_tempas well or does that cause part of the issue? I could make sure then when color_temp is sent we zero out hue/sat and vice-versa. Again since I don't have a bulb I'm not sure which is the right approach.

Can you try this:

example:

mess around changing hue saturation color_temp in different orders and then run after each command:

If you tell me then when you change the hue that is removes an existing color_temp or sets to 0 and vice-versa I can update my simulator to match that behavior and I can test the rest on my end.

I found this post very helpful when I was implementing this: www.briandorey.com/post/tp-link-LB130-Smart-Wi-Fi-LED-Bulb-Python-Control

plasticrake commented 7 years ago

Annnnnd I just broke down and ordered an LB130 from amazon... will be here Sunday. 😵

plasticrake commented 7 years ago

@robertsundstrom Got my bulb, and I think I've figured it out. The bulb doesn't clear the hue/sat values when color_temp is set. And when color_temp > 0 it always shines as the white color regardless of whatever hue/sat values you throw at it. It only shows the hue/sat color mode when color_temp is 0.

So I'll have to change this plugin to ignore the hue/sat reported by the bulb when color_temp >0. and when a hue/sat value is changed to set the color_temp of the bulb to 0.

plasticrake commented 7 years ago

Seems to be working pretty well with the bulb I have. Have you had a chance to upgrade and try it out?

marinasundstrom commented 7 years ago

@plasticrake I've just updated and tested it. Yes, it works!

There is still an issue with the "color temperature" jumping when picking an invalid value, but it is acceptable now when setting color is working.

Good job! Thank you very much! :)

plasticrake commented 7 years ago

By invalid value do you mean a color temperature out of range for your bulb? I have code that should be setting the min/max acceptable values for LB120 vs LB130. Let me know if you find anything, on my LB130 I didn't see any issues.

      case (/LB130/i).test(this.sysInfo.model): return { min: 2500, max: 9000 };
      default: return { min: 2700, max: 6500 };
let {min, max} = bulb.getColorTemperatureRange;
        .setProps({
          minValue: Math.ceil(kelvinToMired(max)), // K and Mired are reversed
          maxValue: Math.floor(kelvinToMired(min))  // K and Mired are reversed
        });