athombv / homey-web-api-issues

This issue tracker is for Homey Developers using the Web API.
4 stars 1 forks source link

api.devices.getDevices() retrieves no new data #20

Closed daneedk closed 1 year ago

daneedk commented 1 year ago

Hi,

My app Heimdall has a function called Pre-Arming check. This function checks the state of motion- and contact sensors before change the Surveillance Mode to an Armed state so the user can be informed on any open windows/doors or movement in the house. For this function I cycle trough all devices and check their states, particularly the alarm_motion and alarm_contact values.

I use this code to get the information from all devices:

   async getDevices() {
        return await this.homeyApi.devices.getDevices();
    }

where homeyApi is available through the following code that's called from the app's onInit()

    async initializeWebApi() {
        this.homeyApi = new HomeyAPIApp({ homey: this.homey });

        await this.homeyApi.devices.connect();
    }

When using athom-api this method worked and I always got(get) realtime device information but when using homey-api this is no longer functioning as before.

Calling getDevices() in homey-api always returns the state from the app's starting point when initializeWebApi was called while using athom-api it always returned realtime information on devices.

To act on changing on a device's state I use device.makeCapabilityInstance('alarm_motion', function(..... (and that works as before) but for this use case I really need te read the information at a specific point in time.

As a sloppy workaround I changed the getDevices() into the code below but this result in executing the new HomeyAPIAPP over and over again and I don't think that's a good thing.

async getDevices() {
        await this.initializeWebApi();
        return await this.homeyApi.devices.getDevices();
    }

I hope this can be fixed. If anything is unclear or you need more information, just let me know

initializeWebApi(): https://github.com/daneedk/com.uc.heimdall/blob/e9f5195f1203e3252e4f3aefda5627f82149bd3b/app.js#L360

getDevices(): https://github.com/daneedk/com.uc.heimdall/blob/e9f5195f1203e3252e4f3aefda5627f82149bd3b/app.js#L367

checkDevicesState(): https://github.com/daneedk/com.uc.heimdall/blob/e9f5195f1203e3252e4f3aefda5627f82149bd3b/app.js#L1023

gruijter commented 1 year ago

I can confirm that homey-api does not provide updates on the capabilitieObj values. In PBTH I need to poll the values every hour. See code here: https://github.com/gruijter/com.gruijter.powerhour/blob/79851a2229370f2c70f2bde0096f46c1f0d76022/drivers/gas/device.js#L73

To mitigate the issue I now do a new getDevice every hour. this.sourceDevice = await this.homey.app.api.devices.getDevice({ id: this.getSettings().homey_device_id, $cache: false, $timeout: 20000 });

And after that collect the capability values from sourceDevice.capabilitieObj . I don't know if overwriting the sourceDevice every hour has any negative impact. It is not as if I can 'destroy' the previous instance. But I also do have capability listeners setup. Those keep working, even when I do a new getDevice, but it is a murky situation for me, and I would rather not have to refetch/overwrite the sourceDevice every hour.

robertklep commented 1 year ago

It looks like enabling realtime device updates (using api.devices.connect()) for some reason also enables caching in getDevices() so you don't get the latest device data.

daneedk commented 1 year ago

With the added information from @gruijter and @robertklep Robert and I did some more testing, here's some observations:

When rewriting from athom-api to homey-api the new relevant code in Heimdall looked like this

image

together with

image

the getDevices() returns an array with the devices that represent the actual status of all devices, so realtime information.

But, problem with this was that the

image

Never got called. (same for the device.create and device.delete variants)

I reported this on slack and was suggested to add await this.homeyApi.devices.connect(); so the initializeWebApi() now looks like this

image

This indeed fixed the problem with the device.update (and device.added and device.delete)

But, now the array returned from the getDevices() function always returned the state from when the initializeWebApi() was called, which only happens at the start of the app, so no realtime information anymore.

I first 'fixed' this by adding await this.initializeWebApi(); to the getDevices() function but changed it later to writing to the capabilitiesObj on receiving capability events in the makeCapabilityInstance functions. This brought back the realtime updates of the needed device capabilities but it's not sure what happens with device going offline or not having a capabilitiesObj

After some more posts on slack and the post here by @gruijter, @robertklep suggested me to try $cache : false in the getDevices() function, I did that and now it looks like this

image

I also disabled the writing to the capabilitiesObj in the makeCapabilityInstance functions.

This seems to fix the problem without using the nasty workarounds! I've done several different tests and all were successful. Tests done by @robertklep confirm this.

So, to conclude, these are the used functions that will give device.update events and realtime information in the devices array returned from the getDevices() function:

image image

@jeroenwienk can you comment on this? Is adding $cache : false to the api.devices.getDevices() command a good an future proof solution?

jeroenwienk commented 1 year ago

Fixed in https://www.npmjs.com/package/homey-api/v/1.10.8