Flipper Zero filesystem operations via serial CLI
Project description
FlipperFS
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 FlipperFileNotFoundError- File or directory not found on FlipperWriteError- Failed to write file to FlipperReadError- 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 operationsbinary_files.py- Binary file handlingsubghz_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:
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Run the test suite
- Submit a pull request
License
MIT License - see LICENSE file for details
Credits
Developed to provide reliable filesystem operations for Flipper Zero devices.
Links
- Repository: https://github.com/AndreMiras/flipper-fs.py
- Issues: https://github.com/AndreMiras/flipper-fs.py/issues
- PyPI: https://pypi.org/project/flipper-fs/
- Flipper Zero: https://flipperzero.one/
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flipper_fs-1.0.0.tar.gz.
File metadata
- Download URL: flipper_fs-1.0.0.tar.gz
- Upload date:
- Size: 11.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4ddec93bc4917b3927c62d028b2b0564624a9f37fe079aa8c9f0fe89a5f34ae4
|
|
| MD5 |
1fc8a0fee353535609f134e0116f3e53
|
|
| BLAKE2b-256 |
fb3d4b840f510a5046c470f20fffd0b2519d71ed72a72f304b554594156bf078
|
File details
Details for the file flipper_fs-1.0.0-py3-none-any.whl.
File metadata
- Download URL: flipper_fs-1.0.0-py3-none-any.whl
- Upload date:
- Size: 12.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7182a99a6ad1b82849d3f06614480db64bfbb3e5ac9332ee14cfac555c96f7ea
|
|
| MD5 |
5a4ba06930b7d9e461c2e0a7636ee4d6
|
|
| BLAKE2b-256 |
7db78205bdeb2318be9af174725fc957bec7354c251b4fb3c9c19d495a8dcbd9
|