
غلاف CLI بلغة Python لأداة Flipper Zero
Flipper Zero Python CLI Wrapper

يجلب هذا الإصدار الغلاف ليتوافق مع سطر أوامر Flipper Zero الحالي (تم التحقق منه على أجهزة حقيقية، البرنامج الثابت unlshd-089e):
info جديدة: flipper.info.device_info() / power_info() / power_debug_info() (الأوامر الحديثة info device / info power).power info → info power: flipper.power.info() لا يزال يعمل ويقرأ الآن info power داخلياً. تم إضافة flipper.power.otg_on()/otg_off().date: استخدم flipper.date.datetime(); تم إصلاح التحليل لتنسيق الإخراج الحالي.KB و KiB، read() يعيد الآن محتوى الملف الكامل متعدد الأسطر، ويتم تحليل بطاقات exFAT / ذات التسمية الفارغة بشكل صحيح (إصلاح #21).NECext، Kaseikyo، RCA، Pioneer، ... تلقائياً (إصلاح #15). جديد flipper.ir.protocols().debug → sysctl debug، subghz tx/rx اكتسب الوسيط device المطلوب، bt hci_info بدون تغيير.scan، dump، emulate، field، apdu، raw، mfu) مع مساعدات ذاكرة تخزين مفاتيح Mifare Classic لكل UID (import_nfc_keys، write_key_cache).ps (→ top)، music_player، nfc detect.$ pip install pyflipper
unlshd-089e)from pyflipper import PyFlipper
# منفذ تسلسلي محلي
flipper = PyFlipper(com="/dev/ttyACM0")
# أو
# خادم serial2websocket عن بعد
flipper = PyFlipper(ws="ws://192.168.1.5:1337")
# TCP
flipper = PyFlipper(tcp='192.168.89.222:22170')
# معلومات (على البرنامج الثابت الحالي يقرأ `info power` داخلياً)
info = flipper.power.info()
# إيقاف التشغيل
flipper.power.off()
# إعادة التشغيل
flipper.power.reboot()
# إعادة التشغيل في وضع DFU
flipper.power.reboot2dfu()
# تشغيل/إيقاف دبوس OTG 5V على رأس GPIO
flipper.power.otg_on()
flipper.power.otg_off()
# تثبيت تحديث من ملف .fuf
flipper.update.install(fuf_file="/ext/update.fuf")
# نسخ احتياطي لـ Flipper إلى ملف .tar
flipper.update.backup(dest_tar_file="/ext/backup.tar")
# استعادة Flipper من ملف .tar للنسخ الاحتياطي
flipper.update.restore(bak_tar_file="/ext/backup.tar")
# قائمة التطبيقات المثبتة
apps = flipper.loader.list()
# فتح تطبيق
flipper.loader.open(app_name="Clock")
# الحصول على تاريخ Flipper (كائن datetime)
date = flipper.date.datetime()
# الحصول على طابع زمني لـ Flipper
timestamp = flipper.date.timestamp()
# الحصول على قاموس معلومات الجهاز (البرنامج الثابت الحالي `info device`، مفاتيح مفصولة بنقاط)
device_info = flipper.info.device_info()
# الحصول على قاموس معلومات الطاقة (البرنامج الثابت الحالي `info power`)
power_info = flipper.info.power_info()
# معلومات تصحيح متقدمة للطاقة/المقياس
power_debug = flipper.info.power_debug_info()
# أمر `device_info` القديم (مفاتيح مفصولة بشرطة سفلية، لا يزال مدعوماً)
legacy_info = flipper.device_info.info()
# الحصول على قاموس معلومات الكومة
heap = flipper.free.info()
# الحصول على سلسلة free_blocks
free_blocks = flipper.free.blocks()
# الحصول على معلومات البلوتوث
bt_info = flipper.bt.info()
توافق البرنامج الثابت. تستهدف هذه المكتبة الآن سطر أوامر Flipper Zero الحالي (البرنامج الثابت 1.x، تم التحقق منه ضد Unleashed
unlshd-089e). تمت إزالة بعض الأوامر القديمة من البرنامج الثابت الرسمي وبالتالي لم تعد متوفرة:ps(استبدل بـtopالتفاعلي)،music_player، وnfc detect(أصبح NFC الآن قشرة فرعية تفاعلية).power infoانتقل إلىinfo power،debugانتقل إلىsysctl debug، وstorageيبلغ الآن عن الأحجام بـKiB— كل هذا يتم التعامل معه بشفافية عبر الأغلفة أعلاه.
# الحصول على معلومات نظام ملفات التخزين
ext_info = flipper.storage.info(fs="/ext")
# الحصول على قاموس /ext للتخزين
ext_list = flipper.storage.list(path="/ext")
# الحصول على قاموس شجري /ext للتخزين
ext_tree = flipper.storage.tree(path="/ext")
# الحصول على معلومات الملف
file_info = flipper.storage.stat(file="/ext/foo/bar.txt")
# إنشاء دليل
flipper.storage.mkdir(new_dir="/ext/foo")
# قراءة ملف
plain_text = flipper.storage.read(file="/ext/foo/bar.txt")
# حذف ملف
flipper.storage.remove(file="/ext/foo/bar.txt")
# نسخ ملف
flipper.storage.copy(src="/ext/foo/source.txt", dest="/ext/bar/destination.txt")
# إعادة تسمية ملف
flipper.storage.rename(file="/ext/foo/bar.txt", new_file="/ext/foo/rab.txt")
# تجزئة MD5 لملف
md5_hash = flipper.storage.md5(file="/ext/foo/bar.txt")
# كتابة ملف دفعة واحدة
file = "/ext/bar.txt"
text = """There are many variations of passages of Lorem Ipsum available,
but the majority have suffered alteration in some form, by injected humour,
or randomised words which don't look even slightly believable.
If you are going to use a passage of Lorem Ipsum,
you need to be sure there isn't anything embarrassing hidden in the middle of text.
"""
flipper.storage.write.file(path=file, text=text)
# كتابة ملف باستخدام مستمع
file = "/ext/foo.txt"
text_one = """There are many variations of passages of Lorem Ipsum available,
but the majority have suffered alteration in some form, by injected humour,
or randomised words which don't look even slightly believable.
If you are going to use a passage of Lorem Ipsum,
you need to be sure there isn't anything embarrassing hidden in the middle of text.
"""
flipper.storage.write.start(file)
time.sleep(2)
flipper.storage.write.send(text_one)
text_two = """All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as
necessary, making this the first true generator on the Internet.
It uses a dictionary of over 200 Latin words, combined with a handful of
model sentence structures, to generate Lorem Ipsum which looks reasonable.
The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
"""
flipper.storage.write.send(text_two)
time.sleep(3)
# لا تنس إيقاف الكتابة
flipper.storage.write.stop()
# تشغيل led عام (r,b,g,bl)
flipper.led.set(led='r', value=255)
# إطفاء الـ led الأزرق
flipper.led.blue(value=0)
# تعيين قيمة الـ led الأخضر
flipper.led.green(value=175)
# تشغيل الإضاءة الخلفية
flipper.led.backlight_on()
# إطفاء الإضاءة الخلفية
flipper.led.backlight_off()
# إطفاء الـ led
flipper.led.off()
# تعيين الاهتزاز True أو False
flipper.vibro.set(True)
# تشغيل الاهتزاز
flipper.vibro.on()
# إيقاف الاهتزاز
flipper.vibro.off()
# تعيين وضع gpio: 0 - إدخال، 1 - إخراج
flipper.gpio.mode(pin_name=PIN_NAME, value=1)
# تعيين قيمة دبوس gpio: 0 - إيقاف، 1 - تشغيل
flipper.gpio.set(pin_name=PIN_NAME, value=1)
# قراءة قيمة دبوس gpio
flipper.gpio.read(pin_name=PIN_NAME)
⚠️ تمت إزالته من البرنامج الثابت الرسمي. تم حذف أمر CLI
music_playerمن البرنامج الثابت الأساسي (التطبيق الآن هو.fapمنفصل). لا تزال هذه الاستدعاءات تعمل على البرامج الثابتة المخصصة التي تحتفظ بالأمر (مثل بناءات Unleashed / RogueMaster التي تشمله)؛ على البرنامج الثابت الأساسي، تُرجع رد "command not found".
# تشغيل أغنية بتنسيق RTTTL
rttl_song = "Littleroot Town - Pokemon:d=4,o=5,b=100:8c5,8f5,8g5,4a5,8p,8g5,8a5,8g5,8a5,8a#5,8p,4c6,8d6,8a5,8g5,8a5,8c#6,4d6,4e6,4d6,8a5,8g5,8f5,8e5,8f5,8a5,4d6,8d5,8e5,2f5,8c6,8a#5,8a#5,8a5,2f5,8d6,8a5,8a5,8g5,2f5,8p,8f5,8d5,8f5,8e5,4e5,8f5,8g5"
# تشغيل في حلقة
flipper.music_player.play(rtttl_code=rttl_song)
# إيقاف الحلقة
flipper.music_player.stop()
# تشغيل لمدة 20 ثانية
flipper.music_player.play(rtttl_code=rttl_song, duration=20)
# إصدار صوت طنين
flipper.music_player.beep()
# إصدار صوت طنين لمدة 5 ثوانٍ
flipper.music_player.beep(duration=5)
على البرنامج الثابت الحالي، NFC هي قشرة فرعية تفاعلية (scanner، dump، emulate، field، apdu، raw، mfu). يدخل هذا الغلاف إلى القشرة الفرعية، ينفذ أمراً واحداً ويخرج مرة أخرى، لذا كل طريقة هي استدعاء عادي يعمل بشكل متزامن. detect() تُحتفظ بها كاسم مستعار لـ scan().
# كشف نوع البطاقة -> {'protocols': ['Mifare Classic'], 'raw': '...'} أو None
tag = flipper.nfc.scan(timeout=5)
# تشغيل مجال NFC لبضع ثوانٍ
flipper.nfc.field(timeout=3)
# إرسال APDU (ISO14443-4 / ISO15693-3)؛ يتم كشف البروتوكول تلقائياً إذا تم حذفه
resp = flipper.nfc.apdu(["00A4 04 00", "A0 00"], protocol="14_4a")
# إرسال بايتات خام مع CRC مُلحق
flipper.nfc.raw("93 20", protocol="14a", crc=True)
# مساعدات Mifare Ultralight
info = flipper.nfc.mfu_info()
block4 = flipper.nfc.mfu_read_block(4)
flipper.nfc.mfu_write_block(4, "00 01 02 03")
# محاكاة ملف .nfc محفوظ
flipper.nfc.emulate(file="/ext/nfc/mycard.nfc", timeout=10)
لا يقوم CLI dump بتشغيل هجوم قاموس: يقرأ المفاتيح من ذاكرة تخزين مؤقتة خاصة بـ UID في /ext/nfc/.cache/<UID>.keys (الملف الذي تكتبه واجهة المستخدم الرسومية بعد قراءة ناجحة). إذا كانت تلك الذاكرة المؤقتة مفقودة، يُرجع dump "failed to read". يمكنك إنشاؤها (أو إعادة إنشائها) من تفريغ .nfc موجود لـ Flipper — المفاتيح مأخوذة من مقطع (sector trailer) كل قطاع:
# تحميل المفاتيح من تفريغ .nfc أصلي إلى ذاكرة تخزين مفاتيح خاصة بـ UID
uid, cache_path = flipper.nfc.import_nfc_keys("/path/to/card.nfc")
# الآن يستطيع CLI dump قراءة البطاقة (رموز البروتوكول: mfc, mfu, 14_4a, ...)
flipper.nfc.dump(protocol="mfc", file="/ext/nfc/card_dump.nfc")
# وقت انتظار افتراضي متزامن 5 ثوانٍ
# قراءة RFID
rfid = flipper.rfid.read()
# محاكاة RFID
emulated = flipper.rfid.emulate(key_type="EM4100", key_data="5500824806")
# كتابة RFID
written = flipper.rfid.write(key_type="EM4100", key_data="5500824806")
# إرسال hex_key N مرة (العدد الافتراضي=10، device=0 -> CC1101_INT، 1 -> CC1101_EXT)
flipper.subghz.tx(hex_key="DEADBEEF", frequency=433920000, count=5, device=0)
# استقبال (التردد الافتراضي=433920000 device=0 raw=False timeout=5 ثوانٍ)
received = flipper.subghz.rx(frequency=433920000, device=0, raw=True, timeout=10)
# إعادة تشغيل إرسال مسجل
flipper.subghz.tx_from_file("/ext/subghz/foo.sub")
# فك تشفير ملف .sub خام
decoded = flipper.subghz.decode_raw(sub_file="/ext/subghz/foo.sub")
# سرد البروتوكولات المدعومة من البرنامج الثابت المتصل (يُقرأ مباشرة من مساعدة `ir`)
protocols = flipper.ir.protocols()
# إرسال hex_address و hex_command مع اختيار بروتوكول
flipper.ir.tx(protocol="Samsung32", hex_address="C000FFEE", hex_command="DEADBEEF")
# NECext مدعوم الآن (قائمة البروتوكولات تقرأ من البرنامج الثابت، وليست مقومة)
flipper.ir.tx(protocol="NECext", hex_address="EF00", hex_command="FD02")
# إرسال عينات خام
flipper.ir.tx_raw(frequency=38000, duty_cycle=0.33, samples=[1337, 8888, 3000, 5555])
# وقت انتظار افتراضي متزامن 5 ثوانٍ
# استقبال
r = flipper.ir.rx(timeout=10)
# قراءة (وقت انتظار افتراضي 5 ثوانٍ)
ikey = flipper.ikey.read()
# كتابة (وقت انتظار افتراضي 5 ثوانٍ)
flipper.ikey.write(key_type="Dallas", key_data="DEADBEEFCOOOFFEE")
# محاكاة (وقت انتظار افتراضي 5 ثوانٍ)
flipper.ikey.emulate(key_type="Dallas", key_data="DEADBEEFCOOOFFEE")
# إرفاق مسجل الأحداث (وقت انتظار افتراضي 10 ثوانٍ)
logs = flipper.log.attach()
# تفعيل وضع التصحيح (يُصدر `sysctl debug 1` على البرنامج الثابت الحالي)
flipper.debug.on()
# إلغاء تفعيل وضع التصحيح
flipper.debug.off()
# بحث
response = flipper.onewire.search()
# الحصول على
response = flipper.i2c.get()
# تفريغ الإدخال
dump = flipper.input.dump()
# إرسال إدخال
flipper.input.send("up", "press")
المجموعة مقسمة إلى قسمين:
test_serial_wrapper.py، test_commands.py) تعمل في أي مكان — تقوم بتشغيل المكتبة مقابل منفذ تسلسلي محاكى (tests/fake_serial.py) يعيد إنتاج إطار سطر أوامر Flipper، لذا لا حاجة لجهاز. هذه تعمل في CI.test_hardware.py) تتحدث مع Flipper حقيقي و يتم تخطيها تلقائياً عندما لا يكون أي جهاز متصلاً. عيّن FLIPPER_COM=/dev/ttyACM0 لتحديد منفذ معين.# كل شيء (اختبارات الأجهزة تتخطى نفسها إذا لم يكن Flipper متصلاً)
python -m unittest discover -s tests -p "test_*.py" -v
# فقط اختبارات بدون أجهزة
python -m unittest tests.test_serial_wrapper tests.test_commands -v
لا تتردد في المساهمة بأي شكل
ZEC: zs13zdde4mu5rj5yjm2kt6al5yxz2qjjjgxau9zaxs6np9ldxj65cepfyw55qvfp9v8cvd725f7tz7
ETH: 0xef3cF1Eb85382EdEEE10A2df2b348866a35C6A54
BTC: 15umRZXBzgUacwLVgpLPoa2gv7MyoTrKat