ST Schema App

Im trying to add battery capability to my app. I added the same in developer workspace under my devices profile as a capability and wrote code accordingly. But Im unable to see the battery status in my schema app even after removing the device and adding it again

Hi, @namithathomas
We’ve noticed that sometimes when we add new capabilities to profiles in the Developer Workspace, the presentation is not updated, so, you might be able to send a new state for this capability from your connector but you won’t see it in the UI. If the capability doesn’t belong to the profile either, you’ll get an error when trying to send a new state for it.

So, the quickest suggestion would be to create a new profile with all the necessary capabilities and use that one instead.
The other would be to verify the presentation is being updated and try to update it manually if it isn’t.

The last can be done as follows:

  1. In the Developer Workspace’s profile, you’ll see the tab “UI Display”
  2. Download the file that contains the device configuration to see its content
    a. Check if the battery capability is included there
  3. Then, check the presentation’s config by making a query to the API.
    a. You can call the API’s /presentation endpoint (see the documentation here)
    b. If you have the ST CLI set up, you can use this command:
smartthings presentation vid mnmn -j

//Example:
smartthings presentation ST_e976b515-9b04-46a2-... 0AJJ -j

The values of vid and mnmn are in the file you downloaded in #2

1 Like

Thank you for the solution. I came across another doubt. It is about state refresh.

How does the state refresh works in ST Schema App? Because the changes happening in the dynamodb table is not refelcting timely in the App UI. I have to go to the app settings everytime-linked services-refresh to see the new changes. Is it because of something i missed in the code?

Is there any other ways to automate this? so that the clients get the updates in timely manner?

Do you mean the status changes on your cloud but you don’t see it in SmartThings?
For that, you need to implement device state callbacks. This interaction type is used to update the status on demand when it changes on your side and doesn’t depend on a command sent from SmartThings.

Remember you need to get a Reciprocal Access Token to authenticate such callbacks and that the token is linked to the instance of the Schema, this means that when you send a state callback, you send the deviceId but internally we know to which connector it belongs based on the Access Token. That’s why you cannot update several devices from different users with a single request.

Please, let me know if you have questions and we can go step by step.

Yes. The changes happening in the cloud is not updating in App.
Could you please tell me the steps to add the device state callback? like the how the cloud connector code should be.

And another issue is in the grantcallbackaccess, even though the client id is same as that of in the developer work space it is showing an error like

“globalError”: {
“detail”: “Client ID xxxx is invalid”,
“errorEnum”: “INVALID-CLIENT”
}

Interesting, are you using the same account in your ST app and the Developer Workspace?

In this sample, you can see how I configured the connector, it’s simplified in the statusRefresh and command handlers for reference purposes:

const connector = new SchemaConnector()
    .enableEventLogging(2)
    .clientId(process.env.ST_CLIENT_ID)
    .clientSecret(process.env.ST_CLIENT_SECRET)
    .discoveryHandler((accessToken, response) => {         
      const d = response.addDevice('smartThermostat4', 'smartThermostat4', 'ed0f1f26-3365-4b90-903f-cc2f1973495e')
      //Device manufacturer
      d.manufacturerName('smartThermostat4');
      //Device model
      d.modelName('smartThermostat4');
    })
    .stateRefreshHandler((accessToken, response) => {
      response.addDevice('smartThermostat4', [...])
    })
    .commandHandler((accessToken, response, devices) => {
      //...
    })
    .callbackAccessHandler((accessToken, callbackAuthentication, callbackUrls) => {
      //Here's where we receive the tokens for the callbacks
      accessTokens = {
        callbackAuthentication,
        callbackUrls
      }
      console.log("granted accessTokens ",accessTokens)
    })
    .integrationDeletedHandler(accessToken => {
      accessTokens = {};
    });

If everything seems correct, have you tried getting a new set of client ID and secret to see if that makes a difference?

About the code of the callback, here’s an example:

 const {StateUpdateRequest,...} = require('st-schema');

accessTokens=getaccessTokens()
/*Sample of accessTokens structure:
accessTokens={
    callbackAuthentication: {
    tokenType: 'Bearer',
    accessToken: 'xxxxx',
    refreshToken: 'xxxx',
    expiresIn: 86400
    },
    callbackUrls: {
    oauthToken: 'https://c2c-us.smartthings.com/oauth/token',
    stateCallback: 'https://c2c-us.smartthings.com/device/events'
    }
}
*/
const updateRequest = new StateUpdateRequest(process.env.ST_CLIENT_ID, process.env.ST_CLIENT_SECRET);
const deviceState = [
  {
    externalDeviceId: 'externalDeviceId',
    states: [
      {
        "component": "main",
        "capability": "st.thermostatMode",
        "attribute": "thermostatMode",
        "value": "auto"
      }
    ]
  }
];

I have regenerated the client id and its fine now. But the statecallback function is not working properly.

async function sendStateUpdate(deviceId, states, oauthToken, stateCallbackUrl) {
if (!stateCallbackUrl || !oauthToken) {
console.error(‘State callback URL or OAuth token not set’);
return;
}

const updateRequest = new StateUpdateRequest(process.env.ST_CLIENT_ID, process.env.ST_CLIENT_SECRET);
updateRequest.callbackAuthentication.tokenType = 'Bearer';
updateRequest.callbackAuthentication.accessToken = oauthToken;

updateRequest.callbackUrls = {
    oauthToken: 'https://c2c-us.smartthings.com/oauth/token',
    stateCallback: stateCallbackUrl
};

updateRequest.addDeviceState({
    externalDeviceId: deviceId,
    states: states
});

const response = await fetch(stateCallbackUrl, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${oauthToken}`
    },
    body: JSON.stringify(updateRequest)
});

if (!response.ok) {
    throw new Error(`Failed to update state: ${response.status} ${response.statusText}`);
}

}
Could you please tell me the way to correct this. The device has temp humidity contact sensor and battery as capabilitites.

Hi, @namithathomas

As you mentioned you solved the issue over DM, could you let us know what you did? This is for other Community members’ reference.

1 Like

Hi, I have just followed the Schema SDK code you mentioned. So state changes are refelcting timely in the app now. Thank you.

SmartThingsCommunity/st-schema-nodejs/blob/master/lib/callbacks/StateUpdateRequest.js

Another doubt I have is rather than routines, is there any way to do the proactive notifications in the schema app like for example, the temperature is too high or low ? I couldn’t find this in the documentation.

Do you mean sending push notifications using the Schema Connector? If so, it isn’t possible, only certain capabilities send notifications without the configuration of a routine:

  • waterSensor
  • carbonMonoxideDetector
  • smokeDetector

But the others require this configuration from the User, you cannot set a configuration from the Schema integration.

2 Likes