TUYA switch integration

Hi all,

i’d like to integrate a TUYA device, a socket. I have the socket configured in tuya app, then i integrate tuya into smartthings app. OK. I have the socket in my ST mobile app and everything its ok.

After that, I’m trying to receive the socket changes with my webhook, my smartapp is in nodejs and works fine with ST devices (leak sensor, temperature, multipurpose and so on)
But all i get its “401 UNAUTHORIZED”.

I have

.permissions([

    "r:devices:*",

    "w:devices:*",

    "x:devices:*",

    "r:locations:*"

])

And a subscription to the capability
context.api.subscriptions.subscribeToCapability(“switch”,“switch.on”,“switchSensorEventHandler”);

But isnt working.

In graph.api.smartthings.com I can see the log:
ed61849e-2058-470e-81c7-563f74865ef8 20:37:18: debug Trying local:

ed61849e-2058-470e-81c7-563f74865ef8 20:37:18: error http post failed: groovyx.net.http.HttpResponseException: Unauthorized

ed61849e-2058-470e-81c7-563f74865ef8 20:37:18: debug Remote Post

Hi, Jorge! Can you give me more details, please?

How are you integrating this device into SmartThings?

In which lifecycle of your SmartApp are you getting the 401 error?

This is related to a POST request error, Is this request made in a DTH?

You can also share with me the source code of your SmartApp and DTH (if you’re using one).

Hi Nayeliz, thanks for your help

I’m integrating TUYA into ST with the ST Android APP ( Pressing “+” -> Device -> TUYA). The device it’s working in the ST Android APP, and also I can see the status in graph.api.smartthings.com

My SmartAPP source code is

const express = require(‘express’);

const SmartApp = require(’@smartthings/smartapp’);

const server = module.exports = express();

const PORT = 3003;

const mqtt=require(‘mqtt’);

const config=require(’…/MQTT_Homie/config’);

var bbdd=require(’…/bbdd’);

server.use(express.json());

var mqttClient = mqtt.connect(config.MQTT.broker,{username:“XXX”,password:“XXX”});

/* Define the SmartApp */

const smartapp = new SmartApp()

// @smartthings_rsa.pub is your on-disk public key

// If you do not have it yet, omit publicKey()

//.publicKey('@smartthings_rsa.pub') // optional until app verified

//.enableEventLogging(2) // logs all lifecycle event requests and responses as pretty-printed JSON. Omit in production

.configureI18n()

.permissions([

    "r:devices:*",

    "w:devices:*",

    "x:devices:*",

    "r:locations:*"

])

.page('mainPage', (context, page, configData) => {

    page.section('contact', section => {

        section

        

            .name('Sensores de contacto')

            .deviceSetting('contactSensor')

            .capabilities(['contactSensor'])

            .multiple(true)

            .required(false);

                           

    });

    page.section('temperature', section => {

        section

            .deviceSetting('temperatureMeasurement')

            .capabilities(['temperatureMeasurement'])

            .multiple(true)

            .required(false);

    });

    page.section('acceleration', section => {

        section

            .deviceSetting('accelerationSensor')

            .capabilities(['accelerationSensor'])

            .multiple(true)

            .required(false);

    });

    page.section('lights', section => {

        section

            .deviceSetting('lights')

            .capabilities(['switch'])

            .multiple(true)

            .permissions('rx');

    });

    page.section('motion', section => {

        section

            .deviceSetting('motionSensor')

            .capabilities(['motionSensor'])

            .multiple(true)

            .required(false);

    });

    page.section('water', section => {

        section

            .deviceSetting('waterSensor')

            .capabilities(['waterSensor'])

            .multiple(true)

            .required(false);

    });

    page.section('switchDev', section => {

        section

            .deviceSetting('switchD')

            .capabilities(['switch'])

            .multiple(true)

            .required(false);

    });

})

.updated(async (context, updateData) => {

    // Called for both INSTALLED and UPDATED lifecycle events if there is no separate installed() handler

    await context.api.subscriptions.unsubscribeAll()

    

    //motion

    context.api.subscriptions.subscribeToDevices(context.config.motionSensor,'motionSensor','motion','motionSensorEventHandler');

    context.api.subscriptions.subscribeToDevices(context.config.motionSensor, 'temperatureMeasurement', 'temperature', 'temperatureMeasurementEventHandler');

    //multipurpose

    context.api.subscriptions.subscribeToDevices(context.config.contactSensor, 'contactSensor', 'contact', 'contactSensorEventHandler');

    context.api.subscriptions.subscribeToDevices(context.config.contactSensor, 'accelerationSensor', 'acceleration', 'accelerationSensorEventHandler');

    context.api.subscriptions.subscribeToDevices(context.config.contactSensor, 'temperatureMeasurement', 'temperature', 'temperatureMeasurementEventHandler');

    

    //water

    context.api.subscriptions.subscribeToDevices(context.config.waterSensor, 'waterSensor', 'water', 'waterSensorEventHandler');

    context.api.subscriptions.subscribeToDevices(context.config.waterSensor, 'temperatureMeasurement', 'temperature', 'temperatureMeasurementEventHandler');

    

    //switch

    //context.api.subscriptions.subscribeToDevices(context.config.switchD, 'switch', 'switch.on', 'switchSensorEventHandler');

    context.api.subscriptions.subscribeToCapability("switch","switch.on","switchSensorEventHandler");

    

})

.subscribedEventHandler('motionSensorEventHandler', (context, event) => {

    const smartappId=context.event.appId;

    var viviendaID=bbdd.getViviendaID(smartappId);

    const value = event.value === 'active' ? '1' : '0';

    console.log("El motion sensor detecta "+value);

    if(mqttClient.connected)

        mqttClient.publish("homie-"+viviendaID+"/"+event.deviceId+"/"+event.deviceId+"/"+event.capability,value);

    //context.api.devices.sendCommands(context.config.lights, 'switch', value);

})

//handlers multiPurpose

.subscribedEventHandler('contactSensorEventHandler', (context, event) => {

    const smartappId=context.event.appId;

    var viviendaID=bbdd.getViviendaID(smartappId);

    const value = event.value === 'open' ? '1' : '0';

    console.log("El contact sensor está "+value);

    console.log("homie-"+viviendaID+"/"+event.deviceId+"/"+event.deviceId+"/"+event.capability);

    if(mqttClient.connected)

        mqttClient.publish("homie-"+viviendaID+"/"+event.deviceId+"/"+event.deviceId+"/"+event.capability,value);

    //context.api.devices.sendCommands(context.config.lights, 'switch', value);

})

.subscribedEventHandler('accelerationSensorEventHandler', (context, event) => {

    const smartappId=context.event.appId;

    var viviendaID=bbdd.getViviendaID(smartappId);

    const value = event.value;

    console.log("La aceleración: "+value);

    if(mqttClient.connected)

        mqttClient.publish("homie-"+viviendaID+"/"+event.deviceId+"/"+event.deviceId+"/"+event.capability,value);

    //context.api.devices.sendCommands(context.config.lights, 'switch', value);

})

.subscribedEventHandler('temperatureMeasurementEventHandler', (context, event) => {

    const smartappId=context.event.appId;

    var viviendaID=bbdd.getViviendaID(smartappId);

    const value = event.value;

    console.log("La temperatura en "+event.deviceId+" es: "+value);

    if(mqttClient.connected)

        mqttClient.publish("homie-"+viviendaID+"/"+event.deviceId+"/"+event.deviceId+"/"+event.capability,value);

    //context.api.devices.sendCommands(context.config.lights, 'switch', value);

})

.subscribedEventHandler('waterSensorEventHandler', (context, event) => {

    const smartappId=context.event.appId;

    var viviendaID=bbdd.getViviendaID(smartappId);

    const value = event.value;

    console.log("Detección de agua EN "+event.deviceId+" es: "+value);

    if(mqttClient.connected)

        mqttClient.publish("homie-"+viviendaID+"/"+event.deviceId+"/"+event.deviceId+"/"+event.capability,value);

    //context.api.devices.sendCommands(context.config.lights, 'switch', value);

})

.subscribedEventHandler('switchSensorEventHandler', (context, event) => {

    const smartappId=context.event.appId;

    var viviendaID=bbdd.getViviendaID(smartappId);

    const value = event.value;

    console.log("ON");

    /*console.log("Detección de agua en "+event.deviceId+" es: "+value);

    if(mqttClient.connected)

        mqttClient.publish("homie-"+viviendaID+"/"+event.deviceId+"/"+event.deviceId+"/"+event.capability,value);*/

    //context.api.devices.sendCommands(context.config.lights, 'switch', value);

});

/* Handle POST requests */

server.post(’/’, function(req, res, next) {

smartapp.handleHttpCallback(req, res);

});

/* Start listening at your defined PORT */

server.listen(PORT, () => console.log(Server is up and running on port ${PORT}));

Hi, there! Thanks for the info.
If your device has two (or more) capabilities that you’d like to subscribe to, you can set that list in one device setting, for example:

page.section('contact', section => {
        section.name('Sensores de contacto')
        .deviceSetting('contactSensor')
        .capabilities(['contactSensor','temperatureMeasurement'])
        .multiple(true)
        .required(false)
        .permissions('rx');
    });

So, you will be able to use the same config entry to create the subscriptions, like below (otherwise, you’ll receive a 422 error):

You mentioned that your SmartApp works correctly with the other sensors, but not the Tuya Switch, right?
The POST error you included only appears when a command is sent from the SmartThings side to that switch?

Also, can you share a screen capture of the 401 error you’re getting, please? I want to know when it is triggered.