مهندسی معکوس ردیاب پرتاب بیبلید و ساخت یه اپ با هوش مصنوعی
خلاصهٔ کاملتر
نویسنده بعد از اینکه دوباره عاشق Beyblade X شد، یه گجت ژاپنی به اسم Beybattle Pass (BX-09) از Takara Tomy خرید. این گجت به لانچر وصل میشه و با بلوتوث مقدار Shoot Power رو، که در واقع همون RPM یعنی دور در دقیقهٔ پرتابه، به اپ رسمی میفرسته. به گفتهٔ نویسنده، یه دیسک سیاه و سفید داخل لانچر موقع کشیدن نخ میچرخه و احتمالاً یه سنسور مادون قرمز سرعت چرخشش رو میخونه.
با ابزارهای LightBlue و PacketLogger ترافیک BLE (بلوتوث کممصرف) رو شنود کرد. دستگاه دو تا characteristic داشت، یعنی دو تا کانال داده: یکی برای خوندن و اعلان، یکی برای نوشتن بدون جواب. هر بار که بیبلید وصل میشد، یه هدر ۱۷ بایتی میومد و بعد از پرتاب یه بستهٔ بزرگ با صفحههایی که با a0، b0 تا b7 و 70 تا 73 شروع میشدن. تو هدر یه شمارندهٔ پرتابهای موفق بود و آدرس دستگاه با ترتیب بایت برعکس.
عددهای پرتاب اول خیلی بزرگ درمیومدن، مثلاً a2 0c میشد ۴۱٬۴۸۴. نویسنده یادش افتاد BLE معمولاً little-endian هست، یعنی بایت کمارزشتر اول میاد. با جابهجا کردن بایتها عدد ۳٬۲۳۴ دراومد که با سرعت معمول پرتاب (حدود ۵٬۰۰۰ RPM) جور بود. یه جفت بایت تو هدر هم رکورد بالاترین پرتاب بود و بایتهای 00 04 نشون میدادن دستگاه آمادهٔ پرتابه. نویسنده حدس میزنه یه بایت دیگه که کمکم پایین میومد، سطح باتری باشه.
بعد از ۵۰ پرتاب دیگه معلوم شد صفحههای b* مثل یه صف FIFO کار میکنن: حداکثر ۵۰ پرتاب ذخیره میشه و با هر پرتاب جدید قدیمیترین پاک میشه. بایت آخر صفحهٔ b7 هم یه checksum سادهست، یعنی جمع بایتهای داده به پیمانهٔ ۲۵۶. با شنود اپ رسمی روی آیفون، سه تا فرمان هم پیدا شد: 0x74 لیست پرتابها رو میده، 0x51 هدر رو و 0x75 کل حافظه رو پاک میکنه. معنی صفحههای 7* هنوز معلوم نیست و نویسنده حدس میزنه دادهٔ خام سنسور باشن.
بعد با این پروتکل اپ DiZZi 0.2 رو ساخت که ظاهرش از کامپیوتر یکی از شخصیتهای انیمهٔ قدیمی بیبلید الهام گرفته. فرانتاند React با WebSocket به یه سرور Express.js وصله که به دستگاه BLE وصل میشه. با هر پرتاب جدید، سرور از Ollama با مدل gemma3:1b یه جملهٔ کوتاه دربارهٔ پرتابها میگیره و Kokoro TTS اونو به صدا تبدیل میکنه. چون مدلهای کوچیک تو حساب ضعیفن، نویسنده روند پرتابها رو خودش حساب میکنه و فقط یه خلاصهٔ متنی به مدل میده:
const avgPrevious = Math.round(previous.reduce((a, b) => a + b, 0) / previous.length);
const diff = lastItem - avgPrevious;
const trend = diff > 300 ? 'improving' : diff < -300 ? 'getting worse' : 'about the same';یه جزئیات قشنگ دیگه انیمیشن صدای DiZZi هست: فایل صوتی از Web Audio API و یه AnalyserNode رد میشه و طیف فرکانسش یه انیمیشن شعلهمانند روی canvas رو میسازه. نویسنده میگه برای مدل سهبعدی بیبلید و همین انیمیشن صدا از Claude کمک گرفته. کد پروژه و همهٔ بستههای ضبطشده روی GitHub هست.
نکات کلیدی:
- Beybattle Pass (BX-09) سرعت پرتاب رو به RPM با بلوتوث کممصرف میفرسته
- عددهای پرتاب بهصورت little-endian ذخیره میشن، مثلاً a2 0c یعنی ۳٬۲۳۴ RPM
- دستگاه حداکثر ۵۰ پرتاب رو بهصورت FIFO نگه میداره و یه checksum به پیمانهٔ ۲۵۶ داره
- فرمان 0x74 لیست پرتابها، 0x51 هدر و 0x75 پاک کردن کل حافظهست
- اپ DiZZi با React، Express.js، Ollama (مدل gemma3:1b) و Kokoro TTS ساخته شده
- معنی صفحههای 7* هنوز کشف نشده




