你可以依据 MQTT API参考文档 来开发设备固件中用于执行配置请求的功能。
如前所述,设备可以在注册过程中由服务器生成访问凭据或提供其自己的访问凭据。请参阅下面每个请求/响应和示例代码:
由服务端创建访问凭据
| Parameter | Example value | 描述 |
|---|---|---|
| deviceName | DEVICE_NAME | ThingsBoard中的设备名称。 |
| provisionDeviceKey | PUT_PROVISION_KEY_HERE | 设备批量化的键, 从已配置的设备配置文件中获取。 |
| provisionDeviceSecret | PUT_PROVISION_SECRET_HERE | 设备批量化的密钥的值,从已配置的设备配置文件中获取。 |
请求参数示例:
{"deviceName": "DEVICE_NAME","provisionDeviceKey": "PUT_PROVISION_KEY_HERE","provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE"}
响应示例:
{"status":"SUCCESS","credentialsType":"ACCESS_TOKEN","credentialsValue":"sLzc0gDAZPkGMzFVTyUY"}
示例脚本
为了与 ThingsBoard 通信,我们将使用 Paho MQTT 模块,因此我们应该安装它:
pip3 install paho-mqtt --user
下面提供了脚本源代码。您可以将其复制粘贴到文件中,例如:
device-provision-example.py
现在,按照以下步骤运行脚本。
您可以使用 python 3 启动脚本:
python3 device-provision-example.py
脚本源代码:
from paho.mqtt.client import Clientfrom json import dumps, loadsRESULT_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 (cloud.thingsboard.io): ")config["host"] = host if host else "cloud.thingsboard.io"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 1883config["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_nameprint("\n", "="*80, "\n", sep="")return configclass ProvisionClient(Client):PROVISION_REQUEST_TOPIC = "/provision/request"PROVISION_RESPONSE_TOPIC = "/provision/response"def __init__(self, host, port, provision_request):super().__init__()self._host = hostself._port = portself._username = "provision"self.on_connect = self.__on_connectself.on_message = self.__on_messageself.__provision_request = provision_requestdef __on_connect(self, client, userdata, flags, rc): # Callback for connectif rc == 0:print("[Provisioning client] Connected to ThingsBoard ")client.subscribe(self.PROVISION_RESPONSE_TOPIC) # Subscribe to provisioning response topicprovision_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 topicelse: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 = Noneif 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@staticmethoddef __get_credentials():new_credentials = Nonetry:with open("credentials", "r") as credentials_file:new_credentials = credentials_file.read()except Exception as e:print(e)return new_credentials@staticmethoddef __save_credentials(credentials):with open("credentials", "w") as credentials_file:credentials_file.write(credentials)@staticmethoddef __clean_credentials():open("credentials", "w").close()def on_tb_connected(client, userdata, flags, rc): # Callback for connect with received credentialsif 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 hostTHINGSBOARD_PORT = config["port"] # ThingsBoard instance MQTT portPROVISION_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 datatb_client = provision_client.get_new_client() # Getting client with provisioned dataif tb_client:tb_client.on_connect = on_tb_connected # Setting callback for connecttb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)tb_client.loop_forever() # Starting infinity loopelse:print("Client was not created!")
由设备提供访问令牌
| Parameter | Example value | Description |
|---|---|---|
| deviceName | DEVICE_NAME | Thingsboard中的设备名称。 |
| provisionDeviceKey | PUT_PROVISION_KEY_HERE | 设备批量化的键, 从已配置的设备配置文件中获取。 |
| provisionDeviceSecret | PUT_PROVISION_SECRET_HERE | 设备批量化的密钥,从已配置的设备配置文件中获取。 |
| credentialsType | ACCESS_TOKEN | 凭证类型参数。 |
| token | DEVICE_ACCESS_TOKEN | 设备访问 Thingsboard 的令牌 |
请求参数示例:
{"deviceName": "DEVICE_NAME","provisionDeviceKey": "PUT_PROVISION_KEY_HERE","provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE","credentialsType": "ACCESS_TOKEN","token": "DEVICE_ACCESS_TOKEN"}
响应示例:
{"credentialsType":"ACCESS_TOKEN","credentialsValue":"DEVICE_ACCESS_TOKEN","status":"SUCCESS"}
示例脚本
为了与 ThingsBoard 通信,我们将使用 Paho MQTT 模块,因此我们应该安装它:
pip3 install paho-mqtt --user
下面提供了脚本源代码。您可以将其复制粘贴到文件中,例如:
device-provision-example.py
现在,按照以下步骤运行脚本。
您可以使用 python 3 启动脚本:
python3 device-provision-example.py
脚本源代码:
from paho.mqtt.client import Clientfrom json import dumps, loadsRESULT_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 (cloud.thingsboard.io): ")config["host"] = host if host else "cloud.thingsboard.io"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 1883config["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_nameprint("\n", "="*80, "\n", sep="")return configclass ProvisionClient(Client):PROVISION_REQUEST_TOPIC = "/provision/request"PROVISION_RESPONSE_TOPIC = "/provision/response"def __init__(self, host, port, provision_request):super().__init__()self._host = hostself._port = portself._username = "provision"self.on_connect = self.__on_connectself.on_message = self.__on_messageself.__provision_request = provision_requestdef __on_connect(self, client, userdata, flags, rc): # Callback for connectif rc == 0:print("[Provisioning client] Connected to ThingsBoard ")client.subscribe(self.PROVISION_RESPONSE_TOPIC) # Subscribe to provisioning response topicprovision_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 topicelse: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 = Noneif 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@staticmethoddef __get_credentials():new_credentials = Nonetry:with open("credentials", "r") as credentials_file:new_credentials = credentials_file.read()except Exception as e:print(e)return new_credentials@staticmethoddef __save_credentials(credentials):with open("credentials", "w") as credentials_file:credentials_file.write(credentials)@staticmethoddef __clean_credentials():open("credentials", "w").close()def on_tb_connected(client, userdata, flags, rc): # Callback for connect with received credentialsif 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 hostTHINGSBOARD_PORT = config["port"] # ThingsBoard instance MQTT portPROVISION_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 datatb_client = provision_client.get_new_client() # Getting client with provisioned dataif tb_client:tb_client.on_connect = on_tb_connected # Setting callback for connecttb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)tb_client.loop_forever() # Starting infinity loopelse:print("Client was not created!")
设备提供基本的 MQTT 凭证
| Parameter | Example value | Description |
|---|---|---|
| deviceName | DEVICE_NAME | Thingsboard中的设备名称 |
| provisionDeviceKey | PUT_PROVISION_KEY_HERE | 设备批量化的键, 从已配置的设备配置文件中获取。 |
| provisionDeviceSecret | PUT_PROVISION_SECRET_HERE | 设备批量化的密钥,从已配置的设备配置文件中获取。 |
| credentialsType | MQTT_BASIC | 凭证类型参数。 |
| username | DEVICE_USERNAME_HERE | Thingsboard中设备的用户名。 |
| password | DEVICE_PASSWORD_HERE | Thingsboard中设备的密码。 |
| clientId | DEVICE_CLIENT_ID_HERE | Client id for device in ThingsBoard.设备在 Thingsboard 中的客户端 ID |
请求参数示例:
{"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"}
响应示例:
{"credentialsType":"MQTT_BASIC","credentialsValue": {"clientId":"DEVICE_CLIENT_ID_HERE","userName":"DEVICE_USERNAME_HERE","password":"DEVICE_PASSWORD_HERE"},"status":"SUCCESS"}
示例脚本
为了与 ThingsBoard 通信,我们将使用 Paho MQTT 模块,因此我们应该安装它:
pip3 install paho-mqtt --user
下面提供了脚本源代码。您可以将其复制粘贴到文件中,例如:
device-provision-example.py
现在,按照以下步骤运行脚本。
您可以使用python 3启动脚本:
python3 device-provision-example.py
脚本源代码:
from paho.mqtt.client import Clientfrom json import dumps, loadsRESULT_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 (cloud.thingsboard.io): ")config["host"] = host if host else "cloud.thingsboard.io"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 1883config["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_nameconfig["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 configclass ProvisionClient(Client):PROVISION_REQUEST_TOPIC = "/provision/request"PROVISION_RESPONSE_TOPIC = "/provision/response"def __init__(self, host, port, provision_request):super().__init__()self._host = hostself._port = portself._username = "provision"self.on_connect = self.__on_connectself.on_message = self.__on_messageself.__provision_request = provision_requestdef __on_connect(self, client, userdata, flags, rc): # Callback for connectif rc == 0:print("[Provisioning client] Connected to ThingsBoard ")client.subscribe(self.PROVISION_RESPONSE_TOPIC) # Subscribe to provisioning response topicprovision_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 topicelse: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 = Noneif client_credentials:new_client = Client(client_id=client_credentials["clientId"]) # Setting client idnew_client.username_pw_set(client_credentials["userName"], client_credentials["password"]) # Setting username and password for ThingsBoard clientprint("[Provisioning client] Read credentials from file.")else:print("[Provisioning client] Cannot read credentials from file!")return new_client@staticmethoddef __get_credentials():new_credentials = Nonetry:with open("credentials", "r") as credentials_file:new_credentials = credentials_file.read()except Exception as e:print(e)return new_credentials@staticmethoddef __save_credentials(credentials):with open("credentials", "w") as credentials_file:credentials_file.write(dumps(credentials))@staticmethoddef __clean_credentials():open("credentials", "w").close()def on_tb_connected(client, userdata, flags, rc): # Callback for connect with received credentialsif 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 hostTHINGSBOARD_PORT = config["port"] # ThingsBoard instance MQTT portPROVISION_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 datatb_client = provision_client.get_new_client() # Getting client with provisioned dataif tb_client:tb_client.on_connect = on_tb_connected # Setting callback for connecttb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)tb_client.loop_forever() # Starting infinity loopelse:print("Client was not created!")
设备提供X.509证书
:::info INFO: To use this feature, you should configure MQTT over SSL in ThingsBoard :::
| Parameter | Example value | Description |
|---|---|---|
| deviceName | DEVICE_NAME | 设备在Thingsboard中的名称。 |
| provisionDeviceKey | PUT_PROVISION_KEY_HERE | 设备批量化的键, 从已配置的设备配置文件中获取。 |
| provisionDeviceSecret | PUT_PROVISION_SECRET_HERE | 设备批量化的密钥,从已配置的设备配置文件中获取。 |
| credentialsType | X509_CERTIFICATE | 凭证类型参数。 |
| hash | MIIB……..AQAB | 设备提供X.509证书 |
预配请求数据示例:
{"deviceName": "DEVICE_NAME","provisionDeviceKey": "PUT_PROVISION_KEY_HERE","provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE","credentialsType": "X509_CERTIFICATE","hash": "MIIB........AQAB"}
预配响应示例:
{"deviceId":"3b829220-232f-11eb-9d5c-e9ed3235dff8","credentialsType":"X509_CERTIFICATE","credentialsId":"f307a1f717a12b32c27203cf77728d305d29f64694a8311be921070dd1259b3a","credentialsValue":"MIIB........AQAB","provisionDeviceStatus":"SUCCESS"}
MQTT示例脚本
要使用此脚本,请将 mqttserver.pub.pem (服务器的公钥) 放入带有脚本的文件夹中。
import sslfrom datetime import datetime, timedeltafrom cryptography import x509from cryptography.x509.oid import NameOIDfrom cryptography.hazmat.primitives import hashesfrom cryptography.hazmat.backends import default_backendfrom cryptography.hazmat.primitives import serializationfrom cryptography.hazmat.primitives.asymmetric import rsafrom paho.mqtt.client import Clientfrom json import dumps, loadsRESULT_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 (cloud.thingsboard.io): ")config["host"] = host if host else "cloud.thingsboard.io"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 8883config["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_nameprint("\n", "="*80, "\n", sep="")return configdef generate_certs(ca_certfile="mqttserver.pub.pem"):root_cert = Nonetry: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 = Nonekey = Nonetry: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, keyclass ProvisionClient(Client):PROVISION_REQUEST_TOPIC = "/provision/request"PROVISION_RESPONSE_TOPIC = "/provision/response"def __init__(self, host, port, provision_request):super().__init__()self._host = hostself._port = portself._username = "provision"self.tls_set(ca_certs="mqttserver.pub.pem", tls_version=ssl.PROTOCOL_TLSv1_2)self.on_connect = self.__on_connectself.on_message = self.__on_messageself.__provision_request = provision_requestdef __on_connect(self, client, userdata, flags, rc): # Callback for connectif rc == 0:print("[Provisioning client] Connected to ThingsBoard ")client.subscribe(self.PROVISION_RESPONSE_TOPIC) # Subscribe to provisioning response topicprovision_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 topicelse: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 = Noneif 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@staticmethoddef __get_credentials():new_credentials = Nonetry:with open("credentials", "r") as credentials_file:new_credentials = credentials_file.read()except Exception as e:print(e)return new_credentials@staticmethoddef __save_credentials(credentials):with open("credentials", "w") as credentials_file:credentials_file.write(credentials)@staticmethoddef __clean_credentials():open("credentials", "w").close()def on_tb_connected(client, userdata, flags, rc): # Callback for connect with received credentialsif 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 hostTHINGSBOARD_PORT = config["port"] # ThingsBoard instance MQTT portPROVISION_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 keycert, key = read_cert() # Read certificate and keyPROVISION_REQUEST["hash"] = certif PROVISION_REQUEST.get("hash") is not None:provision_client = ProvisionClient(THINGSBOARD_HOST, THINGSBOARD_PORT, PROVISION_REQUEST)provision_client.provision() # Request provisioned datatb_client = provision_client.get_new_client() # Getting client with provisioned dataif tb_client:tb_client.on_connect = on_tb_connected # Setting callback for connecttb_client.connect(THINGSBOARD_HOST, THINGSBOARD_PORT, 60)tb_client.loop_forever() # Starting infinity loopelse:print("Client was not created!")else:print("Cannot read certificate.")
