
Wrapper de línea de comandos en Python para Flipper Zero
Envoltorio CLI de Python para Flipper Zero

Esta versión actualiza el envoltorio para alinearse con la CLI actual del Flipper Zero
(validado en hardware real, firmware unlshd-089e):
info: flipper.info.device_info() / power_info() /
power_debug_info() (los comandos modernos info device / info power).power info → info power: flipper.power.info() sigue funcionando y ahora
lee info power internamente. Se agregaron flipper.power.otg_on()/otg_off().date: use flipper.date.datetime(); se corrigió el análisis para el formato
de salida actual.KB como en KiB, read() ahora devuelve
el contenido completo del archivo con múltiples líneas, y las tarjetas exFAT / sin etiqueta se
analizan correctamente (corrige #21).NECext,
Kaseikyo, RCA, Pioneer, … son compatibles automáticamente (corrige #15). Nueva
función flipper.ir.protocols().debug → sysctl debug, subghz tx/rx obtuvo el argumento device
requerido, bt hci_info sin cambios.scan, dump,
emulate, field, apdu, raw, mfu) con ayudas de caché de claves Mifare Classic
por UID (import_nfc_keys, write_key_cache).ps (→ top), music_player, nfc detect.$ pip install pyflipper
unlshd-089e)from pyflipper import PyFlipper
# Puerto serie local
flipper = PyFlipper(com="/dev/ttyACM0")
# O
# Servidor remoto serial2websocket
flipper = PyFlipper(ws="ws://192.168.1.5:1337")
# TCP
flipper = PyFlipper(tcp='192.168.89.222:22170')
# Información (en el firmware actual esto lee `info power` internamente)
info = flipper.power.info()
# Apagar
flipper.power.off()
# Reiniciar
flipper.power.reboot()
# Reiniciar en modo DFU
flipper.power.reboot2dfu()
# Activar/desactivar el pin OTG de 5V en el encabezado GPIO
flipper.power.otg_on()
flipper.power.otg_off()
# Instalar actualización desde archivo .fuf
flipper.update.install(fuf_file="/ext/update.fuf")
# Hacer copia de seguridad del Flipper en archivo .tar
flipper.update.backup(dest_tar_file="/ext/backup.tar")
# Restaurar Flipper desde archivo .tar de copia de seguridad
flipper.update.restore(bak_tar_file="/ext/backup.tar")
# Listar aplicaciones instaladas
apps = flipper.loader.list()
# Abrir aplicación
flipper.loader.open(app_name="Clock")
# Obtener fecha del flipper (objeto datetime)
date = flipper.date.datetime()
# Obtener timestamp del flipper
timestamp = flipper.date.timestamp()
# Obtener diccionario de información del dispositivo (firmware actual `info device`, claves separadas por punto)
device_info = flipper.info.device_info()
# Obtener diccionario de información de energía (firmware actual `info power`)
power_info = flipper.info.power_info()
# Información extendida de depuración de energía/medidor
power_debug = flipper.info.power_debug_info()
# Comando `device_info` heredado (claves separadas por guión bajo, aún compatible)
legacy_info = flipper.device_info.info()
# Obtener diccionario de información del heap
heap = flipper.free.info()
# Obtener cadena free_blocks
free_blocks = flipper.free.blocks()
# Obtener información de Bluetooth
bt_info = flipper.bt.info()
Compatibilidad con firmware. Esta biblioteca ahora apunta a la CLI actual del Flipper Zero (firmware 1.x, verificado contra Unleashed
unlshd-089e). Algunos comandos heredados fueron eliminados del firmware oficial y por lo tanto ya no están disponibles:ps(reemplazado por eltopinteractivo),music_playerynfc detect(NFC ahora es un sub-shell interactivo).power infose movió ainfo power,debugse movió asysctl debug, ystorageahora reporta tamaños enKiB— todo manejado de forma transparente por los envoltorios anteriores.
# Obtener información del sistema de archivos de almacenamiento
ext_info = flipper.storage.info(fs="/ext")
# Obtener el diccionario de /ext del almacenamiento
ext_list = flipper.storage.list(path="/ext")
# Obtener el diccionario del árbol de /ext del almacenamiento
ext_tree = flipper.storage.tree(path="/ext")
# Obtener información de un archivo
file_info = flipper.storage.stat(file="/ext/foo/bar.txt")
# Crear directorio
flipper.storage.mkdir(new_dir="/ext/foo")
# Leer archivo
plain_text = flipper.storage.read(file="/ext/foo/bar.txt")
# Eliminar archivo
flipper.storage.remove(file="/ext/foo/bar.txt")
# Copiar archivo
flipper.storage.copy(src="/ext/foo/source.txt", dest="/ext/bar/destination.txt")
# Renombrar archivo
flipper.storage.rename(file="/ext/foo/bar.txt", new_file="/ext/foo/rab.txt")
# Hash MD5 de archivo
md5_hash = flipper.storage.md5(file="/ext/foo/bar.txt")
# Escribir archivo en un solo bloque
file = "/ext/bar.txt"
text = """Hay muchas variaciones de pasajes de Lorem Ipsum disponibles,
pero la mayoría han sufrido alteraciones de alguna forma, ya sea por humor inyectado,
o palabras aleatorias que no parecen ni siquiera ligeramente creíbles.
Si va a usar un pasaje de Lorem Ipsum,
debe asegurarse de que no haya nada vergonzoso escondido en medio del texto.
"""
flipper.storage.write.file(path=file, text=text)
# Escribir archivo usando un listener
file = "/ext/foo.txt"
text_one = """Hay muchas variaciones de pasajes de Lorem Ipsum disponibles,
pero la mayoría han sufrido alteraciones de alguna forma, ya sea por humor inyectado,
o palabras aleatorias que no parecen ni siquiera ligeramente creíbles.
Si va a usar un pasaje de Lorem Ipsum,
debe asegurarse de que no haya nada vergonzoso escondido en medio del texto.
"""
flipper.storage.write.start(file)
time.sleep(2)
flipper.storage.write.send(text_one)
text_two = """Todos los generadores de Lorem Ipsum en Internet tienden a repetir fragmentos predefinidos según sea necesario,
lo que lo convierte en el primer generador verdadero en Internet.
Utiliza un diccionario de más de 200 palabras latinas, combinado con un puñado de
estructuras de oraciones modelo, para generar Lorem Ipsum que parece razonable.
El Lorem Ipsum generado por lo tanto está siempre libre de repeticiones, humor inyectado o palabras no características, etc.
"""
flipper.storage.write.send(text_two)
time.sleep(3)
# No olvide detener
flipper.storage.write.stop()
# Establecer led genérico (r,b,g,bl)
flipper.led.set(led='r', value=255)
# Apagar led azul
flipper.led.blue(value=0)
# Establecer valor de led verde
flipper.led.green(value=175)
# Encender retroiluminación
flipper.led.backlight_on()
# Apagar retroiluminación
flipper.led.backlight_off()
# Apagar led
flipper.led.off()
# Establecer vibro True o False
flipper.vibro.set(True)
# Activar vibro
flipper.vibro.on()
# Desactivar vibro
flipper.vibro.off()
# Establecer modo gpio: 0 - entrada, 1 - salida
flipper.gpio.mode(pin_name=PIN_NAME, value=1)
# Establecer valor del pin gpio: 0 - apagado, 1 - encendido
flipper.gpio.set(pin_name=PIN_NAME, value=1)
# Leer valor del pin gpio
flipper.gpio.read(pin_name=PIN_NAME)
⚠️ Eliminado del firmware oficial. El comando CLI
music_playerfue eliminado del firmware estándar (la aplicación ahora es un.fapseparado). Estas llamadas aún funcionan en firmwares personalizados que mantienen el comando (por ejemplo, versiones Unleashed / RogueMaster que lo incluyen); en firmware estándar devuelven una respuesta "comando no encontrado".
# Reproducir canción en formato 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"
# Reproducir en bucle
flipper.music_player.play(rtttl_code=rttl_song)
# Detener bucle
flipper.music_player.stop()
# Reproducir durante 20 segundos
flipper.music_player.play(rtttl_code=rttl_song, duration=20)
# Beep
flipper.music_player.beep()
# Beep durante 5 segundos
flipper.music_player.beep(duration=5)
En el firmware actual, NFC es un sub-shell interactivo (scanner, dump,
emulate, field, apdu, raw, mfu). Este envoltorio ingresa al sub-shell,
ejecuta un comando y sale, por lo que cada método es una llamada bloqueante normal.
detect() se mantiene como un alias de scan().
# Detectar el tipo de etiqueta -> {'protocols': ['Mifare Classic'], 'raw': '...'} o None
tag = flipper.nfc.scan(timeout=5)
# Activar el campo NFC durante unos segundos
flipper.nfc.field(timeout=3)
# Enviar un APDU (ISO14443-4 / ISO15693-3); protocolo detectado automáticamente si se omite
resp = flipper.nfc.apdu(["00A4 04 00", "A0 00"], protocol="14_4a")
# Enviar bytes sin procesar con CRC añadido
flipper.nfc.raw("93 20", protocol="14a", crc=True)
# Ayudantes de Mifare Ultralight
info = flipper.nfc.mfu_info()
block4 = flipper.nfc.mfu_read_block(4)
flipper.nfc.mfu_write_block(4, "00 01 02 03")
# Emular un archivo .nfc guardado
flipper.nfc.emulate(file="/ext/nfc/mycard.nfc", timeout=10)
La CLI dump no ejecuta un ataque de diccionario: lee las claves de una
caché por UID en /ext/nfc/.cache/<UID>.keys (el archivo que la GUI escribe después de una
lectura exitosa). Si esa caché falta, dump devuelve "error al leer".
Puede (re)crearla a partir de un volcado .nfc existente del Flipper: las claves se toman de
cada sector trailer:
# Cargar claves desde un volcado .nfc nativo a la caché de claves por UID
uid, cache_path = flipper.nfc.import_nfc_keys("/path/to/card.nfc")
# Ahora la CLI dump puede leer la tarjeta (tokens de protocolo: mfc, mfu, 14_4a, ...)
flipper.nfc.dump(protocol="mfc", file="/ext/nfc/card_dump.nfc")
# Tiempo de espera predeterminado síncrono de 5 segundos
# Leer RFID
rfid = flipper.rfid.read()
# Emular RFID
emulated = flipper.rfid.emulate(key_type="EM4100", key_data="5500824806")
# Escribir RFID
written = flipper.rfid.write(key_type="EM4100", key_data="5500824806")
# Transmitir hex_key N veces (count predeterminado=10, device=0 -> CC1101_INT, 1 -> CC1101_EXT)
flipper.subghz.tx(hex_key="DEADBEEF", frequency=433920000, count=5, device=0)
# Recibir (frecuencia predeterminada=433920000 device=0 raw=False timeout=5 segundos)
received = flipper.subghz.rx(frequency=433920000, device=0, raw=True, timeout=10)
# Repetir transmisión grabada
flipper.subghz.tx_from_file("/ext/subghz/foo.sub")
# Decodificar archivo .sub sin procesar
decoded = flipper.subghz.decode_raw(sub_file="/ext/subghz/foo.sub")
# Listar los protocolos compatibles con el firmware conectado (se lee en vivo de la ayuda `ir`)
protocols = flipper.ir.protocols()
# Transmitir hex_address y hex_command seleccionando un protocolo
flipper.ir.tx(protocol="Samsung32", hex_address="C000FFEE", hex_command="DEADBEEF")
# NECext ahora es compatible (la lista de protocolos se lee del firmware, no está codificada)
flipper.ir.tx(protocol="NECext", hex_address="EF00", hex_command="FD02")
# Muestras de transmisión sin procesar
flipper.ir.tx_raw(frequency=38000, duty_cycle=0.33, samples=[1337, 8888, 3000, 5555])
# Tiempo de espera predeterminado síncrono de 5 segundos
# Recibir tx
r = flipper.ir.rx(timeout=10)
# Leer (tiempo de espera predeterminado 5 segundos)
ikey = flipper.ikey.read()
# Escribir (tiempo de espera predeterminado 5 segundos)
flipper.ikey.write(key_type="Dallas", key_data="DEADBEEFCOOOFFEE")
# Emular (tiempo de espera predeterminado 5 segundos)
flipper.ikey.emulate(key_type="Dallas", key_data="DEADBEEFCOOOFFEE")
# Adjuntar registrador de eventos (tiempo de espera predeterminado 10 segundos)
logs = flipper.log.attach()
# Activar modo de depuración (emite `sysctl debug 1` en el firmware actual)
flipper.debug.on()
# Desactivar modo de depuración
flipper.debug.off()
# Buscar
response = flipper.onewire.search()
# Obtener
response = flipper.i2c.get()
# Volcado de entrada
dump = flipper.input.dump()
# Enviar entrada
flipper.input.send("up", "press")
El conjunto se divide en dos:
test_serial_wrapper.py, test_commands.py) se ejecutan
en cualquier lugar: conducen la biblioteca contra un puerto serie simulado
(tests/fake_serial.py) que reproduce el marco de la CLI del Flipper, por lo que no se requiere
ningún dispositivo. Estas se ejecutan en CI.test_hardware.py) se comunican con un Flipper real y
se omiten automáticamente cuando no hay ningún dispositivo conectado. Establezca
FLIPPER_COM=/dev/ttyACM0 para fijar un puerto específico.# Todo (las pruebas de hardware se omiten si no hay un Flipper conectado)
python -m unittest discover -s tests -p "test_*.py" -v
# Solo las pruebas sin necesidad de hardware
python -m unittest tests.test_serial_wrapper tests.test_commands -v
Siéntase libre de contribuir de cualquier manera
ZEC: zs13zdde4mu5rj5yjm2kt6al5yxz2qjjjgxau9zaxs6np9ldxj65cepfyw55qvfp9v8cvd725f7tz7
ETH: 0xef3cF1Eb85382EdEEE10A2df2b348866a35C6A54
BTC: 15umRZXBzgUacwLVgpLPoa2gv7MyoTrKat