پیکربندی دستگاه
شرح مورد استفاده
به عنوان یک تولیدکننده دستگاه یا توسعهدهنده فریمور، مایلم دستگاههایم بهصورت خودکار در ThingsConnect تأمین شوند. در طی فرآیند تأمین خودکار، دستگاه ممکن است بهطور خودکار اعتبارنامههای منحصربهفردی تولید کند یا از سرور درخواست کند تا این اعتبارنامهها را برای آن فراهم نماید.
از نسخه 3.5، ThingsConnect امکان تأمین خودکار دستگاههای جدید را در هنگام احراز هویت از طریق MQTT با استفاده از زنجیره گواهی X.509 فراهم میکند.
نحوه عملکرد
https://img.thingsboard.io/user-guide/device-provisioning/flow.svg
دستگاه ممکن است یک درخواست تأمین دستگاه (Request) به ThingsConnect ارسال کند. این درخواست باید همواره شامل یک کلید تأمین (Provision key) و یک کد محرمانه (secret) باشد. همچنین، درخواست میتواند بهصورت اختیاری شامل نام دستگاه و اعتبارنامههایی باشد که توسط دستگاه تولید شدهاند. در صورتی که این اعتبارنامهها وجود نداشته باشند، سرور یک توکن دسترسی (Access Token) برای استفاده دستگاه تولید خواهد کرد.
نمونه درخواست تأمین:
{
"deviceName": "DEVICE_NAME",
"provisionDeviceKey": "YOUR_PROVISION_KEY_HERE",
"provisionDeviceSecret": "YOUR_PROVISION_SECRET_HERE"
}
ThingsConnect درخواست تأمین را اعتبارسنجی کرده و با پاسخ تأمین دستگاه (Response) پاسخ میدهد. در پاسخ موفق، شناسه دستگاه (device id)، نوع اعتبارنامه (credentials type) و بدنه (body) ارائه میشود. اگر اعتبارسنجی موفقیتآمیز نباشد، پاسخ تنها شامل وضعیت (status) خواهد بود.
نمونه پاسخ تأمین:
{
"provisionDeviceStatus":"SUCCESS",
"credentialsType":"ACCESS_TOKEN",
"accessToken":"sLzc0gDAZPkGMzFVTyUY"
}
در طی فرآیند اعتبارسنجی درخواست، ThingsConnect ابتدا کلید تأمین دستگاه (provisionDeviceKey) و کد محرمانه تأمین دستگاه (provisionDeviceSecret) ارائهشده را بررسی میکند تا پروفایل دستگاه مربوطه را پیدا کند. پس از یافتن پروفایل، پلتفرم از استراتژی تأمین پیکربندیشده برای اعتبارسنجی نام دستگاه استفاده میکند. دو استراتژی تأمین موجود است:
- اجازه ایجاد دستگاههای جدید – این استراتژی بررسی میکند که دستگاهی با همان نام قبلاً در ThingsConnect ثبت نشده باشد. این روش زمانی مفید است که هنگام تولید دستگاهها لیستی از نامهای منحصربهفرد دستگاهها (مانند آدرس MAC و غیره) در دسترس نیست، اما خود دستگاه به این اطلاعات در فریمور دسترسی دارد. پیادهسازی آن آسانتر است، اما امنیت کمتری نسبت به استراتژی دوم دارد.
- بررسی دستگاههای از پیش تأمینشده – این استراتژی بررسی میکند که دستگاهی با همان نام قبلاً در ThingsConnect ایجاد شده، اما هنوز تأمین نشده باشد. این روش زمانی مفید است که میخواهید تأمین دستگاهها را فقط برای یک لیست خاص از دستگاهها مجاز کنید. فرض کنیم که شما لیستی از شناسههای منحصربهفرد (مانند آدرس MAC و غیره) را در طی فرآیند تولید جمعآوری کردهاید. میتوانید از تأمین به صورت عمده استفاده کنید تا این لیست را در ThingsConnect آپلود کنید. اکنون، دستگاههای موجود در این لیست میتوانند درخواست تأمین ارسال کنند و سایر دستگاهها قادر به تأمین خودکار نخواهند بود.
پس از تکمیل فرآیند تأمین، ThingsConnect ویژگی سرور provisionState دستگاه را به مقدار «تأمینشده» بهروزرسانی خواهد کرد.
پیکربندی پروفایل دستگاه
برای فعالسازی قابلیت تأمین، باید پروفایل دستگاه را پیکربندی کرده و کلید و کد محرمانه تأمین دستگاه را جمعآوری کنید.
- میتوانید یک پروفایل دستگاه جدید ایجاد کنید یا پروفایل موجود را باز کنید. برای ایجاد یک پروفایل جدید، صفحه پروفایلهای دستگاه را باز کرده و روی آیکون «+» در بالای جدول کلیک کنید.
- نامی برای پروفایل جدید وارد کرده و سپس به مرحله 4 از جادوگر «افزودن پروفایل دستگاه» بروید. در این مثال، از نام «آزمایش تأمین دستگاه» استفاده میکنیم. با این حال، معمولاً باید نام مدل دستگاه شما یا مشابه آن باشد.
- یکی از استراتژیهای تأمین را انتخاب کنید، کلید تأمین و کد محرمانه را کپی کرده و در نهایت روی «افزودن» کلیک کنید.
APIهای تأمین دستگاه
APIهای MQTT دستگاه
میتوانید از مرجع APIهای MQTT برای توسعه فریمور دستگاه خود استفاده کنید که درخواست تأمین را انجام دهد. همانطور که پیشتر ذکر شد، دستگاه میتواند در طول فرآیند ثبتنام از سرور درخواست کند که اعتبارنامهها را تولید کند یا اعتبارنامههای خود را ارائه دهد. نمونههای درخواست/پاسخ و کد برای هر یک از این گزینهها در ادامه آمده است:
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"deviceName": "DEVICE_NAME",
"provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
"provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE"
}
نمونه پاسخ تأمین:
{
"status":"SUCCESS",
"credentialsType":"ACCESS_TOKEN",
"credentialsValue":"sLzc0gDAZPkGMzFVTyUY"
}
نمونه اسکریپت
برای ارتباط با ThingsConnect از ماژول Paho MQTT استفاده خواهیم کرد، بنابراین باید آن را نصب کنیم:
pip3 install paho-mqtt --user
کد منبع اسکریپت در ادامه ارائه شده است. میتوانید آن را کپی کرده و در یک فایل ذخیره کنید، برای مثال:
python3 device-provision-example.py
اکنون باید اسکریپت را اجرا کرده و مراحل داخل آن را دنبال کنید.
میتوانید اسکریپت را با استفاده از Python 3 اجرا کنید:
python3 device-provision-example.py
کد منبع اسکریپت:
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!")
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"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"
}
نمونه اسکریپت
برای ارتباط با ThingsConnect از ماژول Paho MQTT استفاده خواهیم کرد، بنابراین باید آن را نصب کنیم:
pip3 install paho-mqtt --user
کد منبع اسکریپت در ادامه ارائه شده است. میتوانید آن را کپی کرده و در یک فایل ذخیره کنید، برای مثال:
device-provision-example.py
اکنون باید اسکریپت را اجرا کرده و مراحل داخل آن را دنبال کنید.
میتوانید اسکریپت را با استفاده از Python 3 اجرا کنید:
python3 device-provision-example.py
کد منبع اسکریپت:
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!")
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"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
برای تغییر این متن بر روی دکمه ویرایش کلیک کنید. لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.
console.log( 'Code is Poetry' );
حالا باید اسکریپت را اجرا کرده و مراحل داخل آن را دنبال کنید.
میتوانید اسکریپت را با استفاده از Python 3 اجرا کنید:
python3 device-provision-example.py
کد منبع اسکریپت:
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!")
اطلاعات: برای استفاده از این ویژگی، باید MQTT را بر روی SSL در ThingsConnect پیکربندی کنید.
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"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 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.")
API دستگاه HTTP
شما میتوانید از مرجع API HTTP برای توسعهی فریمور دستگاه خود که درخواست تأمین را انجام میدهد، استفاده کنید. همانطور که قبلاً ذکر شد، دستگاه ممکن است از سرور درخواست کند تا اعتبارنامهها را تولید کند یا خود اعتبارنامههای خود را در طول فرآیند ثبتنام ارائه دهد. برای مشاهده درخواست/پاسخها و مثالهای کد مربوط به هر گزینه، به شرح زیر مراجعه کنید:
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"deviceName": "DEVICE_NAME",
"provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
"provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE"
}
نمونه پاسخ تأمین:
{
"status":"SUCCESS",
"credentialsType":"ACCESS_TOKEN",
"credentialsValue":"sLzc0gDAZPkGMzFVTyUY"
}
نمونه اسکریپت
کد منبع اسکریپت در زیر در دسترس است. میتوانید آن را کپی کرده و در یک فایل ذخیره کنید، برای مثال:
device-provision-example.py
اکنون باید اسکریپت را اجرا کرده و مراحل داخل آن را دنبال کنید.
میتوانید اسکریپت را با استفاده از Python 3 اجرا کنید:
python3 device-provision-example.py
کد منبع اسکریپت:
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"))
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"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"
}
نمونه اسکریپت
کد منبع اسکریپت در زیر در دسترس است. میتوانید آن را کپی کرده و در یک فایل ذخیره کنید، برای مثال:
device-provision-example.py
اکنون باید اسکریپت را اجرا کرده و مراحل داخل آن را دنبال کنید.
میتوانید اسکریپت را با استفاده از Python 3 اجرا کنید:
python3 device-provision-example.py
کد منبع اسکریپت:
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"))
API دستگاه CoAP
شما میتوانید از مرجع API CoAP برای توسعهی فریمور دستگاه خود که درخواست تأمین را انجام میدهد، استفاده کنید. همانطور که قبلاً ذکر شد، دستگاه ممکن است از سرور درخواست کند تا اعتبارنامهها را تولید کند یا خود اعتبارنامههای خود را در طول فرآیند ثبتنام ارائه دهد. برای مشاهده درخواست/پاسخها و مثالهای کد مربوط به هر گزینه، به شرح زیر مراجعه کنید:
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"deviceName": "DEVICE_NAME",
"provisionDeviceKey": "PUT_PROVISION_KEY_HERE",
"provisionDeviceSecret": "PUT_PROVISION_SECRET_HERE"
}
نمونه پاسخ تأمین:
{
"status":"SUCCESS",
"credentialsType":"ACCESS_TOKEN",
"credentialsValue":"sLzc0gDAZPkGMzFVTyUY"
}
نمونه اسکریپت
برای ارتباط با ThingsBoard از ماژولهای asyncio و aiocoap استفاده خواهیم کرد، بنابراین باید آنها را نصب کنیم
pip3 install asyncio aiocoap --user
کد منبع اسکریپت در زیر در دسترس است. میتوانید آن را کپی کرده و در یک فایل ذخیره کنید، برای مثال:
device-provision-example.py
اکنون باید اسکریپت را اجرا کرده و مراحل داخل آن را دنبال کنید.
میتوانید اسکریپت را با استفاده از Python 3 اجرا کنید:
python3 device-provision-example.py
کد منبع اسکریپت:
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())
فیلد |
نوع داده |
داده ورودی |
---|---|---|
latitude |
Double |
(عرض جغرافیایی دارایی) |
longitude |
Double |
(عرض جغرافیایی دارایی) |
units |
String |
"metric" برای سرعت باد به متر بر ثانیه و دمای سلسیوس، "imperial" برای سرعت باد به مایل بر ساعت و دمای فارنهایت، یا خالی برای سرعت باد به متر بر ثانیه و دمای کلوین |
نمونه دادههای درخواست تأمین:
{
"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 از ماژولهای asyncio و aiocoap استفاده خواهیم کرد، بنابراین باید آنها را نصب کنیم:
pip3 install asyncio aiocoap --user
کد منبع اسکریپت در زیر در دسترس است. میتوانید آن را کپی کرده و در یک فایل ذخیره کنید، برای مثال:
device-provision-example.py
اکنون باید اسکریپت را اجرا کرده و مراحل داخل آن را دنبال کنید.
میتوانید اسکریپت را با استفاده از Python 3 اجرا کنید:
python3 device-provision-example.py
کد منبع اسکریپت:
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())
مراحل بعدی
- راهنماهای شروع به کار: این راهنماها یک مرور سریع از ویژگیهای اصلی ThingsConnect ارائه میدهند. طراحی شدهاند تا در ۱۵ تا ۳۰ دقیقه تکمیل شوند.
- اتصال دستگاه خود: یاد بگیرید که چگونه دستگاهها را بر اساس فناوری یا راهحل اتصال خود متصل کنید.
- بصریسازی دادهها: این راهنماها شامل دستورالعملهایی برای پیکربندی داشبوردهای پیچیده در ThingsConnect هستند.
- پردازش دادهها و اقدامات: یاد بگیرید که چگونه از موتور قوانین ThingsConnect استفاده کنید.
- تحلیل دادههای IoT: یاد بگیرید که چگونه از موتور قوانین برای انجام وظایف تحلیلی پایه استفاده کنید.
- نمونههای سختافزاری: یاد بگیرید که چگونه پلتفرمهای مختلف سختافزاری را به ThingsConnect متصل کنید.
- مشارکت و توسعه: درباره مشارکت و توسعه در ThingsConnect بیشتر بدانید. ThingsConnect