web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

Community site session details

Community site session details

Session Id :
Power Platform Community / Forums / Power Automate / Using PowerAutomate to...
Power Automate
Unanswered

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

Categories:
I have the same question (0)
  • Verified answer
    lbendlin Profile Picture
    8,474 Super User 2025 Season 2 on at

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

  • Rookie1 Profile Picture
    28 on at

    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
            }
        })
    }


     

     

     

  • Rookie1 Profile Picture
    28 on at

    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. 

  • lbendlin Profile Picture
    8,474 Super User 2025 Season 2 on at

    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

    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,474 Super User 2025 Season 2 on at

    Understood. All the devices I mentioned are Tuya based.

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

Forum hierarchy changes are complete!

In our never-ending quest to improve we are simplifying the forum hierarchy…

Ajay Kumar Gannamaneni – Community Spotlight

We are honored to recognize Ajay Kumar Gannamaneni as our Community Spotlight for December…

Leaderboard > Power Automate

#1
Michael E. Gernaey Profile Picture

Michael E. Gernaey 538 Super User 2025 Season 2

#2
Tomac Profile Picture

Tomac 405 Moderator

#3
abm abm Profile Picture

abm abm 252 Most Valuable Professional

Last 30 days Overall leaderboard