نحوه اتصال BeagleBone Black به ThingsConnect
مقدمه
BeagleBone Black یک پلتفرم توسعه پایین هزینه با پشتیبانی از جامعه است که مناسب برای حرفهایان و علاقهمندان به همراهی است. با استفاده از یک کابل USB، در کمتر از ۱۰ ثانیه به لینوکس بوت کرده و با یک کابل USB تنها میتوانید پروژههای خود را توسعه دهید. BeagleBone Black آخرین اضافهکردن به خانواده BeagleBoard.org است و مانند پیشینیانش، برای جامعه توسعه باز، خریداران اولیه و هر کسی که علاقهمند به یک پردازنده با هسته ARM Cortex-A8 با قیمت پایین است. این دستگاه با مجموعهای کمی از ویژگیها تجهیز شده است تا کاربر را قادر سازد تا قدرت پردازنده را تجربه کند و به عنوان یک پلتفرم توسعه کامل تلقی نشود، زیرا بسیاری از عملکردها و رابطهای ارائه شده توسط پردازنده در BeagleBone Black از طریق سیستم جاسازی شده در دسترس نیستند. این یک محصول کامل برای انجام هر عملکرد خاصی نیست. این برای آزمایش و یادگیری برنامهنویسی پردازنده و دسترسی به دستگاههای جانبی از طریق ایجاد نرمافزار و سختافزار خود شماست. همچنین، به شما امکان دسترسی به بسیاری از رابطها را میدهد و استفاده از صفحههای اضافی برای افزودن ترکیبات مختلفی از عملکردها را ممکن میسازد. کاربر همچنین میتواند برد خود را طراحی کند یا مدارهای خود را اضافه کند.
در این راهنما، خواهیم آموخت که چگونه یک دستگاه را در Thingsboard ایجاد کنیم، کتابخانهها و ابزارهای مورد نیاز را نصب کنیم. پس از آن، کد خود را تغییر داده و به دستگاه بارگذاری کنیم و نتایج کدزنی خود را بررسی کنیم و از طریق داشبورد وارد شده، دادهها را در Thingsboard بررسی کنیم. دستگاه ما با استفاده از قابلیت درخواستهای مشترک و ویژگیهای کلاینت با Thingsboard همگام میشود. البته، ما میتوانیم دستگاه خود را با استفاده از قابلیتهای ارائه شده مانند ویژگیهای مشترک یا درخواستهای RPC کنترل کنیم.
پیشنیازها
برای ادامه کار با این راهنما، به موارد زیر نیاز دارید:
- BeagleBone Black
- کتابخانه tb-mqtt-client
- پایتون ≥ ۳.۷
- 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 ، ابتدا باید اطلاعات احراز هویت دستگاه را دریافت کنید. ThingsBoard انواع مختلفی از احراز هویت دستگاه را پشتیبانی میکند. ما توصیه میکنیم از اطلاعات احراز هویت پیشفرض و خودکار تولید شده استفاده کنید که در این راهنما یک توکن دسترسی است.
- روی ردیف دستگاه در جدول کلیک کنید تا جزئیات دستگاه را باز کنید.
- روی “کپی کردن توکن دسترسی” کلیک کنید. توکن به کلیپبورد شما کپی خواهد شد. لطفاً آن را در جایی امن ذخیره کنید.
//img
حالا شما آمادهاید تا دادههای تلمتری را به نمایندگی از دستگاهتان منتشر کنید. همانطور که قبلاً ذکر شد، ما از کتابخانه “thingsboard-python-client-sdk” استفاده خواهیم کرد. بیایید پروژهمان را راهاندازی کنیم:
- ایجاد پوشه پروژه:
mkdir thingsboard_example && cd thingsboard_example
- نصب بسته ها
pip install tb-mqtt-client
- ایجاد اسکریپت اصلی
nano main.py
- کد زیر را کپی و پیست کنید:
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 ...
در قسمت ارسال داده، همانطور که در زیر مشاهده میکنید، ما ویژگیها و دادههای تلمتری را هر 60 ثانیه ارسال میکنیم (اگر میخواهید بروزرسانی دادهها به صورت مکررتر انجام شود، لطفاً آن را تغییر دهید).
... 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) ...
برای امکان دریافت دادهها توسط توابع فراخوانی (callbacks)، باید یک درخواست به ThingsBoard ارسال کنیم. این عملکرد به ما امکان میدهد پس از راهاندازی مجدد، وضعیت فعلی را حفظ کنیم.
بررسی دادهها در ThingsBoard
پس از موفقیتآمیز انتشار ویژگیها و دادههای تلمتری، باید آنها را به سرعت در برگه Telemetry دستگاه مشاهده کنید:
- روی ردیف دستگاه در جدول کلیک کنید تا جزئیات دستگاه را باز کنید.
- به برگه Telemetry هدایت شوید.
//img
همچنین، بیایید ویژگیها و دادههای تلمتری سیستم تختریزی را در یک داشبورد نمایش دهیم. برای این کار، میتوانید یک داشبورد سفارشی با ویجتهای خود ایجاد کنید یا از یک داشبورد آماده استفاده کنید و آن را به سادگی وارد کنید.
- داشبورد وارداتی
- داشبورد جدید
وارد کردن داشبورد
شما قادرید یک داشبورد را در فرمت JSON وارد کنید. برای وارد کردن یک داشبورد، باید به گروه داشبوردها بروید و روی دکمه “+” در گوشه بالا و راست صفحه کلیک کنید و “وارد کردن داشبورد” را انتخاب کنید. پنجره وارد کردن داشبورد باید ظاهر شود و شما به آپلود کردن فایل JSON و کلیک بر روی “وارد کردن” دعوت خواهید شد.
//img
در زیر میتوانید فایل JSON داشبورد را مشاهده کنید:
بررسی و کنترل دادههای دستگاه در داشبورد
پس از وارد کردن، باید برای دستگاه خود نام مستعار موجودیت را انتخاب کنیم.
برای این کار – باید روی آیکون قلم بزنیم و مستعارهای موجودیت را انتخاب کنیم، مستعار “دستگاه من” را انتخاب کرده و با زدن آیکون قلم آن را برای ویرایش باز کنیم.
سپس یک دستگاه با نام “دستگاه من” را از لیست کشویی انتخاب کنید و مستعار موجودیت را ذخیره کنید، حالا باید قادر به دیدن دادهها از دستگاه باشید.
اگر همه چیز را به درستی انجام دادهاید، باید داشبورد زیر را مشاهده کنید:
//img
ایجاد داشبورد جدید
ما یک داشبورد جدید ایجاد خواهیم کرد و ابزارهای محبوب را اضافه خواهیم کرد. دستورالعملها را در زیر ببینید.
- صفحه داشبوردها را باز کنید. بر روی آیکون “+” در گوشه بالا و سمت راست کلیک کنید. “ایجاد داشبورد جدید” را انتخاب کنید.
- نام داشبورد را وارد کنید. به عنوان مثال، “داشبورد جدید من”. برای افزودن داشبورد کلید “افزودن” را کلیک کنید.
- اکنون داشبورد شما باید در ابتدا لیست شده باشد، زیرا جدول داشبوردها را به طور پیش فرض بر اساس زمان ایجاد مرتب میکند. بر روی آیکون “باز کردن داشبورد” کلیک کنید.
//img
افزودن مستعار موجودیت
مستعار مرجعی به یک موجودیت یا گروهی از موجودیتها است که در ابزارها استفاده میشود. یک مستعار میتواند استاتیک یا پویا باشد. برای سادگی، ما از مستعار “موجودیت تکی” استفاده خواهیم کرد که به تنها یک موجودیت (“OrangePI” در مورد ما) مرجع میشود. ممکن است یک مستعاری که به چندین دستگاه مرجع است را پیکربندی کنید. به عنوان مثال، دستگاههایی از نوع خاص یا مرتبط با دارایی خاص. میتوانید درباره مستعارهای مختلف بیشتر بیاموزید.
- حالت ویرایش را وارد کنید. بر روی دکمه قلم در گوشه پایین و سمت راست کلیک کنید.
- در بخش بالا و سمت راست صفحه بر روی آیکون “مستعارهای موجودیت” کلیک کنید. لیستی خالی از مستعارهای موجودیت را خواهید دید.
- بر روی “افزودن مستعار” کلیک کنید.
- نام مستعار را وارد کنید، به عنوان مثال “OrangePI”. نوع فیلتر را به “موجودیت تکی” تنظیم کنید. نوع را “دستگاه” انتخاب کرده و “My New” را تایپ کنید تا اتوکامپلیت فعال شود. از لیست اتوکامپلیت دستگاه خود را انتخاب کنید و بر روی آن کلیک کنید.
- بر روی “افزودن” و سپس “ذخیره” کلیک کنید.
- در نهایت، برای ذخیره تغییرات بر روی “اعمال تغییرات” در ویرایشگر داشبورد کلیک کنید. سپس باید دوباره به حالت ویرایش وارد شوید.
//img
برای اضافه کردن ابزارک جدید، باید آن را از کتابخانه ابزارک انتخاب کنیم. ابزارکها به گروههایی به نام “بستههای ابزارک” تقسیم میشوند. هر ابزارک منبع دادهای دارد. این منبع داده به ابزارک میگوید که چه دادههایی را نمایش دهد. برای مشاهدهی آخرین مقدار داده “cpu_usage” که در مرحله ۲ ارسال کردیم، باید منبع داده را پیکربندی کنیم.
- حالت ویرایش را وارد کنید. بر روی دکمه “اضافه کردن ابزارک جدید” کلیک کنید.
- بسته ابزارک “نمودارها” را انتخاب کنید. بر روی هدر ابزارک “موجودیتها” کلیک کنید. پنجره “افزودن ابزارک” ظاهر خواهد شد.
- بر روی “افزودن” کلیک کنید تا منبع داده را اضافه کنید. یک ابزارک میتواند چندین منبع داده داشته باشد، اما در این حالت فقط از یکی استفاده خواهیم کرد.
- مستعار موجودیت “OrangePI” را انتخاب کنید. سپس بر روی فیلد ورودی در سمت راست کلیک کنید. اتوکامپلیت با نقاط داده موجود ظاهر میشود. نقطه داده “cpu_usage” را انتخاب کنید و بر روی “افزودن” کلیک کنید.
- ابزارک را تغییر اندازه دهید تا کمی بزرگتر شود. فقط گوشه پایین و سمت راست ابزارک را بکشید. همچنین میتوانید با تنظیمات پیشرفته بازی کنید اگر میخواهید ابزارک را ویرایش کنید.
کنترل دستگاه با استفاده از ویژگیهای مشترک:
لطفاً فراموش نکنید که ویژگی مشترک “blinkingPeriod” را برای دستگاه خود ایجاد کنید.
علاوه بر این، ما میتوانیم با استفاده از قابلیت بهروزرسانی ویژگیهای مشترک، دوره چشمک زنی را تغییر دهیم.
این نوع ویژگی تنها برای دستگاهها در دسترس است. این شبیه به ویژگیهای سمت سرور است، اما یک تفاوت مهم دارد. نرمافزار/برنامه دستگاه میتواند مقدار ویژگیهای مشترک را درخواست کند یا به بهروزرسانی ویژگیها مشترک شود. یکی از کاربردهای رایج ویژگیهای مشترک، ذخیره تنظیمات دستگاه است.
برای اجرای کد این بخش از راهنما، توصیه میکنیم از Python نسخه 3.9 یا بالاتر استفاده کنید.
اگر هنوز 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 در تابع blink استفاده میکنیم. همچنین، از تابع attribute_callback استفاده میکنیم که در زمان تغییر مقدار ویژگی مشترک فراخوانی میشود. و در نهایت، تابع callback را به مشترک متصل میکنیم.
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 را برای دریافت دادههای تلمتری اورنجپای به طور فوری پیکربندی میکنیم. اگر از داشبورد وارد شده استفاده میکنید، نیازی به پیکربندی هیچ چیزی ندارید زیرا در داشبورد خود میتوانید ویجت زیر را ببینید:
//img
اگر یک داشبورد جدید ایجاد کنید، میتوانید از ویجت “دکمه RPC” برای ارتباط یکطرفه RPC که در بستهی “ابزارهای کنترل” قرار دارد، استفاده کنید.
در حال حاضر، آمادهایم کدهایمان را بنویسیم. ابتدا نیاز داریم تا یک تابع rpc_callback ایجاد کنیم که هنگام دریافت RPC از سرور فراخوانی شود. همچنین، همانند مثال با ویژگیهای مشترک، نیاز داریم تا تابع rpc callback خود را با subscriber در تابع اصلی متصل کنیم.
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) ...
در نهایت، بیایید دکمه را فشار داده و تلاش کنیم تا دادههای اورنجپای را دریافت کنیم.
//img
همچنین، اگر همه چیز را به درستی انجام دادهاید، باید خروجی کنسول زیر را مشاهده کنید:
{‘method’: ‘getTelemetry’, ‘params’: {}}
نتیجهگیری
با دانشی که در این راهنما توضیح داده شد، میتوانید به سادگی دستگاه BeagleBone Black خود را به ThingsBoard متصل کنید و دادهها را ارسال کنید.
برای کسب اطلاعات بیشتر درباره مفاهیم و ویژگیهای کلیدی، به مستندات پلتفرم مراجعه کنید. به عنوان مثال، میتوانید قوانین هشدار یا داشبوردها را پیکربندی کنید.