Current state of MQTT on Smartthings- Hoping to be taught a bit on the subject (How to)

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 :frowning:

1 Like

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

2 Likes

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