ST-Schema cloud connector example not working

I’m trying to write a cloud connected smartthings device using st-schema in nodejs. I set up the example and it adds the device to my smartthings app. However it doesn’t seem to update correctly, it gives the error “This device hasn’t updated all of its status information yet. Check again later” its state is also empty, when it should have a starting state as defined in the code.

I am using the following code for the connector:

const { SchemaConnector, DeviceErrorTypes } = require('st-schema')
const deviceStates = { switch: 'off', level: 100 }
const connector = new SchemaConnector()
    .discoveryHandler((accessToken, response) => {
        response.addDevice('external-device-1', 'Test Dimmer', 'c2c-dimmer')
            .manufacturerName('Example Connector')
            .modelName('Virtual Dimmer');
    })
    .stateRefreshHandler((accessToken, response) => {
        response.addDevice('external-device-1', [
            {
                component: 'main',
                capability: 'st.switch',
                attribute: 'switch',
                value: deviceStates.switch
            },
            {
                component: 'main',
                capability: 'st.switchLevel',
                attribute: 'level',
                value: deviceStates.level
            }
        ])
    })
    .commandHandler((accessToken, response, devices) => {
        for (const device of devices) {
            const deviceResponse = response.addDevice(device.externalDeviceId);
            for (cmd of device.commands) {
                const state = {
                    component: cmd.component,
                    capability: cmd.capability
                };
                if (cmd.capability === 'st.switchLevel' && cmd.command === 'setLevel') {
                    state.attribute = 'level';
                    state.value = deviceStates.level = cmd.arguments[0];
                    deviceResponse.addState(state);

                } else if (cmd.capability === 'st.switch') {
                    state.attribute = 'switch';
                    state.value = deviceStates.switch = cmd.command === 'on' ? 'on' : 'off';
                    deviceResponse.addState(state);

                } else {
                    deviceResponse.setError(
                        `Command '${cmd.command} of capability '${cmd.capability}' not supported`,
                        DeviceErrorTypes.CAPABILITY_NOT_SUPPORTED)
                }
            }
        }
    });

module.exports = connector

and the following code for the server

require('dotenv').config()

const express = require('express');
const connector = require('./connector');
const server = express();
const port = 4040
server.use(express.json());

server.post('/', (req, res) => {
    if (accessTokenIsValid(req)) {
        connector.handleHttpCallback(req, res)
    }
});

function accessTokenIsValid(req) {
    // Replace with proper validation of issued access token
    if (req.body.authentication.token) {
        return true;
    }
    res.status(401).send('Unauthorized')
    return false;
}

server.listen(port, "0.0.0.0");
console.log(`Listening on port ${port}`)

Hi @merrychrysler Welcome to SmartThings Community
Let me check. I noticed that you forgot to declare cmd with const, which may be causing a reference error.

for (const cmd of device.commands) 

After sending the request from the mobile app, did you see any errors in your connector logs?

I just tried declaring cmd as const but it doesn’t make a difference. I don’t see any errors in the connector logs, just seemingly normal responses when enabling event logging. Interacting with the device in the mobile app doesn’t give any output. I can’t interact in any other way than in the devices overview either, as the device details screen is completely disabled and only gives the “this device hasn’t updated its status information yet” error. Trying to turn off the device from the overview just seems to load for a while until giving up.

@merrychrysler I took some time to test the code that you shared but I couldn’t reproduce the error, I noticed that the Android screenshot is displayed on a different device that is created on the discoveryHander

.discoveryHandler((accessToken, response) => {
        response.addDevice('external-device-1', 'Test Dimmer', 'c2c-dimmer')
            .manufacturerName('Example Connector')
            .modelName('Virtual Dimmer');
    })

This is the c2c-dimmer profile that has switch and switchLevel capabilities. However, your device only has the switch capability. Is the device in the screenshot the same as on the connector, or are you using another connector?

{
    "id": "8c78413a-09d0-39f7-b92c-988fad1548a2",
    "name": "c2c-dimmer",
    "metadata": {
        "vid": "SmartThings-smartthings-c2c-dimmer",
        "mnmn": "SmartThings"
    },
    "migrationStatus": "NOT_MIGRATED",
    "status": "PUBLISHED",
    "preferences": [],
    "components": [
        {
            "label": "main",
            "id": "main",
            "capabilities": [
                {
                    "id": "switch",
                    "version": 1,
                    "ephemeral": false
                },
                {
                    "id": "switchLevel",
                    "version": 1,
                    "ephemeral": false
                },
                {
                    "id": "refresh",
                    "version": 1,
                    "ephemeral": false
                },
                {
                    "id": "healthCheck",
                    "version": 1,
                    "ephemeral": false
                },
                {
                    "id": "synthetic.lightingEffectFade",
                    "version": 1,
                    "ephemeral": false
                }
            ],
            "categories": []
        }
    ],
    "owner": {
        "ownerType": "IMPLICIT",
        "ownerId": "44"
    }
}

Sorry for the slow response, I’ve had a bit of a busy week. I must have accidentally attached the wrong screenshot, I am only using one connector, the dimmer. It gives the same error and both the on/off switch and the dimmer level slider are greyed out.

No problem, it seems like there’s an issue with the initial values of your device. However, if you are using the following code, it should work correctly.

.stateRefreshHandler((accessToken, response) => {
        response.addDevice('external-device-1', [
            {
                component: 'main',
                capability: 'st.switch',
                attribute: 'switch',
                value: deviceStates.switch
            },
            {
                component: 'main',
                capability: 'st.switchLevel',
                attribute: 'level',
                value: deviceStates.level
            }
        ])
    })

it’s strange I copied your code and work correctly, so, can you see the interaction result on your logs related to this interaction type?

I get logs for the discovery response, however, when I try to interact with the device from my phone it simply hangs on the spinner around the power button indefinitely.

Listening on port 4040
(node:24192) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
REQUEST {
  "headers": {
    "schema": "st-schema",
    "version": "1.0",
    "interactionType": "grantCallbackAccess",
    "requestId": "6a4d2dff-81d2-446b-84ac-78c3379b289d"
  },
  "authentication": {
    "tokenType": "Bearer",
    "token": "<token>"
  },
  "callbackAuthentication": {
    "grantType": "authorization_code",
    "scope": "callback-access",
    "code": "<code>",
    "clientId": "764fff1d-846f-41c7-9de8-d3e617fdc1a1"
  },
  "callbackUrls": {
    "oauthToken": "https://c2c-eu.smartthings.com/oauth/token",
    "stateCallback": "https://c2c-eu.smartthings.com/device/events"
  }
}
RESPONSE {
  "headers": {
    "schema": "st-schema",
    "version": "1.0",
    "interactionType": "grantCallbackAccess",
    "requestId": "6a4d2dff-81d2-446b-84ac-78c3379b289d"
  }
}
REQUEST {
  "headers": {
    "schema": "st-schema",
    "version": "1.0",
    "interactionType": "discoveryRequest",
    "requestId": "6a4d2dff-81d2-446b-84ac-78c3379b289d"
  },
  "authentication": {
    "tokenType": "Bearer",
    "token": "<token>"
  }
}
RESPONSE {
  "headers": {
    "schema": "st-schema",
    "version": "1.0",
    "interactionType": "discoveryResponse",
    "requestId": "6a4d2dff-81d2-446b-84ac-78c3379b289d"
  },
  "devices": [
    {
      "externalDeviceId": "external-device-1",
      "friendlyName": "Test Dimmer",
      "deviceHandlerType": "c2c-dimmer",
      "manufacturerInfo": {
        "manufacturerName": "Example Connector",
        "modelName": "Virtual Dimmer"
      }
    }
  ]
}

The weird thing is that nothing about the interaction shows up in the logs

Let me check the logs on Smartthings with the requesteId to understand what is happening

@merrychrysler in the logs I can see an issue at the moment refreshing the accessToken, the discoveryRequest works correctly, and the devices were created but on the stateRefreshRequest SmartThings needs to refresh the accessToken, it failed because your OAuth server takes too long to respond, this could be a possible reason why your devices didn’t update all the capabilities status.