基于 Python 和涂鸦云开发平台的 IoT 设备控制实践

更新时间:2021-09-08 03:44:28

概况

利用涂鸦云开发平台,您可以获取涂鸦 IoT 平台 OpenAPI 的调用权限。通过简单的代码编程就可以轻易控制 Powered By Tuya 智能设备。本文主要介绍如何使用涂鸦云开发平台并通过 Python 调用相关 API 控制一款智能设备。

物料清单

硬件 (1)软件 (1)
  • (可选)一款智能硬件设备

    数量:1

    任何 Powered By Tuya 设备皆可,您也可以前往涂鸦智选平台采购样品。查看详情

步骤

  • 第 1 步:配置云项目

    创建并配置云项目是开发 IoT 服务的第一步,在项目配置环节您需要完成以下操作。

    • 新建一个项目:云项目是 IoT 平台资源(设备、API 权限、数据资产等)的集合,不同云开发项目之间的资源可以实现相互隔离。
    • 开通并授权所需云服务:您可以基于业务场景选择涂鸦智能为您开放的云服务,加速您的业务实现。
    • 构建资产和用户体系:项目所有者对资产用户体系下的资源(设备、用户、API 权限、数据资产等)具备管理员权限,便于企业实现项目资源的灵活管控。

    前提条件

    已注册 涂鸦 IoT 平台 账号。

    操作步骤

    云项目是涂鸦云开发平台管理开发资源的单位,每个云项目的资源和权限相互隔离。开发 IoT 应用前,您需要创建一个云项目。

    1. 登录 涂鸦 IoT 平台。
      image.png

    2. 在左侧导航栏中,单击云开发>云开发。
      image.png

    3. 在我的云项目的页面,点击页面右侧 创建云项目。

    4. 在创建项目对话框中,配置项目参数后点击 创建。

      • 项目名称:自定义项目的名称。
      • 项目描述:自定义项目的描述。
      • 开发方式:本示例选择自定义开发。不同开发方式特征参见 开发方式。
      • 服务行业:自定义选择您项目的行业类型,便于后期统计分析。
      • 可用区域:填入对应您所在区域对应的服务器地址。

      image.png

    5. 在 批量授权 API 产品 中,除了默认选择的 API 服务外,还需添加 设备状态通知 和 行业项目客户端服务 API,添加完成后单击 开通授权。

      image.png

    6. 创建初始资产和初始账号,初始资产将自动授权至该初始账号。

      说明 :请牢记您配置的账号和密码,您后续使用 IoT 设备管理 App 添加设备或使用 API 控制设备时都将会使用。您也可以根据实际业务场景构建您的资产架构,构建方法参见 管理资产结构。

      image.png

    后续步骤

    完成项目创建和配置后,您可以关联设备 至您的云项目。

  • 第 2 步:添加设备

    本步骤我们目的是将智能设备添加到资产下,从而允许 API 进行控制。

    说明: 如果您身边暂时没有 Powered By Tuya 设备,您可以使用虚拟设备服务,使用方法参见 添加虚拟设备。

    前提条件

    操作步骤

    1. 在 设备 页面,将鼠标悬停支持 添加设备,单击 使用 IoT 设备管理 App 添加设备。
      image.png

    2. 使用 IoT 设备管理 App 扫描项目的二维码,完成项目授权。
      image.png

    3. 使用创建项目时候配置的初始账号登录 IoT 设备管理 App。
      e6bf16021c6e954518e7fb5488b6ce61_gaitubao_290x335.jpg

    4. 在 资产与设备 页面,点击目标资产名称,进入 资产 页签。

    5. 点击资产列表右上角的 添加 符号。

    6. 在下方的弹框中,点击 智能设备配网 选项。

      智能设备配网

      说明: 本教程以 智能设备配网 方式为例,边缘网关激活方式参见 边缘网关激活。

    7. 添加设备。结合后续的代码,本示例中您需要添加一个灯带(或者灯带的虚拟设备)。支持通过 手动添加 和 自动发现 两种方式来添加设备。具体操作,请参考 涂鸦智能 App 的 添加设备。

      添加设备

    后续步骤

    完成设备添加以后,您可以通过 调试设备 功能,模拟您的真实业务场景,下发指令控制设备,检测设备的可用性,确保业务的稳定运行。

    或者您可以直接选择自己熟悉编程语言的 SDK 开发 IoT 服务。

  • 第 3 步:调试设备

    您可以通过设备调试功能模拟您的真实业务场景,下发指令控制设备,检测设备的可用性,确保业务的稳定运行。

    说明:目前仅支持 资产 体系下的设备和 关联涂鸦 App 账号 下的设备进行设备调试。本实践为您介绍如何调试 资产 体系下的设备。

    前提条件

    已在云项目中添加设备。

    操作步骤

    第一步:登录调试页面

    1. 登录 云开发平台。
    2. 在 云开发> 我的云项目 区域,单击目标项目。
    3. 在顶部导航栏,单击 资产。
    4. 单击目标 资产结构 节点。
      image.png
    5. 在 设备下设备 页面,选择目标设备并单击 调试设备。
      image.png

    第二步:调试设备

    1. 查看基础信息。
      您可以在 基础信息 界面确认设备 ID、产品类型、设备所归属的项目和资产等信息。
      调试设备界面.png

    2. 发送设备下发指令。
      在 设备调试 页面的右侧查看 设备指令集 和 设备状态集 的填写方法。

      说明: 点击 设备调试 页面顶部的 更新设备状态 可以获取设备的最新状态。

      1. 更新设备功能参数。
        • 在可视化界面,调整可视化控件,变更设备功能点状态。
        • 点击 设备调试 页面顶部的 JSON 编辑,根据标准指令集,输入状态更新的指令。
      2. 单击 发送指令。
      3. 下发成功,提示指令发送成功。

      调试设备控制.png

    3. 发送设备上报指令。
      开发者可以模拟设备数据上报,进行消息订阅接收等相关对接测试。

      说明:目前只支持 虚拟设备 发送上报指令。如果设备状态无变更,则无法执行上报操作。

      1. 单击页面顶部的 模式设备上报,右侧 通讯日志 页面将显示 MQTT connect success。
      2. 修改设备的功能点参数或开关。
      3. 点击下方上报,通讯日志显示 上报数据 即为成功。

      模拟数据上报.png

    第三步:查看设备日志

    您在调试设备中所有执行的上报或下发操作都将返回对应的日志,您可以在 设备日志 页面根据功能点、设备事件、执行时间进行查询。
    设备日志.png

    后续步骤

    完成设备添加和调试后,您可以通过 IoT SDK 快速 开发 IoT 服务。

  • 第 4 步:开发设备控制和消息订阅服务(Python SDK)

    本文介绍如何基于涂鸦云开发平台开放的能力和 SDK,开发一个控制 Powered By Tuya 的智能设备的程序。

    前提条件

    操作步骤

    第一步:配置开发环境

    本步骤基于 Tuya-connector-Python SDK。Tuya-connector 集成了开发者在涂鸦云云对接(OpenAPI 或者消息订阅)项目过程中的云端连接和处理过程,可以让开发者如同本地开发一样,聚焦于自身的业务逻辑。

    1. 在 Tuya-connector-Python 获取 SDK 项目地址。

      image.png

    2. 在 Projects > Get from VCS > URL,输入 SDK 项目地址,单击 Clone。
      image.png

    3. (独立项目开发)导入 Python 依赖包

      说明: GitHub 托管平台包含了 SDK 源码,本文使用的接口调用为 SDK 项目内的源码,若开发者开发独立项目,可使用 PIP 工具,导入 Python 依赖包。

      导入代码: pip3 install tuya-connector-python

    第二步:编辑配置文件

    在您的 py 文件中配置环境变量。

    image.png

    • ACCESS_ID 和 ACCESS_KEY:云应用密钥 Access ID 和 Access Key,获取方法参见 查询项目信息。-

    • API_ENDPOINT: API 请求 数据中心地址,参考 tuya-connector-python/tuya_connector/tuya_enums.py 文件。

    • MQ_ENDPOINT: 消息订阅 请求地址,参考 tuya-connector-python/tuya_connector/tuya_enums.py 文件。

      地域 API_ENDPOINT MQ_ENDPOINT
      中国区 https://openapi.tuyacn.com wss://mqe.tuyacn.com:8285/
      美国区 https://openapi.tuyaus.com wss://mqe.tuyaus.com:8285/
      欧洲区 https://openapi.tuyaeu.com wss://mqe.tuyaeu.com:8285/
      印度区 https://openapi.tuyain.com wss://mqe.tuyain.com:8285/

    示例如下

    ACCESS_ID = "xtu7m*****48ufod"
    ACCESS_KEY = "479bcba6d*******d9c4e080f7"
    API_ENDPOINT = "https://openapi.tuyacn.com"
    MQ_ENDPOINT = "wss://mqe.tuyacn.com:8285/"
    

    第三步:控制设备实践

    编辑项目配置参数后,您可以开始代码开发。最常见的功能类型为设备控制。
    以下为云项目的 授权密钥鉴权 和 查询设备详情、获取设备指令集、下发指令集、查询设备状态 的代码示例,供您参考。

    image.png

    设备查询、下发指令代码示例:device_control.py

    import logging
    from tuya_connector import TuyaOpenAPI, TUYA_LOGGER
    
    ACCESS_ID = "xtu7m*****48ufod"
    ACCESS_KEY = "479bcba6d*******d9c4e080f7"
    API_ENDPOINT = "https://openapi.tuyacn.com"
    
    
    # Enable debug log
    TUYA_LOGGER.setLevel(logging.DEBUG)
    
    # Init openapi and connect
    openapi = TuyaOpenAPI(API_ENDPOINT, ACCESS_ID, ACCESS_KEY)
    openapi.connect()
    
    # set up device_id
    DEVICE_ID ="vdevo********74966"
    
    # Call API from Tuya
    #Get the device information
    response = openapi.get("/v1.0/iot-03/devices/{}".format(DEVICE_ID))
    
    #Get the instruction set of the device
    response = openapi.get("/v1.0/iot-03/devices/{}/functions".format(DEVICE_ID))
    
    #Send commands
    commands = {'commands': [{'code': 'switch_led', 'value': False}]}
    openapi.post('/v1.0/iot-03/devices/{}/commands'.format(DEVICE_ID), commands)
    
    #Get the status of a single device
    response = openapi.get("/v1.0/iot-03/devices/{}/status".format(DEVICE_ID))
    

    返回结果示例:

    /Users/even/Documents/SDK/Python/ttuya-connector-python1/venv/bin/python /Users/even/Documents/SDK/Python/ttuya-connector-python/example/device_control.py
    [2021-08-24 16:27:21,832] [tuya-openapi] Request: method = GET,url = https://openapi.tuyacn.com/v1.0/token,params = {'grant_type': 1},body = None,t = 1629793641832
    [2021-08-24 16:27:22,007] [tuya-openapi] Response: {
      "result": {
        "access_token": "***",
        "expire_time": 6147,
        "refresh_token": "***",
        "uid": "***"
      },
      "success": true,
      "t": 1629793642090
    }
    [2021-08-24 16:27:22,007] [tuya-openapi] Request: method = GET,url = https://openapi.tuyacn.com/v1.0/iot-03/devices/vdevo********74966,params = None,body = None,t = 1629793642007
    [2021-08-24 16:27:22,183] [tuya-openapi] Response: {
      "result": {
        "active_time": 1629792940,
        "asset_id": "14178********2832",
        "category": "dj",
        "category_name": "Light Source",
        "create_time": 1629792940,
        "gateway_id": "",
        "icon": "smart/icon/bay161786******240908156830dd.png",
        "id": "vdevo********74966",
        "ip": "***",
        "lat": "***",
        "local_key": "***",
        "lon": "***",
        "model": "",
        "name": "可调白光灯(C)_SIG-vdevo",
        "online": true,
        "product_id": "ppg6apfp",
        "product_name": "可调白光灯(C)_SIG",
        "sub": false,
        "time_zone": "+08:00",
        "update_time": 1629793223,
        "uuid": "vdevo********74966"
      },
      "success": true,
      "t": 1629793642263
    }
    [2021-08-24 16:27:22,183] [tuya-openapi] Request: method = GET,url = https://openapi.tuyacn.com/v1.0/iot-03/devices/vdevo********74966/functions,params = None,body = None,t = 1629793642183
    [2021-08-24 16:27:22,256] [tuya-openapi] Response: {
      "result": {
        "category": "dj",
        "functions": [
          {
            "code": "switch_led",
            "desc": "switch led",
            "name": "switch led",
            "type": "Boolean",
            "values": "{}"
          },
          {
            "code": "work_mode",
            "desc": "work mode",
            "name": "work mode",
            "type": "Enum",
            "values": "{\"range\":[\"white\",\"colour\",\"scene\",\"music\"]}"
          },
          {
            "code": "bright_value_v2",
            "desc": "bright value v2",
            "name": "bright value v2",
            "type": "Integer",
            "values": "{\"min\":10,\"max\":1000,\"scale\":0,\"step\":1}"
          },
          {
            "code": "scene_data_v2",
            "desc": "scene data v2",
            "name": "scene data v2",
            "type": "Json",
            "values": "{\"scene_num\":{\"min\":1,\"scale\":0,\"max\":8,\"step\":1},\"scene_units\": {\"unit_change_mode\":{\"range\":[\"static\",\"jump\",\"gradient\"]},\"unit_switch_duration\":{\"min\":0,\"scale\":0,\"max\":100,\"step\":1},\"unit_gradient_duration\":{\"min\":0,\"scale\":0,\"max\":100,\"step\":1},\"bright\":{\"min\":0,\"scale\":0,\"max\":1000,\"step\":1},\"temperature\":{\"min\":0,\"scale\":0,\"max\":1000,\"step\":1},\"h\":{\"min\":0,\"scale\":0,\"unit\":\"\",\"max\":360,\"step\":1},\"s\":{\"min\":0,\"scale\":0,\"unit\":\"\",\"max\":1000,\"step\":1},\"v\":{\"min\":0,\"scale\":0,\"unit\":\"\",\"max\":1000,\"step\":1}}}"
          },
          {
            "code": "countdown_1",
            "desc": "countdown 1",
            "name": "countdown 1",
            "type": "Integer",
            "values": "{\"unit\":\"s\",\"min\":0,\"max\":86400,\"scale\":0,\"step\":1}"
          }
        ]
      },
      "success": true,
      "t": 1629793642338
    }
    [2021-08-24 16:27:22,256] [tuya-openapi] Request: method = POST,url = https://openapi.tuyacn.com/v1.0/iot-03/devices/vdevo********74966/commands,params = None,body = {'commands': [{'code': 'switch_led', 'value': False}]},t = 1629793642256
    [2021-08-24 16:27:22,386] [tuya-openapi] Response: {
      "result": true,
      "success": true,
      "t": 1629793642470
    }
    [2021-08-24 16:27:22,386] [tuya-openapi] Request: method = GET,url = https://openapi.tuyacn.com/v1.0/iot-03/devices/vdevo********74966/status,params = None,body = None,t = 1629793642386
    [2021-08-24 16:27:22,461] [tuya-openapi] Response: {
      "result": [
        {
          "code": "switch_led",
          "value": false
        },
        {
          "code": "work_mode",
          "value": "white"
        },
        {
          "code": "bright_value_v2",
          "value": 10
        },
        {
          "code": "scene_data_v2",
          "value": ""
        },
        {
          "code": "countdown_1",
          "value": 0
        }
      ],
      "success": true,
      "t": 1629793642546
    }
    
    Process finished with exit code 0
    
    

    登陆鉴权

    # Init openapi and connect
    openapi = TuyaOpenAPI(API_ENDPOINT, ACCESS_ID, ACCESS_KEY)
    openapi.connect()
    

    查询设备详情

    response = openapi.get("/v1.0/iot-03/devices/{}".format(DEVICE_ID))
    

    获取设备指令集

    response = openapi.get("/v1.0/iot-03/devices/{}/functions".format(DEVICE_ID))
    

    下发指令

    commands = {'commands': [{'code': 'switch_led', 'value': true}]}
    openapi.post('/v1.0/iot-03/devices/{}/commands'.format(DEVICE_ID), commands)
    

    查询设备状态

    response = openapi.get("/v1.0/iot-03/devices/{}/status".format(DEVICE_ID))
    

    第四步:监听设备状态

    本代码实现了消息订阅的转发功能,包含了设备在线、离线、状态上报等。

    说明: 该功能需要开通 消息订阅 服务,开通方式参见 管理消息订阅。

    image.png

    消息订阅代码示例:Mq.py

    import logging
    from tuya_connector import TUYA_LOGGER, TuyaOpenPulsar, TuyaCloudPulsarTopic
    
    ACCESS_ID = "xtu7m*****48ufod"
    ACCESS_KEY = "479bcba6d*******d9c4e080f7"
    MQ_ENDPOINT = "wss://mqe.tuyacn.com:8285/"
    
    
    # Enable debug log
    TUYA_LOGGER.setLevel(logging.DEBUG)
    
    # Init Message Queue
    open_pulsar = TuyaOpenPulsar(
        ACCESS_ID, ACCESS_KEY, MQ_ENDPOINT, TuyaCloudPulsarTopic.PROD
    )
    # Add Message Queue listener
    open_pulsar.add_message_listener(lambda msg: print(f"---\nexample receive: {msg}"))
    
    # Start Message Queue
    open_pulsar.start()
    
    input()
    # Stop Message Queue
    open_pulsar.stop()
    

    返回结果示例:

    /Users/even/Documents/SDK/Python/ttuya-connector-python1/venv/bin/python /Users/even/Documents/SDK/Python/ttuya-connector-python/example/Mq.py
    [2021-08-24 16:44:56,274] [tuya-openpulsar] start
    [2021-08-24 16:44:56,274] [tuya-openpulsar] ws-client connect status is not ok.
                         trying to reconnect for the  1 time
    [2021-08-24 16:44:56,274] [tuya-openpulsar] ---
    ws-client connecting...
    [2021-08-24 16:45:16,198] [tuya-openpulsar] received message origin payload: {"data":"hBfzoXBHP4H5S44R41JYQ6SoW2dYdwIBh/OVljw/BWnHceQwrrF0vuCyPhPmcgsLzQtf9wFhkSQ6IBE2P3yYPvavGWoPpl0r3fkcooWquX8JfG8gnY2R7wUL3Xn4MP48poM3HepgaRZOkpsSKmAqgdxobOPC7kNpk92hmXjB0PEOZ2Du4MbP4NSN49QcJ4MPl9NsbN/2CZpBNFtIusOL74T+aj0XxXAkcYXc/URNLpxRJ3xeyrLXEwM+0nBc+60qvhnd5XA0Y7aFpHh02iIbzZfTbGzf9gmaQTRbSLrDi+/NOqojg8fRo3AW+Cq6m/AtpGIRH8fwQo+FZ9RzGrk+V7bzGsXu3MK7mEqvJpca8eT7C2ZAat2eM9LwAcsDgOoQaWYWiLcqj04ZYzJqLETUGyRFs3pL4aNsWiTEGuQkMHNV0yTN7Nw/PmMonsmdM3aYSaAwQM37T2HC7gqa2exumamfEL7hh+lWoqymRU/hApq0SeBffyniddW2Daw8AUet","protocol":4,"pv":"2.0","sign":"0e523e66fea32a3873b122152fc04c84","t":1629794716261}
    [2021-08-24 16:45:16,198] [tuya-openpulsar] received message descripted: {"dataId":"9aa9d3c4-04b7-11ec-8396-02425b0322e7","devId":"vdevo********74966","productKey":"ppg6apfp","status":[{"1":"true","code":"switch_led","t":1629794716199,"value":true},{"2":"white","code":"work_mode","t":1629794716199,"value":"white"},{"3":"10","code":"bright_value_v2","t":1629794716199,"value":10},{"code":"countdown_1","t":1629794716199,"7":"0","value":0}]}
    ---
    example receive: {"dataId":"9aa9d3c4-04b7-11ec-8396-02425b0322e7","devId":"vdevo********74966","productKey":"ppg6apfp","status":[{"1":"true","code":"switch_led","t":1629794716199,"value":true},{"2":"white","code":"work_mode","t":1629794716199,"value":"white"},{"3":"10","code":"bright_value_v2","t":1629794716199,"value":10},{"code":"countdown_1","t":1629794716199,"7":"0","value":0}]}
    

小结

本文介绍了如何使用 Python 基于涂鸦云开发平台,调用基础 API 控制一个智能设备。由于 Powered By Tuya 设备体系严格的统一性,您可以将这个控制方式拓展到所有 Powered By Tuya 设备中。让您无需考虑设备异构性,能够快速构建 IoT 应用和服务。