Stand with Ukraine flag
Pricing Try it now
Cloud
North America
Documentation > Other features > Device provisioning
Getting Started
Devices Library Guides API FAQ
On this page

Provisioning devices

Use Case description

As a device manufacturer or firmware developer, I would like my devices to automatically provision themselves in ThingsBoard. During the automatic provisioning, the device may either generate unique credentials or ask the server to provide unique credentials for the device.

From the 3.5 version, ThingsBoard allows the auto-provision of new devices on authentication over MQTT using X.509 Certificate chain.

How it works?

The device may send a device provisioning request (Request) to the ThingsBoard. The Request should always contain a Provision key and secret. The Request may optionally include the device name and credentials generated by the device. If those credentials are absent, the Server will generate an Access Token to be used by the device.

Provisioning request example:

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

The ThingsBoard validates the Request and replies with the device provisioning response (Response). The successful response contains device id, credentials type, and body. If the validation was not successful, the Response will contain only the status.

Provisioning response example:

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

During the validation of the Request, ThingsBoard will first check the supplied provisionDeviceKey and provisionDeviceSecret to find the corresponding Device Profile. Once the profile is found, the platform will use the configured provision strategy to validate the device name. There are two provision strategies available:

  • Allowing creating new devices - checks that the device with the same name has not registered in ThingsBoard yet. This strategy is useful when you don’t know the list of unique device names (MAC addresses, etc.) during manufacturing, but the device itself has access to this info in the firmware. It is easier to implement, but it is less secure than the second strategy.
  • Checking pre-provisioned devices - checks that the device with the same name has been already created in ThingsBoard, but hasn’t been provisioned yet. This strategy is useful when you want to allow provisioning only for a specific list of devices. Let’s assume that you have collected a list of unique IDS (MAC addresses, etc) during the manufacturing. You can use bulk provisioning to upload this list to ThingsBoard. Now, devices from the list can issue provision requests, and no other devices will be able to provision themselves.

Once the provisioning is complete, ThingsBoard will update provisionState server attribute of the device and will set it to provisioned value.

Device profile configuration

You should configure the device profile to enable provisioning feature, collect provision device key and provision device secret.

  • You can either create a new device profile or open the existing one. To create a new one you should open the Device profiles page and click on the "+" icon in the table header.
  • Input a name of the new device profile and click on Step 4 of the "Add device profile" wizard. We will use name "Device Provisioning Test" in this example. However, typically this should be your device model or similar.
  • Choose one of the provisioning strategies, copy the provisioning key and secret, and finally click "Add".

Provision Device APIs

MQTT Device APIs

You can use the MQTT API reference to develop your device firmware that will perform the provision request. As mentioned earlier, a device can request the server to generate the credentials or to provide its own credentials during the registration process. See request/response and code examples for each option below:

Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.

Provisioning request data example:

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

Provisioning response example:

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

Sample script

To communicate with ThingsBoard we will use Paho MQTT module, so we should install it:

1 
pip3 install paho-mqtt --user 

The script source code is available below. You may copy-paste it to a file, for example:

1 
device-provision-example.py 

Now you should run the script and follow the steps inside.
You may launch the script using python 3:

1 
python3 device-provision-example.py 

The script source code:

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 (mqtt.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!") 
Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.
credentialsType ACCESS_TOKEN Credentials type parameter.
token DEVICE_ACCESS_TOKEN Access token for device in ThingsBoard.

Provisioning request data example:

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

Provisioning response example:

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

Sample script

To communicate with ThingsBoard we will use Paho MQTT module, so we should install it:

1 
pip3 install paho-mqtt --user 

The script source code is available below. You may copy-paste it to a file, for example:

1 
device-provision-example.py 

Now you should run the script and follow the steps inside.
You may launch the script using python 3:

1 
python3 device-provision-example.py 

The script source code:

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 (mqtt.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!") 
Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.
credentialsType MQTT_BASIC Credentials type parameter.
username DEVICE_USERNAME_HERE Username for device in ThingsBoard.
password DEVICE_PASSWORD_HERE Password for device in ThingsBoard.
clientId DEVICE_CLIENT_ID_HERE Client id for device in ThingsBoard.

Provisioning request data example:

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

Provisioning response example:

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

Sample script

To communicate with ThingsBoard we will use Paho MQTT module, so we should install it:

1 
pip3 install paho-mqtt --user 

The script source code is available below. You may copy-paste it to a file, for example:

1 
device-provision-example.py 

Now you should run the script and follow the steps inside.
You may launch the script using python 3:

1 
python3 device-provision-example.py 

The script source code:

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 (mqtt.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!") 
Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.
credentialsType X509_CERTIFICATE Credentials type parameter.
hash MIIB……..AQAB Public key X509 hash for device in ThingsBoard.

Provisioning request data example:

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

Provisioning response example:

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

MQTT Example script

To use this script put your mqttserver.pub.pem (public key of the server) into the folder with script.

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 (mqtt.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 Device APIs

You may use the HTTP API reference to develop your device firmware that will perform the provision request. As mentioned earlier, the device may request server to generate the credentials or provide its own credentials during the registration process. See request/response and code examples for each option below:

Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.

Provisioning request data example:

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

Provisioning response example:

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

Sample script

The script source code is available below. You may copy-paste it to a file, for example:

1 
device-provision-example.py 

Now you should run the script and follow the steps inside.
You may launch the script using python 3:

1 
python3 device-provision-example.py 

The script source code:

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")) 
Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.
credentialsType ACCESS_TOKEN Credentials type parameter.
token DEVICE_ACCESS_TOKEN Access token for device in ThingsBoard.

Provisioning request data example:

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

Provisioning response example:

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

Sample script

The script source code is available below. You may copy-paste it to a file, for example:

1 
device-provision-example.py 

Now you should run the script and follow the steps inside.
You may launch the script using python 3:

1 
python3 device-provision-example.py 

The script source code:

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 Device APIs

You may use the CoAP API reference to develop your device firmware that will perform the provision request.
As mentioned earlier, the device may request server to generate the credentials or provide its own credentials during the registration process. See request/response and code examples for each option below:

Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.

Provisioning request data example:

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

Provisioning response example:

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

Sample script

To communicate with ThingsBoard we will use asyncio and aiocoap modules, so we should install it:

1 
pip3 install asyncio aiocoap --user 

The script source code is available below. You may copy-paste it to a file, for example:

1 
device-provision-example.py 

Now you should run the script and follow the steps inside.
You may launch the script using python 3:

1 
python3 device-provision-example.py 

The script source code:

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 (coap.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()) 
Parameter Example value Description
deviceName DEVICE_NAME Device name in ThingsBoard.
provisionDeviceKey PUT_PROVISION_KEY_HERE Provisioning device key, you should take it from configured device profile.
provisionDeviceSecret PUT_PROVISION_SECRET_HERE Provisioning device secret, you should take it from configured device profile.
credentialsType ACCESS_TOKEN Credentials type parameter.
token DEVICE_ACCESS_TOKEN Access token for device in ThingsBoard.

Provisioning request data example:

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

Provisioning response example:

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

Sample script

To communicate with ThingsBoard we will use asyncio and aiocoap modules, so we should install it:

1 
pip3 install asyncio aiocoap --user 

The script source code is available below. You may copy-paste it to a file, for example:

1 
device-provision-example.py 

Now you should run the script and follow the steps inside.
You may launch the script using python 3:

1 
python3 device-provision-example.py 

The script source code:

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 (coap.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()) 

Next steps