Code Monkey home page Code Monkey logo

Comments (7)

dgburtonbv avatar dgburtonbv commented on July 22, 2024

Think it might be something todo with these multiple PUT's for Hue and Sat both using different XY co-ords...

image

from homebridge-hue.

dgburtonbv avatar dgburtonbv commented on July 22, 2024

I can work around it by moving the updating of the local hk.hue and hk.sat values to before the PUT request, like this.

Not very elegant but seems to work!

image

from homebridge-hue.

ebaauw avatar ebaauw commented on July 22, 2024

Thanks for your comments!

This looks like an asynchronous execution timing issue: the this.bridge.request callback in setHue comes in after setSat is fired from homekit so setSat computes xy using the old homekit hue value. Recalling a scene or setting a favourite colour probably changes the homekit saturation quicker after changing the hue than the colour wheel does. Group commands to the hue bridge are like 10x more expensive than light commands, so the callback comes later.

Indeed, the structural solution would be to collect the hue and sat changes into one bridge update (and one computation of xy).

Not sure about the (lack of) elegance of your workaround, though. As the homekit value has changed, it seems correct to update homebridge-hue's cache of the homekit state, regardless whether updating the Hue bridge state succeeds or not.

from homebridge-hue.

dgburtonbv avatar dgburtonbv commented on July 22, 2024

Thanks @ebaauw :-)

from homebridge-hue.

ebaauw avatar ebaauw commented on July 22, 2024

"If You're Not Embarrassed By The First Version Of Your Product, You’ve Launched Too Late"

I've been struggling with the homebridge-hue plug-in logic dealing with homekit values vs hue bridge values and how to update these. Just putting down my thoughts, mainly for myself.

The main logic

  • A change to a homekit characteristic value emits a set event, which fires setChar(), which computes the hue bridge value and calls bridge.request().
  • A change to a bridge value is detected by heartbeat() comparing the latest bridge state with the cached value. It then computes the homekit value and calls setCharacteristic().
  • Of course setCharacteristic() causes setChar() to be fired. To prevent the bridge value to be updated again, setChar() checks whether the homekit value has actually changed.

The issue: rounding errors
The conversion from homekit value to hue bridge value back to homekit value might yield a different homekit value, due to rounding errors. So setChar() compares the new value to the homekit value computed from the new bridge value, rather than to the previous homekit value.
This was implemented originally in HueLight.js (long before I put it on GitHub) and is still implemented in HueSensor.js and HueSchedule.js: in the bridge.request() callback, the cached bridge state is updated, and refresh() is called to update the "cached" homekit values, which might differ (slightly) from the actual homekit values.

Colours: worse than rounding errors
For colours, the conversion from homekit value to hue bridge value back to homekit value is way more complex, causing more significant rounding errors. The conversion from Hue and Saturation to xy and back could yield entirely different Hue and Saturation values for out-of-gamut colours. In this case, I want the homekit value to reflect the bridge value, rather than simply ignore some small rounding errors (the same might hold for Color Temperature, due to the huge difference in granularity between ColorTemperature, from 2000K to 6540K, and ct, from 153 to 500).

Colormode
The hue bridge supports three different colormodes: xy, ct, and hs. I only know how to convert the xy values to homekit Hue and Saturation. When setting a light colour on the bridge using ct or hs, the light will actually compute the corresponding xy value, but it takes the bridge up to 30 seconds to update its cache of the light state. So I figured I need to rely on heartbeat() to detect these changes anyway and update the cached homekit value with the new value from homekit, instead of the value computed from the new bridge value. In the process I made two errors:

  • I neglected to update the cached bridge value in the bridge.request() callback (hence the superfluous debug message that the bridge xy value has changed, even through homebridge-hue just made that change itself);
  • I left the update in the bridge.request() callback, where it was originally, without realising this is not the same update (hence the issue that setting group colours might not work correctly). Moving this update before the bridge.request() is the right answer.

Closing remarks

  • I don't like different patterns for the same problem. I planned to change HueSensor.js and HueSchedule.js` to apply the same pattern as HueLight.js, but I got a request to publish homebridge-hue before I got to that.
  • I'm still somewhat worried about causing an infinite update loop where homekit value h1 translates to bridge value b1, which translates to homekit value h2, which translates to bridge value b2, which translates back to homekit value h1. That's why I decided to ignore the rounding errors at first.
  • Then, of course, there's the additional complication that Hue and Saturation are two separate characteristics, but commonly updated together (as Color), and needed together to compute the corresponding bridge value for xy. While inefficient, I'm not sure that the current workaround of doing two consecutive bridge updates will actually be noticeable with the standard transition time.

from homebridge-hue.

ebaauw avatar ebaauw commented on July 22, 2024

@dgburton : I just pushed version 0.0.7 to npm, which, I hope, solved this issue.

from homebridge-hue.

dgburtonbv avatar dgburtonbv commented on July 22, 2024

Thank you!

from homebridge-hue.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.