Skip to main content

Flipper Zero filesystem operations via serial CLI

Project description

FlipperFS

Tests

Reliable Flipper Zero filesystem operations via serial CLI

FlipperFS is a Python library that provides direct, reliable access to the Flipper Zero filesystem through serial communication at 230400 baud. Unlike other libraries with buggy storage operations, FlipperFS uses the proven serial CLI interface for rock-solid file operations.

Features

  • 🔌 Direct Serial Communication - No middleware, talks directly to Flipper CLI at 230400 baud
  • 📁 Complete Filesystem Operations - read, write, list, stat, mkdir, remove, copy, rename
  • 🔢 Binary File Support - Handle both text and binary files with chunk operations
  • 📡 Sub-GHz Utilities - Optional specialized operations for Sub-GHz signal files
  • 🛡️ Robust Error Handling - Custom exceptions with meaningful error messages
  • 🐍 Pythonic API - Context managers, type hints, clean interfaces
  • Production Ready - Comprehensive test coverage and proven in production

Installation

pip install flipper-fs

Import as:

import flipperfs

Development Installation

# Clone the repository
git clone https://github.com/AndreMiras/flipper-fs.py
cd flipper-fs.py

# Install in development mode with dev dependencies
pip install -e ".[dev]"

For reproducible CI/CD builds:

pip install -r requirements-dev.txt

Quick Start

Basic Usage

from flipperfs import FlipperStorage

# Connect to Flipper Zero
with FlipperStorage(port='/dev/ttyACM0') as storage:
    # List files
    files = storage.list('/any/subghz')
    print(f"Found {len(files)} items")

    # Read a file
    content = storage.read('/any/subghz/signal.sub')
    print(content)

    # Write a file
    storage.write('/any/test.txt', 'Hello from FlipperFS!')

    # Check if path exists
    if storage.exists('/any/subghz'):
        print("Sub-GHz directory exists")

    # Get file info
    info = storage.stat('/any/test.txt')
    print(f"File size: {info['size']} bytes")

    # Clean up
    storage.remove('/any/test.txt')

Sub-GHz Operations

from flipperfs.extras import SubGhzStorage

with SubGhzStorage(port='/dev/ttyACM0') as subghz:
    # List all signal files
    signals = subghz.list_signals()
    print(f"Found {len(signals)} signal files")

    # Read and parse signal file
    signal_data = subghz.read_signal('my_signal.sub')
    print(f"Frequency: {signal_data['Frequency']}")
    print(f"Protocol: {signal_data['Protocol']}")

    # Create a new signal file
    subghz.write_signal(
        signal_name='test_signal',
        hex_key='00000012F6CC053C',
        frequency=433920000,
        protocol='Dooya',
        bit_length=40
    )

    # Create temporary signal for transmission
    temp_path = subghz.create_temp_signal(
        hex_key='00000012F6CC053C',
        protocol='Dooya'
    )
    print(f"Temp signal created at: {temp_path}")

    # Clean up
    subghz.remove(temp_path)

API Reference

FlipperStorage

Main class for filesystem operations.

Connection

storage = FlipperStorage(port='/dev/ttyACM0', baud_rate=230400)

Parameters:

  • port (str): Serial port path (default: /dev/ttyACM0)
  • baud_rate (int): Serial baud rate (default: 230400)

Methods

info(path='/any') -> Dict[str, str] Get filesystem information (size, free space, etc.)

list(path='/any') -> List[Dict[str, Union[str, int]]] List files and directories. Returns list of dicts with keys: type, name, size, path

read(file_path) -> str Read text file content

write(file_path, content) -> bool Write text content to file

read_binary(file_path, chunk_size=1024) -> bytes Read binary file using chunk operations

write_binary(file_path, data, chunk_size=1024) -> bool Write binary data to file using chunk operations

stat(path) -> Optional[Dict[str, Union[str, int]]] Get file or directory statistics

exists(path) -> bool Check if file or directory exists

remove(path) -> bool Delete file or directory

mkdir(path) -> bool Create directory

copy(source, destination) -> bool Copy file to new location

rename(old_path, new_path) -> bool Rename or move file

md5(file_path) -> str Calculate MD5 hash of file

tree(path='/any') -> str Get recursive directory listing as formatted string

close() Close serial connection

SubGhzStorage

Extended storage operations for Sub-GHz signal files (inherits from FlipperStorage).

Methods

list_signals(directory='/any/subghz') -> List[str] List all .sub signal files in directory

read_signal(signal_name) -> Dict[str, str] Read and parse .sub file content into dictionary

write_signal(signal_name, hex_key, frequency=433920000, protocol='Dooya', preset='FuriHalSubGhzPresetOok650Async', bit_length=40) -> bool Create a new .sub signal file with specified parameters

create_temp_signal(hex_key, **kwargs) -> str Create temporary signal file and return path

Exceptions

All exceptions inherit from FlipperFilesystemError:

  • ConnectionError - Failed to connect or communicate with Flipper
  • FileNotFoundError - File or directory not found on Flipper
  • WriteError - Failed to write file to Flipper
  • ReadError - Failed to read file from Flipper

Environment Variables

You can set default values via environment variables:

export FLIPPER_PORT=/dev/ttyACM1
export FLIPPER_BAUD=230400

Then in your code:

import os
from flipperfs import FlipperStorage

port = os.getenv('FLIPPER_PORT', '/dev/ttyACM0')
storage = FlipperStorage(port=port)

Serial Port Detection

On Linux, Flipper Zero typically appears as /dev/ttyACM0 or /dev/ttyACM1.

To find your Flipper's port:

# List serial ports
ls /dev/tty* | grep ACM

# Or use dmesg
dmesg | grep tty

On macOS:

ls /dev/cu.usbmodem*

On Windows:

# Check Device Manager for COM ports

Development

Running Tests

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=flipperfs --cov-report=html

Code Formatting

# Format code
black flipperfs tests examples

# Check style
flake8 flipperfs tests examples

# Type checking
mypy flipperfs

Examples

See the examples/ directory for complete examples:

  • basic_operations.py - Basic filesystem operations
  • binary_files.py - Binary file handling
  • subghz_signals.py - Sub-GHz signal management

Why FlipperFS?

Existing libraries like PyFlipper have known bugs in their storage operations, particularly with file writes. FlipperFS was built from the ground up using direct serial CLI communication, which has proven reliable in production.

Advantages

  • Proven reliability - Battle-tested in production environments
  • Direct serial - No wrapper layers to cause issues
  • Complete API - All filesystem operations supported
  • Well tested - Comprehensive test suite
  • Clean code - Well-structured, documented, maintainable

Troubleshooting

Permission Denied on Linux

Add your user to the dialout group:

sudo usermod -a -G dialout $USER
# Log out and back in for changes to take effect

Or run with sudo (not recommended):

sudo python your_script.py

Connection Timeout

  • Ensure Flipper is powered on
  • Check the serial port is correct (ls /dev/tty*)
  • Verify no other programs are using the serial port
  • Try unplugging and replugging the USB cable

Import Errors

Make sure pyserial is installed:

pip install pyserial

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Run the test suite
  5. Submit a pull request

License

MIT License - see LICENSE file for details

Credits

Developed to provide reliable filesystem operations for Flipper Zero devices.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flipper_fs-1.0.1.tar.gz (18.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flipper_fs-1.0.1-py3-none-any.whl (12.5 kB view details)

Uploaded Python 3

File details

Details for the file flipper_fs-1.0.1.tar.gz.

File metadata

  • Download URL: flipper_fs-1.0.1.tar.gz
  • Upload date:
  • Size: 18.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for flipper_fs-1.0.1.tar.gz
Algorithm Hash digest
SHA256 081e7603329b3a606a3a1c9f893a8f76170c3c7c1453e9e807067aad6e3ef5fe
MD5 a41b18cc7538c77814f6ea8943dc16fe
BLAKE2b-256 123f70dba02c148d5ed6a6f9a8f26b332fffcf571ca1acfec9225ba878bb1a96

See more details on using hashes here.

File details

Details for the file flipper_fs-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: flipper_fs-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 12.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for flipper_fs-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 78f4251805ae2b50ff18ea8a3b121da19684196a0a38b9f8d7f6bb95b1d7421c
MD5 fb5ec8e3228b362e4cf5814798948b48
BLAKE2b-256 b1f43181767baa94132f4ed89023a9f23c50861868d8e26b430a793a91142d12

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page