通过bash调用涂鸦API

问题描述 投票:0回答:3

我在使用curl时调用涂鸦API遇到困难。

涂鸦需要生成签名,如下: HMAC-SHA256(client_id + t,秘密)。 我构建了一个小脚本,完全按照 Tuya 的要求进行操作。我还通过尝试使用其文档中的相同 client_id、t 和密钥生成签名进行了双重检查,生成的签名与文档中的内容相符。

client_id是预先分配的值 t 是 13 位时间戳(这里我认为是错误所在) 秘密是预先分配的值

签名构建完成后,需要在 POST 调用中通过curl使用,但涂鸦一直拒绝签名,并出现以下错误:

{"code":1004,"msg":"签名无效","成功":false,"t":1664314067553}

现在,我认为问题在于时机。 为了让我的脚本生成签名需要几毫秒,并且当 t 的值传递给curl 时,它与curl 的执行不匹配(当然)。这是我的代码:

t=($(($(date +%s%N)/1000000))); sign1=$(echo -n "yyr8hxxxxxxxxd4mji$t" | openssl dgst -sha256 -hmac "cc75fd7xxxxxxxxx63d032b" | awk '{print$2}') && sign2=$(echo ${sign1^^}) ; curl --request POST "https://openapi.tuyaeu.com/v1.0/iot-03/devices/717715xxxxxxx520/commands" --header "sign_method: HMAC-SHA256" --header "client_id: yyr8hxxxxxxxxd4mji" --header "t: t" --header "mode: cors" --header "sign: $sign2" --header "access_token: cc75fd7xxxxxxxxx63d032b" --data "{"commands":[{"code":"switch_1","value":true}]}"

我当然已经尝试过使用 && 一起执行所有命令,但没有任何变化。有人有什么想法吗?

bash curl tuya
3个回答
6
投票

我有一个用例,我想从涂鸦智能插头中提取设备的电量。我按照 https://github.com/jasonacox/tuyapower 的 Tuya API 创建说明进行操作,然后遇到了与您相同的问题,永远得到

{"code":1004,"msg":"sign invalid"," ...

bobolecoco 的原始答案也不适合我。使用Tuya的文档https://developer.tuya.com/en/docs/iot/singnature?id=Ka43a5mtx1gsc我发现生成的

sign
由于换行而无效,并使用
printf
代替
echo
。请参阅下面的代码,该代码易于调试并且在 bash 5.1.16 中适用于我。

# Set debug value to true or false to (de)activate output

debug=true

# Declare constants

ClientID="<<ENTER CLIENT ID HERE>>"
ClientSecret="<<ENTER CLIENT SECRET HERE>>"
BaseUrl="https://openapi.tuyaeu.com"
EmptyBodyEncoded="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
tuyatime=`(date +%s)`
tuyatime=$tuyatime"000"
if ($debug) then echo Tuyatime is now $tuyatime; fi;


# Get Access Token

URL="/v1.0/token?grant_type=1"

StringToSign="${ClientID}${tuyatime}GET\n${EmptyBodyEncoded}\n\n${URL}"
if ($debug) then echo StringToSign is now $StringToSign; fi;

AccessTokenSign=$(printf $StringToSign | openssl sha256 -hmac  "$ClientSecret" | tr '[:lower:]' '[:upper:]' |sed "s/.* //g")
if ($debug) then echo AccessTokenSign is now $AccessTokenSign; fi;

AccessTokenResponse=$(curl -sSLkX GET "$BaseUrl$URL" -H "sign_method: HMAC-SHA256" -H "client_id: $ClientID" -H "t: $tuyatime"  -H "mode: cors" -H "Content-Type: application/json" -H "sign: $AccessTokenSign")
if ($debug) then echo AccessTokenResponse is now $AccessTokenResponse; fi;

AccessToken=$(echo $AccessTokenResponse | sed "s/.*\"access_token\":\"//g"  |sed "s/\".*//g")
if ($debug) then echo Access token is now $AccessToken; fi;

# Send Device status request

URL="/v1.0/iot-03/devices/status?device_ids=<<ENTER DEVICE IDs HERE, COMMA SEPARATED>>"

StringToSign="${ClientID}${AccessToken}${tuyatime}GET\n${EmptyBodyEncoded}\n\n${URL}"
if ($debug) then echo StringToSign is now $StringToSign; fi;

RequestSign=$(printf $StringToSign | openssl sha256 -hmac  "$ClientSecret" | tr '[:lower:]' '[:upper:]' |sed "s/.* //g")
if ($debug) then echo RequestSign is now $RequestSign; fi;

RequestResponse=$(curl -sSLkX GET "$BaseUrl$URL" -H "sign_method: HMAC-SHA256" -H "client_id: $ClientID" -H "t: $tuyatime"  -H "mode: cors" -H "Content-Type: application/json" -H "sign: $RequestSign" -H "access_token: $AccessToken")
if ($debug) then echo RequestResponse is now $RequestResponse; fi;

3
投票

您的

sign
无效。

声明你的变量:

ClientID="replace_with_you_client_Id yyr8hxxxxxxxxd4mji"
ClientSecret="replace_with_you_client_secret cc75fd7xxxxxxxxx63d032b"
Device="replace_with_your_device 717715xxxxxxx520"

首先你必须得到一个

access_token
:

AccessToken=$(t=$(date +%s%N |sed "s/......$//g"); curl -sSLkX GET "https://openapi.tuyaeu.com/v1.0/token?grant_type=1" -H "sign_method: HMAC-SHA256" -H "client_id: $ClientID" -H "t: $t" -H "mode: cors" -H "Content-Type: application/json" -H "sign: $(echo -en "${ClientID}${t}GET\ne3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n\n/v1.0/token?grant_type=1" | openssl dgst -sha256 -hmac "$ClientSecret"  | tr '[:lower:]' '[:upper:]' |sed "s/.* //g")" -H "access_token: " | sed "s/.*\"access_token\":\"//g"  |sed "s/\".*//g")`

然后你需要计算好“标志”。你需要你

ClientId
,时间戳,
access_token
,方法,
encoded_body
url

TimeStamp=$(date +%s%N |sed "s/......$//g")
METHOD='POST'
BODY='{"commands":[{"code":"switch_1","value":true}]}'
encodedBody=$(echo -n "$BODY" | openssl dgst -sha256 | sed "s/.*[ ]//g")
URL="/v1.0/iot-03/devices/$Device/commands"

计算

sign

SIGN=$(echo -n "$ClientID${AccessToken}${TimeStamp}${METHOD}
$encodedBody

$URL" | openssl dgst -sha256 -hmac "$ClientSecret"  | tr '[:lower:]' '[:upper:]' |sed "s/.* //g")`

或者一行:

SIGN=$(echo -en "$ClientID${AccessToken}${TimeStamp}${METHOD}\n$encodedBody\n\n$URL" | openssl dgst -sha256 -hmac "$ClientSecret"  | tr '[:lower:]' '[:upper:]' |sed "s/.* //g")

然后发送请求:

curl -sSLkX $METHOD "https://openapi.tuyaeu.com$URL" -H "sign_method: HMAC-SHA256" -H "client_id: $ClientID" -H "t: $TimeStamp" -H "mode: cors" -H "Content-Type: application/json" -H "sign: $SIGN" -H "access_token: $AccessToken" -d "$BODY"

0
投票

此页面是搜索有关创建 shell 脚本以打开和关闭 Tuya 设备的帮助时的首要结果,因此我希望能够帮助到这里的其他人。

此 shell 脚本在 DD-WRT 路由器上运行,根据“commands”值设置为“true”或“false”来打开和关闭其下方的风扇。风扇只需连接涂鸦智能插头即可。现有答案的结合使我得到了一个成功的剧本。只是想与其他正在寻找有效的 POST 命令脚本的人分享。感谢这里的所有人提供的所有帮助。

#!/bin/bash

# Declare Constants
DeviceID="YOUR_DEVICE_ID"
Commands='{"commands":[{"code":"switch_1","value":true}]}'
ClientID="YOUR_CLIENT_ID"
ClientSecret="YOUR_CLIENT_SECRET"
BaseUrl="https://openapi.tuyaus.com"
tuyatime=$(date +%s000)

# Get Access Token
URL="/v1.0/token?grant_type=1"
StringToSign="${ClientID}${tuyatime}GET\n"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"\n\n${URL}"
AccessTokenSign=$(printf "$StringToSign" | openssl sha256 -hmac "$ClientSecret" | awk '{print toupper($0)}' | sed 's/^.*= //')
AccessTokenResponse=$(curl -sSLkX GET "$BaseUrl$URL" -H "sign_method: HMAC-SHA256" -H "client_id: $ClientID" -H "t: $tuyatime"  -H "mode: cors" -H "Content-Type: application/json" -H "sign: $AccessTokenSign")
AccessToken=$(echo $AccessTokenResponse | sed "s/.*\"access_token\":\"//g"  |sed "s/\".*//g")

# Send Commands to Turn ON Device
URL="/v1.0/iot-03/devices/$DeviceID/commands"
StringToSign="${ClientID}${AccessToken}${tuyatime}POST\n$(echo -n "$Commands" | openssl dgst -sha256 | sed "s/.*[ ]//g")\n\n${URL}"
RequestSign=$(printf $StringToSign | openssl sha256 -hmac  "$ClientSecret" | awk '{print toupper($0)}' | sed 's/^.*= //')
RequestResponse=$(curl -sSLkX POST "$BaseUrl$URL" -H "sign_method: HMAC-SHA256" -H "client_id: $ClientID" -H "t: $tuyatime" -H "mode: cors" -H "Content-Type: application/json" -H "sign: $RequestSign" -H "access_token: $AccessToken" -d "$Commands")

# Success Message
timestamp=$(date '+%-I:%M%p 'on' %-m-%-d-%Y' | sed 's/AM/am/;s/PM/pm/')
success=$(echo "$RequestResponse" | grep -o '"success":[^,]*' | awk -F ':' '{print $2}')
if [ "$success" = "true" ]; then
    echo "Device turned ON successfully at $timestamp"
else
    echo "Device failed to be turned ON at $timestamp"
fi
© www.soinside.com 2019 - 2024. All rights reserved.