cflurin / homebridge-mqtt

Homebridge-mqtt is a Plugin for Homebridge.
Apache License 2.0
229 stars 38 forks source link

Could we add Service to the /from/set Response? #94

Closed mriksman closed 4 years ago

mriksman commented 4 years ago

When I add a new device, I need;

{
  "name":"Name",
  "service_name":"Service Name",
  "service":"Service"
}

To make things... 'dynamic'... in Node-RED, I set the FullTopic in Tasmota to be Name/Service_Name/Service/%prefix% For example Bed Switch and Sensor/Bed Switch/Switch/%prefix% Bed Switch and Sensor/Bed Temperature/TemperatureSensor/%prefix% So now in Node-RED, I can parse the topic, and create the JSON to fill in the required name, service_name and service. Great.

Now I want to capture a command in the Home app and send it to the Tasmota device. I change the switch, and in /from/set/ I see;

{
  "name":"Name",
  "service_name":"Service Name",
  "characteristic":"On",
  "value": true
}

Problem is, I cannot take that and convert it back to the original topic. I am missing service.

Could we please add service to the /from/set/ response? In fact, all responses should include name, service_name, service and characteristic, (where possible) for good measure.

cflurin commented 4 years ago

Hi, I think this could be done. Please provide a PR.

A workaround is to define a global.accessories in node-red (as I do anyway to add the accessories) and retrieve the service from global.accessories.

global.accessories:

{
    "at_home": {
        "name": "at_home",
        "service": "Switch"
    },
    "heating_control": {
        "name": "heating_control",
        "service": "Switch"
    },
    "garden_blind": {
        "name": "garden_blind",
        "service": "WindowCovering",
        "CurrentPosition": {
            "minStep": 10
        },
        "TargetPosition": {
            "minStep": 10
        }
    }
....
}
mriksman commented 4 years ago

Oh yikes. I don’t know how to do a Pull Request... Doesn’t that mean I have to actually write the code myself!? Way over my head :/ I wouldn’t even know where to start...

So are you maintaining your own list to global.accessories variable? Manually? Couldn’t this be lost/screwed up if Node-RED fails/reloads or something? Wouldn’t it be better to get a fresh list using /to/get?

cflurin commented 4 years ago

Well, maybe a developer likes your idea and can do it for you, let's see.

But, keep in mind that there will be something new in the future.

Have a look here: https://www.connectedhomeip.com/

So, maybe homebridge will be obsolete.

As soon as I find some spare time I'll explain how to use global.accessories in node-red.

mriksman commented 4 years ago

Hmmm. I’m too impatient to wait that long :)

Any pointers on what needs to happen to your code to pull off my goal? I’ll have a good hot shot at it. Always up for a challenge.

mriksman commented 4 years ago

I’ll focus around line 230 in Accessory.js Accessory.prototype.get = function(callback, context, displayName, iid) Seems to be where it all begins.

I’m curious though; a general Homebridge/HomeKit question. What actually calls the.get function? What defines those variables callback, context, displayName, iid? Is it the same for every Homebridge plugin; those same variables are sent to the.get function call?

cflurin commented 4 years ago

You'll find more info on the homebridge repository.

It's a while since I developed homebridge-mqtt. As far as I remember I had to expand the API to achieve the flexibility I needed.

See Accessory.prototype.allocate.

mriksman commented 4 years ago

No worries - I JUST then saw Accessory.prototype.allocate is where the magic happens. HomeKit calls these (from Characteristic.ts)

[CharacteristicEventTypes.GET]: (cb: CharacteristicGetCallback, context?: any, connectionID?: string) => void;
[CharacteristicEventTypes.SET]: (value: CharacteristicValue, cb: CharacteristicSetCallback, context?: any, connectionID?: string) => void;

I will have a look and try out a Pull Request. Thanks mate!

cflurin commented 4 years ago

... I had a quick look at it > you can get the service in the function Accessory.prototype.set from service_types:

var a_service = this.service_types[this.name]);
mriksman commented 4 years ago

Legend. Now to work out how best to update the code and do the PR and such

Thanks!

cflurin commented 4 years ago

there are many howtos but generally: