peter-murray / node-hue-api

Node.js Library for interacting with the Philips Hue Bridge and Lights
Apache License 2.0
1.19k stars 145 forks source link

[Enhancement] Control presence sensor state #136

Closed foxriver76 closed 4 years ago

foxriver76 commented 4 years ago

In the API it is possible to switch on/off a presence sensor to deactivate its functionality.

peter-murray commented 4 years ago

It is provided it is a CLIP sensor type. You can perform an update to the sensor attributes. It is expose under sensors.updateSenorState().

There is an example in the test suites https://github.com/peter-murray/node-hue-api/blob/master/lib/api/Sensors.test.js#L208

I can see that I have pending documentation on this, so will get that sorted in the next few days.

foxriver76 commented 4 years ago

Thanks for clarification. Including it into the docs would be awesome. ;-)

foxriver76 commented 4 years ago

@peter-murray I got another question, because I can't find an example. How can I simply activate a scene with v3. With v2 it was just api.activateScene(id).

Thanks for your help

peter-murray commented 4 years ago

The scene activation is really a feature of the groups API, it has been ever since it groups were introduced.

groups.setGroupState() is the API call you want, https://github.com/peter-murray/node-hue-api/blob/master/docs/groups.md#setgroupstate

You can provide the scene identifier in the GroupLightState object.

The lights that will activate the scene are the intersection of the group light members and those of the scene with the specified scene id. So to ensure you target all the lights in the stored scene you can use the all lights group, group id 0.

Scenes are a bit of a weird thing in the underlying Hue API as it has matured and groups are generally easier to use that scenes, as these have to be pre-stored where as if you are building a software solution you can more easily build a light state payload and specifically target an existing group. The only benefit to the Scenes these days is the ability to share them across the whole Hue eco system, i.e your custom software, iOS application, etc...

peter-murray commented 4 years ago

If you think it would be beneficial, I could look to add in an "activate" for a scene in the API that effectively does the heavy lifting of the group setState() call.

foxriver76 commented 4 years ago

Thank you so much for your detailed answer. Works exactly like you've described it. It would be good to explain how to turn on a scene in the related Readme part or providing the helper function like in v2 would also be a good thing.

peter-murray commented 4 years ago

I will get on to that tomorrow, thanks for the feedback

peter-murray commented 4 years ago

The activateScene(id) function has now been added to version 3.3.0 and the documentation updated

foxriver76 commented 4 years ago

Great. Thanks.

I finally tried to implement the sensor example. But my users are not able to turn on/off a presence sensor. (Unfortunately I don't own a sensor).

const sensor = await api.sensors.get(sensorId);
sensor.on = state.val; // try to turn off sensor
api.sensors.updateSensorState(sensor);

this results in

Error: parameter, presence, is not modifiable

I only have the virtual daylight sensor of the bridge. Stringified it looks like

{"_rawData":{"state":{"daylight":null,"lastupdated":"none"},"config":{"on":true,"configured":false,"sunriseoffset":30,"sunsetoffset":-30},"name":"Daylight","type":"Daylight","modelid":"PHDL00","manufacturername":"Philips","swversion":"1.0"},"_id":1,"_type":"Daylight","_configAttributes":{"on":false,"configured":false,"sunriseoffset":30,"sunsetoffset":-30},"_stateAttributes":{"daylight":null,"lastupdated":"none"}}

I also tried to modify on states inside the json and tried to set it again but this also results in a similar error as above.

peter-murray commented 4 years ago

The only sensors that you can modify are CLIP based ones, the others are hardware based sensors, that work over the Zigbee protocol.

Things like IFTTT and some of the advanced hue labs stuff that you can apply to your Hue environment will create these CLIP based sensors so that they can post changes to the Bridge.

You can effectively create a CLIP based sensor for presence and then you will be in control of the presence state. Using that you would then be able to trigger a scene or group off changes to that using Rules.

foxriver76 commented 4 years ago

Not sure if this is what I am searching for. I don't want to set the presence state, only the on of an original Hue presence sensor. According to some users this is possible in some apps. So when the sensor is turned off, it wont detect any presence.

It seems like your example is more from the view of programming a own sensor which will work with Hue.

peter-murray commented 4 years ago

The library does a standard call to the bridge, there are no other API s for setting values other than update state or update config. The bridge is the thing that enforces what can and cannot be written to.

In this case though, the library will be sending all the state or config attributes to the bridge for the sensor. If it is true that you can modify only one of the state values, but not others, then that would be the source of this issue (if that state value is modifiable under the current version of the bridge firmware).

I no longer have one of these sensors, or access to one.

Can you provide me with the data for the sensor and the config or state variable you are trying to modify. If I have that, I can make some modifications and issue you with a modified version to test against, before I make an official released change.

peter-murray commented 4 years ago

I managed to find some documentation on the ZLL Presence - Hue Motion Sensor and the on value for it is not a state value, it is a config value.

Looking back at the code sample you posted, it is calling updateSensorState() which will not work as the states are controlled via the hardware.

You need to call the updateSensorConfig() function as that is where the on configuration value you are appear to be looking for should be stored. You can check this from the toStringDetailed() information you get from the Sensor from the Bridge.

foxriver76 commented 4 years ago

Should be config.on


 {"_rawData":{"state":{"presence":false,"lastupdated":"2019-10-17T14:47:09"},"swupdate":{"state":"noupdates","lastinstall":"2019-03-11T13:39:24"},"config":{"on":true,"battery":100,"reachable":true,"alert":"none","ledindication":false,"usertest":false,"sensitivity":2,"sensitivitymax":2,"pending":[]},"name":"Küche Sensor","type":"ZLLPresence","modelid":"SML001","manufacturername":"Philips","productname":"Hue motion sensor","swversion":"6.1.1.27575","uniqueid":"00:17:88:01:03:29:d9:8a-02-0406","capabilities":{"certified":true,"primary":true}},"_id":13,"_type":"ZLLPresense","_configAttributes":{"on":true,"battery":100,"reachable":true,"alert":"none","ledindication":false,"usertest":false,"sensitivity":2,"sensitivitymax":2,"pending":[]},"_stateAttributes":{"presence":false,"lastupdated":"2019-10-17T14:47:09"}}```
foxriver76 commented 4 years ago

I will try that later. Thank you

peter-murray commented 4 years ago

So in your case you will want to call:

sensor.on(true); or sensor.on(false); on the sensor object you have from the bridge, that will set the configuration attribute of the sensor.

Once that is done, you just need to call the sensors.updateSensorConfig(sensor) and it will post the change back to the bridge. If that config parameter can be modified, then it should take.

The library will post all the config back to the bridge, so it might generate an error if one or more of those configuration values are not modifiable, but it should be ok.

foxriver76 commented 4 years ago

Thanks I will give it someone to test. Guess it has to be sensor.on = true (or editing sensor.config.on ?) like in my first example, because sensor Object has no on method.

foxriver76 commented 4 years ago

And another problem appeared while porting the code to v3. With the old API I could also turn Osram Smart Plugs on and off. When trying this with v3:

const lightState = new v3.lightStates.LightState();
lightState.on(true);

await api.lights.setLightState(idOfOsramPlug, lightState);

results in Error: Unknown type, On/Off plug-in unit

Do you have any idea how to implement it with the new version?

peter-murray commented 4 years ago

Can you provide the result from getting the Light object with that id, as the code now builds up an Object representation and it performs some matching against the model ids and other metadata that is provided.

The older v2 version of this basically just gave you the JSON back so it could support anything, whereas now I need to match things to a type of Device Object.

I don't have any non-hue based devices, so this has not been tested out, so clearly I have missed something here.

foxriver76 commented 4 years ago

I have some Ikea Tradfiri light bulbs which are working fine. But many people of our community are using the Osram smart plugs, I found an old one in my boxroom and paired it. The JSON looks like this:

"22":{"state":{"on":false,"alert":"select","mode":"homeautomation","reachable":false},"swupdate":{"state":"notupdatable","lastinstall":"2019-10-17T17:15:22"},"type":"On/Off plug-in unit","name":"On/Off plug 1","modelid":"Plug 01","manufacturername":"OSRAM","productname":"On/Off plug","capabilities":{"certified":false,"control":{},"streaming":{"renderer":false,"proxy":false}},"config":{"archetype":"classicbulb","function":"functional","direction":"omnidirectional"},"uniqueid":"84:18:26:00:00:0e:c7:3a-03","swversion":"V1.04.12"}
peter-murray commented 4 years ago

I just released version 3.3.1 to add support for the On/Off type, so hopefully that will sort out your issues there.

foxriver76 commented 4 years ago

Works, thank you.