技术交流

学习资料

立即试用 商务报价
社区版
社区版 专业版 云服务 Edge Edge PE 网关 授权服务 Trendz分析 Mobile 应用程序 Mobile PE应用程序
文档 > 其它特点 > 设备预配置
入门
指南 安装 架构 API 常见问题

本页目录

设备预配置

描述

ThingsBoard可以根据设备生产厂商提供的设备唯一凭证实现自动配置设备。

时序图

设备向平台发送包含deviceName、provisionDeviceKey和provisionDeviceSecret配置信息完成请求。

预配置请求实例:

1
2
3
4
5
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "YOUR_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "YOUR_PROVISION_SECRET_HERE"
}

ThingsBoard验证请求并使用设备预配置回复响应,如果响应设备ID、credentialsType和accessToken表示成功否则响应只包含状态。

预配置响应示例:

1
2
3
4
5
{
  "provisionDeviceStatus":"SUCCESS",  
  "credentialsType":"ACCESS_TOKEN",
  "accessToken":"sLzc0gDAZPkGMzFVTyUY"
}

在验证过程中将首先检查提供的provisionDeviceKey和provisionDeviceSecret参数并找到对应的Device Profile后使用配置的策略来验证设备名称并在设备配置成功后将设备的服务端属性更新为所配置的值。
支持如下两种策略:

  • 允许创建新设备 - 如果设备厂商在生产过程中不知道设备名称列表时检查设备是否注册使用此策略,设备自身可以访问固件中的信息(MAC、ID等)实现设备名称的唯一性。
  • 检查预配置设备 - 如果检查相同的设备名称尚未被使用则可以为指定的设备进行配置时使用策略,你可以使用批量配置功能将列表上传至平台,只有列表中的设备才能发送配置请求而其它设备则无法进行自动配置。

设备配置

启用预配置功能会得到预配设备密钥和预配设备密钥名称。

  • 创建设备配置
  • 输入名称
  • 选择策略并添加

配置API

MQTT

你可以使用MQTT API开发硬件设备的预配置。
如前所述设备可以请求服务器生成凭据或在注册过程中由自己提供的凭据。
请参阅下面每个选项的请求/响应和代码示例:

参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥

预配置请求数据示例:

1
2
3
4
5
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE"
}

预配置响应示例:

1
2
3
4
5
{
  "status":"SUCCESS",
  "credentialsType":"ACCESS_TOKEN",
  "credentialsValue":"sLzc0gDAZPkGMzFVTyUY"
}

示例脚本

安装Paho MQTT模块与平台通信:

1
pip3 install paho-mqtt --user

你可以将如下源代码脚本复制到文件中:

1
device-provision-example.py

现在按照步骤操作并运行脚本。
使用python3运行脚本:

1
python3 device-provision-example.py

脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from paho.mqtt.client import Client
from json import dumps, loads

RESULT_CODES = {
    1: "incorrect protocol version",
    2: "invalid client identifier",
    3: "server unavailable",
    4: "bad username or password",
    5: "not authorised",
    }



def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning with basic authorization example script.\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93mhost\033[0m or leave it blank to use default (thingsboard.cloud): ")
    config["host"] = host if host else "mqtt.thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mport\033[0m or leave it blank to use default (1883): ")
    config["port"] = int(port) if port else 1883
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    print("\n", "="*80, "\n", sep="")
    return config


class ProvisionClient(Client):
    PROVISION_REQUEST_TOPIC = "/provision/request"
    PROVISION_RESPONSE_TOPIC = "/provision/response"

    def __init__(self, host, port, provision_request):
        super().__init__()
        self._host = host
        self._port = port
        self._username = "provision"
        self.on_connect = self.__on_connect
        self.on_message = self.__on_message
        self.__provision_request = provision_request

    def __on_connect(self, client, userdata, flags, rc):  # Callback for connect
        if rc == 0:
            print("[Provisioning client] Connected to ThingsBoard ")
            client.subscribe(self.PROVISION_RESPONSE_TOPIC)  # Subscribe to provisioning response topic
            provision_request = dumps(self.__provision_request)
            print("[Provisioning client] Sending provisioning request %s" % provision_request)
            client.publish(self.PROVISION_REQUEST_TOPIC, provision_request)  # Publishing provisioning request topic
        else:
            print("[Provisioning client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])

    def __on_message(self, client, userdata, msg):
        decoded_payload = msg.payload.decode("UTF-8")
        print("[Provisioning client] Received data from ThingsBoard: %s" % decoded_payload)
        decoded_message = loads(decoded_payload)
        provision_device_status = decoded_message.get("status")
        if provision_device_status == "SUCCESS":
            self.__save_credentials(decoded_message["credentialsValue"])
        else:
            print("[Provisioning client] Provisioning was unsuccessful with status %s and message: %s" % (provision_device_status, decoded_message["errorMsg"]))
        self.disconnect()

    def provision(self):
        print("[Provisioning client] Connecting to ThingsBoard (provisioning client)")
        self.__clean_credentials()
        self.connect(self._host, self._port, 60)
        self.loop_forever()

    def get_new_client(self):
        client_credentials = self.__get_credentials()
        new_client = None
        if client_credentials:
            new_client = Client()
            new_client.username_pw_set(client_credentials)
            print("[Provisioning client] Read credentials from file.")
        else:
            print("[Provisioning client] Cannot read credentials from file!")
        return new_client

    @staticmethod
    def __get_credentials():
        new_credentials = None
        try:
            with open("credentials", "r") as credentials_file:
                new_credentials = credentials_file.read()
        except Exception as e:
            print(e)
        return new_credentials

    @staticmethod
    def __save_credentials(credentials):
        with open("credentials", "w") as credentials_file:
            credentials_file.write(credentials)

    @staticmethod
    def __clean_credentials():
        open("credentials", "w").close()


def on_tb_connected(client, userdata, flags, rc):  # Callback for connect with received credentials
    if rc == 0:
        print("[ThingsBoard client] Connected to ThingsBoard with credentials: %s" % client._username.decode())
    else:
        print("[ThingsBoard client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])


if __name__ == '__main__':

    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance MQTT port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],  # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],  # Provision device secret, replace this value with your value from device profile.
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]
    provision_client = ProvisionClient(THINGSBOARD_HOST, THINGSBOARD_PORT, PROVISION_REQUEST)
    provision_client.provision()  # Request provisioned data
    tb_client = provision_client.get_new_client()  # Getting client with provisioned data
    if tb_client:
        tb_client.on_connect = on_tb_connected  # Setting callback for connect
        tb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)
        tb_client.loop_forever()  # Starting infinity loop
    else:
        print("Client was not created!")

参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥
credentialsType ACCESS_TOKEN 凭据类型参数
token DEVICE_ACCESS_TOKEN 平台中设备的访问令牌

预配置请求数据示例:

1
2
3
4
5
6
7
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE",
  "credentialsType": "ACCESS_TOKEN",
  "token": "DEVICE_ACCESS_TOKEN"
}

预配置响应示例:

1
2
3
4
5
{
  "credentialsType":"ACCESS_TOKEN",
  "credentialsValue":"DEVICE_ACCESS_TOKEN",
  "status":"SUCCESS"
}

示例脚本

安装Paho MQTT模块与平台通信:

1
pip3 install paho-mqtt --user

你可以将如下源代码脚本复制到文件中:

1
device-provision-example.py

现在按照步骤操作并运行脚本。
使用python3运行脚本:

1
python3 device-provision-example.py

脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from paho.mqtt.client import Client
from json import dumps, loads

RESULT_CODES = {
    1: "incorrect protocol version",
    2: "invalid client identifier",
    3: "server unavailable",
    4: "bad username or password",
    5: "not authorised",
    }



def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning with access token authorization example script. MQTT API\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93mhost\033[0m or leave it blank to use default (thingsboard.cloud): ")
    config["host"] = host if host else "mqtt.thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mport\033[0m or leave it blank to use default (1883): ")
    config["port"] = int(port) if port else 1883
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    config["token"] = input("Please write \033[93mdevice access token\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    print("\n", "="*80, "\n", sep="")
    return config


class ProvisionClient(Client):
    PROVISION_REQUEST_TOPIC = "/provision/request"
    PROVISION_RESPONSE_TOPIC = "/provision/response"

    def __init__(self, host, port, provision_request):
        super().__init__()
        self._host = host
        self._port = port
        self._username = "provision"
        self.on_connect = self.__on_connect
        self.on_message = self.__on_message
        self.__provision_request = provision_request

    def __on_connect(self, client, userdata, flags, rc):  # Callback for connect
        if rc == 0:
            print("[Provisioning client] Connected to ThingsBoard ")
            client.subscribe(self.PROVISION_RESPONSE_TOPIC)  # Subscribe to provisioning response topic
            provision_request = dumps(self.__provision_request)
            print("[Provisioning client] Sending provisioning request %s" % provision_request)
            client.publish(self.PROVISION_REQUEST_TOPIC, provision_request)  # Publishing provisioning request topic
        else:
            print("[Provisioning client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])

    def __on_message(self, client, userdata, msg):
        decoded_payload = msg.payload.decode("UTF-8")
        print("[Provisioning client] Received data from ThingsBoard: %s" % decoded_payload)
        decoded_message = loads(decoded_payload)
        provision_device_status = decoded_message.get("status")
        if provision_device_status == "SUCCESS":
            self.__save_credentials(decoded_message["credentialsValue"])
        else:
            print("[Provisioning client] Provisioning was unsuccessful with status %s and message: %s" % (provision_device_status, decoded_message["errorMsg"]))
        self.disconnect()

    def provision(self):
        print("[Provisioning client] Connecting to ThingsBoard (provisioning client)")
        self.__clean_credentials()
        self.connect(self._host, self._port, 60)
        self.loop_forever()

    def get_new_client(self):
        client_credentials = self.__get_credentials()
        new_client = None
        if client_credentials:
            new_client = Client()
            new_client.username_pw_set(client_credentials)
            print("[Provisioning client] Read credentials from file.")
        else:
            print("[Provisioning client] Cannot read credentials from file!")
        return new_client

    @staticmethod
    def __get_credentials():
        new_credentials = None
        try:
            with open("credentials", "r") as credentials_file:
                new_credentials = credentials_file.read()
        except Exception as e:
            print(e)
        return new_credentials

    @staticmethod
    def __save_credentials(credentials):
        with open("credentials", "w") as credentials_file:
            credentials_file.write(credentials)

    @staticmethod
    def __clean_credentials():
        open("credentials", "w").close()


def on_tb_connected(client, userdata, flags, rc):  # Callback for connect with received credentials
    if rc == 0:
        print("[ThingsBoard client] Connected to ThingsBoard with credentials: %s" % client._username.decode())
    else:
        print("[ThingsBoard client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])


if __name__ == '__main__':

    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance MQTT port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],  # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],  # Provision device secret, replace this value with your value from device profile.
                         "credentialsType": "ACCESS_TOKEN",
                         "token": config["token"],
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]
    provision_client = ProvisionClient(THINGSBOARD_HOST, THINGSBOARD_PORT, PROVISION_REQUEST)
    provision_client.provision()  # Request provisioned data
    tb_client = provision_client.get_new_client()  # Getting client with provisioned data
    if tb_client:
        tb_client.on_connect = on_tb_connected  # Setting callback for connect
        tb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)
        tb_client.loop_forever()  # Starting infinity loop
    else:
        print("Client was not created!")

参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥
credentialsType MQTT_BASIC 凭据类型参数
username DEVICE_USERNAME_HERE 平台中的设备用户名称
password DEVICE_PASSWORD_HERE 平台中的设备密码
clientId DEVICE_CLIENT_ID_HERE 平台中的设备客户端ID

预配置请求数据示例:

1
2
3
4
5
6
7
8
9
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE",
  "credentialsType": "MQTT_BASIC",
  "username": "DEVICE_USERNAME_HERE",
  "password": "DEVICE_PASSWORD_HERE",
  "clientId": "DEVICE_CLIENT_ID_HERE"
}

预配置响应示例:

1
2
3
4
5
6
7
8
9
{
  "credentialsType":"MQTT_BASIC",
  "credentialsValue": {
    "clientId":"DEVICE_CLIENT_ID_HERE",
    "userName":"DEVICE_USERNAME_HERE",
    "password":"DEVICE_PASSWORD_HERE"
    },
  "status":"SUCCESS"
}

示例脚本

安装Paho MQTT模块与平台通信:

1
pip3 install paho-mqtt --user

你可以将如下源代码脚本复制到文件中:

1
device-provision-example.py

现在按照步骤操作并运行脚本。
使用python3运行脚本:

1
python3 device-provision-example.py

脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
from paho.mqtt.client import Client
from json import dumps, loads

RESULT_CODES = {
    1: "incorrect protocol version",
    2: "invalid client identifier",
    3: "server unavailable",
    4: "bad username or password",
    5: "not authorised",
    }



def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning with basic authorization example script.\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93mhost\033[0m or leave it blank to use default (thingsboard.cloud): ")
    config["host"] = host if host else "mqtt.thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mport\033[0m or leave it blank to use default (1883): ")
    config["port"] = int(port) if port else 1883
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    config["clientId"] = input("Please write \033[93mclient Id\033[0m: ")
    config["username"] = input("Please write \033[93musername\033[0m: ")
    config["password"] = input("Please write \033[93mpassword\033[0m: ")
    print("\n", "="*80, "\n", sep="")
    return config


class ProvisionClient(Client):
    PROVISION_REQUEST_TOPIC = "/provision/request"
    PROVISION_RESPONSE_TOPIC = "/provision/response"

    def __init__(self, host, port, provision_request):
        super().__init__()
        self._host = host
        self._port = port
        self._username = "provision"
        self.on_connect = self.__on_connect
        self.on_message = self.__on_message
        self.__provision_request = provision_request

    def __on_connect(self, client, userdata, flags, rc):  # Callback for connect
        if rc == 0:
            print("[Provisioning client] Connected to ThingsBoard ")
            client.subscribe(self.PROVISION_RESPONSE_TOPIC)  # Subscribe to provisioning response topic
            provision_request = dumps(self.__provision_request)
            print("[Provisioning client] Sending provisioning request %s" % provision_request)
            client.publish(self.PROVISION_REQUEST_TOPIC, provision_request)  # Publishing provisioning request topic
        else:
            print("[Provisioning client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])

    def __on_message(self, client, userdata, msg):
        decoded_payload = msg.payload.decode("UTF-8")
        print("[Provisioning client] Received data from ThingsBoard: %s" % decoded_payload)
        decoded_message = loads(decoded_payload)
        provision_device_status = decoded_message.get("status")
        if provision_device_status == "SUCCESS":
            self.__save_credentials(decoded_message["credentialsValue"])
        else:
            print("[Provisioning client] Provisioning was unsuccessful with status %s and message: %s" % (provision_device_status, decoded_message["errorMsg"]))
        self.disconnect()

    def provision(self):
        print("[Provisioning client] Connecting to ThingsBoard (provisioning client)")
        self.__clean_credentials()
        self.connect(self._host, self._port, 60)
        self.loop_forever()

    def get_new_client(self):
        client_credentials = loads(self.__get_credentials())
        new_client = None
        if client_credentials:
            new_client = Client(client_id=client_credentials["clientId"])  # Setting client id
            new_client.username_pw_set(client_credentials["userName"], client_credentials["password"])  # Setting username and password for ThingsBoard client
            print("[Provisioning client] Read credentials from file.")
        else:
            print("[Provisioning client] Cannot read credentials from file!")
        return new_client

    @staticmethod
    def __get_credentials():
        new_credentials = None
        try:
            with open("credentials", "r") as credentials_file:
                new_credentials = credentials_file.read()
        except Exception as e:
            print(e)
        return new_credentials

    @staticmethod
    def __save_credentials(credentials):
        with open("credentials", "w") as credentials_file:
            credentials_file.write(dumps(credentials))

    @staticmethod
    def __clean_credentials():
        open("credentials", "w").close()


def on_tb_connected(client, userdata, flags, rc):  # Callback for connect with received credentials
    if rc == 0:
        print("[ThingsBoard client] Connected to ThingsBoard with credentials: username: %s, password: %s, client id: %s" % (client._username.decode(), client._password.decode(), client._client_id.decode()))
    else:
        print("[ThingsBoard client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])


if __name__ == '__main__':
    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance MQTT port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],
                         # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],
                         # Provision device secret, replace this value with your value from device profile.
                         "credentialsType": "MQTT_BASIC",
                         "username": config["username"],
                         "password": config["password"],
                         "clientId": config["clientId"],
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]
    provision_client = ProvisionClient(THINGSBOARD_HOST, THINGSBOARD_PORT, PROVISION_REQUEST)
    provision_client.provision()  # Request provisioned data
    tb_client = provision_client.get_new_client()  # Getting client with provisioned data
    if tb_client:
        tb_client.on_connect = on_tb_connected  # Setting callback for connect
        tb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)
        tb_client.loop_forever()  # Starting infinity loop
    else:
        print("Client was not created!")

信息:使用此功能必须在ThingsBoard中基于MQTT配置SSL

参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥
credentialsType X509_CERTIFICATE 凭据类型参数
hash MIIB……..AQAB 平台中的设备的hash值

预配置请求数据示例:

1
2
3
4
5
6
7
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE",
  "credentialsType": "X509_CERTIFICATE",
  "hash": "MIIB........AQAB"
}

预配置响应示例:

1
2
3
4
5
6
7
{
  "deviceId":"3b829220-232f-11eb-9d5c-e9ed3235dff8",
  "credentialsType":"X509_CERTIFICATE",
  "credentialsId":"f307a1f717a12b32c27203cf77728d305d29f64694a8311be921070dd1259b3a",
  "credentialsValue":"MIIB........AQAB",
  "provisionDeviceStatus":"SUCCESS"
}

MQTT

使用此脚本请将你的mqttserver.pub.pem(服务公钥)放入包含脚本的文件夹中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
import ssl
from datetime import datetime, timedelta
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from paho.mqtt.client import Client
from json import dumps, loads

RESULT_CODES = {
    1: "incorrect protocol version",
    2: "invalid client identifier",
    3: "server unavailable",
    4: "bad username or password",
    5: "not authorised",
    }


def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning with X509 certificate authorization example script. MQTT API\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93mhost\033[0m or leave it blank to use default (thingsboard.cloud): ")
    config["host"] = host if host else "mqtt.thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mSSL port\033[0m or leave it blank to use default (8883): ")
    config["port"] = int(port) if port else 8883
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    print("\n", "="*80, "\n", sep="")
    return config

def generate_certs(ca_certfile="mqttserver.pub.pem"):
    root_cert = None
    try:
        with open(ca_certfile, "r") as ca_file:
            root_cert = x509.load_pem_x509_certificate(str.encode(ca_file.read()), default_backend())
    except Exception as e:
        print("Failed to load CA certificate: %r" % e)
    if root_cert is not None:
        private_key = rsa.generate_private_key(
            public_exponent=65537, key_size=2048, backend=default_backend()
            )
        new_subject = x509.Name([
        x509.NameAttribute(NameOID.COMMON_NAME, "localhost")
    ])
        certificate = (
            x509.CertificateBuilder()
            .subject_name(new_subject)
            .issuer_name(new_subject)
            .public_key(private_key.public_key())
            .serial_number(x509.random_serial_number())
            .not_valid_before(datetime.utcnow())
            .not_valid_after(datetime.utcnow() + timedelta(days=365*10))
            .add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
            .sign(private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend())
        )

        with open("cert.pem", "wb") as cert_file:
            cert_file.write(certificate.public_bytes(encoding=serialization.Encoding.PEM))

        with open("key.pem", "wb") as key_file:
            key_file.write(private_key.private_bytes(encoding=serialization.Encoding.PEM,
                                                     format=serialization.PrivateFormat.TraditionalOpenSSL,
                                                     encryption_algorithm=serialization.NoEncryption(),
                                                ))


def read_cert():
    cert = None
    key = None
    try:
        with open("cert.pem", "r") as cert_file:
            cert = cert_file.read()
        with open("key.pem", "r") as key_file:
            key = key_file.read()
    except Exception as e:
        print("Cannot read certificate with error: %r" % e)
    return cert, key


class ProvisionClient(Client):
    PROVISION_REQUEST_TOPIC = "/provision/request"
    PROVISION_RESPONSE_TOPIC = "/provision/response"

    def __init__(self, host, port, provision_request):
        super().__init__()
        self._host = host
        self._port = port
        self._username = "provision"
        self.tls_set(ca_certs="mqttserver.pub.pem", tls_version=ssl.PROTOCOL_TLSv1_2)
        self.on_connect = self.__on_connect
        self.on_message = self.__on_message
        self.__provision_request = provision_request

    def __on_connect(self, client, userdata, flags, rc):  # Callback for connect
        if rc == 0:
            print("[Provisioning client] Connected to ThingsBoard ")
            client.subscribe(self.PROVISION_RESPONSE_TOPIC)  # Subscribe to provisioning response topic
            provision_request = dumps(self.__provision_request)
            print("[Provisioning client] Sending provisioning request %s" % provision_request)
            client.publish(self.PROVISION_REQUEST_TOPIC, provision_request)  # Publishing provisioning request topic
        else:
            print("[Provisioning client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])

    def __on_message(self, client, userdata, msg):
        decoded_payload = msg.payload.decode("UTF-8")
        print("[Provisioning client] Received data from ThingsBoard: %s" % decoded_payload)
        decoded_message = loads(decoded_payload)
        provision_device_status = decoded_message.get("status")
        if provision_device_status == "SUCCESS":
            if decoded_message["credentialsValue"] == cert.replace("-----BEGIN CERTIFICATE-----\n", "")\
                                                          .replace("-----END CERTIFICATE-----\n", "")\
                                                          .replace("\n", ""):
                print("[Provisioning client] Provisioning success! Certificates are saved.")
                self.__save_credentials(cert)
            else:
                print("[Provisioning client] Returned certificate is not equal to sent one.")
        else:
            print("[Provisioning client] Provisioning was unsuccessful with status %s and message: %s" % (provision_device_status, decoded_message["errorMsg"]))
        self.disconnect()

    def provision(self):
        print("[Provisioning client] Connecting to ThingsBoard (provisioning client)")
        self.__clean_credentials()
        self.connect(self._host, self._port, 60)
        self.loop_forever()

    def get_new_client(self):
        client_credentials = self.__get_credentials()
        new_client = None
        if client_credentials:
            new_client = Client()
            new_client.tls_set(ca_certs="mqttserver.pub.pem", certfile="cert.pem", keyfile="key.pem", cert_reqs=ssl.CERT_REQUIRED,
                               tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
            new_client.tls_insecure_set(False)
            print("[Provisioning client] Read credentials from file.")
        else:
            print("[Provisioning client] Cannot read credentials from file!")
        return new_client

    @staticmethod
    def __get_credentials():
        new_credentials = None
        try:
            with open("credentials", "r") as credentials_file:
                new_credentials = credentials_file.read()
        except Exception as e:
            print(e)
        return new_credentials

    @staticmethod
    def __save_credentials(credentials):
        with open("credentials", "w") as credentials_file:
            credentials_file.write(credentials)

    @staticmethod
    def __clean_credentials():
        open("credentials", "w").close()


def on_tb_connected(client, userdata, flags, rc):  # Callback for connect with received credentials
    if rc == 0:
        print("[ThingsBoard client] Connected to ThingsBoard with credentials: username: %s, password: %s, client id: %s" % (client._username, client._password, client._client_id))
    else:
        print("[ThingsBoard client] Cannot connect to ThingsBoard!, result: %s" % RESULT_CODES[rc])


if __name__ == '__main__':

    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance MQTT port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],  # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],  # Provision device secret, replace this value with your value from device profile.
                         "credentialsType": "X509_CERTIFICATE",
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]
    generate_certs()  # Generate certificate and key
    cert, key = read_cert()  # Read certificate and key
    PROVISION_REQUEST["hash"] = cert
    if PROVISION_REQUEST.get("hash") is not None:
        provision_client = ProvisionClient(THINGSBOARD_HOST, THINGSBOARD_PORT, PROVISION_REQUEST)
        provision_client.provision()  # Request provisioned data
        tb_client = provision_client.get_new_client()  # Getting client with provisioned data
        if tb_client:
            tb_client.on_connect = on_tb_connected  # Setting callback for connect
            tb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)
            tb_client.loop_forever()  # Starting infinity loop
        else:
            print("Client was not created!")
    else:
        print("Cannot read certificate.")

HTTP

你可以使用HTTP API开发硬件设备的预配置。
如前所述设备可以请求服务器生成凭据或在注册过程中由自己提供的凭据。
请参阅下面每个选项的请求/响应和代码示例:

参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥

预配置请求数据示例:

1
2
3
4
5
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE"
}

预配置响应示例:

1
2
3
4
5
{
  "status":"SUCCESS",
  "credentialsType":"ACCESS_TOKEN",
  "credentialsValue":"sLzc0gDAZPkGMzFVTyUY"
}

示例脚本

你可以将如下源代码脚本复制到文件中:

1
device-provision-example.py

现在按照步骤操作并运行脚本。
使用python3运行脚本:

1
python3 device-provision-example.py

脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

from requests import post
from json import dumps


def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning without authorization example script. HTTP API\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93mhost\033[0m or leave it blank to use default (https://thingsboard.cloud): ")
    config["host"] = host if host else "https://thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mHTTP port\033[0m or leave it blank to use default (443): ")
    config["port"] = int(port) if port else 443
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    print("\n", "="*80, "\n", sep="")
    return config


# Example for message to ThingsBoard
to_publish = {
  "stringKey": "value1",
  "booleanKey": True,
  "doubleKey": 42.0,
  "longKey": 73,
  "jsonKey": {
    "someNumber": 42,
    "someArray": [1, 2, 3],
    "someNestedObject": {"key": "value"}
  }
}

if __name__ == '__main__':

    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance MQTT port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],  # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],  # Provision device secret, replace this value with your value from device profile.
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]
    response = post("%s:%i/api/v1/provision" % (THINGSBOARD_HOST, THINGSBOARD_PORT), json=PROVISION_REQUEST)
    decoded_response = response.json()
    print("Received response: ")
    print(decoded_response)
    received_token = decoded_response.get("credentialsValue")
    if received_token is not None:
        response = post('%s:%i/api/v1/%s/telemetry' % (THINGSBOARD_HOST, THINGSBOARD_PORT, received_token,), dumps(to_publish))
        print("[THINGSBOARD CLIENT] Response code from Thingsboard.")
        print(response.status_code)
    else:
        print("Failed to get access token from response.")
        print(decoded_response.get("errorMsg"))


参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥
credentialsType ACCESS_TOKEN 凭据类型参数
token DEVICE_ACCESS_TOKEN 平台中设备的访问令牌

预配置请求数据示例:

1
2
3
4
5
6
7
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE",
  "credentialsType": "ACCESS_TOKEN",
  "token": "DEVICE_ACCESS_TOKEN"
}

预配置响应示例:

1
2
3
4
5
{
  "credentialsType":"ACCESS_TOKEN",
  "credentialsValue":"DEVICE_ACCESS_TOKEN",
  "status":"SUCCESS"
}

示例脚本

你可以将如下源代码脚本复制到文件中:

1
device-provision-example.py

现在按照步骤操作并运行脚本。
使用python3运行脚本:

1
python3 device-provision-example.py

脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

from requests import post
from json import dumps


def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning with access token authorization example script. HTTP API\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93murl\033[0m or leave it blank to use default (https://thingsboard.cloud): ")
    config["host"] = host if host else "https://thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mHTTP port\033[0m or leave it blank to use default (443): ")
    config["port"] = int(port) if port else 443
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    config["token"] = input("Please write \033[93mdevice access token\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    print("\n", "="*80, "\n", sep="")
    return config


# Example for message to ThingsBoard
to_publish = {
  "stringKey": "value1",
  "booleanKey": True,
  "doubleKey": 42.0,
  "longKey": 73,
  "jsonKey": {
    "someNumber": 42,
    "someArray": [1, 2, 3],
    "someNestedObject": {"key": "value"}
  }
}

if __name__ == '__main__':

    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance MQTT port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],  # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],  # Provision device secret, replace this value with your value from device profile.
                         "credentialsType": "ACCESS_TOKEN",
                         "token": config["token"],
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]
    response = post("%s:%i/api/v1/provision" % (THINGSBOARD_HOST, THINGSBOARD_PORT), json=PROVISION_REQUEST)
    decoded_response = response.json()
    print("Received response: ")
    print(decoded_response)
    received_token = decoded_response.get("credentialsValue")
    if received_token is not None:
        response = post('%s:%i/api/v1/%s/telemetry' % (THINGSBOARD_HOST, THINGSBOARD_PORT, received_token,), dumps(to_publish))
        print("[THINGSBOARD CLIENT] Response code from Thingsboard.")
        print(response.status_code)
    else:
        print("Failed to get access token from response.")
        print(decoded_response.get("errorMsg"))


CoAP

你可以使用CoAP API开发硬件设备的预配置。
如前所述设备可以请求服务器生成凭据或在注册过程中由自己提供的凭据。
请参阅下面每个选项的请求/响应和代码示例:

参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥

预配置请求数据示例:

1
2
3
4
5
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE"
}

预配置响应示例:

1
2
3
4
5
{
  "status":"SUCCESS",
  "credentialsType":"ACCESS_TOKEN",
  "credentialsValue":"sLzc0gDAZPkGMzFVTyUY"
}

示例脚本

安装aiocoap模块与平台通信:

1
pip3 install asyncio aiocoap --user

你可以将如下源代码脚本复制到文件中:

1
device-provision-example.py

现在按照步骤操作并运行脚本。
使用python3运行脚本:

1
python3 device-provision-example.py

脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import logging
import asyncio

from aiocoap import Context, Message, Code
from json import loads, dumps

THINGSBOARD_HOST = ""
THINGSBOARD_PORT = ""

logging.basicConfig(level=logging.INFO)


def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning without authorization example script. CoAP API\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93mhost\033[0m or leave it blank to use default (thingsboard.cloud): ")
    config["host"] = host if host else "coap.thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mCoAP port\033[0m or leave it blank to use default (5683): ")
    config["port"] = int(port) if port else 5683
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    print("\n", "="*80, "\n", sep="")
    return config


# Example for message to ThingsBoard
to_publish = {
  "stringKey": "value1",
  "booleanKey": True,
  "doubleKey": 42.0,
  "longKey": 73,
  "jsonKey": {
    "someNumber": 42,
    "someArray": [1, 2, 3],
    "someNestedObject": {"key": "value"}
  }
}


async def process():
    server_address = "coap://" + THINGSBOARD_HOST + ":" + str(THINGSBOARD_PORT)

    client_context = await Context.create_client_context()
    await asyncio.sleep(2)
    try:
        msg = Message(code=Code.POST, payload=str.encode(dumps(PROVISION_REQUEST)), uri=server_address+'/api/v1/provision')
        request = client_context.request(msg)
        try:
            response = await asyncio.wait_for(request.response, 60000)
        except asyncio.TimeoutError:
            raise Exception("Request timed out!")

        if response is None:
            raise Exception("Response is empty!")

        decoded_response = loads(response.payload)
        logging.info("Received response: %s", decoded_response)
        received_token = decoded_response.get("credentialsValue")
        if received_token is not None:
            msg = Message(code=Code.POST, payload=str.encode(dumps(to_publish)),
                          uri=server_address+('/api/v1/%s/telemetry' % received_token))
            request = client_context.request(msg)
            try:
                response = await asyncio.wait_for(request.response, 60000)
            except asyncio.TimeoutError:
                raise Exception("Request timed out!")

            if response:
                logging.info("[THINGSBOARD CLIENT] Response from Thingsboard.")
                logging.info(response)
            else:
                raise Exception("[THINGSBOARD CLIENT] Cannot save telemetry with received credentials!")
        else:
            logging.error("Failed to get access token from response.")
            logging.error(decoded_response.get("errorMsg"))
    except Exception as e:
        logging.error(e)
    finally:
        await client_context.shutdown()

if __name__ == '__main__':

    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],  # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],  # Provision device secret, replace this value with your value from device profile.
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]

    asyncio.run(process())

参数 参数示例 描述
deviceName DEVICE_NAME 平台中的设备名称
provisionDeviceKey PUT_PROVISION_KEY_HERE 平台中的预配置设备键名
provisionDeviceSecret PUT_PROVISION_SECRET_HERE 平台中的预配置设备密钥
credentialsType ACCESS_TOKEN 凭据类型参数
token DEVICE_ACCESS_TOKEN 平台中设备的访问令牌

预配置请求数据示例:

1
2
3
4
5
6
7
{
  "deviceName": "DEVICE_NAME",
  "provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
  "provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE",
  "credentialsType": "ACCESS_TOKEN",
  "token": "DEVICE_ACCESS_TOKEN"
}

预配置响应示例:

1
2
3
4
5
{
  "credentialsType":"ACCESS_TOKEN",
  "credentialsValue":"DEVICE_ACCESS_TOKEN",
  "status":"SUCCESS"
}

示例脚本

安装aiocoap模块与平台通信:

1
pip3 install asyncio aiocoap --user

你可以将如下源代码脚本复制到文件中:

1
device-provision-example.py

现在按照步骤操作并运行脚本。
使用python3运行脚本:

1
python3 device-provision-example.py

脚本源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import logging
import asyncio

from aiocoap import Context, Message, Code
from json import loads, dumps

THINGSBOARD_HOST = ""
THINGSBOARD_PORT = ""

logging.basicConfig(level=logging.INFO)


def collect_required_data():
    config = {}
    print("\n\n", "="*80, sep="")
    print(" "*10, "\033[1m\033[94mThingsBoard device provisioning with access token authorization example script. CoAP API\033[0m", sep="")
    print("="*80, "\n\n", sep="")
    host = input("Please write your ThingsBoard \033[93mhost\033[0m or leave it blank to use default (thingsboard.cloud): ")
    config["host"] = host if host else "coap.thingsboard.cloud"
    port = input("Please write your ThingsBoard \033[93mCoAP port\033[0m or leave it blank to use default (5683): ")
    config["port"] = int(port) if port else 5683
    config["provision_device_key"] = input("Please write \033[93mprovision device key\033[0m: ")
    config["provision_device_secret"] = input("Please write \033[93mprovision device secret\033[0m: ")
    config["token"] = input("Please write \033[93mdevice access token\033[0m: ")
    device_name = input("Please write \033[93mdevice name\033[0m or leave it blank to generate: ")
    if device_name:
        config["device_name"] = device_name
    print("\n", "="*80, "\n", sep="")
    return config


# Example for message to ThingsBoard
to_publish = {
  "stringKey": "value1",
  "booleanKey": True,
  "doubleKey": 42.0,
  "longKey": 73,
  "jsonKey": {
    "someNumber": 42,
    "someArray": [1, 2, 3],
    "someNestedObject": {"key": "value"}
  }
}


async def process():
    server_address = "coap://" + THINGSBOARD_HOST + ":" + str(THINGSBOARD_PORT)

    client_context = await Context.create_client_context()
    await asyncio.sleep(2)
    try:
        msg = Message(code=Code.POST, payload=str.encode(dumps(PROVISION_REQUEST)), uri=server_address+'/api/v1/provision')
        request = client_context.request(msg)
        try:
            response = await asyncio.wait_for(request.response, 60000)
        except asyncio.TimeoutError:
            raise Exception("Request timed out!")

        if response is None:
            raise Exception("Response is empty!")

        decoded_response = loads(response.payload)
        logging.info("Received response: %s", decoded_response)
        received_token = decoded_response.get("credentialsValue")
        if received_token is not None:
            msg = Message(code=Code.POST, payload=str.encode(dumps(to_publish)),
                          uri=server_address+('/api/v1/%s/telemetry' % received_token))
            request = client_context.request(msg)
            try:
                response = await asyncio.wait_for(request.response, 60000)
            except asyncio.TimeoutError:
                raise Exception("Request timed out!")

            if response:
                logging.info("[THINGSBOARD CLIENT] Response from Thingsboard.")
                logging.info(response)
            else:
                raise Exception("[THINGSBOARD CLIENT] Cannot save telemetry with received credentials!")
        else:
            logging.error("Failed to get access token from response.")
            logging.error(decoded_response.get("errorMsg"))
    except Exception as e:
        logging.error(e)
    finally:
        await client_context.shutdown()

if __name__ == '__main__':

    config = collect_required_data()

    THINGSBOARD_HOST = config["host"]  # ThingsBoard instance host
    THINGSBOARD_PORT = config["port"]  # ThingsBoard instance port

    PROVISION_REQUEST = {"provisionDeviceKey": config["provision_device_key"],  # Provision device key, replace this value with your value from device profile.
                         "provisionDeviceSecret": config["provision_device_secret"],  # Provision device secret, replace this value with your value from device profile.
                         "credentialsType": "ACCESS_TOKEN",
                         "token": config["token"],
                         }
    if config.get("device_name") is not None:
        PROVISION_REQUEST["deviceName"] = config["device_name"]

    asyncio.run(process())

下一步

  • 入门指南 - 快速学习ThingsBoard相关功能。

  • 安装指南 - 学习如何在各种操作系统上安装ThingsBoard。

  • 连接设备 - 学习如何根据你的连接方式或解决方案连接设备。

  • 可 视 化 - 学习如何配置复杂的ThingsBoard仪表板说明。

  • 数据处理 - 学习如何使用ThingsBoard规则引擎。

  • 数据分析 - 学习如何使用规则引擎执行基本的分析任务。

  • 硬件样品 - 学习如何将各种硬件平台连接到ThingsBoard。

  • 开发指南 - 学习ThingsBoard中的贡献和开发。