نحوه اتصال Lenovo Leez SBC P710 به ThingsConnect
مقدمه
لنوو لیز اسبیسی پی۷۱۰ یک رایانهی تکتکه (Single-Board Computer) است که برای سازندگان و توسعهدهندگان طراحی شده است.
این رایانه دارای یک پردازندهی چهار هستهای ARM Cortex-A53 با نام Allwinner H5، ۲ گیگابایت حافظهی DDR3، ۱۶ گیگابایت حافظهی فلش eMMC و یک GPU Mali-450MP4 است.
همچنین از اترنت گیگابیت، Wi-Fi 802.11ac و بلوتوث ۴.۲ برای اتصال استفاده میکند، همچنین پورتهای مختلفی برای دستگاهها و توسعهها دارد.
در این راهنما، خواهیم آموخت که چگونه دستگاهی را در Thingsboard ایجاد کنیم، کتابخانهها و ابزارهای مورد نیاز را نصب کنیم.
سپس کد خود را تغییر داده و آن را بر روی دستگاه آپلود کرده و نتایج کدزنی را و با استفاده از داشبورد وارد شده، دادهها را در ThingsBoard بررسی خواهیم کرد. دستگاه ما با استفاده از قابلیت درخواستهای مشترک و ویژگیهای اشتراکی با ThingsBoard همگام میشود.
البته، ما قادر خواهیم بود دستگاه خود را با استفاده از قابلیتهای ارائه شده مانند ویژگیهای اشتراکی یا درخواستهای RPC کنترل کنیم.
پیشنیازها
برای ادامهی این راهنما، به موارد زیر نیاز خواهیم داشت:
- Lenovo Leez SBC P710
- کتابخانه tb-mqtt-client
- Python ≥ 3.7
- Adafruit-Blinka
- حساب کاربری ThingsBoard
ایجاد دستگاه در ThingsBoard
بهمنظور سادگی، ما دستگاه را بهصورت دستی ایجاد خواهیم کرد و از رابط کاربری (UI) استفاده میکنیم.
- به نمونه ThingsBoard خود وارد شوید و به بخش “Entities” رفته و سپس روی صفحه “Devices” کلیک کنید.
- بر روی آیکون “+” در گوشهی بالا و سمت راست جدول کلیک کنید و سپس “Add new device” را انتخاب کنید.
- نام دستگاه را وارد کنید. بهعنوان مثال، “دستگاه من”. در این مرحله نیازی به تغییر دیگری نیست. روی “Add” کلیک کنید تا دستگاه اضافه شود.
- دستگاه شما اضافه شده است.
//Img
نصب کتابخانهها و ابزارهای مورد نیاز
شما باید کتابخانه thingsboard-python-client-sdk را نصب کرده باشید که با استفاده از دستور زیر قابل نصب است. با این حال، ما توصیه میکنیم که بستهها را در محیطی خارج از محیط سراسری نصب کنید:
pip3 install tb-mqtt-client
همچنین، شما باید ابزارهایی را که به شما امکان ویرایش کد را میدهد نصب کنید. به عنوان مثال، شما میتوانید از ویرایشگر Nano که پیشفرض استفاده میشود استفاده کنید، یا هر ویرایشگر کد دیگری که با آن آشنایی دارید را نصب کنید.
اتصال دستگاه به ThingsBoard
برای اتصال دستگاه، ابتدا باید اطلاعات اعتبارهای دستگاه را دریافت کنید. ThingsBoard از انواع مختلف اعتبارهای دستگاه پشتیبانی میکند. ما توصیه میکنیم که برای این راهنما از اعتبارهای پیشفرضی که به طور خودکار تولید میشوند و توکن دسترسی را در بر میگیرند استفاده کنید.
- بر روی ردیف دستگاه در جدول کلیک کنید تا جزئیات دستگاه را باز کنید.
- روی “Copy access token” کلیک کنید. توکن در کلیپبورد شما کپی میشود. لطفاً آن را در یک مکان امن ذخیره کنید.
//img
حالا شما آماده هستید تا دادههای تلمتری به نیابت از دستگاهتان منتشر کنید. همانطور که قبلاً گفته شد، از کتابخانه “thingsboard-python-client-sdk” استفاده خواهیم کرد. بیایید پروژه خود را راهاندازی کنیم:
- ایجاد پوشه پروژه:
mkdir thingsboard_example && cd thingsboard_example
- نصب بستهها:
pip install tb-mqtt-client
- ایجاد اسکریپت اصلی:
nano main.py
- کد زیر را کپی و در آن روی paste کنید:
import logging.handlers import time import os from tb_gateway_mqtt import TBDeviceMqttClient ACCESS_TOKEN = "TEST_TOKEN" THINGSBOARD_SERVER = 'demo.thingsboard.io' THINGSBOARD_PORT = 1883 logging.basicConfig(level=logging.DEBUG) client = None # default blinking period period = 1.0 # callback function that will call when we will change value of our Shared Attribute def attribute_callback(result, _): print(result) # make sure that you paste YOUR shared attribute name period = result.get('blinkingPeriod', 1.0) # callback function that will call when we will send RPC def rpc_callback(id, request_body): # request body contains method and other parameters print(request_body) method = request_body.get('method') if method == 'getTelemetry': attributes, telemetry = get_data() client.send_attributes(attributes) client.send_telemetry(telemetry) else: print('Unknown method: ' + method) def get_data(): cpu_usage = round(float(os.popen('''grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage }' ''').readline().replace('\n', '').replace(',', '.')), 2) ip_address = os.popen('''hostname -I''').readline().replace('\n', '').replace(',', '.')[:-1] mac_address = os.popen('''cat /sys/class/net/*/address''').readline().replace('\n', '').replace(',', '.') processes_count = os.popen('''ps -Al | grep -c bash''').readline().replace('\n', '').replace(',', '.')[:-1] swap_memory_usage = os.popen("free -m | grep Swap | awk '{print ($3/$2)*100}'").readline().replace('\n', '').replace(',', '.')[:-1] ram_usage = float(os.popen("free -m | grep Mem | awk '{print ($3/$2) * 100}'").readline().replace('\n', '').replace(',', '.')[:-1]) st = os.statvfs('/') used = (st.f_blocks - st.f_bfree) * st.f_frsize boot_time = os.popen('uptime -p').read()[:-1] avg_load = (cpu_usage + ram_usage) / 2 attributes = { 'ip_address': ip_address, 'macaddress': mac_address } telemetry = { 'cpu_usage': cpu_usage, 'processes_count': processes_count, 'disk_usage': used, 'RAM_usage': ram_usage, 'swap_memory_usage': swap_memory_usage, 'boot_time': boot_time, 'avg_load': avg_load } print(attributes, telemetry) return attributes, telemetry # request attribute callback def sync_state(result, exception=None): global period if exception is not None: print("Exception: " + str(exception)) else: period = result.get('shared', {'blinkingPeriod': 1.0})['blinkingPeriod'] def main(): global client client = TBDeviceMqttClient(THINGSBOARD_SERVER, THINGSBOARD_PORT, ACCESS_TOKEN) client.connect() client.request_attributes(shared_keys=['blinkingPeriod'], callback=sync_state) # now attribute_callback will process shared attribute request from server sub_id_1 = client.subscribe_to_attribute("blinkingPeriod", attribute_callback) sub_id_2 = client.subscribe_to_all_attributes(attribute_callback) # now rpc_callback will process rpc requests from server client.set_server_side_rpc_request_handler(rpc_callback) while not client.stopped: attributes, telemetry = get_data() client.send_attributes(attributes) client.send_telemetry(telemetry) time.sleep(60) if __name__=='__main__': if ACCESS_TOKEN != "TEST_TOKEN": main() else: print("Please change the ACCESS_TOKEN variable to match your device access token and run script again.")
در کد فوق، مقادیر متغیرهای زیر را به مقادیر اعتبارهای خود تغییر دهید – THINGSBOARD_SERVER و ACCESS_TOKEN.
متغیرهای ضروری برای اتصال:
//جدول
- برای ذخیره کردن فایل، کلیدهای Ctrl+X و سپس Ctrl+O را فشار دهید.
- و در نهایت، بیایید اسکریپت خود را اجرا کنیم:
python3 main.py
اگر همه چیز را به درستی انجام داده باشید، باید خروجی کنسول زیر را مشاهده کنید:
> INFO:tb_device_mqtt:connection SUCCESS > > > {'ip_address': '192.168.1.198', 'macaddress': '3c:06:30:44:e0:24'} {'cpu_usage': 6.6, 'processes_count': 8, 'disk_usage': 70.0, 'RAM_usage': 73.9, 'swap_memory_usage': 69.4, 'battery': 29, 'boot_time': 1675154176.0} >
بیایید کد خود را مرور کرده و توضیحی در مورد آن ارائه دهیم. در این مرحله، ما به تابع get_data علاقهمندیم. در این تابع، دادهها بستهبندی میشوند و در صورت نیاز میتوانید به راحتی اطلاعات تلمتری یا ویژگیهای جدید را به دیکشنری اضافه کنید اگر میخواهید مقادیر بیشتری را نظارت کنید:
... def get_data(): cpu_usage = round(float(os.popen('''grep 'cpu ' /proc/stat | awk '{usage=($2+$4)*100/($2+$4+$5)} END {print usage }' ''').readline().replace('\n', '').replace(',', '.')), 2) ip_address = os.popen('''hostname -I''').readline().replace('\n', '').replace(',', '.')[:-1] mac_address = os.popen('''cat /sys/class/net/*/address''').readline().replace('\n', '').replace(',', '.') processes_count = os.popen('''ps -Al | grep -c bash''').readline().replace('\n', '').replace(',', '.')[:-1] swap_memory_usage = os.popen("free -m | grep Swap | awk '{print ($3/$2)*100}'").readline().replace('\n', '').replace(',', '.')[:-1] ram_usage = float(os.popen("free -m | grep Mem | awk '{print ($3/$2) * 100}'").readline().replace('\n', '').replace(',', '.')[:-1]) st = os.statvfs('/') used = (st.f_blocks - st.f_bfree) * st.f_frsize boot_time = os.popen('uptime -p').read()[:-1] avg_load = (cpu_usage + ram_usage) / 2 attributes = { 'ip_address': ip_address, 'macaddress': mac_address } telemetry = { 'cpu_usage': cpu_usage, 'processes_count': processes_count, 'disk_usage': used, 'RAM_usage': ram_usage, 'swap_memory_usage': swap_memory_usage, 'boot_time': boot_time, 'avg_load': avg_load } print(attributes, telemetry) return attributes, telemetry ...
بخش ارسال داده، همانطور که در زیر مشاهده میکنید، ما ویژگیها و دادههای تلمتری خود را هر ۶۰ ثانیه ارسال میکنیم (اگر میخواهید بروزرسانیهای دادهها به صورت مکررتر انجام شود، میتوانید آن را تغییر دهید):
... while not client.stopped: attributes, telemetry = get_data() client.send_attributes(attributes) client.send_telemetry(telemetry) time.sleep(60) ...
همگامسازی وضعیت دستگاه با استفاده از درخواستهای کلاینت و صفات مشترک
فراموش نکنید که ویژگی اشتراکی با نام “blinkingPeriod” را بر روی دستگاه خود ایجاد کنید.
برای دریافت وضعیت دستگاه از ThingsBoard در هنگام بوت شدن، قابلیتی در کد وجود دارد که این کار را انجام میدهد. بخشهای مسئول در کد نمونه عبارتند از:
تابع بازخورد ویژگیها (Attribute callback):
def sync_state(result, exception=None): global period if exception is not None: print("Exception: " + str(exception)) else: period = result.get('shared', {'blinkingPeriod': 1.0})['blinkingPeriod']
درخواست ویژگی:
def main(): client = TBDeviceMqttClient("thingsboard.cloud", 1883, "ACCESS_TOKEN") client.connect() client.request_attributes(shared_keys=['blinkingPeriod'], callback=sync_state) ...
برای قادرساختن کالبکهایمان به دریافت دادهها، باید یک درخواست به ThingsBoard ارسال کنیم. این قابلیت به ما امکان میدهد تا پس از راهاندازی مجدد، وضعیت فعلی را حفظ کنیم.
بررسی دادهها در ThingsBoard
پس از موفقیتآمیز انتشار ویژگیها و دادههای تلمتری، باید آنها را بلافاصله در بخش “تلمتری دستگاه” مشاهده کنید:
- روی ردیف دستگاه در جدول کلیک کنید تا جزئیات دستگاه را باز کنید.
- به بخش تلمتری هدایت شوید.
//img
همچنین، بیایید ویژگیها و دادههای تلمتری یک رایانهی تک برد را در یک داشبورد نمایش دهیم. برای این کار، شما میتوانید یک داشبورد سفارشی با ویجتهای دلخواه خود ایجاد کنید یا از یک داشبورد آماده استفاده کرده و آن را به سادگی وارد کنید.
- داشبورد وارداتی
- داشبورد جدید
وارد کردن داشبورد
شما قادرید یک داشبورد را به فرمت JSON وارد کنید. برای وارد کردن یک داشبورد، باید به گروه داشبورد بروید و روی دکمه “+” در گوشه سمت راست صفحه کلیک کرده و “وارد کردن داشبورد” را انتخاب کنید. پنجره وارد کردن داشبورد ظاهر خواهد شد و شما مجبور میشوید فایل JSON را بارگذاری کرده و روی “وارد کردن” کلیک کنید.
//img
در زیر شما میتوانید فایل JSON داشبورد را بیابید:
بررسی و کنترل دادههای داشبورد دستگاه
بعد از وارد کردن، باید برای دستگاه خود نام مستعار موجودیت را انتخاب کنیم.
برای انجام این کار، باید بر روی آیکون قلم نشانه گذاری کنیم و مستعارهای موجودیت را انتخاب کنیم، سپس مستعار “دستگاه من” را انتخاب و با فشار دادن آیکون قلم آن را برای ویرایش باز کنیم.
سپس دستگاهی با نام “دستگاه من” را از فهرست کشویی انتخاب کنید و مستعار موجودیت را ذخیره کنید. حالا باید قادر باشید دادهها را از دستگاه مشاهده کنید.
اگر همه چیز را به درستی انجام داده باشید، باید داشبورد زیر را ببینید:
//img
در زیر میتوانید فایل JSON داشبورد را بیابید:
چک و کنترل دادههای دستگاه
بعد از وارد کردن، باید برای دستگاه خود یک نام مستعار برگزینیم.
برای این کار، باید بر روی آیکون قلم کلیک کنیم و سپس “نام مستعارهای دستگاه” را انتخاب کنیم، نام مستعار “دستگاه من” را انتخاب و با فشار دادن آیکون قلم آن را برای ویرایش باز کنیم.
سپس دستگاهی با نام “دستگاه من” را از فهرست کشویی انتخاب کنید و نام مستعار دستگاه را ذخیره کنید، اکنون باید قادر به مشاهده دادههای دستگاه خود باشید.
اگر همه چیز را به درستی انجام دادید، باید داشبورد زیر را مشاهده کنید:
//img
ایجاد داشبورد جدید
ما یک داشبورد جدید ایجاد میکنیم و ابزارکهای محبوب را اضافه میکنیم. دستورالعملها را در زیر ببینید.
- صفحه داشبوردها را باز کنید. بر روی آیکون “+” در گوشه سمت راست کلیک کنید. “ایجاد
- داشبورد جدید” را انتخاب کنید.
نام داشبورد را وارد کنید. به عنوان مثال، “داشبورد جدید من”. برای اضافه کردن داشبورد، بر روی “افزودن” کلیک کنید. - اکنون داشبورد شما باید در ابتدای لیست قرار گیرد زیرا جدول داشبوردها را به طور پیش فرض بر اساس زمان ایجاد مرتب میکند. بر روی آیکون “باز کردن داشبورد” کلیک کنید.
//img
افزودن نام مستعار موجودیت
نام مستعار یک ارجاع به یک موجودیت یا گروهی از موجودیتها است که در ابزارکها استفاده میشود. یک نام مستعار ممکن است ثابت یا پویا باشد. برای سادگی، ما از نام مستعار “Single entity” استفاده خواهیم کرد که به یک موجودیت تکی (“OrangePI” در مورد ما) ارجاع میدهد. ممکن است یک نام مستعار را پیکربندی کنید که به چندین دستگاه ارجاع دهد. به عنوان مثال، دستگاههایی از یک نوع خاص یا مرتبط با یک دارایی خاص. میتوانید بیشتر درباره نام مستعارهای مختلف اطلاعات بیابید.
- وارد حالت ویرایش شوید. بر روی دکمه مداد در گوشه پایین سمت راست کلیک کنید.
- در قسمت بالا سمت راست صفحه روی آیکون “نام مستعار موجودیتها” کلیک کنید. لیست خالی از نام مستعارهای موجودیت را مشاهده خواهید کرد.
- بر روی “افزودن نام مستعار” کلیک کنید.
- نام مستعار را وارد کنید، به عنوان مثال “OrangePI”. نوع فیلتر را به “Single entity” تنظیم کنید. نوع را به “Device” تنظیم کنید و “My New” را تایپ کنید تا قابلیت تکمیل خودکار فعال شود. دستگاه خود را از موارد پیشنهاد شده انتخاب کرده و روی آن کلیک کنید.
- روی “افزودن” و سپس “ذخیره” کلیک کنید.
- در نهایت، در ویرایشگر داشبورد بر روی “اعمال تغییرات” کلیک کنید تا تغییرات ذخیره شوند. سپس باید دوباره وارد حالت ویرایش شوید.
//img
برای اضافه کردن ویجت جدید، باید آن را از کتابخانه ویجت انتخاب کنیم. ویجتها به بستههای ویجت تقسیم میشوند. هر ویجت منبع دادهای دارد. این است که ویجت “میداند” چه دادههایی را نمایش دهد. برای مشاهده آخرین مقدار داده “cpu_usage” که در مرحله 2 ارسال کردیم، باید منبع داده را پیکربندی کنیم.
- وارد حالت ویرایش شوید. بر روی دکمه “افزودن ویجت جدید” کلیک کنید.
- بسته ویجت “نمودارها” را انتخاب کنید. بر روی هدر ویجت “موجودیتها” کلیک کنید. پنجره “افزودن ویجت” ظاهر خواهد شد.
- برای افزودن منبع داده روی “افزودن” کلیک کنید. یک ویجت ممکن است چندین منبع داده داشته باشد، اما در این مورد فقط از یک منبع استفاده خواهیم کرد.
- منبع داده “OrangePI” را انتخاب کنید. سپس بر روی فیلد ورودی در سمت راست کلیک کنید. تکمیل خودکار با نقاط دادههای در دسترس ظاهر میشود. نقطه داده “cpu_usage” را انتخاب کرده و روی “افزودن” کلیک کنید.
- ویجت را تغییر اندازه داده تا کمی بزرگتر شود. فقط گوشه پایین سمت راست ویجت را بکشید. همچنین اگر میخواهید ویجت را ویرایش کنید، میتوانید با تنظیمات پیشرفته بازی کنید.
کنترل دستگاه با استفاده از ویژگیهای مشترک
فراموش نکنید ویژگی مشترک “blinkingPeriod” را بر روی دستگاه خود ایجاد کنید.
علاوه بر این، میتوانیم با استفاده از قابلیت بهروزرسانی ویژگی مشترک، دوره چشمکزنی را تغییر دهیم.
این نوع ویژگی تنها برای دستگاهها در دسترس است. آن شبیه به ویژگیهای سمت سرور است اما تفاوت مهمی دارد. برنامه و رابط کاربری دستگاه میتواند درخواست مقدار ویژگیهای مشترک را ارسال کند یا به بهروزرسانی ویژگیها مشترک شود. شاید مورد استفاده رایجتر ویژگیهای مشترک ذخیره تنظیمات دستگاه باشد.
برای اجرای کد این بخش از راهنما، توصیه میکنیم از نسخه 3.9 یا بالاتر Python استفاده کنید.
اگر Python را نصب نکردهاید، لطفاً مراحل زیر را دنبال کنید:
sudo apt update sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.9
sudo apt-get install -y python3 git python3-pip
همچنین، نیاز به کتابخانه Adafruit-Blinka داریم. لطفاً از دستور زیر برای نصب آن استفاده کنید:
pip3 install Adafruit-Blinka
در حال حاضر، آماده نوشتن کد هستیم. در این بخش، از بستههای جدیدی برای چشمک زدن LED در تابع چشمک استفاده میکنیم. همچنین، از تابع `attribute_callback` استفاده میکنیم که هنگام تغییر مقدار ویژگی مشترکمان فراخوانی میشود. و در نهایت، فراخوانیمان را به مشترک در تابع اصلی `main` متصل میکنیم.
import digitalio import board ... # default blinking period period = 1.0 # callback function that will call when we will change value of our Shared Attribute def attribute_callback(client, result): print(client, result) # make sure that you paste YOUR shared attribute name period = result.get('blinkingPeriod', 1.0) def main(): ... # make sure that you paste YOUR shared attribute name sub_id_1 = client.subscribe_to_attribute("blinkingPeriod", attribute_callback) sub_id_2 = client.subscribe_to_all_attributes(attribute_callback) led = digitalio.DigitalInOut(board.PD14) led.direction = digitalio.Direction.OUTPUT ... led.value = True time.sleep(period) led.value = False time.sleep(period)
همچنین، اگر از داشبورد وارد شده استفاده میکنید، میتوانید دوره چشمک زدن را با استفاده از ویجت زیر تغییر دهید که در گوشه پایین سمت راست داشبورد مشاهده میکنید.
//img
کنترل دستگاه با استفاده از RPC
ThingsBoard به شما امکان میدهد تا فراخوانیهای روی دستگاه (RPC) را از برنامههای سمت سرور به دستگاهها و بالعکس ارسال کنید. به طور کلی، این قابلیت به شما امکان میدهد تا دستورات را به دستگاهها ارسال کرده و نتایج اجرای دستور را دریافت کنید.
در این راهنما، فرمان RPC را برای دریافت دادههای تلمتری برد OrangePI فوراً پیکربندی میکنیم. اگر از داشبورد وارد شده استفاده میکنید، نیازی به پیکربندی چیزی نیست زیرا در داشبورد شما ویجت زیر را میبینید:
//img
💡 اگر یک داشبورد جدید ایجاد کنید، میتوانید از ویجت “دکمه RPC” برای انجام فراخوانیهای یکطرفه RPC استفاده کنید که در بسته “ویجتهای کنترلی” قرار دارد.
در حال حاضر، آماده هستیم کد خود را بنویسیم. در ابتدا، نیاز داریم تابع `rpc_callback` را ایجاد کنیم که هنگام دریافت RPC از سرور فراخوانی خواهد شد. همچنین، مشابه مثال با ویژگیهای مشترک، نیاز داریم تا تابع `rpc_callback` را با مشترک در تابع اصلی `main` مرتبط کنیم.
client = None ... # callback function that will call when we will send RPC def rpc_callback(id, request_body): # request body contains method and other parameters print(request_body) method = request_body.get('method') if method == 'getTelemetry': attributes, telemetry = get_data() client.send_attributes(attributes) client.send_telemetry(telemetry) else: print('Unknown method: ' + method) ... def main(): ... # now rpc_request_response will process rpc requests from server client.set_server_side_rpc_request_handler(rpc_callback) ...
در نهایت، بیایید دکمه را فشار دهیم و تلاش کنیم برای دریافت دادههای OrangePI:
//img
همچنین، اگر همه چیز را به درستی انجام دادهاید، باید خروجی کنسول زیر را ببینید:
{‘method’: ‘getTelemetry’, ‘params’: {}}
نتیجهگیری
با دانشی که در این راهنما بررسی شد، میتوانید به راحتی دستگاه Lenovo Leez SBC P710 خود را به ThingsBoard متصل کرده و دادهها را ارسال کنید.
برای کسب اطلاعات بیشتر درباره مفاهیم و ویژگیهای کلیدی، از مستندات پلتفرم استفاده کنید. به عنوان مثال، قوانین هشدار را پیکربندی کنید یا داشبوردها را تنظیم کنید.