Iâm simply building off of the glitch subscriptions api example, Glitch :シďžâ§, but Iâve added some routes and changed some to suit my needs. In the original, the user signs into smartthings and authorizes one of locations in their account, in turn authorizing access to all of the devices in that location.
server.get('/oauth/callback', async (req, res, next) => {
try {
console.log('OAUTH CALLBACK', req.query)
// Store the SmartApp context including access and refresh tokens. Returns a context object for use in making
// API calls to SmartThings
const ctx = await apiApp.handleOAuthCallback(req)
// Get the location name (for display on the web page)
const location = await ctx.api.locations.get(ctx.locationId)
// Set the cookie with the context, including the location ID and name
req.session.smartThings = {
locationId: ctx.locationId,
locationName: location.name,
installedAppId: ctx.installedAppId
}
**// Remove any existing subscriptions and unsubscribe to device switch events**
** await ctx.api.subscriptions.delete()
** await ctx.api.subscriptions.subscribeToCapability('switch', 'switch', 'switchHandler');**
// Redirect back to the main page
res.redirect('/')
} catch (error) {
next(error)
}
})`
Iâm not only interested in subscribing only to events of the âswitchâ capability, I am interested in subscribing to all and any events that occur to specific devices,
the application generally flows like this: user opens app. selects âadd devicesâ button which brings them to an onboarding page. from there they will click on a button for the platform from which they will add their devices to my app. this button is linked to send the user through the oauth process. Iâve created the smartapp, and its callback is my glitch app, which redirects to another route within my app âcallbackToAppâ:
server.get('/calbackToApp', async function(req, res) {
const data = req.session.smartThings
const installedAppId = data.installedAppId
res.send(`<html>
<head><title>Authentication Success</title></head>
<body>
<script>
window.installedAppId = ${JSON.stringify(installedAppId)};
window.postMessage('authSuccess');
</script>
Authentication Successful. Please return to the app.
</body>
</html>`)
});
I know this is an uncommon way of doing things but it was the only way I could think of to get those credentials back to my application.( I know that the installedappid should be encrypted before sending and it is, I just simplified it for the purposes of getting to the point. )
from there, the user sends the installedAppId as an encrypted header which my server decrypts when it is received.
when my app gets the installed App Id, it calls to the âviewDataâ endpoint, which I have also modified to categorize devices in to different âtypesâ, as was necessary for my application, and returns that devices array to my app, and my app presents a window to my user to select which devices they would like to choose. there is a done button. when they click it, the app calls to âsetup-subscriptionsâ:
server.post('/setup-subscriptions', async (req, res) => {
const installedAppId = req.header('installed-App-Id');
// const encryptedAppId = req.header('installed-App-Id');
const installedAppId = decryptInstalledAppId(encryptedAppId)
const deviceIds = req.body.deviceIDs; //array of deviceIds from app
if (!installedAppId) {
return res.status(400).send({ error: 'Missing installedAppId in headers' });
}
if (!deviceIds || deviceIds.length === 0) {
return res.status(400).send({ error: 'No devices provided or invalid device format' });
}
try {
const ctx = await apiApp.withContext(installedAppId);
if (!ctx) {
throw new Error('Failed to establish context with SmartThings API');
}
// Construct device configurations from device IDs
const devicesConfig = deviceIds.map(deviceId => ({
deviceId: deviceId,
componentId: "main"
}));
// Options for subscription
const options = {
stateChangeOnly: true
};
// Subscribe to all capabilities and attributes for each device
const subscriptionPromises = devicesConfig.map(deviceConfig =>
ctx.api.subscriptions.subscribeToDevices(
[deviceConfig],
'*', // All capabilities
'*', // All attributes
'switchHandler',
options
).catch(error => {
console.error(`Failed to subscribe device ${deviceConfig.deviceId}: ${error}`);
return { deviceId: deviceConfig.deviceId, error: error.message };
})
);
const subscriptionResults = await Promise.all(subscriptionPromises);
res.send({ success: true, results: subscriptionResults });
} catch (error) {
console.error(`Error subscribing to devices: ${error}`);
res.status(500).send({ error: error.message });
}
});
and Iâm getting a success response. but when I change the state of subscribed to devices, im not gettin anything in any console, not in the ice where I build the app, and not in the glitch logs.