Send device health info through webhook endpoint

Hi there!
I faced the problem. I can select the device capability healthCheck only using European accounts. When I use my UA account, I cannot select this capability in order to use it in SmartApp.

Also, when I send GET request to the /devices/<deviceId>/health endpoint, I receive information about online/offline status of the device, which is a bit weird:)

The questions are:

  1. Why can I not subscribe to healthCheck capability?
  2. Can I send this information to my webhook endpoint in the SmartApp?

What Iā€™m trying to do is to add a new feature to our app to tell devices are offline. I need to subscribe to HealthCheck capability and use CheckInterval property(I guessā€¦) to ping devices with some frequency. And I want to have these events sent via Webhook endpoint in our SmartApp.

Can someone help me? Tagging @nayelyz
Thanks

Rather than subscribing to the Health Check capability, subscribe to DEVICE_HEALTH.

2 Likes

Hi, @sandra-nestor!

The correct place to get the health status is this endpoint /devices/<deviceId>/health. The healthCheck capability is no longer used to provide this status. It was only used by DTHs which will be deprecated soon.
For Hub-Connected devices that work with Edge drivers, the health check (ping) is handled internally. So, if you subscribe to the event mentioned by @orangebucket, you should get an event in your Webhook indicating if the device changed its state to offline/online.

1 Like

Thank you, @nayelyz @orangebucket! Iā€™ll try that)

Hi @nayelyz @orangebucket, I have successfully subscribed to DEVICE_HEALTH, but I canā€™t understand how it works((

As you can see, I have a 200 response code, so my device_health subscription has definitely been created.

But when my device goes offline, I donā€™t receive any info about the changed device status on my webhook endpoint(but I can see it in the SmartThings app).
I havenā€™t found any docs concerning DEVICE_HEALTH. So should I receive info that the device goes offline immediately? Or are there some settings on how often online/offline status is updated?

And also, I suspect that online/offline status will be provided in the ā€˜EVENTā€™ lifecycle, am I right?

It seems that I found a bug here. When we take out the battery from our motion sensor while it has active motion event, the offline status isnā€™t updated. It remains with ā€˜motion detectedā€™ status, currently for more than an hour:((

These two motion sensors are without batteries, so they are offline. But as you can see, the first one displays incorrect status.

You should receive it once the device is marked offline, did you define the correct event handler? It is different from a capability subscription, its name is subscribedDeviceHealthEventHandler.

Correct, it will tell you the type of event and provide the deviceId involved.

Is it the same in the APIā€™s health endpoint or only in the app?

Thanks for the reply, @nayelyz.

Yes, this was the same in the APIā€™s health endpoint. But today it seems to work fine. The status is updated within 15-20 mins.

We are using only your API, I used this endpoint. Payload:

{
      sourceType: 'DEVICE_HEALTH',
      deviceHealth: {
        subscriptionName: 'device_health_subscription',
        deviceIds: [device_ids]
      }
    }

All event handling we do on our side. And also, we log all events that are coming to our webhook endpoint (before processing it). So Iā€™m 100% sure I donā€™t miss anything.

Ah, ok. Then, it might have been a glitch, you said it is working fine now, right? If the problem persists it would be good to know if the device is handled by a DTH or Edge driver.

No, I havenā€™t received any events from my device_health_subscription yetā€¦
I meant that the offline status is behaving ok in the SmartThings app now. Maybe it was a glitch.

Our devices are handled by Edge drivers. When I make a request to list all subscriptions, I see DEVICE_HEALTH in the list:

{
    "items": [
        {
            "id": "dfca-4237",
            "installedAppId": "eca3d3d5",
            "sourceType": "DEVICE",
            "device": {
                "deviceId": "7843396a",
                "componentId": "main",
                "capability": "*",
                "attribute": "*",
                "value": "*",
                "stateChangeOnly": true,
                "subscriptionName": "button_0_subscription",
                "modes": []
            }
        },
        {
            "id": "d9a75c27",
            "installedAppId": "eca3d3d5-26cd",
            "sourceType": "DEVICE",
            "device": {
                "deviceId": "23c90510",
                "componentId": "main",
                "capability": "*",
                "attribute": "*",
                "value": "*",
                "stateChangeOnly": true,
                "subscriptionName": "contactSensor_0_subscription",
                "modes": []
            }
        },
        {
            "id": "c14198ff",
            "installedAppId": "eca3d3d5",
            "sourceType": "DEVICE",
            "device": {
                "deviceId": "2c5b376",
                "componentId": "main",
                "capability": "*",
                "attribute": "*",
                "value": "*",
                "stateChangeOnly": true,
                "subscriptionName": "motionSensor_0_subscription",
                "modes": []
            }
        },
        {
            "id": "c02a276d",
            "installedAppId": "eca3d3d5",
            "sourceType": "DEVICE",
            "device": {
                "deviceId": "1bc5fcd0",
                "componentId": "main",
                "capability": "*",
                "attribute": "*",
                "value": "*",
                "stateChangeOnly": true,
                "subscriptionName": "motionSensor_1_subscription",
                "modes": []
            }
        },
        {
            "id": "618584d4",
            "installedAppId": "eca3d3d5",
            "sourceType": "DEVICE_HEALTH",
            "deviceHealth": {
                "deviceIds": [
                    "1bc5fcd0",
                    "23c90510",
                    "2c5b376a",
                    "7843396a"
                ],
                "subscriptionName": "device_health_subscription",
                "locationId": "*"
            }
        }
    ],
    "_links": {}
}

So I cannot get it. I have a subscription to devices health. Why events are not coming?((

Have you tried the subscription using the locationId rather than the individual deviceIds?

Hmm, I tried, its not working. I receive 403 response code


The payload is:

{
      sourceType: 'DEVICE_HEALTH',
      deviceHealth: {
        subscriptionName: 'device_health_subscription',
        locationId: location_id
      }
    }

I take the locationId from INSTALL lifecycle data.

Hi, @sandra-nestor.
Indeed using the locationId is better as @orangebucket said. Thereā€™s a limit of 20 DeviceIDs to use in the array of the subscription.
I created the subscription using the SDK and this is what I found getting itā€™s details from the API:

{
    "id": "d9738d37-48a8-4605-...",
    "installedAppId": "b5ccfb08-d26d-4e03-...",
    "sourceType": "DEVICE_HEALTH",
    "deviceHealth": {
        "deviceIds": [],
        "subscriptionName": "healthEventHandler",
        "locationId": "0b018721-6bc0-483c-..."
    }
}

I got health update events of the devices in my location. Are you using the scopes of r:devices:* and r:locations:*?

I think that the problem is in locationId. Devicesā€™ location and the location of installed app could be different, thatā€™s why I receive 403 response when trying to subscribe to device health using locationId. And thatā€™s why I donā€™t receive events from my health subscription when subscribing using deviceIds.

Iā€™ll try to debug this and create a health subscription using locationId. Hope, this will help me) Iā€™ll share my success with you.

1 Like

Hi @nayelyz! Could you please share the script you used to subscribe to the device health events? And could you specify the version of SDK you are using? Is it smartapp-sdk-nodejs version 4.0.0?

Also, Iā€™ve managed to create a subscription to device health using deviceIds, but not locationId. I think that the reason why I receive 403 error for locationId is the problem with auth_token provided by INSTALL lifecycle. It just seems to me that it does not have ā€œr:locations:*ā€ scope. But when creating an app I select all possible scopes:

Hi, @sandra-nestor!
Did you include the scope in the SmartAppā€™s definition? That might be the difference.
When we select them in the Dev Workspace, weā€™re only whitelisting them but not using them directly. The SmartApp definition I used to create a location health subscription is:

app.enableEventLogging().appId("location-room-request")
.permissions([
    "r:locations:*","r:devices:*"
])
.page('mainPage', (context, page, configData) => {
    page.section('sensors', section => {
        //This section doesn't affect the location subscription
    });
})
.updated(async (context, updateData) => {
    await context.api.subscriptions.unsubscribeAll();
    return Promise.all([
        context.api.subscriptions.subscribeToDeviceHealth('healthEventHandler')
    ])
})
.subscribedDeviceHealthEventHandler('healthEventHandler', (context, deviceEvent) => {
    console.log('health event',deviceEvent)
})

Hi, @nayelyz! Thank you so much for your support! One more question. I wasnā€™t able to find a way how to set up additional permissions for a certain installed app using this doc. Is there a way to define these permissions like you did it here:

.permissions([
    "r:locations:*","r:devices:*"
])

via SmartThings API?

For the SmartApp, if you registered it using the Developer Workspace, you only need to select them there to whitelist them.
However, you can change them through the API as well. I suggest you do this carefully as any change you make through the API wonā€™t be shown in the Dev WS.

To do that, you need to follow these steps:

  1. First need to get the Oauth config from the app and copy the result from that query:
    Apps endoint > GET OAuth config
  2. Paste that config into the body of a PUT request to the same endpoint, remember you need to add the redirectURL. For example:
{
    "clientName": "TestSmartApp2023",
    "scope": [
        "r:devices:*",
        "r:locations:*",
        "w:devices:*",
        "x:devices:*"
    ],
    "redirectUris": [
        "https://domain.com"
    ]
}
1 Like