
Wrapper Python CLI pour Flipper Zero
Wrapper Python CLI pour Flipper Zero

Cette version met le wrapper en conformité avec le CLI actuel du Flipper Zero
(validé sur du matériel réel, firmware unlshd-089e) :
info : flipper.info.device_info() / power_info() /
power_debug_info() (les commandes modernes info device / info power).power info → info power : flipper.power.info() continue de fonctionner et lit
désormais info power en interne. Ajout de flipper.power.otg_on()/otg_off().date : utilisez flipper.date.datetime() ; l'analyse a été corrigée pour le format
de sortie actuel.KB et KiB, read() renvoie désormais
le contenu complet du fichier multiligne, et les cartes exFAT / sans étiquette
sont correctement analysées (corrige #21).NECext,
Kaseikyo, RCA, Pioneer, … sont supportés automatiquement (corrige #15). Nouveau
flipper.ir.protocols().debug → sysctl debug, subghz tx/rx a obtenu l'argument device
obligatoire, bt hci_info inchangé.scan, dump,
emulate, field, apdu, raw, mfu) avec des aides de cache de clés
Mifare Classic par UID (import_nfc_keys, write_key_cache).ps (→ top), music_player, nfc detect.$ pip install pyflipper
unlshd-089e)from pyflipper import PyFlipper
# Port série local
flipper = PyFlipper(com="/dev/ttyACM0")
# OU
# Serveur distant serial2websocket
flipper = PyFlipper(ws="ws://192.168.1.5:1337")
# TCP
flipper = PyFlipper(tcp='192.168.89.222:22170')
# Info (sur le firmware actuel, cela lit `info power` en interne)
info = flipper.power.info()
# Extinction
flipper.power.off()
# Redémarrage
flipper.power.reboot()
# Redémarrage en mode DFU
flipper.power.reboot2dfu()
# Basculer la broche OTG 5V sur l'en-tête GPIO
flipper.power.otg_on()
flipper.power.otg_off()
# Installer une mise à jour à partir du fichier .fuf
flipper.update.install(fuf_file="/ext/update.fuf")
# Sauvegarder le Flipper dans un fichier .tar
flipper.update.backup(dest_tar_file="/ext/backup.tar")
# Restaurer le Flipper à partir d'un fichier .tar de sauvegarde
flipper.update.restore(bak_tar_file="/ext/backup.tar")
# Lister les applications installées
apps = flipper.loader.list()
# Ouvrir une application
flipper.loader.open(app_name="Clock")
# Obtenir la date du Flipper (objet datetime)
date = flipper.date.datetime()
# Obtenir le timestamp du Flipper
timestamp = flipper.date.timestamp()
# Obtenir le dictionnaire d'informations sur le périphérique (firmware actuel `info device`, clés séparées par des points)
device_info = flipper.info.device_info()
# Obtenir le dictionnaire d'informations sur l'alimentation (firmware actuel `info power`)
power_info = flipper.info.power_info()
# Informations de débogage étendues sur l'alimentation/la jauge
power_debug = flipper.info.power_debug_info()
# Commande `device_info` héritée (clés séparées par des underscores, toujours supportée)
legacy_info = flipper.device_info.info()
# Obtenir le dictionnaire d'informations sur le tas
heap = flipper.free.info()
# Obtenir la chaîne free_blocks
free_blocks = flipper.free.blocks()
# Obtenir les informations Bluetooth
bt_info = flipper.bt.info()
Compatibilité du firmware. Cette bibliothèque cible désormais le CLI actuel du Flipper Zero (firmware 1.x, vérifié avec Unleashed
unlshd-089e). Quelques commandes héritées ont été supprimées du firmware officiel et ne sont donc plus disponibles :ps(remplacé par letopinteractif),music_playeretnfc detect(NFC est maintenant un sous-shell interactif).power infoa été déplacé versinfo power,debugverssysctl debug, etstoragesignale désormais les tailles enKiB— tout est géré de manière transparente par les wrappers ci-dessus.
# Obtenir les informations du système de fichiers de stockage
ext_info = flipper.storage.info(fs="/ext")
# Obtenir le dictionnaire du stockage /ext
ext_list = flipper.storage.list(path="/ext")
# Obtenir le dictionnaire de l'arborescence du stockage /ext
ext_tree = flipper.storage.tree(path="/ext")
# Obtenir les informations d'un fichier
file_info = flipper.storage.stat(file="/ext/foo/bar.txt")
# Créer un répertoire
flipper.storage.mkdir(new_dir="/ext/foo")
# Lire un fichier
plain_text = flipper.storage.read(file="/ext/foo/bar.txt")
# Supprimer un fichier
flipper.storage.remove(file="/ext/foo/bar.txt")
# Copier un fichier
flipper.storage.copy(src="/ext/foo/source.txt", dest="/ext/bar/destination.txt")
# Renommer un fichier
flipper.storage.rename(file="/ext/foo/bar.txt", new_file="/ext/foo/rab.txt")
# Hash MD5 d'un fichier
md5_hash = flipper.storage.md5(file="/ext/foo/bar.txt")
# Écrire un fichier en un seul bloc
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)
# Écrire un fichier en utilisant un écouteur
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)
# N'oubliez pas d'arrêter
flipper.storage.write.stop()
# Allumer une LED générique (r,b,g,bl)
flipper.led.set(led='r', value=255)
# Éteindre la LED bleue
flipper.led.blue(value=0)
# Définir la valeur de la LED verte
flipper.led.green(value=175)
# Allumer le rétroéclairage
flipper.led.backlight_on()
# Éteindre le rétroéclairage
flipper.led.backlight_off()
# Éteindre la LED
flipper.led.off()
# Activer ou désactiver le vibreur
flipper.vibro.set(True)
# Activer le vibreur
flipper.vibro.on()
# Désactiver le vibreur
flipper.vibro.off()
# Définir le mode GPIO : 0 - entrée, 1 - sortie
flipper.gpio.mode(pin_name=PIN_NAME, value=1)
# Définir la valeur de la broche GPIO : 0 - éteint, 1 - allumé
flipper.gpio.set(pin_name=PIN_NAME, value=1)
# Lire la valeur de la broche GPIO
flipper.gpio.read(pin_name=PIN_NAME)
⚠️ Supprimé du firmware officiel. La commande CLI
music_playera été retirée du firmware stock (l'application est maintenant un.fapséparé). Ces appels fonctionnent encore sur les firmwares personnalisés qui conservent la commande (par ex. les builds Unleashed / RogueMaster qui l'incluent) ; sur le firmware stock, ils renvoient une réponse "commande introuvable".
# Jouer une chanson au format 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"
# Jouer en boucle
flipper.music_player.play(rtttl_code=rttl_song)
# Arrêter la boucle
flipper.music_player.stop()
# Jouer pendant 20 secondes
flipper.music_player.play(rtttl_code=rttl_song, duration=20)
# Bip
flipper.music_player.beep()
# Bip pendant 5 secondes
flipper.music_player.beep(duration=5)
Sur le firmware actuel, NFC est un sous-shell interactif (scanner, dump,
emulate, field, apdu, raw, mfu). Ce wrapper entre dans le sous-shell,
exécute une commande et en ressort, donc chaque méthode est un appel bloquant normal.
detect() est conservé comme alias de scan().
# Détecter le type de tag -> {'protocols': ['Mifare Classic'], 'raw': '...'} ou None
tag = flipper.nfc.scan(timeout=5)
# Activer le champ NFC pendant quelques secondes
flipper.nfc.field(timeout=3)
# Envoyer une APDU (ISO14443-4 / ISO15693-3) ; le protocole est auto-détecté s'il est omis
resp = flipper.nfc.apdu(["00A4 04 00", "A0 00"], protocol="14_4a")
# Envoyer des octets bruts avec CRC ajouté
flipper.nfc.raw("93 20", protocol="14a", crc=True)
# Aides pour Mifare Ultralight
info = flipper.nfc.mfu_info()
block4 = flipper.nfc.mfu_read_block(4)
flipper.nfc.mfu_write_block(4, "00 01 02 03")
# Émuler un fichier .nfc sauvegardé
flipper.nfc.emulate(file="/ext/nfc/mycard.nfc", timeout=10)
Le dump du CLI n'exécute pas d'attaque par dictionnaire : il lit les clés depuis un
cache par UID situé dans /ext/nfc/.cache/<UID>.keys (le fichier que l'interface graphique
écrit après une lecture réussie). Si ce cache est absent, dump renvoie "échec de la lecture".
Vous pouvez le (re)créer à partir d'un dump .nfc existant du Flipper — les clés sont extraites
de chaque secteur d'en-tête :
# Charger les clés depuis un dump .nfc natif dans le cache de clés par UID
uid, cache_path = flipper.nfc.import_nfc_keys("/path/to/card.nfc")
# Maintenant le dump CLI peut lire la carte (jetons de protocole : mfc, mfu, 14_4a, ...)
flipper.nfc.dump(protocol="mfc", file="/ext/nfc/card_dump.nfc")
# Par défaut synchrone avec un délai d'attente de 5 secondes
# Lire le RFID
rfid = flipper.rfid.read()
# Émuler le RFID
emulated = flipper.rfid.emulate(key_type="EM4100", key_data="5500824806")
# Écrire le RFID
written = flipper.rfid.write(key_type="EM4100", key_data="5500824806")
# Transmettre hex_key N fois (count=10 par défaut, device=0 -> CC1101_INT, 1 -> CC1101_EXT)
flipper.subghz.tx(hex_key="DEADBEEF", frequency=433920000, count=5, device=0)
# Recevoir (fréquence par défaut=433920000 device=0 raw=False timeout=5 secondes)
received = flipper.subghz.rx(frequency=433920000, device=0, raw=True, timeout=10)
# Rejouer une transmission enregistrée
flipper.subghz.tx_from_file("/ext/subghz/foo.sub")
# Décoder un fichier .sub brut
decoded = flipper.subghz.decode_raw(sub_file="/ext/subghz/foo.sub")
# Lister les protocoles supportés par le firmware connecté (lue en direct depuis l'aide `ir`)
protocols = flipper.ir.protocols()
# Transmettre hex_address et hex_command en sélectionnant un protocole
flipper.ir.tx(protocol="Samsung32", hex_address="C000FFEE", hex_command="DEADBEEF")
# NECext est maintenant supporté (la liste des protocoles est lue depuis le firmware, non codée en dur)
flipper.ir.tx(protocol="NECext", hex_address="EF00", hex_command="FD02")
# Échantillons de transmission brute
flipper.ir.tx_raw(frequency=38000, duty_cycle=0.33, samples=[1337, 8888, 3000, 5555])
# Par défaut synchrone avec un délai d'attente de 5 secondes
# Réception de transmission
r = flipper.ir.rx(timeout=10)
# Lire (délai d'attente par défaut 5 secondes)
ikey = flipper.ikey.read()
# Écrire (délai d'attente par défaut 5 secondes)
flipper.ikey.write(key_type="Dallas", key_data="DEADBEEFCOOOFFEE")
# Émuler (délai d'attente par défaut 5 secondes)
flipper.ikey.emulate(key_type="Dallas", key_data="DEADBEEFCOOOFFEE")
# Attacher le journaliseur d'événements (délai d'attente par défaut 10 secondes)
logs = flipper.log.attach()
# Activer le mode débogage (émet `sysctl debug 1` sur le firmware actuel)
flipper.debug.on()
# Désactiver le mode débogage
flipper.debug.off()
# Recherche
response = flipper.onewire.search()
# Obtenir
response = flipper.i2c.get()
# Dump des entrées
dump = flipper.input.dump()
# Envoyer une entrée
flipper.input.send("up", "press")
La suite est divisée en deux parties :
test_serial_wrapper.py, test_commands.py) s'exécutent
partout — ils pilotent la bibliothèque contre un port série simulé
(tests/fake_serial.py) qui reproduit le trame du CLI Flipper, donc aucun périphérique
n'est requis. Ceux-ci s'exécutent dans l'CI.test_hardware.py) communiquent avec un vrai Flipper et
sont ignorés automatiquement lorsqu'aucun périphérique n'est connecté. Définissez
FLIPPER_COM=/dev/ttyACM0 pour spécifier un port particulier.# Tout (les tests matériels s'ignorent eux-mêmes si aucun Flipper n'est attaché)
python -m unittest discover -s tests -p "test_*.py" -v
# Seulement les tests sans matériel
python -m unittest tests.test_serial_wrapper tests.test_commands -v
N'hésitez pas à contribuer de quelque manière que ce soit
ZEC: zs13zdde4mu5rj5yjm2kt6al5yxz2qjjjgxau9zaxs6np9ldxj65cepfyw55qvfp9v8cvd725f7tz7
ETH: 0xef3cF1Eb85382EdEEE10A2df2b348866a35C6A54
BTC: 15umRZXBzgUacwLVgpLPoa2gv7MyoTrKat