Can't get messages from tuyapi to node red

296 views Asked by At

I have a Tuya Mini Switch which doesn't seem to work with the various tuyapi nodes on offer, so I decided to write my own. In node.js I can use tuyapi to control the device and report on the device status. However when I try to port this to node red it only half works. I can fire an event (basically turn the switch on or off), but I can't send any status messages to msg.payload. I can send messages to console.log and retrieve them in a roundabout way, but it would make things a lot easier and simpler if I can receive messages via msg.payload and then react to them accordingly.

Unfortunately my knowledge of javascript is limited so finding a solution to this problem would also be a great learning experience. The following is my sample code:

    // Node Red version of require 
    global.get('TuyAPI');    

    // New instance of tuyapi
    const device = new TuyAPI({
        id: 'XXXXXXXXXXXXXXXXXXXXXXXX',
        key: 'XXXXXXXXXXXXXXXX'
    });

    // Variable to indicate the switch is on/off
    let stateHasChanged = false;
    
    // Connect listener event 
    device.find().then(() => {
        // Connect to device
        device.connect();
    });

    // Disconnect listener event
    device.on('disconnected', () => {
        return msg;
    });

    // Data handling listener event
    device.on('data', (/** @type {{ dps: { [x: string]: any; }; }} */ data) => {
        msg.payload = "${ data.dps['1'] }"
        if (!stateHasChanged) {
            device.set({ set: !(data.dps['1']) });
            stateHasChanged = true;
        }
    });

    // Run for 5 seconds then disconnect
    setTimeout(() => { device.disconnect(); }, 5000); 



Result: switch toggles on/off, msg.payload is blank

Thanks in advance for any help of suggestions.

1

There are 1 answers

0
jhorv On

Thanks to comments from hardillb I found the solution. Part of it had to do with my inexperience with javascript, that is, I forgot that a global variable doesn't mean you can simply export data out of a function via the variable. So accessing the data and exporting it has to all be done within the same procedure. What I didn't know and what hardillb kindly pointed out to me what the use of node.send which basically does exactly what I want, to export data from within a procedure.

Below is a working copy of my original code with the redundant procedure (on.disconnect) removed. Hope the code and explanation helps others with a similar problem.

global.get('TuyAPI');

const device = new TuyAPI({
    id: 'XXXXXXXXXXXXXXXXXXXXXX',
    key: 'XXXXXXXXXXXXXXXX'
});

let stateHasChanged = false;

// Find device on network
device.find().then(() => {
    // Connect to device
    device.connect();
});

device.on('data', (/** @type {{ dps: { [x: string]: any; }; }} */ data) => {
     if (!stateHasChanged) {
        device.set({ set: !(data.dps['1']) });
        stateHasChanged = true;
        msg.payload = data.dps['1'];  // position changed; previously it returned the state BEFORE the switch event
        node.send(msg);  // used node.send instead of returning the message object and not having this within the on.disconnect listening event 
    }
});

// Disconnect after 5 seconds
setTimeout(() => { device.disconnect(); }, 5000);