设备连接求助

云开发产品技术讨论,包括IoT Core和其他云服务API、数据分析产品等话题


Post Reply
13155558863
Posts: 2

尝试使用万能红外遥控器通过接口控制空调。目前postman已经调通。
调通的接口文本:

Code: Select all

url = "https://openapi.tuyacn.com/v1.0/devices/6cb0efdfcfd228ef8baai2/commands"

body= json.dumps({
  "commands": [
    {
      "code": "PowerOff"
    }
  ]
})
headers = {
  'client_id': '5yw7u9j445wfxpsw5e35',
  'access_token': 'd1aead51031ddba6bf31ee96e038a771',
  'sign': 'C8659450EC11AE1A9ACC1FFDBEF238673951ABF516A75E62CA7CB5495C89FBEC',
  't': '1713080039881',
  'sign_method': 'HMAC-SHA256',
  'Content-Type': 'application/json',
  'nonce': '',
  'stringToSign': ''
}

但在转换成python脚本的时候遇到问题,我基于同样的access_token和t已经可以生成相同的sign了,但是调用接口返回 sign invalid 。

我的python脚本:

Code: Select all

import time
import hmac
import hashlib
import requests
ACCESS_ID = "5yw7u9j445wfxpsw5e35"
token = "d1aead51031ddba6bf31ee96e038a771"

timestamp = int(time.time() * 1000)
#timestamp = 1713080039881
url = "https://openapi.tuyacn.com/v1.0/devices/6cb0efdfcfd228ef8baai2/commands"
signstr = "POST\nf935b82a0bdb9902f68d673da0c4595ca7c1213898d778a6d48bd2c24a2008bd\n\n/v1.0/devices/6cb0efdfcfd228ef8baai2/commands"
fullstr = f"{ACCESS_ID}{token}{timestamp}{signstr}".encode('utf-8')
comsignature = hmac.new(secret, fullstr, hashlib.sha256).hexdigest().upper()

payload = json.dumps({
  "commands": [
    {
      "code": "PowerOff"
    }
  ]
})
headers = {
  'client_id': ACCESS_ID,
  'access_token': token,
  'sign': comsignature,
  't': f"{timestamp}",
  'sign_method': 'HMAC-SHA256',
  'Content-Type': 'application/json',
  'nonce': '',
  'stringToSign': ''
}

response = requests.request("POST", url, headers=headers, data=payload)

我基于同样的access_token和t生成的header:
{'client_id': '5yw7u9j445wfxpsw5e35',
'access_token': 'd1aead51031ddba6bf31ee96e038a771',
'sign': 'C8659450EC11AE1A9ACC1FFDBEF238673951ABF516A75E62CA7CB5495C89FBEC',
't': '1713080039881',
'sign_method': 'HMAC-SHA256',
'Content-Type': 'application/json',
'nonce': '',
'stringToSign': ''}

已经实现了和前面基于postman pre_request scripts生成的接口内容一致,但替换成timestamp = int(time.time() * 1000)后,如何运行都是sign invalid 。


Tags:
panda-cat
Posts: 11

Re: 设备连接求助

看报错信息是时间戳过期,应该是参数构建中有使用到时间戳与当前时间差距过大。错误码信息:“1013 request time is invalid 请求时间戳过期 请检查请求的时间戳是否已过期,或与当前时间差距过大,可参考 请求结构”(https://developer.tuya.com/cn/docs/iot/ ... 9ruxx88swc)。建议直接使用涂鸦提供的sdk进行对接,避免各种参数构造问题:https://developer.tuya.com/cn/docs/iot/ ... 09frvx48db

panda-cat
Posts: 11

Re: 设备连接求助

验证了一下你提供的python脚本,signstr内的Content-SHA256不正确,singstr内容应该是:POST\n13f0f1d055453515abe85aa6a09e20bf73d32f14377b72907c04ee4a585b5b76\n\n/v1.0/devices/6cb0efdfcfd228ef8baai2/commands
建议使用sdk对接:https://github.com/tuya/tuya-connector-python

sign计算参考脚本如下(请查看SDK内的openapi.py文件):
def _calculate_sign(
self,
method: str,
path: str,
params: Optional[Dict[str, Any]] = None,
body: Optional[Dict[str, Any]] = None,
) -> Tuple[str, int]:

Code: Select all

    # HTTPMethod
    str_to_sign = method
    str_to_sign += "\n"

    # Content-SHA256
    content_to_sha256 = (
        "" if body is None or len(body.keys()) == 0 else json.dumps(body)
    )

    str_to_sign += (
        hashlib.sha256(content_to_sha256.encode(
            "utf8")).hexdigest().lower()
    )
    str_to_sign += "\n"

    # Header
    str_to_sign += "\n"

    # URL
    str_to_sign += path

    if params is not None and len(params.keys()) > 0:
        str_to_sign += "?"

        query_builder = ""
        params_keys = sorted(params.keys())

        for key in params_keys:
            query_builder += f"{key}={params[key]}&"
        str_to_sign += query_builder[:-1]

    # Sign
    t = int(time.time() * 1000)

    message = self.access_id
    if self.token_info is not None:
        message += self.token_info.access_token
    message += str(t) + str_to_sign
    sign = (
        hmac.new(
            self.access_secret.encode("utf8"),
            msg=message.encode("utf8"),
            digestmod=hashlib.sha256,
        )
        .hexdigest()
        .upper()
    )
    return sign, t
13155558863
Posts: 2

Re: 设备连接求助

感谢您的回复,我之前尝试过sdk对接(https://github.com/tuya/tuya-connector-python),但是没有成功,查询服务端的日志显示:

Code: Select all

{
  "msg": "permission deny",
  "code": 1106,
  "t": 1713183217136,
  "success": false,
  "tid": "96631529fb2111eeba765ed3ad93e519"
}

我问tuya提供的ai助手,它表示是因为没有获取token。但是我看(https://github.com/tuya/tuya-connector-python)中没有包含token获取的提示。所以就尝试自己对照postman的模板来写。

panda-cat
Posts: 11

Re: 设备连接求助

😅抱歉这么晚才看到您提的新问题,根据报错请求使用的接口判断当前您正在使用授权码模式授权登录场景,这个场景比较特殊,无法使用tuya-connector-python做接入,需要您自己code来完成接口接入,验签部分建议使用openapi.py内_calculate_sign方法来处理。96631529fb2111eeba765ed3ad93e519 这个报错的原因我具体分析下后再回复您。

panda-cat
Posts: 11

Re: 设备连接求助

96631529fb2111eeba765ed3ad93e519 的报错应该是参数错误,请确认输入的账号是否存在,且使用对应密码可以正常登录所授权的app。

Post Reply