Any tips on how you changed it? We are getting closer and closer to the deadline and this is still a thorn in my side despite all of Todd’s great effort
Oh. Sure. I’m travelling until Tuesday but as soon as I’m back. I’ll send a link to a fork so you can see what I did
Oh dear. When I looked at my derivation of Todd’s mqttout,js its quite different, mainly because in order for me to understand the code, I went through it and changed stuff that didn’t need changing, In my defence I was creating a docker app and also integrating it with my secure web url.
I am not really comfortable sharing it formally at the moment. However, I will provide the relevant changes I made
Todd has a device page config…
.page('devicepage', (context, page, configData) => {
page.previousPageId('mainpage')
page.section('devices', section => {
section.deviceSetting('buttonList')
.capabilities(['button'])
.multiple(true)
.required(false)
.permissions('r')
section.deviceSetting('contactList')
.capabilities(['contactSensor'])
.multiple(true)
.required(false)
.permissions('r')
section.deviceSetting('motionList')
.capabilities(['motionSensor'])
.multiple(true)
.required(false)
.permissions('r')
section.deviceSetting('presenceList')
.capabilities(['presenceSensor'])
.multiple(true)
.required(false)
.permissions('r')
section.deviceSetting('switchList')
.capabilities(['switch'])
.multiple(true)
.required(false)
.permissions('r')
});
})
I have a capability page
.page('capabilitypage', (context, page, configData) => {
page.previousPageId('mainpage');
page.section('capabilities', async section => {
const capabilityGroups = require("./capabilities.json");
const caps = Object.entries(capabilityGroups)
.filter( ([k,v]) => (k != "deprecated" && k != "dead") )
.sort( (a,b) => ( (a[0] == "common") ? -1 : (b[0] == "common") ? 1 : 0) )
.map( ([k,v]) => ( {name: k, options: v.map( cap => ({id: cap, name: cap})) } ) );
section.enumSetting('capabilities').translateOptions(false).groupedOptions(caps).required(true).multiple(true)
});
})
This relies on a capabilities.json file in the JSON with the capabilities that you want to subscribe to (This is not nice, but I couldn’t see another quick way to deal with configuring capability choice. You could just hard code the capabilities you want to subscribe to.
{
"Common": [
"contactSensor",
"battery",
"switchLevel",
"relativeHumidityMeasurement",
"temperatureMeasurement",
"switch",
"presenceSensor",
"powerMeter",
"motionSensor"
]
}
Thats the messiest bit sigh
Then Scott’s .updated code
.updated(async (context, updateData) => {
await context.api.subscriptions.unsubscribeAll();
var sublist = [];
if (context.config.hasOwnProperty('buttonList')) {
sublist.push(context.api.subscriptions.subscribeToDevices(context.config.buttonList, 'button', 'button', 'buttonHandler'))
}
if (context.config.hasOwnProperty('contactList')) {
sublist.push(context.api.subscriptions.subscribeToDevices(context.config.contactList, 'contactSensor', 'contact', 'contactHandler'))
}
if (context.config.hasOwnProperty('motionList')) {
sublist.push(context.api.subscriptions.subscribeToDevices(context.config.motionList, 'motionSensor', 'motion', 'motionHandler'))
}
if (context.config.hasOwnProperty('presenceList')) {
sublist.push(context.api.subscriptions.subscribeToDevices(context.config.presenceList, 'presenceSensor', 'presence', 'presenceHandler'))
}
if (context.config.hasOwnProperty('switchList')) {
sublist.push(context.api.subscriptions.subscribeToDevices(context.config.switchList, 'switch', 'switch', 'switchHandler'))
}
// Take care of any MQTT-related setting changes
maintain_mqttconfig(context.config);
return Promise.all(sublist)
})
Here is mine
.updated(async (context, updateData) => { /* Handle SmartApp Configuration Updates (also called first time SmartApp is installed via mobile app */
await context.api.subscriptions.unsubscribeAll();
const sublist = context.config.capabilities.map( cap => {return context.api.subscriptions.subscribeToCapability(cap.stringConfig.value, "*", cap.stringConfig.value) } );
context.config.capabilities.forEach( cap => {
if (!capabilityHandlers[cap.stringConfig.value]) capabilityHandlers[cap.stringConfig.value] = false;
});
maintain_mqttconfig(context.config);
console.log(" We have " + Object.keys(capabilityHandlers).length + " subscriptions " + Object.keys(capabilityHandlers).join(","));
Object.keys(capabilityHandlers).forEach( cap => {
//console.log("Checking we have a handler for " + cap);
if (!capabilityHandlers[cap]) {
capabilityHandlers[cap] = true;
app.subscribedEventHandler(cap, (context, deviceEvent) => { common_handler(context, deviceEvent) });
console.log("Setting a handler for " + cap);
}
});
return Promise.all(sublist)
})
Sorry this isnt very convenient, If you attempt this and have problems, please don’t hesitate to reach out