dxdc / homebridge-blinds

:sunrise: Homebridge Plugin to control my blinds over HTTP
https://www.npmjs.com/package/homebridge-blinds
ISC License
54 stars 26 forks source link

Sending exact position in request body #63

Closed codyzu closed 2 years ago

codyzu commented 3 years ago

Hello.

My blinds are controlled with deCONZ and they have a robust REST API. I was able to integrate my blinds into homebridge using the homebridge-hue plugin. However, since my blinds are seen as lights by deCONZ, homebridge-hue, homebridge, and finally homekit... it feels a bit awkward to control them with homekit. So I was trying to test out homebridge-blinds to control the REST API directly.

The blinds support moving to an exact position via the REST API. However, the position is set in the request body, not a query parameter as supported in homebridge-blinds.

I was thinking about how to modify the plugin to support setting the position in the body. I could probably come up with a PR to help.

Here are my ideas for the moment:

Any thoughts before I try to put something together???

dxdc commented 3 years ago

Using jsonata would probably give the most flexibility, since very API may format the body differently

Probably true. However, there are some other simple ways to go about this without necessarily getting too complicated with code editing, if your rest api will work with a 0-100 response.

The other thing that is doable is a simple middleware type application which will receive the request from this plugin and then do whatever you need on the other side. Just a suggestion in case that happens to be easier for your use case.

Still, the relevant section of the code is here:

let shallowObj = Object.assign({}, url);
shallowObj.url = shallowObj.url.replace(exp, pos); 
return shallowObj;

If it's just a simple modification, we could try something like this:

let shallowObj = Object.assign({}, url);
shallowObj.url = shallowObj.url.replace(exp, pos);
if (shallowObj.body) {
    shallowObj.body = shallowObj.body.replace(exp, pos);
}
return shallowObj;

Using jsonata is doable too, but just not sure it's needed in all cases? Probably better to somehow use some kind of different function for replace(exp, pos). I don't think jsonata is really needed here because we're not getting some kind of unexpected json response.

My API does not have specific up and down URLs, instead it just as a set position URL. Is it this due to the way homekit works??? Or is it worth trying to refactor a way to support set position only?

This is due to the fact that many manufacturers provide separate URLs because these are operated by remote only. So, there is an up button and down button. You can use the same URL for each, it won't affect anything.

Lastly, you may want to review #54. Haven't had time to look at this yet.

codyzu commented 3 years ago

Hmmm... that may work. My API takes JSON data, so the replace on a string may or may not work...

If I force the content type header to json and then make the body a string maybe the replace would work and request will still appear as JSON encoded. I guess I was thinking with jsonata it could all be treated as JS objects, but your idea may work and provide a simpler solution :thinking:

I'll do some experimenting...

dxdc commented 3 years ago

You could try something like this as well....

if (shallowObj.body) {
    if (typeof shallowObj.body === 'string') {
        shallowObj.body = shallowObj.body.replace(exp, pos);
    } else {
        shallowObj.body = JSON.parse(JSON.stringify(shallowObj.body).replace(exp, pos));
    }
}
codyzu commented 3 years ago

ah... interesting idea. I'm guessing it won't work because my API expects the position to be a JSON number, so no quotes. My JSON (and homebridge config) won't be valid if I have { "bri": %%POS%% } in the body... :thinking:

I've been reading over #54 and still wondering if this will give me more control over my blinds??? It currently works with the homebridge-hue plugin, but the blinds show up as lights. I'm a bit concerned that this plugin will only present some other side-effects because:

My objective in all of this was to find a way to make my blinds appear as window coverings in homekit. However, I'm really not sure what advantage that will give me over them appearing as lights today. The dedicated stop button is one advantage, but I could probably come up with another solution since my API has a stop URL. What other advantages are there to them being "real" window coverings??? :thinking:

dxdc commented 3 years ago

my API seems to be asynchronous, i.e. it returns immediately after sending the set position request

You may be better off with: https://www.npmjs.com/package/homebridge-mqttthing

You will have to build a small polling app to sync your blinds status w/ MQTT but it may be much easier for you.

the GET position endpoint does not update until the movement is over (i.e., if it is requested while moving, it will show the old position)

This is already handled by this plugin. You set a movement time, and it will not check the status until the expected movement time is over.

What other advantages are there to them being "real" window coverings??? 🤔

You can have them report "in motion" when they are going up / down, and you can set an obstruction detected flag in the case the blinds are moving but should.

There may be some other subtleties, like HK tends to group all lights so you can turn off all your lights at once, for example.

dxdc commented 3 years ago

@codyzu I implemented what you requested a bit of a different way:

You can use { "bri": "%%POSINT%%" } in the body. It will replace the quotes also with just an integer. I hope it solves your issue... would appreciate any feedback you have!

To install:

sudo npm install -g homebridge-blinds@1.3.25-beta.3
# restart homebridge