Skip to main content

Notifications

Community site session details

Community site session details

Session Id :
Power Automate - Using Connectors
Answered

Using PowerAutomate to talk to Tuya devices

(0) ShareShare
ReportReport
Posted on by 28

I am busy with an energy saving applications. In this I need to simply switch power to my geyser to make sure it is switched on when the sun is shining (This is connected to a set of rules, all defined in PowerApps).

 

I have a Tuya compatible switch, user id and secret code. I studied the API and can execute the switching function both in the Tuya platform and got it working in Postman. There is an amount of pre-processing that needs to happen to get a token (Use usercode, secret, time, etc in a Shifting algorithm to get a token valid for 2 hours, that can be refreshed). I tried powerapps custom connector development (it seems similar to OAuth2.0, but I cannot find a place to add the code (this is defined in Postman as a pre-request script). All of this written in JavaScript.   

 

Is there a non-obvious place to add the JavaScript? Is there a different way to go aboy

  • lbendlin Profile Picture
    8,041 Super User 2025 Season 1 on at
    Re: Using PowerAutomate to talk to Tuya devices

    Understood. All the devices I mentioned are Tuya based.

  • Rookie1 Profile Picture
    28 on at
    Re: Using PowerAutomate to talk to Tuya devices

    I think the first to determine is the API for the manufacturer of your devices. In my case, Tuya provided this platform. Also consider IFFFTT as a platform. Next step is to apply for the API username and password and getting a manual for the calls to be performed. Once there, just a question of figuring out the steps in your flow.

     

    This could be an interesting control project.

     

    The reason why I had to include the coding part was  because Tuya has a very elaborate authentication mechanism. Other connectors that I built was much less complicated (eg to my inverter).

  • lbendlin Profile Picture
    8,041 Super User 2025 Season 1 on at
    Re: Using PowerAutomate to talk to Tuya devices

    I would be interested in using this for my thermostat and window blinds. (both for temperature and insolation control).  I guess I have to figure out the JSON for the control calls?

     

  • Rookie1 Profile Picture
    28 on at
    Re: Using PowerAutomate to talk to Tuya devices

    I implemented a combination of Powerautomate and Custom Connectors if anybody is interested.

     

    I created the following:

    Custom Connector 1. This only has C# code which I translated from jScript in Postman. This calculates the signstring to be used for the token call

    Flow : Execute Custom connector to get parameters, parse JSON,  and then use this to calculate the token

    Custom Connector 2. This takes the token and convert it to a signstring for commands (different for on and off)

    Depending on on or off parameter set in input to flows.

    Flow : Use parameters retrieved above , Parse JSON to perform a command call for on or off.

     

    I previously built a connector to my inverter and can now do multiple calculations in powerapps to optimize powerusage for my geyser.

     

    Project not complete, but learnt a lot. 

  • Rookie1 Profile Picture
    28 on at
    Re: Using PowerAutomate to talk to Tuya devices

    Thanks, I am actually pursuing to build custom connector to calculate the token alone, my c# skills just very low. I am just worried that I am over-complicating things.

     

    There is an option to import a postman script. I imported a working postman script through the import method. 

     

    It created all the flows in the custom connectors, but uses variables setup as pm.environment variables 

    like below:

    Rookie1_0-1712201372600.png

     

    It misses a set of functions used to calculate the variables.

     

     

     

    Below Postman Pre-request Java script for info:

    I guess I could try and translate this to c#, but this might deceive the object.

    (function () {
    pm.environment.set("variable_key", "variable_value");
    pm.collectionVariables.get("variable_key");
    pm.variables.get("variable_key");
    pm.globals.get("variable_key");
    pm.environment.get("variable_key");
        var timestamp = getTime();
        pm.environment.set("timestamp",timestamp);

        const clientId = pm.environment.get("client_id");
        const secret = pm.environment.get("secret");

        var accessToken = "";
        if(pm.environment.has("easy_access_token")){
            accessToken = pm.environment.get("easy_access_token")
        }

        const httpMethod = pm.request.method.toUpperCase();
        const query = pm.request.url.query;
        const mode = pm.request.body.mode;
        const headers = pm.request.headers;
       
        // sha256
        var signMap = stringToSign(query, mode, httpMethod, secret)
        var urlStr = signMap["url"]
        var signStr = signMap["signUrl"]
        pm.request.url = pm.request.url.host + urlStr
        var nonce = ""
        if (headers.has("nonce")) {
            var jsonHeaders = JSON.parse(JSON.stringify(headers))
            jsonHeaders.forEach(function(item){
                if (item.key == "nonce" && !item.disabled) {
                    nonce = headers.get("nonce")
                }
            })
        }
        var sign = calcSign(clientId, timestamp, nonce, signStr, secret);
        pm.environment.set('easy_sign', sign);
    })();

    function getTime(){
        var timestamp = new Date().getTime();
        return timestamp;
    }

    // Token verification calculation
    function calcSign(clientId,timestamp,nonce,signStr,secret){
        var str = clientId +timestamp + nonce + signStr;
        var hash = CryptoJS.HmacSHA256(str, secret);
        var hashInBase64 = hash.toString();
        var signUp = hashInBase64.toUpperCase();
        return signUp;
    }

    // // Business verification calculation
    // function calcSign(clientId,accessToken,timestamp,nonce,signStr,secret){
    //     var str = clientId + accessToken +timestamp + nonce + signStr;
    //     var hash = CryptoJS.HmacSHA256(str, secret);
    //     var hashInBase64 = hash.toString();
    //     var signUp = hashInBase64.toUpperCase();
    //     return signUp;
    // }

    // Generate signature string
    function stringToSign(query, mode, method, secret){
        var sha256 = "";
        var url = "";
        var headersStr = ""
        const headers = pm.request.headers;
        var map = {}
        var arr = []
        var bodyStr = ""
        if(query){
            toJsonObj(query, arr, map)
        }
        if (pm.request.body && mode) {
            if (mode != "formdata" && mode != "urlencoded"){
                bodyStr = replacePostmanParams(pm.request.body.toString())
            } else if (mode == "formdata") {
                // Traversing form key value pairs
                toJsonObj(pm.request.body["formdata"], arr, map)
            } else if (mode == "urlencoded") {
                // Traversing form key value pairs
                toJsonObj(pm.request.body["urlencoded"], arr, map)
            }
        }
        sha256 = CryptoJS.SHA256(bodyStr)
        arr = arr.sort()
        arr.forEach(function(item){
                url += item + "=" + map[item] + "&"
        })
        if (url.length > 0 ) {
            url = url.substring(0, url.length-1)
            url = "/" + pm.request.url.path.join("/") + "?" + url
        } else {
            url = "/" + pm.request.url.path.join("/")
        }
       
        if (headers.has("Signature-Headers") && headers.get("Signature-Headers")) {
            var jsonHeaders = JSON.parse(JSON.stringify(headers))
            var signHeaderStr = headers.get("Signature-Headers")
            const signHeaderKeys = signHeaderStr.split(":")
            signHeaderKeys.forEach(function(item){
                var val = ""
                if (isSelected(jsonHeaders,item) && headers.get(item)) {
                    val = headers.get(item)
                }
                headersStr += item + ":" + val + "\n"
            })
        }
        var map = {}

        url = replacePostmanUrl(url)    
        map["signUrl"] = method + "\n" + sha256 + "\n" + headersStr + "\n" + url
        map["url"] = url
        return map
    }

    function isSelected(jsonHeaders,key){
        var result = true;
        jsonHeaders.forEach(function(item){
            if (item.key == key && item.disabled) {
                result = false
            }
        })
        return result
    }

    function replacePostmanParams(str){
        while(str.indexOf("{{")!=-1&&str.indexOf("}}")!=-1){
            const key = str.substring(str.indexOf("{{")+2,str.indexOf("}}"))
            var value = pm.environment.get(key)
            if(!value) value=""
            str = str.replace("{{"+key+"}}", value)
        }
        return str
    }

    function replacePostmanUrl(str){
        console.log("str:",str)
        while(str.indexOf("{{")!=-1&&str.indexOf("}}")!=-1){
            const key = str.substring(str.indexOf("{{")+2,str.indexOf("}}"))
            var value = pm.environment.get(key)
            if(!value) value=""
            str = str.replace("{{"+key+"}}", value)
        }

        while(str.indexOf(":")!=-1){
            const tempStr = str.substring(str.indexOf(":")+1,str.length);
            var key = "";
            if(tempStr.indexOf("/")!=-1){
                key = tempStr.substring(0,tempStr.indexOf("/"))
            }else if(tempStr.indexOf("?")!=-1){
                key = tempStr.substring(0,tempStr.indexOf("?"))
            }else {
                key = tempStr.substring(0,tempStr.length)
            }
            var value = pm.request.url.variables.get(key)
            if(!value) value=""
            str = str.replace(":"+key, value)
        }
        return str
    }


    function toJsonObj(params, arr, map){
        var jsonBodyStr = JSON.stringify(params)
        var jsonBody = JSON.parse(jsonBodyStr)
        jsonBody.forEach(function(item){
            if(!item.disabled){
                arr.push(item.key)
                map[item.key] = item.value
            }
        })
    }


     

     

     

  • Verified answer
    lbendlin Profile Picture
    8,041 Super User 2025 Season 1 on at
    Re: Using PowerAutomate to talk to Tuya devices

    Custom connectors have a place to add code but it needs to be in C#

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Paul Stork – Community Spotlight

We are honored to recognize Paul Stork as our July 2025 Community…

Congratulations to the June Top 10 Community Leaders!

These are the community rock stars!

Announcing the Engage with the Community forum!

This forum is your space to connect, share, and grow!

Leaderboard > Power Automate

#1
Michael E. Gernaey Profile Picture

Michael E. Gernaey 497 Super User 2025 Season 1

#2
David_MA Profile Picture

David_MA 436 Super User 2025 Season 1

#3
Riyaz_riz11 Profile Picture

Riyaz_riz11 244 Super User 2025 Season 1

Featured topics