Documentation
¶
Index ¶
- Variables
- func ConnectURL(ctx context.Context, rawURL string, timeout time.Duration) (*Flipper, *ConnectionReport, error)
- func IRProtocolNames() []string
- func SanitizeArg(s string) string
- type Capabilities
- type Check
- type CheckLevel
- type CommandRoute
- type CommandSupport
- type ConnectionReport
- func (r *ConnectionReport) Add(c Check)
- func (r *ConnectionReport) Checks() []Check
- func (r *ConnectionReport) Complete()
- func (r *ConnectionReport) Duration() time.Duration
- func (r *ConnectionReport) FailedCount() int
- func (r *ConnectionReport) MarshalJSON() ([]byte, error)
- func (r *ConnectionReport) PassedCount() int
- func (r *ConnectionReport) SkippedCount() int
- func (r *ConnectionReport) Summary() string
- func (r *ConnectionReport) ToJSON() any
- func (r *ConnectionReport) WarningCount() int
- type Flipper
- func (f *Flipper) BLEClient() *rpc.Client
- func (f *Flipper) BTHCIInfo() (string, error)
- func (f *Flipper) BackupCreate(path string) (string, error)
- func (f *Flipper) BackupRestore(path string) (string, error)
- func (f *Flipper) BadUSBRun(scriptPath string) (string, error)
- func (f *Flipper) Capabilities() Capabilities
- func (f *Flipper) Close() error
- func (f *Flipper) ConnectionReport() *ConnectionReport
- func (f *Flipper) CryptoDecrypt(slot string, data string) (string, error)
- func (f *Flipper) CryptoEncrypt(slot string, data string) (string, error)
- func (f *Flipper) CryptoHasKey(slot string) (string, error)
- func (f *Flipper) CryptoStoreKey(slot int, keyType string, keySize int, keyHex string) (string, error)
- func (f *Flipper) DateGet() (string, error)
- func (f *Flipper) DateSet(unix int64) (string, error)
- func (f *Flipper) DesktopIsLocked() (bool, error)
- func (f *Flipper) DesktopUnlock() error
- func (f *Flipper) DetectApps()
- func (f *Flipper) DetectCapabilities() (Capabilities, error)
- func (f *Flipper) DeviceInfo() (string, error)
- func (f *Flipper) DeviceInfoMap() (map[string]string, error)
- func (f *Flipper) EnterRPC(ctx context.Context) (*rpc.Client, func(), error)
- func (f *Flipper) Exec(command string) (string, error)
- func (f *Flipper) ExecCtx(ctx context.Context, command string) (string, error)
- func (f *Flipper) ExecLong(command string, timeout time.Duration) (string, error)
- func (f *Flipper) ExecLongCtx(ctx context.Context, command string, timeout time.Duration) (string, error)
- func (f *Flipper) FactoryReset() (string, error)
- func (f *Flipper) GPIORead(pin string) (string, error)
- func (f *Flipper) GPIOSet(pin string, value int) (string, error)
- func (f *Flipper) GuiScreenStream(duration time.Duration) (string, error)
- func (f *Flipper) I2CScan() (string, error)
- func (f *Flipper) IButtonEmulate(protocol string, hexData string, duration time.Duration) (string, error)
- func (f *Flipper) IButtonEmulateCtx(ctx context.Context, protocol string, hexData string, duration time.Duration) (string, error)
- func (f *Flipper) IButtonRead(timeout time.Duration) (string, error)
- func (f *Flipper) IButtonReadCtx(ctx context.Context, timeout time.Duration) (string, error)
- func (f *Flipper) IButtonWrite(hexData string) (string, error)
- func (f *Flipper) IRDecodeFile(path string) (string, error)
- func (f *Flipper) IRRx(timeout time.Duration) (string, error)
- func (f *Flipper) IRRxCtx(ctx context.Context, timeout time.Duration) (string, error)
- func (f *Flipper) IRRxRaw(timeout time.Duration) (string, error)
- func (f *Flipper) IRRxRawCtx(ctx context.Context, timeout time.Duration) (string, error)
- func (f *Flipper) IRRxRawStream(ctx context.Context, timeout time.Duration, ...) (string, error)
- func (f *Flipper) IRRxStream(ctx context.Context, timeout time.Duration, ...) (string, error)
- func (f *Flipper) IRTxParsed(protocol string, address string, command string) (string, error)
- func (f *Flipper) IRTxRaw(frequency uint32, dutyCycle float64, data string) (string, error)
- func (f *Flipper) IRUniversal(remoteName string, signalName string) (string, error)
- func (f *Flipper) IRUniversalList(library string) (string, error)
- func (f *Flipper) InputSend(button string, eventType string) (string, error)
- func (f *Flipper) InvalidateState()
- func (f *Flipper) IsBLE() bool
- func (f *Flipper) IsSuspended() bool
- func (f *Flipper) JSRun(path string, duration time.Duration) (string, error)
- func (f *Flipper) LED(channel string, value int) (string, error)
- func (f *Flipper) LaunchBridge(ctx context.Context, command string) (string, error)
- func (f *Flipper) LoaderClose() (string, error)
- func (f *Flipper) LoaderInfo() (string, error)
- func (f *Flipper) LoaderList() (string, error)
- func (f *Flipper) LoaderListParsed() (LoaderApps, error)
- func (f *Flipper) LoaderLogicAnalyzer() (string, error)
- func (f *Flipper) LoaderMFKey() (string, error)
- func (f *Flipper) LoaderMagSpoof() (string, error)
- func (f *Flipper) LoaderMifareNested() (string, error)
- func (f *Flipper) LoaderNFCMagic() (string, error)
- func (f *Flipper) LoaderNRF24Mousejacker() (string, error)
- func (f *Flipper) LoaderNRF24Sniffer() (string, error)
- func (f *Flipper) LoaderOpen(appName string, args string) (string, error)
- func (f *Flipper) LoaderOscilloscope() (string, error)
- func (f *Flipper) LoaderPicopass() (string, error)
- func (f *Flipper) LoaderPocsagPager() (string, error)
- func (f *Flipper) LoaderProtoView() (string, error)
- func (f *Flipper) LoaderSPIMemManager() (string, error)
- func (f *Flipper) LoaderSeader() (string, error)
- func (f *Flipper) LoaderSentrySafe() (string, error)
- func (f *Flipper) LoaderSignal(signal int, argHex string) (string, error)
- func (f *Flipper) LoaderSignalGenerator() (string, error)
- func (f *Flipper) LoaderSpectrumAnalyzer() (string, error)
- func (f *Flipper) LoaderSubGHzBruteforcer() (string, error)
- func (f *Flipper) LoaderSubGHzJammerDetect() (string, error)
- func (f *Flipper) LoaderSubGHzPlaylist() (string, error)
- func (f *Flipper) LoaderT5577MultiWriter() (string, error)
- func (f *Flipper) LoaderUARTTerminal() (string, error)
- func (f *Flipper) LoaderUnitemp() (string, error)
- func (f *Flipper) LoaderWeatherStation() (string, error)
- func (f *Flipper) LogStream(duration time.Duration, level string) (string, error)
- func (f *Flipper) LogStreamCtx(ctx context.Context, duration time.Duration, level string) (string, error)
- func (f *Flipper) LogStreamLines(ctx context.Context, duration time.Duration, level string, ...) (string, error)
- func (f *Flipper) NFCAPDU(apduHex string, timeout time.Duration) (string, error)
- func (f *Flipper) NFCDetect(timeout time.Duration) (string, error)
- func (f *Flipper) NFCDumpProtocol(protocol string, timeout time.Duration) (string, error)
- func (f *Flipper) NFCEmulate(filePath string) (string, error)
- func (f *Flipper) NFCMFURead(page int, timeout time.Duration) (string, error)
- func (f *Flipper) NFCMFUWrite(page int, hexData string, timeout time.Duration) (string, error)
- func (f *Flipper) NFCRawFrame(hexData string, timeout time.Duration) (string, error)
- func (f *Flipper) NFCSubcommand(subcommand string, timeout time.Duration) (string, error)
- func (f *Flipper) OneWireSearch(duration time.Duration) (string, error)
- func (f *Flipper) OneWireSearchCtx(ctx context.Context, duration time.Duration) (string, error)
- func (f *Flipper) Power3V3(enable bool) (string, error)
- func (f *Flipper) Power5V(enable bool) (string, error)
- func (f *Flipper) PowerInfo() (string, error)
- func (f *Flipper) PowerInfoMap() (map[string]string, error)
- func (f *Flipper) PowerOff() (string, error)
- func (f *Flipper) PowerRebootDFU() (string, error)
- func (f *Flipper) PropertyGet(key string) ([]struct{ ... }, error)
- func (f *Flipper) RFIDEmulate(protocol string, data string, duration time.Duration) (string, error)
- func (f *Flipper) RFIDEmulateCtx(ctx context.Context, protocol string, data string, duration time.Duration) (string, error)
- func (f *Flipper) RFIDRawAnalyze(filePath string) (string, error)
- func (f *Flipper) RFIDRawEmulate(filePath string, duration time.Duration) (string, error)
- func (f *Flipper) RFIDRawEmulateCtx(ctx context.Context, filePath string, duration time.Duration) (string, error)
- func (f *Flipper) RFIDRawRead(mode, filePath string, duration time.Duration) (string, error)
- func (f *Flipper) RFIDRead(ctx context.Context, mode string, timeout time.Duration) (string, error)
- func (f *Flipper) RFIDWrite(protocol string, data string) (string, error)
- func (f *Flipper) RawCLI(command string) (string, error)
- func (f *Flipper) Reboot() (string, error)
- func (f *Flipper) Reconnect(ctx context.Context) error
- func (f *Flipper) SetConnectionReport(r *ConnectionReport)
- func (f *Flipper) SetExecTimeout(d time.Duration)
- func (f *Flipper) SetLED(color string, brightness int) error
- func (f *Flipper) SetMaxAccumBytes(n int)
- func (f *Flipper) SetPipeline(p PipelineProfile)
- func (f *Flipper) SetPipelineBundle(p Pipeline)
- func (f *Flipper) SetReconnectCallback(cb func(phase, message string))
- func (f *Flipper) SetWriteFileTimeout(d time.Duration)
- func (f *Flipper) State(ctx context.Context) (State, error)
- func (f *Flipper) StorageCopy(src, dst string) (string, error)
- func (f *Flipper) StorageExtract(archive, outdir string) (string, error)
- func (f *Flipper) StorageFSInfo(path string) (string, error)
- func (f *Flipper) StorageFSInfoMap(path string) (map[string]string, error)
- func (f *Flipper) StorageFormat() (string, error)
- func (f *Flipper) StorageList(path string) (string, error)
- func (f *Flipper) StorageMD5(path string) (string, error)
- func (f *Flipper) StorageMkdir(path string) (string, error)
- func (f *Flipper) StorageRead(path string) (string, error)
- func (f *Flipper) StorageRemove(path string) (string, error)
- func (f *Flipper) StorageRename(src, dst string) (string, error)
- func (f *Flipper) StorageStat(path string) (string, error)
- func (f *Flipper) StorageTree(path string) (string, error)
- func (f *Flipper) StorageWrite(path string, data string) error
- func (f *Flipper) StorageWriteCtx(ctx context.Context, path string, data string) error
- func (f *Flipper) StreamCtx(ctx context.Context, command string, onLine func(line string) (stop bool)) error
- func (f *Flipper) SubGHzChat(frequency uint32, duration time.Duration) (string, error)
- func (f *Flipper) SubGHzChatCtx(ctx context.Context, frequency uint32, duration time.Duration) (string, error)
- func (f *Flipper) SubGHzChatDevice(frequency uint32, duration time.Duration, device int) (string, error)
- func (f *Flipper) SubGHzChatDeviceCtx(ctx context.Context, frequency uint32, duration time.Duration, device int) (string, error)
- func (f *Flipper) SubGHzDecode(filePath string) (string, error)
- func (f *Flipper) SubGHzRx(frequency uint32, duration time.Duration) (string, error)
- func (f *Flipper) SubGHzRxCtx(ctx context.Context, frequency uint32, duration time.Duration) (string, error)
- func (f *Flipper) SubGHzRxRaw(frequency uint32, duration time.Duration) (string, error)
- func (f *Flipper) SubGHzRxRawCtx(ctx context.Context, frequency uint32, duration time.Duration) (string, error)
- func (f *Flipper) SubGHzRxRawStream(ctx context.Context, frequency uint32, duration time.Duration, ...) (string, error)
- func (f *Flipper) SubGHzRxStream(ctx context.Context, frequency uint32, duration time.Duration, ...) (string, error)
- func (f *Flipper) SubGHzTx(filePath string) (string, error)
- func (f *Flipper) SubGHzTxKey(keyHex string, freq uint32, te uint32, repeat int) (string, error)
- func (f *Flipper) SubGHzTxKeyDevice(keyHex string, freq uint32, te uint32, repeat int, device int) (string, error)
- func (f *Flipper) Suspend(reason string) error
- func (f *Flipper) SuspensionReason() string
- func (f *Flipper) Transport() transport.Transport
- func (f *Flipper) UpdateInstall(manifestPath string) (string, error)
- func (f *Flipper) Vibro(on bool) (string, error)
- func (f *Flipper) WriteFile(path string, data []byte) error
- func (f *Flipper) WriteFileCtx(ctx context.Context, path string, data []byte) error
- type LoaderApps
- type NFCDetectResult
- type Pipeline
- type PipelineProfile
- type RouteDecision
- type State
- type StorageStatResult
- type SubGHzCandidate
- type SubGHzReceiveResult
Constants ¶
This section is empty.
Variables ¶
var ErrCommandRequiresUSB = errors.New("this Flipper command has no RPC equivalent in firmware and is only available over USB")
ErrCommandRequiresUSB is returned by Flipper command methods when the underlying transport is BLE and the requested operation has no equivalent RPC verb in the firmware. Sub-GHz, NFC, IR, RFID, iButton, and BadUSB are CLI-only on every Flipper firmware (stock + Momentum) because the firmware exposes only RPC over BLE Serial — see flipperdevices/flipperzero-firmware applications/services/bt and applications/services/rpc/. Surface this error to operators with the command name + the suggestion to attach the Flipper via USB.
var ErrConnectTimeout = errors.New("timeout waiting for Flipper CLI prompt")
ErrConnectTimeout is returned when the Flipper does not produce a CLI prompt within the connect timeout. The Flipper is likely inside an app or on a dialog that has taken over the CLI — press Back on the device and retry.
var ErrFlipperSuspended = errors.New("flipper offline (UART bridge active)")
ErrFlipperSuspended is returned by CLI methods when the Flipper handle is suspended (typically because the Flipper firmware is in USB-UART bridge mode and the CLI is unreachable by design). The wording is public-facing — it surfaces in agent tool errors and the web UI banner.
var ErrInRPCMode = errors.New("flipper is in RPC (mirror) mode; release the mirror to use CLI commands")
ErrInRPCMode is returned by CLI methods when the Flipper is held by a concurrent RPC session. Release the mirror (call the closure returned by EnterRPC) before issuing CLI commands.
var ErrResponseTruncated = errors.New("flipper response truncated: exceeded max accumulator size")
ErrResponseTruncated is returned by read paths when accumulated output exceeds the configured cap. Partial output is still returned alongside the error so callers can inspect what arrived before the overflow.
Functions ¶
func ConnectURL ¶
func ConnectURL(ctx context.Context, rawURL string, timeout time.Duration) (*Flipper, *ConnectionReport, error)
ConnectURL opens the transport identified by rawURL and performs the CLI handshake. rawURL is any scheme registered with the transport package; a bare device path (e.g. "/dev/ttyACM0") is accepted as shorthand for serial://.
Returns the connected handle, a populated *ConnectionReport detailing each step's outcome and timing (always non-nil — even on error so operators can see which step actually failed), and any terminal error. On error the transport is already closed and the *Flipper is nil. On success the report is also stashed on the returned handle (Flipper.ConnectionReport) so /api/device can surface it.
The handshake is cancelable: if ctx is cancelled or timeout elapses before the prompt arrives, ConnectURL closes the transport and returns ctx.Err() or ErrConnectTimeout respectively.
func IRProtocolNames ¶ added in v0.182.0
func IRProtocolNames() []string
IRProtocolNames returns the sorted list of valid IR protocols. Used in the validation error message and exposed for any caller that wants to enumerate the firmware-supported set (e.g. spec schema generators).
func SanitizeArg ¶
SanitizeArg is the exported wrapper for callers outside this package that build Flipper CLI commands directly (e.g. the agent's inline bruteforce dispatch). Prefer the typed wrapper functions when one exists. Delegates to clisafe.SanitizeArg.
Types ¶
type Capabilities ¶
type Capabilities struct {
// ===== Identity (existing, preserved) =====
FirmwareFork string // "" (stock/OFW), "Unleashed", "Momentum", "Xtreme", "RogueMaster", …
FirmwareVersion string // fork-specific version string from firmware_version
FirmwareCommit string // short git SHA from firmware_commit
FirmwareDate string // build date string from firmware_build_date (DD-MM-YYYY)
HardwareUID string // STM32 unique ID (16 hex chars) from hardware_uid
HardwareName string // user-settable dolphin name from hardware_name
// ===== Identity (new) =====
// FirmwareBand is the resolved fork+version band, e.g. "momentum/mntm-dev",
// "unleashed/unlshd-086", "stock/1.0.x". See resolveBand() for the full
// value set (firmware-matrix.md §3.6).
FirmwareBand string
FirmwareAPIMajor int // from firmware_api_major (numeric); 80-83=OFW 0.10x, 85+=OFW 1.x, 77-79=Momentum, 70-72=Xtreme, 86-87=Unleashed/RM
FirmwareAPIMinor int // from firmware_api_minor
FirmwareCommitDirty bool // from firmware_commit_dirty ("1" → true); nightly-build signal
FirmwareOriginGit string // from firmware_origin_git (upstream repo URL)
HardwareRegion string // from hardware_region — string form (EU/US/JP/WW or numeric)
HardwareVer int // from hardware_ver (board revision; F7 production = 13)
// DeviceInfoKeyStyle indicates which key separator the parser saw.
// Always "underscore" when populated via device_info (the standard path);
// set to "dotted" if a future caller uses `info device` output instead.
DeviceInfoKeyStyle string
// ===== CLI surface (existing, preserved) =====
// PowerInfoCmd is the CLI verb that returns power/battery information.
// All modern forks use "info power"; empty means unavailable.
PowerInfoCmd string // "info power" on all modern forks
HasNFCSubshell bool // `nfc` subshell present; false only on Xtreme
SubGHzNeedsDev bool // `subghz tx/rx` requires a trailing `<device>` arg (0=INT, 1=EXT)
NFCFlaggedArgs bool // NFC subshell uses flag-based args (-p, -d, -b) rather than positional
SubGHzRxRawHasFilePath bool // `subghz rx_raw` accepts a file-path arg (false on all modern forks — streams to stdout)
// ===== CLI surface (new — architect additions §C.1) =====
// JSEngineKind is the CLI verb prefix for the JS engine ("mjs" on all
// four active forks including archived Xtreme; firmware-matrix.md §4.1
// found no divergence despite the runbook's earlier claim).
JSEngineKind string // "mjs" universally; "" if JS is absent
HasBLESpam bool // BLE Spam FAP present (Momentum/Xtreme in-tree; RM optimistic default)
HasSubGHzBruteforcer bool // Sub-GHz Bruteforcer FAP available on this fork
HasMouseJackerFAP bool // NRF24 Mousejacker FAP (NRF24 add-on required)
HasSeaderFAP bool // HID iCLASS Seader FAP (Momentum/Unleashed/RM)
HasPicopassFAP bool // PicoPass FAP (all custom forks)
HasNFCMagicFAP bool // NFC Magic card-writer FAP (all custom forks)
HasMFKeyFAP bool // MFKey32 FAP (all custom forks; Unleashed ships it in-tree)
HasMifareNestedFAP bool // Mifare Nested attack FAP (all custom forks)
UniversalIRLibraryName string // SD path for the universal IR library; "assets/infrared/assets" (stock/Unleashed/RM) vs "infrared/assets" (Momentum/Xtreme)
// ===== CLI surface (new — research additions §4.2) =====
HasStorageFormatExt bool // `storage format_ext` verb present (all custom forks; absent on stock OFW)
HasSubGHzEncryptKeeloq bool // `subghz encrypt_keeloq` verb present (all custom forks)
HasSubGHzChat bool // `subghz chat` verb present (universal — all five forks)
HasPsCmd bool // `ps` alias for `top` present (Momentum + Xtreme)
HasClearCmd bool // `clear` terminal-clear command present (Momentum only)
// ===== Storage quirks (new) =====
// StorageExtFatLabel is the FAT volume label of the SD card.
// Defaults to "Flipper SD"; Momentum freshly formats with "MOMENTUM".
StorageExtFatLabel string
// SnapshotPrefix is the root path for pre-write SD snapshots used by /rewind.
SnapshotPrefix string
// ===== Marauder-side (probed separately; not set by device_info) =====
// MarauderDetected and MarauderCompatBand are set by the Marauder
// connect path, not by DetectCapabilities. Left as zero-value TODOs
// here for a follow-up v0.5.1 research task (firmware-matrix.md §6 Q6).
MarauderDetected bool
MarauderCompatBand string
}
Capabilities captures the firmware-specific CLI surface of the connected Flipper, detected from `device_info` at connect time. Different custom firmwares (stock, Unleashed, RogueMaster, Xtreme, Momentum, ...) expose different CLI commands and behaviours; wrappers branch on these flags to stay portable across all five active forks.
Field ordering: identity → CLI surface → RF/NFC quirks → apps/FAPs → storage → marauder. Existing fields are preserved byte-for-byte; new fields are appended in their sections so callers that embed Capabilities by value are not broken.
func (Capabilities) FriendlyFork ¶
func (c Capabilities) FriendlyFork() string
FriendlyFork returns a display-ready fork name, falling back to "stock" when the fork field is empty (OFW omits firmware_origin_fork entirely).
type Check ¶ added in v0.13.0
type Check struct {
Name string `json:"name"`
Level CheckLevel `json:"level"`
Detail string `json:"detail,omitempty"`
Elapsed time.Duration `json:"elapsed_ns"`
}
Check is one step's outcome inside a ConnectionReport.
Name is a stable, machine-readable identifier (snake_case with dotted namespacing — e.g. "transport.dial", "handshake", "detect_capabilities"). Detail is operator-facing free text — kept short, no ANSI. Elapsed is the wall-clock time the step took.
type CheckLevel ¶ added in v0.13.0
type CheckLevel string
CheckLevel classifies a single ConnectionReport step's outcome.
LevelPass: the step completed cleanly. LevelWarn: the step succeeded after a recovery, or completed with a non-fatal degradation that the operator should know about. LevelFail: the step failed terminally; downstream steps were skipped. LevelSkipped: the step did not run on this transport / firmware (e.g. CLI handshake on a BLE link).
const ( LevelPass CheckLevel = "pass" LevelWarn CheckLevel = "warn" LevelFail CheckLevel = "fail" LevelSkipped CheckLevel = "skipped" )
type CommandRoute ¶ added in v0.13.0
type CommandRoute int
CommandRoute enumerates the dispatch paths a Flipper command can take. The set is closed: every (transport, support) pair in RouteFor must resolve to one of these values.
const ( // RouteTextCLI sends the command as plain text down the serial // channel and parses the firmware's `>: ` prompt response. This // is the default route for USB transports where the firmware // exposes a text CLI. RouteTextCLI CommandRoute = iota // RouteRPC streams a protobuf request through the persistent // rpc.Client. This is the default route for BLE transports — the // firmware exposes ONLY protobuf RPC over BLE Serial, never a // text CLI — and is also valid on USB when the caller prefers // the structured response shape. RouteRPC // RouteUSBOnly indicates the requested operation cannot be // serviced on the live transport. Most often this means the // firmware has no RPC verb for the operation and the caller is // on BLE; the wrapper must surface ErrCommandRequiresUSB. RouteUSBOnly )
func (CommandRoute) String ¶ added in v0.13.0
func (r CommandRoute) String() string
String returns a stable, lower-case route name suitable for log lines and error reasons.
type CommandSupport ¶ added in v0.13.0
CommandSupport describes the capability surface a wrapper expects from the firmware. Each field captures a single yes/no fact about the command:
- HasRPCVerb — true when the firmware exposes a protobuf RPC request for this operation. Default false (most CLI verbs do NOT have an RPC equivalent — Sub-GHz, NFC, IR, RFID, iButton, BadUSB are CLI-only on every fork).
- HasCLI — true when the firmware exposes a text-CLI verb for this operation. Default true (almost every command this codebase wraps is a CLI verb; the exceptions are pure-RPC ops like the gpio/loader pairs that some forks dropped from CLI).
- FirmwareForkRequired — when non-empty, the operation is only supported on the named fork (case-insensitive). Used for Momentum-only or Xtreme-only features.
The zero value (HasRPCVerb=false, HasCLI=false, fork="") is intentionally "broken" — every wrapper must explicitly state at least one supported transport. RouteFor returns RouteUSBOnly with a clear reason when the zero value is passed, which gives the migration script a loud failure if a wrapper forgot to fill the struct.
type ConnectionReport ¶ added in v0.13.0
type ConnectionReport struct {
StartedAt time.Time
CompletedAt time.Time
// contains filtered or unexported fields
}
ConnectionReport is the structured trail of every step ConnectURL took to bring a Flipper online. It is appended to in-order and never re-shuffled; the JSON shape is the operator-facing contract surfaced in /api/device.
func NewConnectionReport ¶ added in v0.13.0
func NewConnectionReport() *ConnectionReport
NewConnectionReport stamps StartedAt and returns an empty report ready for Add. The zero-value ConnectionReport is also usable; this helper just records the start time consistently.
func (*ConnectionReport) Add ¶ added in v0.13.0
func (r *ConnectionReport) Add(c Check)
Add appends a check to the report. Safe for concurrent use — although ConnectURL drives steps sequentially today, /api/device may read the report from a different goroutine.
func (*ConnectionReport) Checks ¶ added in v0.13.0
func (r *ConnectionReport) Checks() []Check
Checks returns a copy of the recorded checks. The slice is detached so callers can range over it without holding the report lock.
func (*ConnectionReport) Complete ¶ added in v0.13.0
func (r *ConnectionReport) Complete()
Complete stamps CompletedAt. Idempotent on the assumption ConnectURL calls it once, but a second call simply overwrites with a fresher timestamp.
func (*ConnectionReport) Duration ¶ added in v0.13.0
func (r *ConnectionReport) Duration() time.Duration
Duration returns CompletedAt - StartedAt when both are set, otherwise the time since StartedAt. Zero when the report has not started.
func (*ConnectionReport) FailedCount ¶ added in v0.13.0
func (r *ConnectionReport) FailedCount() int
FailedCount returns the number of checks at LevelFail.
func (*ConnectionReport) MarshalJSON ¶ added in v0.13.0
func (r *ConnectionReport) MarshalJSON() ([]byte, error)
MarshalJSON produces operator-readable JSON. The rendered shape is the stable contract surfaced via /api/device.connection_report.
func (*ConnectionReport) PassedCount ¶ added in v0.13.0
func (r *ConnectionReport) PassedCount() int
PassedCount returns the number of checks at LevelPass.
func (*ConnectionReport) SkippedCount ¶ added in v0.13.0
func (r *ConnectionReport) SkippedCount() int
SkippedCount returns the number of checks at LevelSkipped.
func (*ConnectionReport) Summary ¶ added in v0.13.0
func (r *ConnectionReport) Summary() string
Summary renders a one-line operator summary of the report's terminal state, e.g. "3 passed, 1 warning". Used by --verbose mode and any caller that wants a banner-friendly digest without iterating Checks.
func (*ConnectionReport) ToJSON ¶ added in v0.13.0
func (r *ConnectionReport) ToJSON() any
ToJSON returns the report rendered as an interface{} suitable for embedding in another JSON response. Convenience wrapper around MarshalJSON for /api/device, which assembles a single map[string]any payload.
func (*ConnectionReport) WarningCount ¶ added in v0.13.0
func (r *ConnectionReport) WarningCount() int
WarningCount returns the number of checks at LevelWarn.
type Flipper ¶
type Flipper struct {
// contains filtered or unexported fields
}
Flipper is the command-layer handle for a connected device. It wraps a transport.Transport and layers prompt framing, capability detection, and hot-plug reconnect on top. All command wrappers (commands.go) go through Exec / ExecLong / StreamCtx / WriteFile — none touch the transport directly.
func Connect ¶
func Connect(ctx context.Context, portName string, baudRate int, timeout time.Duration) (*Flipper, error)
Connect opens a serial port and performs the CLI handshake.
Preserves the pre-Phase-6 signature — the tree has ~5 callers (cmd main, tests in flipper_mock_test.go / primitives_mock_test.go) that pass a path + baud + timeout directly. Internally, Connect builds a serial:// URL and hands it to ConnectURL; new callers that want to pick a non-serial transport should use ConnectURL directly.
func NewForTest ¶ added in v0.3.0
func NewForTest(caps Capabilities) *Flipper
NewForTest returns a Flipper with preloaded capabilities and no transport. Intended for unit tests in other packages that need to exercise State-consuming code paths without wiring up a mock serial port. The returned Flipper will never successfully Exec — only capability-derived and transport-less-safe methods should be called.
func (*Flipper) BLEClient ¶ added in v0.12.0
BLEClient returns the persistent RPC client opened at connect time when the transport is BLE, or nil otherwise. Callers must check IsBLE first; on USB the client is constructed on demand via EnterRPC and is not held on the Flipper handle.
func (*Flipper) BTHCIInfo ¶
BTHCIInfo returns local Bluetooth controller info (chip, firmware version, MAC). Read-only; does not bring up a BLE stack — native BLE operations still require an external devboard. CLI: bt hci_info
func (*Flipper) BackupCreate ¶ added in v0.16.0
BackupCreate writes a tar archive of the Flipper's internal flash (/int) to the given SD-card path. Uses a 5-minute deadline — same budget as UpdateInstall.
Rejects empty/whitespace path before transport. An empty path produces `update backup ` which writes to firmware-default location on some forks and errors on others; reject up front so the operator always knows where the backup landed. CLI: update backup <path>
func (*Flipper) BackupRestore ¶ added in v0.16.0
BackupRestore restores a previously created backup archive. Destructive — overwrites current /int contents. The Spec risk band enforces confirmation.
Rejects empty/whitespace path before transport. Empty path on the destructive restore path is particularly dangerous: some forks treat it as "restore from default location" which could surface a stale backup. The operator should always name the file explicitly. CLI: update restore <path>
func (*Flipper) BadUSBRun ¶
BadUSBRun launches a BadUSB script via the app loader.
Rejects empty/whitespace scriptPath before transport: an empty path produces `loader open "Bad USB" ` (trailing space) which either crashes the loader or launches BadUSB with no script — the operator then sees the app idle on the Flipper screen with no diagnostic. CLI: loader open "Bad USB" <script_path>
func (*Flipper) Capabilities ¶
func (f *Flipper) Capabilities() Capabilities
Capabilities returns the detected firmware capability map. If DetectCapabilities has not yet been called (or failed), returns a zero-valued struct with the conservative defaults (power_info, nfc subshell, no subghz device arg).
func (*Flipper) ConnectionReport ¶ added in v0.13.0
func (f *Flipper) ConnectionReport() *ConnectionReport
ConnectionReport returns the most recently attached ConnectionReport, or nil when none has been set. Callers must treat the returned value as read-only.
func (*Flipper) CryptoDecrypt ¶ added in v0.16.0
CryptoDecrypt decrypts hex-encoded ciphertext using the key in the named slot. slot must be a decimal-integer string in 1-100. CLI: crypto decrypt <slot> <hex-data>
func (*Flipper) CryptoEncrypt ¶ added in v0.16.0
CryptoEncrypt encrypts hex-encoded data using the key in the named slot. slot is a decimal-integer string in 1-100 (matches the firmware's crypto_cli_encrypt slot parser). CLI: crypto encrypt <slot> <hex-data>
func (*Flipper) CryptoHasKey ¶ added in v0.16.0
CryptoHasKey reports whether a key is stored in the named slot. slot must be a decimal-integer string in 1-100. CLI: crypto has_key <slot>
func (*Flipper) CryptoStoreKey ¶
func (f *Flipper) CryptoStoreKey(slot int, keyType string, keySize int, keyHex string) (string, error)
CryptoStoreKey stores a key in one of the Flipper's secure-storage slots. Overwrites whatever was in that slot. keyType: "master", "simple", or "encrypted" keySize: 128 or 256 (bits); keyHex must be exactly keySize/8 bytes as hex.
Validates slot/keyType/keySize/keyHex before transport. Wrong key types or hex/size mismatches surface as opaque firmware errors otherwise. CLI: crypto store_key <slot> <keyType> <keySize> <keyHex>
func (*Flipper) DateGet ¶ added in v0.16.0
DateGet returns the current device time as reported by the RTC. CLI: date
func (*Flipper) DateSet ¶ added in v0.16.0
DateSet synchronises the Flipper's RTC to the given Unix timestamp. The OFW CLI form is: date YYYY-MM-DD HH:MM:SS WD where WD is the ISO-8601 weekday (1=Monday … 7=Sunday). The timestamp is interpreted in UTC — the Flipper firmware stores UTC. CLI: date <YYYY-MM-DD> <HH:MM:SS> <1-7>
func (*Flipper) DesktopIsLocked ¶ added in v0.12.0
DesktopIsLocked reports whether the device's home screen is currently pin-locked. Returns (true, nil) when locked, (false, nil) when unlocked. Errors are reserved for transport / protocol failures — "unlocked" is a legitimate state the firmware signals via CommandStatus_ERROR on the response Empty, which DesktopIsLocked translates to (false, nil).
USB transports: returns ErrCommandRequiresUSB-wrapped error. The firmware exposes no equivalent CLI verb, so this is structurally a BLE-only operation today.
func (*Flipper) DesktopUnlock ¶ added in v0.12.0
DesktopUnlock dismisses the pin-lock screen if one is active. Safe to call when the device is already unlocked — the firmware returns success either way.
USB transports: returns ErrCommandRequiresUSB-wrapped error (no equivalent CLI verb on any current firmware fork).
func (*Flipper) DetectApps ¶ added in v0.5.0
func (f *Flipper) DetectApps()
DetectApps queries the connected Flipper's FAP (Flipper App Package) list via `loader list` and updates the capability flags for app-presence fields (HasBLESpam, HasSubGHzBruteforcer, HasMouseJackerFAP, etc.).
This is a best-effort probe: if `loader list` fails or times out, the FAP flags retain their fork-typical static defaults from detectCapabilities (set conservatively for Unleashed and optimistically for RogueMaster per firmware-matrix.md §6 Q8). A failed probe never propagates an error — the device_info parse is the authoritative signal for fork/version detection.
Integration note: DetectApps should be called from DetectCapabilities (serial.go) after the device_info parse and initial caps.Store. Since serial.go is managed by the transport layer (not in this engineer's write scope for v0.5), callers may invoke DetectApps() independently after DetectCapabilities() when FAP-presence accuracy is required. The firmware_introspect Handler (internal/tools/firmware.go) calls it when refresh=true.
Name-to-flag mapping (firmware-matrix.md §4.3):
"BLE Spam" → HasBLESpam "SubGHz Bruteforcer" → HasSubGHzBruteforcer "Sub-GHz BF" → HasSubGHzBruteforcer (alternate name on some forks) "NRF24 Mousejacker" → HasMouseJackerFAP "Seader" → HasSeaderFAP "PicoPass" → HasPicopassFAP "NFC Magic" → HasNFCMagicFAP "MFKey" → HasMFKeyFAP (Unleashed in-tree path) "MFKey32" → HasMFKeyFAP (RM/Momentum external FAP) "Mifare Nested" → HasMifareNestedFAP
func (*Flipper) DetectCapabilities ¶
func (f *Flipper) DetectCapabilities() (Capabilities, error)
DetectCapabilities queries device_info and caches the parsed capability map. Best-effort: on error, leaves prior caps (or defaults) in place.
func (*Flipper) DeviceInfo ¶
DeviceInfo returns device information.
CLI transport: `device_info` text command, response parsed by the caller. RPC transport (BLE — text CLI is not available there): a SystemDeviceInfoRequest streamed via the persistent rpc.Client; the (key, value) pairs are reformatted as the same `key: value\n` block the CLI emits so downstream parsing in DeviceInfoMap / parseKVBlock is transport-agnostic.
Migrated to the compat-layer dispatch (Phase A). The viaCLI/viaRPC closures wrap the same code paths the old inline `if f.IsBLE()` branch used, so the public behaviour is identical.
func (*Flipper) DeviceInfoMap ¶ added in v0.2.0
DeviceInfoMap runs device_info and parses the output into a flat key→value map. Blank lines and lines missing a colon are skipped. The full surface is preserved — callers wanting one field (e.g. the dolphin name) should look up the key directly. Numeric-looking values stay as strings so consumers decide the typing (some fields like storage_sdcard_totalSpace are huge int64s that don't survive JavaScript number coercion without care).
func (*Flipper) EnterRPC ¶ added in v0.9.2
EnterRPC transitions the Flipper into RPC mode and returns a typed client along with a release closure.
Semantics on USB CDC:
- Acquires f.mu for the entire RPC session.
- Attempts reconnect if the transport is marked disconnected.
- Drains any pending CLI output from the buffer.
- Constructs rpc.NewClient, calls Open. On error: unlocks and returns.
- Sets rpcMode to true.
- Returns the client and a release closure that: clears rpcMode, closes the client, re-handshakes the CLI prompt, and unlocks the mutex.
Semantics on BLE:
The Flipper firmware has no text CLI on its BLE Serial endpoint — RPC is permanent for the lifetime of the connection. ConnectURL already opened the persistent client (f.bleClient) at handshake time and latched rpcMode=true, so EnterRPC returns that client with a no-op release closure. The caller's release() call is therefore safe and idempotent on both transports, but on BLE no CLI re-handshake runs (there is no CLI to return to).
The release closure is safe to call exactly once; subsequent calls are no-ops.
func (*Flipper) Exec ¶
Exec sends a CLI command and returns the full response. Preserved for backward compatibility; new callers should use ExecCtx so cancellation propagates through to the reconnect path.
func (*Flipper) ExecCtx ¶
ExecCtx is the context-aware variant of Exec. The ctx is honoured during reconnect polling and during the 10 s per-command read deadline.
func (*Flipper) ExecLong ¶
ExecLong sends a command that may take a while (captures, brute force, etc). Preserved for backward compatibility; new callers should use ExecLongCtx so cancellation propagates through to the reconnect path.
func (*Flipper) ExecLongCtx ¶
func (f *Flipper) ExecLongCtx(ctx context.Context, command string, timeout time.Duration) (string, error)
ExecLongCtx is the context-aware variant of ExecLong. A non-positive timeout is floored to 60 s so a caller passing a zero duration still gets a sane per-command deadline.
func (*Flipper) FactoryReset ¶ added in v0.16.0
FactoryReset schedules a factory reset that takes effect on the next reboot. Destructive — all user data and settings are erased. The Spec risk band enforces confirmation; this method is a plain wire wrapper. CLI: factory_reset
func (*Flipper) GPIORead ¶
GPIORead reads the current value of a GPIO pin.
CLI transport: `gpio read <pin>` text command. Output format from firmware is "Pin <name> = <0|1>" (with mild fork-to-fork variation). RPC transport (BLE): gpio_read_pin streamed via the persistent rpc.Client. The numeric value is reformatted as the same single-line "Pin <name> = <0|1>\n" string the CLI emits so downstream parsers (workflows.gpioValueFromOutput) work without knowing which transport produced the output. CLI: gpio read <pin>
func (*Flipper) GPIOSet ¶
GPIOSet sets a GPIO pin to a value.
CLI transport: `gpio set <pin> <value>` text command. RPC transport (BLE — text CLI is not available there): selected on the value:
- 0 or 1: gpio_write_pin (output mode + drive level).
- anything else: gpio_set_pin_mode with mode=INPUT, treated as "switch this pin to read mode before a subsequent gpio_read". The CLI has no in-band equivalent for this — it's a transport- specific hook for callers who need to flip a pin to input via RPC before reading.
CLI emits no output on success, so the RPC branch returns an empty string to match. CLI: gpio set <pin> <value>
func (*Flipper) GuiScreenStream ¶ added in v0.16.0
GuiScreenStream collects display frames from the Flipper for the given duration via the Protobuf RPC screen-stream path and returns them as base64-encoded PBM (P4 binary, 128×64) frames, one per line.
RPC is available only when the underlying transport is BLE (f.bleClient is non-nil). On USB the web-UI mirror owns the screen-stream lifecycle via EnterRPC; calling this method on USB returns a descriptive error so the caller can surface the correct user prompt.
RPC: Gui.StartScreenStreamRequest → collect frames → StopScreenStreamRequest
func (*Flipper) I2CScan ¶
I2CScan scans the I²C bus for connected devices. Tries the built-in `i2c scan` CLI first (available on Xtreme and forks that ship it); if the firmware rejects the command, falls back to launching the "I2C Scanner" FAP via loader_open. Buzzes on success. CLI: i2c scan → loader open "I2C Scanner"
func (*Flipper) IButtonEmulate ¶
func (f *Flipper) IButtonEmulate(protocol string, hexData string, duration time.Duration) (string, error)
IButtonEmulate emulates an iButton key for the given duration. The firmware command is streaming (prints "Emulating key ..." then waits for Ctrl+C), so the wrapper uses ExecLong with streaming semantics. Supported protocols: Dallas, Cyfral, Metakom. A reader must be in contact with the iButton contacts during the emulation window. CLI: ikey emulate <protocol> <hex_data>
func (*Flipper) IButtonEmulateCtx ¶ added in v0.62.0
func (f *Flipper) IButtonEmulateCtx(ctx context.Context, protocol string, hexData string, duration time.Duration) (string, error)
IButtonEmulateCtx is the context-aware variant of IButtonEmulate.
Validates protocol against the three-entry firmware allowlist and hexData as valid hex before transport. Bad protocol names otherwise reach the firmware as opaque "unknown protocol" banners; malformed hex gets rejected mid-stream after the emulation window has already burned wall-clock.
func (*Flipper) IButtonRead ¶
IButtonRead reads an iButton key. CLI: ikey read
func (*Flipper) IButtonReadCtx ¶ added in v0.62.0
IButtonReadCtx is the context-aware variant of IButtonRead. Preserves the 120 ms success-buzz wrapper.
func (*Flipper) IButtonWrite ¶
IButtonWrite writes an iButton key (Dallas only).
Dallas keys are exactly 8 bytes (16 hex chars including family code + serial + CRC); shorter / longer input or non-hex characters are rejected up front rather than handed to the firmware writer. CLI: ikey write Dallas <hex_data>
func (*Flipper) IRDecodeFile ¶
IRDecodeFile parses a saved .ir file and returns the decoded entries. Read-only and local to the SD card — no transmit. CLI: ir decode <path>
func (*Flipper) IRRxCtx ¶ added in v0.62.0
IRRxCtx is the context-aware variant of IRRx. Preserves the 120 ms success-buzz wrapper.
func (*Flipper) IRRxRawCtx ¶ added in v0.62.0
IRRxRawCtx is the context-aware variant of IRRxRaw.
func (*Flipper) IRRxRawStream ¶ added in v0.57.0
func (f *Flipper) IRRxRawStream(ctx context.Context, timeout time.Duration, onLine func(line string) (stop bool)) (string, error)
IRRxRawStream is the line-streaming variant of IRRxRaw. Each pulse line emitted while `ir rx raw` is running lands at onLine; stop=true ends the capture early. No success buzz — the raw stream typically runs to completion via a duration budget rather than a discrete "captured" moment. CLI: ir rx raw
func (*Flipper) IRRxStream ¶ added in v0.57.0
func (f *Flipper) IRRxStream(ctx context.Context, timeout time.Duration, onLine func(line string) (stop bool)) (string, error)
IRRxStream is the line-streaming variant of IRRx. Each line emitted by `ir rx` (typically the decoded signal once a remote button is pressed) lands at onLine; stop=true ends the capture. Wraps the streaming call in withSuccessBuzz so a successful capture still triggers the 120 ms vibration on completion — operators rely on the buzz to confirm the IR signal was caught without looking at the screen. CLI: ir rx
func (*Flipper) IRTxParsed ¶
IRTxParsed transmits a decoded infrared signal.
Validates protocol against the firmware allowlist before transport. Common LLM hallucinations ("Sony" instead of SIRC, "Panasonic" instead of Kaseikyo, lower-case "nec") otherwise reach the firmware as an opaque "unknown protocol" banner with a usage dump. CLI: ir tx <protocol> <address_hex> <command_hex>
func (*Flipper) IRTxRaw ¶
IRTxRaw transmits a raw infrared signal.
Validates frequency and duty cycle before transport: out-of-range values either silently no-op on the firmware or come back as an opaque "invalid frequency" error several seconds later. Reject up front so the LLM gets a useful diagnostic on its next turn. CLI: ir tx RAW F:<freq> DC:<duty_cycle> <data>
func (*Flipper) IRUniversal ¶
IRUniversal brute-forces every variant of the named signal category across all manufacturer codes in the specified universal remote library. It is NOT a single-shot transmission — the firmware sweeps all frames of that signal type (e.g. "Power" fires every known power-off frame). CLI: ir universal <remote_name> <signal_name>
func (*Flipper) IRUniversalList ¶
IRUniversalList lists entries in a universal remote library file so the agent can see which buttons are available before calling IRUniversal. CLI: ir universal list <library>
func (*Flipper) InputSend ¶
InputSend sends a synthetic button input event.
CLI transport: `input send <button> <type>`. RPC transport (BLE): a gui_send_input_event_request dispatched via the persistent rpc.Client. The RPC produces no response body, so on success both transports return an empty string — preserving the (string, error) contract.
CLI: input send <button> <type> button: up, down, left, right, ok, back eventType: press, release, short, long
func (*Flipper) InvalidateState ¶ added in v0.3.0
func (f *Flipper) InvalidateState()
InvalidateState drops the cached snapshot so the next State() call forces a re-query. Intended for use after operations that might change the observable state materially (firmware updates, power reboots, storage format), not for every write — the 2 s TTL already covers ordinary drift.
func (*Flipper) IsBLE ¶ added in v0.12.0
IsBLE reports whether the underlying transport is BLE. BLE transports can only speak Protobuf RPC (not text CLI), so command dispatchers branch on this to either route through the persistent RPC client (f.bleClient) or — for commands without an RPC equivalent — return ErrCommandRequiresUSB.
func (*Flipper) IsSuspended ¶ added in v0.10.0
IsSuspended reports whether Suspend has been called.
func (*Flipper) JSRun ¶
JSRun executes a saved JavaScript file on the Flipper's JS runtime. Fork-gated: only the Xtreme, Momentum, and RogueMaster forks ship a JS engine. On stock the call returns a friendly-fork error rather than issuing a no-op CLI command that hangs. CLI: js <path>
func (*Flipper) LED ¶
LED sets a single LED channel to a brightness value (0-255).
Validates channel against the four-entry firmware allowlist and value to [0, 255] before transport. Unknown channels are silently no-op'd on stock firmware; out-of-range values either clamp or trigger an opaque firmware banner depending on fork. CLI: led <r|g|b|bl> <0-255> channel: "r" (red), "g" (green), "b" (blue), "bl" (backlight)
func (*Flipper) LaunchBridge ¶ added in v0.12.0
LaunchBridge launches the Flipper's USB-UART Bridge and returns the firmware's response text (empty on BLE).
USB transport: sends the literal command string (default `loader open "USB-UART Bridge"`) — preserved for older Flipper firmware builds where that name was a registered launchable. On modern Momentum the bridge cannot be entered while USB CDC is locked for CLI/RPC anyway (gpio_scene_start.c:109), so this path will surface "Application not found" via classifyBridgeRejection.
BLE transport: ignores the command string and runs the canonical Momentum-compatible sequence directly:
- app_start_request(name="GPIO") — opens the GPIO app (the ContainingApp for the USB-UART Bridge scene per applications/main/gpio/gpio_scene_start.c).
- brief settle so the scene-manager renders GpioSceneStart with "USB-UART Bridge" highlighted at index 0 (the default menu item).
- gui_send_input_event(OK, SHORT) — fires GpioStartEventUsbUart; because USB CDC isn't locked on a BLE-only session, the firmware navigates to GpioSceneUsbUart whose on_enter unconditionally calls usb_uart_enable() with the default config (vcp_ch=0, uart_ch=0, baudrate default — Marauder's 115200 baud).
This path is the only one that actually starts the bridge on Momentum: the loader-open shortcut "USB-UART Bridge" was never a registered application, only a menu label. The firmware's gpio_scene_usb_uart.c on_enter is what actually flips USB CDC into UART pass-through mode.
func (*Flipper) LoaderClose ¶
LoaderClose closes the currently running application.
CLI transport: `loader close`. RPC transport (BLE): an AppExitRequest dispatched via the persistent rpc.Client. Both paths return an empty success string on the happy path; non-OK firmware status (e.g. ERROR_APP_NOT_RUNNING when no app is open) surfaces via the wrapped error.
CLI: loader close
func (*Flipper) LoaderInfo ¶
LoaderInfo returns metadata about the currently running app (name, flags). CLI: loader info
USB-only: the Flipper firmware exposes no RPC verb that returns the currently-running app's metadata. (app_lock_status_request only reports a boolean lock state.) On BLE this returns ErrCommandRequiresUSB.
func (*Flipper) LoaderList ¶
LoaderList lists all available applications. CLI: loader list
USB-only: the Flipper firmware exposes no RPC verb for enumerating the FAP registry. On BLE this returns ErrCommandRequiresUSB so callers can surface a clear "connect via USB" message instead of an opaque transport-mode error from Exec.
func (*Flipper) LoaderListParsed ¶
func (f *Flipper) LoaderListParsed() (LoaderApps, error)
LoaderListParsed returns the app/settings lists as structured data so the agent can decide whether a target app is installed before calling loader_open. Returned fields are empty slices (not nil) when a section is missing from the output.
USB-only: depends on `loader list`, which has no firmware RPC verb. On BLE this returns ErrCommandRequiresUSB directly so callers see a clear error from the parser layer rather than a transport-level one.
func (*Flipper) LoaderLogicAnalyzer ¶ added in v0.205.0
LoaderLogicAnalyzer launches the "Logic Analyzer" FAP (RogueMaster/flipperzero-firmware-wPlugins). 8-channel logic capture on the Flipper's GPIO header. Sample-only — no signal generation. Pairs with the hw_recon workflow as the device-internal scope path before reaching for a Bus Pirate or external logic analyzer.
Source: docs/catalog/gap-analysis.md §3 rank 12 (gpio_logic_capture).
func (*Flipper) LoaderMFKey ¶
LoaderMFKey launches the "MFKey32" FAP for MIFARE Classic key recovery.
func (*Flipper) LoaderMagSpoof ¶ added in v0.204.0
LoaderMagSpoof launches the "MagSpoof" FAP from zacharyweiss/magspoof_flipper — Samy Kamkar's wireless mag-stripe emulator, GPIO-driven coil over the Flipper's external header. Emits Track 1/2/3 data into nearby mag-stripe readers; the Electronic Cats fork takes an external coil module instead.
Source: apps top-20 #9 per docs/catalog/gap-analysis.md §3 (rank 3).
func (*Flipper) LoaderMifareNested ¶
LoaderMifareNested launches the "Mifare Nested" FAP (nested attack recovery).
func (*Flipper) LoaderNFCMagic ¶
LoaderNFCMagic launches the "NFC Magic" FAP used to write MIFARE magic tags.
func (*Flipper) LoaderNRF24Mousejacker ¶
LoaderNRF24Mousejacker launches the "NRF24 Mousejacker" FAP. Requires an external NRF24L01+ devboard wired to the Flipper's GPIO header. The FAP takes over the screen and reads target addresses from /ext/apps_data/nrfsniff/addresses.txt plus DuckyScript payloads from /ext/mousejacker/*.txt. Momentum firmware exposes no nrf24 CLI, so all run-time interaction happens through the FAP UI (navigate via input_send; back-button to exit).
func (*Flipper) LoaderNRF24Sniffer ¶ added in v0.3.1
LoaderNRF24Sniffer launches the companion "NRF24 Sniffer" FAP. The FAP scans 2.4 GHz bands for active wireless-peripheral addresses and writes hits to /ext/apps_data/nrfsniff/addresses.txt (comma-separated address,rate lines). Prerequisite for any Mousejack flow — the FAP UI is operator-driven; there is no CLI equivalent.
func (*Flipper) LoaderOpen ¶
LoaderOpen opens a Flipper application by name with optional arguments. The app name is always double-quoted so multi-word names (e.g. "Bad USB", "Sub-GHz BF") are parsed as a single token by the firmware's args_read_probably_quoted_string_and_trim.
CLI transport: `loader open "<app_name>" [args]`. RPC transport (BLE): an AppStartRequest dispatched via the persistent rpc.Client. Both paths return an empty success string on success — `loader open` produces no CLI output when the launch succeeds, and the RPC ack carries no body either, so the (string, error) contract is identical across transports.
CLI: loader open "<app_name>" [args]
Rejects empty/whitespace appName before transport. Empty names produce `loader open ""` which the firmware rejects with an opaque parse error.
func (*Flipper) LoaderOscilloscope ¶ added in v0.205.0
LoaderOscilloscope launches the "Oscilloscope" FAP (Next-Flip/Momentum-Apps/oscilloscope). 1 MS/s single-channel ADC visualiser on the GPIO header. Companion to the 8-channel Logic Analyzer FAP — same sample-only safety class.
Source: docs/catalog/apps.md line 234 (Flipper Scope), referenced by gap-analysis.md §3 rank 12.
func (*Flipper) LoaderPicopass ¶
LoaderPicopass launches the "PicoPass" FAP (HID iClass/Picopass tooling).
func (*Flipper) LoaderPocsagPager ¶ added in v0.204.0
LoaderPocsagPager launches the "Pocsag Pager" FAP from Next-Flip/Momentum-Apps. Receive-only POCSAG paging decoder on the Flipper's CC1101 — common European paging dragnet target. Bundled in Momentum / RogueMaster / ATP / Unleashed firmwares.
Source: apps top-20 #11 per docs/catalog/gap-analysis.md §3 (rank 4).
func (*Flipper) LoaderProtoView ¶
LoaderProtoView launches the "ProtoView" FAP for raw Sub-GHz signal visualisation.
func (*Flipper) LoaderSPIMemManager ¶
LoaderSPIMemManager launches the "SPI Mem Manager" FAP for reading and writing SPI flash chips via the GPIO header.
func (*Flipper) LoaderSeader ¶
LoaderSeader launches the "SEADER" FAP (HID iClass SE advanced tooling).
func (*Flipper) LoaderSentrySafe ¶ added in v0.204.0
LoaderSentrySafe launches the "Sentry Safe" FAP from H4ckd4ddy/flipperzero-sentry-safe-plugin. Drives the factory-test backdoor sequence on Sentry / Master Lock electronic safes via the Flipper GPIO header (TX line into the safe's debug port). Physical pentest primitive — needs the operator to wire the Flipper to the target safe's reset pads before launching.
Source: apps top-20 #10 per docs/catalog/gap-analysis.md §3 (rank 2).
func (*Flipper) LoaderSignal ¶
LoaderSignal sends a numeric signal to the currently running app with an optional hex argument (many apps document custom opcodes that consume argHex). Pass "" to omit the argument. CLI: loader signal <n> [<hex>]
USB-only: the firmware exposes app_button_press / app_button_release / app_data_exchange RPC verbs but no generic "send numeric signal" equivalent that matches the CLI's free-form (signal, hex) shape, so this remains CLI-only. On BLE returns ErrCommandRequiresUSB.
func (*Flipper) LoaderSignalGenerator ¶
LoaderSignalGenerator launches the "Signal Generator" FAP.
func (*Flipper) LoaderSpectrumAnalyzer ¶
LoaderSpectrumAnalyzer launches the "Spectrum Analyzer" FAP.
func (*Flipper) LoaderSubGHzBruteforcer ¶
LoaderSubGHzBruteforcer launches the "Sub-GHz BF" brute-force FAP. Destructive by design — runs enormous code sweeps.
func (*Flipper) LoaderSubGHzJammerDetect ¶ added in v0.205.0
LoaderSubGHzJammerDetect launches the "Sub-GHz Jammer Detect" FAP (RogueMaster/flipperzero-firmware-wPlugins). Receive-only RSSI floor + dwell heuristic that flags suspected jammer activity in the 300-928 MHz bands. Defensive primitive — no transmission.
Source: docs/catalog/gap-analysis.md §3 rank 16 (subghz_jammer_detect).
func (*Flipper) LoaderSubGHzPlaylist ¶
LoaderSubGHzPlaylist launches the "Playlist" FAP that replays a sequence of .sub captures.
func (*Flipper) LoaderT5577MultiWriter ¶
LoaderT5577MultiWriter launches the "T5577 Multiwriter" FAP for batch writing of 125 kHz T5577 tags.
func (*Flipper) LoaderUARTTerminal ¶
LoaderUARTTerminal launches the "UART Terminal" FAP for serial comms on the Flipper's GPIO header.
func (*Flipper) LoaderUnitemp ¶
LoaderUnitemp launches the "Unitemp" FAP for reading external temperature sensors over the GPIO header.
func (*Flipper) LoaderWeatherStation ¶ added in v0.205.0
LoaderWeatherStation launches the "Weather Station" FAP (flipperdevices/flipperzero-good-faps/weather_station). Receive-only 433 MHz decoder for LaCrosse / Acurite / Oregon Scientific weather sensors. Bundled in OFW, Momentum, RogueMaster, ATP.
Source: docs/catalog/gap-analysis.md §3 rank 5 (subghz_weather_decode).
func (*Flipper) LogStream ¶
LogStream opens a live log stream from the Flipper for the supplied duration, returning the captured text. Read-only; the Flipper keeps running after the stream ends. level filters the minimum severity — empty string means the firmware's default; recognised values are "default", "error", "warn", "info", "debug", "trace". CLI: log [<level>]
func (*Flipper) LogStreamCtx ¶ added in v0.62.0
func (f *Flipper) LogStreamCtx(ctx context.Context, duration time.Duration, level string) (string, error)
LogStreamCtx is the context-aware variant of LogStream.
func (*Flipper) LogStreamLines ¶ added in v0.57.0
func (f *Flipper) LogStreamLines(ctx context.Context, duration time.Duration, level string, onLine func(line string) (stop bool)) (string, error)
LogStreamLines is the line-streaming variant of LogStream. Each log line emitted by firmware is delivered to onLine as it arrives; returning stop=true ends the capture early.
Empty level uses the firmware default. Recognised values match LogStream. CLI: log [<level>]
func (*Flipper) NFCAPDU ¶
NFCAPDU sends an APDU command to a contactless smart card (ISO7816) via the nfc subshell. Fork-gated. Subshell verb (stock/Unleashed): apdu <hex> Subshell verb (Momentum): apdu -d <hex>
func (*Flipper) NFCDetect ¶
NFCDetect enters the NFC subshell, runs the scanner subcommand, and exits. The subshell prompt is "[nfc]>: ". Not all firmware forks expose an NFC CLI — Xtreme XFW ships an empty `nfc` subsystem — so we surface a clear error rather than hanging on a non-responsive subcommand.
func (*Flipper) NFCDumpProtocol ¶
NFCDumpProtocol dumps tag contents for a specific NFC protocol via the nfc subshell. Callers pass the canonical friendly name ("Mifare_Classic", "Mifare_Ultralight", "Mifare_Plus", "FeliCa"); the wrapper translates to the firmware's accepted token.
Subshell verb (stock/Unleashed): dump <protocol> Subshell verb (Momentum): dump -p <token> (token is mfc/mfu/mfp/felica)
Pass an empty string to skip the protocol arg entirely — Momentum's `dump` (no -p) auto-detects the protocol and writes a .nfc file in /ext/nfc/dump-YYYYMMDD-HHMMSS.nfc. That auto-save shape is the real "scan and save" workflow on Momentum and is preferred when the caller doesn't already know the protocol.
func (*Flipper) NFCEmulate ¶
NFCEmulate launches the NFC emulation app via the loader, waits for the app to exit, then verifies the loader is free before returning. This ensures subsequent Exec calls are not blocked by "application is open" errors. Returns an error if the loader does not free within ~1 second. CLI: loader open NFC <file_path> → loader close → poll loader info
func (*Flipper) NFCMFURead ¶
NFCMFURead reads a single MIFARE Ultralight page/block. Fork-gated. Subshell verb (stock/Unleashed): mfu rdbl <page> Subshell verb (Momentum): mfu rdbl -b <page>
func (*Flipper) NFCMFUWrite ¶
NFCMFUWrite writes 4 bytes of hex data to a MIFARE Ultralight page/block. Destructive — overwrites whatever the tag currently holds. Fork-gated. Subshell verb (stock): mfu wrbl <page> <hex> Subshell verb (Momentum/Unleashed): mfu wrbl -b <page> -d <hex>
func (*Flipper) NFCRawFrame ¶
NFCRawFrame sends a raw ISO14443 frame to a tag via the nfc subshell and returns the tag's response. Fork-gated: not available on Xtreme (no NFC CLI subshell). Subshell verb (stock/Unleashed): raw <hex> Subshell verb (Momentum): raw -p iso14a -d <hex> Momentum's NFC CLI uses a flag-based parser; positional args are rejected. Protocol defaults to iso14a (ISO 14443-3A), the most common NFC protocol.
func (*Flipper) NFCSubcommand ¶
NFCSubcommand enters the NFC subshell, sends an arbitrary subcommand, and exits. Valid subcommands include: scanner, emulate, dump, field, raw, apdu, mfu. Not available on firmware forks without an NFC CLI subshell (e.g., Xtreme).
func (*Flipper) OneWireSearch ¶
OneWireSearch enumerates devices on the 1-Wire bus. Read-only; buzzes on success so the user knows something was found. CLI: onewire search
func (*Flipper) OneWireSearchCtx ¶ added in v0.62.0
OneWireSearchCtx is the context-aware variant of OneWireSearch. Preserves the 120 ms success-buzz wrapper.
func (*Flipper) Power3V3 ¶ added in v0.16.0
Power3V3 enables (enable=true) or disables (enable=false) the 3.3 V GPIO supply rail on the Flipper's external header. CLI: power 3v3 1 or power 3v3 0
func (*Flipper) Power5V ¶ added in v0.16.0
Power5V enables (enable=true) or disables (enable=false) the 5 V GPIO supply rail on the Flipper's external header. CLI: power 5v 1 or power 5v 0
func (*Flipper) PowerInfo ¶
PowerInfo returns power/battery information. The CLI spelling differs by fork: Xtreme uses `info power`; stock/Unleashed/RogueMaster use `power_info`. The capability map stores the right verb at connect time. On BLE the firmware exposes a single SystemPowerInfoRequest regardless of fork — fork-specific CLI spelling is not relevant — and the (key, value) pairs are reformatted to the same `key: value` block the CLI emits.
Migrated to the compat-layer dispatch (Phase A). Fork-specific CLI verb selection still happens inside the viaCLI closure — the compat layer doesn't know about per-fork verb spellings, only about transport-level routing.
func (*Flipper) PowerInfoMap ¶ added in v0.2.0
PowerInfoMap runs the fork-appropriate power_info command and returns the parsed key→value map (charge_level, battery_voltage, capacity_*, etc.).
Separate from DeviceInfoMap because none of the forks expose power fields via device_info: Xtreme and Momentum serve them via `info power` (dot-separated keys — normalised to underscore here), stock/Unleashed/RogueMaster via the legacy `power_info` (already underscore-separated).
func (*Flipper) PowerOff ¶ added in v0.16.0
PowerOff powers off the Flipper. The device will not respond after this until the user presses the power button. The Spec risk band enforces confirmation. CLI: power off
func (*Flipper) PowerRebootDFU ¶
PowerRebootDFU reboots the Flipper into the STM32 DFU bootloader. Leaves the device without a running firmware until a host reflashes or the user power-cycles — recovery is physical. Guarded as Critical at the risk layer.
CLI transport: `power reboot2dfu` text command. RPC transport (BLE): SystemRebootRequest with mode=DFU streamed via the persistent rpc.Client. As with Reboot, the firmware does not emit a response — the link drops immediately. Both branches return an empty string on success. CLI: power reboot2dfu
func (*Flipper) PropertyGet ¶ added in v0.12.0
PropertyGet retrieves the (key, value) pairs the firmware exposes under the supplied key prefix. An empty prefix returns every exposed property. The returned slice preserves the firmware's emission order — useful for callers that want to keep keys grouped by namespace (e.g. "devinfo.").
USB transports: returns ErrCommandRequiresUSB-wrapped error.
func (*Flipper) RFIDEmulate ¶
RFIDEmulate emulates an RFID tag for the given duration. The firmware command is streaming (prints "Emulating RFID..." then waits for Ctrl+C), so the wrapper uses ExecLong with streaming semantics: on deadline the lower layer sends \x03 to abort and returns the accumulated output with nil error. Pass a reasonable duration (typical: 2–10 s) — a reader needs to be pointed at the Flipper during the window. CLI: rfid emulate <protocol> <hex_data>
func (*Flipper) RFIDEmulateCtx ¶ added in v0.62.0
func (f *Flipper) RFIDEmulateCtx(ctx context.Context, protocol string, data string, duration time.Duration) (string, error)
RFIDEmulateCtx is the context-aware variant of RFIDEmulate.
Validates protocol non-empty and data as valid hex before the emulation window opens. Malformed hex would otherwise silently emulate a corrupted card for the full duration.
func (*Flipper) RFIDRawAnalyze ¶
RFIDRawAnalyze post-processes a raw LF capture, attempting to decode the contained protocol. Pure local analysis — no RF activity. CLI: rfid raw_analyze <file_path>
func (*Flipper) RFIDRawEmulate ¶
RFIDRawEmulate replays a raw 125 kHz capture against a reader. Active transmission — use with authorisation. CLI: rfid raw_emulate <file_path>
func (*Flipper) RFIDRawEmulateCtx ¶ added in v0.62.0
func (f *Flipper) RFIDRawEmulateCtx(ctx context.Context, filePath string, duration time.Duration) (string, error)
RFIDRawEmulateCtx is the context-aware variant of RFIDRawEmulate.
func (*Flipper) RFIDRawRead ¶
RFIDRawRead performs a raw 125 kHz capture to a file for later analysis. Mode is "ask" or "psk" (pass "" for auto); filePath is where the raw capture is written. Read-only from the RF perspective — no transmit. CLI: rfid raw_read [<mode>] <file_path>
Momentum firmware (confirmed via Next-Flip/Momentum-Firmware lfrfid_cli.c) uses the same `rfid raw_read` verb with the same arg shape as stock. Firmware-side arg errors are reported as a usage banner (no error code), which callers would otherwise see as a silent success. Output-scanning converts the banner to an explicit error.
func (*Flipper) RFIDRead ¶
RFIDRead reads a 125kHz RFID tag. mode is optional (normal, indala, ask, psk); pass "" for auto. Unlike a plain ExecLong, this streams the Flipper's output and returns as soon as a tag is decoded — so a successful scan takes ~1-2 seconds instead of waiting out the full timeout. If nothing appears within timeout, a helpful "no tag detected" error is returned. CLI: rfid read [mode]
func (*Flipper) RFIDWrite ¶
RFIDWrite writes data to an RFID tag.
Same up-front validation as RFIDEmulateCtx — malformed data silently writes a corrupted T5577 blank, which is much harder to spot than a clean error before TX. CLI: rfid write <protocol> <hex_data>
func (*Flipper) RawCLI ¶
RawCLI sends an arbitrary CLI command string to the Flipper and returns its output. Escape hatch for firmware features we haven't wrapped, or for debugging. Callers MUST risk-gate this — it can reboot the device, write arbitrary files, jam frequencies, etc. The 30s timeout is a safety cap; for long-running commands use ExecLong directly from a wrapper.
func (*Flipper) Reboot ¶
Reboot reboots the Flipper Zero.
CLI transport: `power reboot` text command. The firmware reboots immediately so Exec returns whatever bytes (if any) the CLI emitted before the device dropped off the bus. RPC transport (BLE — text CLI is not available there): SystemRebootRequest with mode=OS streamed via the persistent rpc.Client. The firmware does not emit a response for reboot requests; the BLE link drops as soon as the bytes are flushed. Both branches return an empty string on success to match the CLI's typical short/empty output. CLI: power reboot
Migrated to the compat-layer dispatch (Phase A).
func (*Flipper) Reconnect ¶
Reconnect forces a fresh reconnect cycle: closes the current transport, asks the transport to rescan + reopen, re-handshakes, and re-detects capabilities. Useful from a /reconnect slash command when the user has replugged and auto-detect didn't fire (e.g., the agent was idle and no IO error surfaced the drop).
func (*Flipper) SetConnectionReport ¶ added in v0.13.0
func (f *Flipper) SetConnectionReport(r *ConnectionReport)
SetConnectionReport stashes a ConnectionReport on the Flipper handle so /api/device and --verbose can read it after ConnectURL returns.
Stored via atomic.Pointer because /api/device may read concurrently with a future Reconnect path that wants to refresh the report.
func (*Flipper) SetExecTimeout ¶ added in v0.2.5
SetExecTimeout overrides the per-command read deadline for ExecCtx. A zero or negative value restores the 10 s default.
func (*Flipper) SetLED ¶
SetLED sets the RGB LED to the given color + brightness (0-255). Best-effort — errors are returned but most callers ignore them. The REPL drives this at turn scope so the LED stays steady for the whole prompt, rather than flickering on/off per scan. Color is one of "r", "g", "b" (or "bl" for backlight).
func (*Flipper) SetMaxAccumBytes ¶
SetMaxAccumBytes overrides the per-operation read-buffer cap. Values <= 0 reset to the default (8 MiB). The cap applies to the next Exec/Stream call.
func (*Flipper) SetPipeline ¶ added in v0.13.0
func (f *Flipper) SetPipeline(p PipelineProfile)
SetPipeline swaps the active profile bundle on f. The swap is atomic (atomic.Pointer) so an in-flight ExecCtx that read the old pipeline reference completes against the old values; the next ExecCtx sees the new bundle. Empty / unknown names resolve to ProfileBalanced via ProfileSettings.
func (*Flipper) SetPipelineBundle ¶ added in v0.13.0
SetPipelineBundle is a Pipeline-typed counterpart to SetPipeline used by callers (and tests) that have already resolved a Pipeline by hand — e.g. tests asserting a specific timeout, or a future auto-tuner emitting bundles that don't correspond to one of the three named profiles. A zero-valued Pipeline is rejected with a warn log (every timeout would be 0, so ExecCtx / WriteFileCtx would fire context.DeadlineExceeded immediately on every call); pass ProfileSettings(ProfileBalanced) to reset.
The reject path was promised by the docstring but pre-this-fix not enforced — a caller passing `Pipeline{}` silently wedged the agent's CLI dispatch on the next command.
func (*Flipper) SetReconnectCallback ¶
SetReconnectCallback registers a function invoked at each reconnect phase ("start", "success", "fail"). Called while f.mu is held, so keep the handler quick — typically a single stderr write via the output mutex.
func (*Flipper) SetWriteFileTimeout ¶ added in v0.2.5
SetWriteFileTimeout overrides the post-payload read deadline for WriteFileCtx. A zero or negative value restores the 10 s default.
func (*Flipper) State ¶ added in v0.3.0
State returns the freshest State snapshot that satisfies the cache TTL. On a cache miss it re-queries capabilities + power_info with the caller's context; partial results (capabilities only, no power data) are still cached and returned because they carry useful framing for the agent. A genuinely empty cache is returned with Connected=false and an error — the caller treats that as "skip injection this turn".
func (*Flipper) StorageCopy ¶
StorageCopy copies a file or directory on the Flipper SD card. CLI: storage copy <src> <dst>
USB-only: there is no storage_copy_request RPC verb on any firmware fork (the protobuf surface lacks it — see flipperdevices/flipperzero- protobuf storage.proto). On BLE we surface a descriptive error rather than hang; agent callers gate on errors.Is(err, ErrCommandRequiresUSB) to suggest the operator attach the Flipper via USB.
func (*Flipper) StorageExtract ¶ added in v0.16.0
StorageExtract unpacks a tar archive on the Flipper SD card.
Rejects empty/whitespace archive or outdir before transport. Empty either side produces `storage extract /ext/foo` (double-space) or `storage extract /ext/x.tar ` (trailing space) which the firmware either parses as the wrong shape or rejects with an opaque banner. CLI: storage extract <archive.tar> <outdir>
func (*Flipper) StorageFSInfo ¶ added in v0.2.0
StorageFSInfo returns filesystem info for a storage root. CLI: storage info <path>
A real Flipper emits a multi-line block like:
Label: Flipper SD Type: FAT32 60194KiB total 42088KiB free
Or, when the filesystem isn't ready (no SD card inserted):
Storage error: not ready
func (*Flipper) StorageFSInfoMap ¶ added in v0.2.0
StorageFSInfoMap runs `storage info <path>` and parses it into a flat key→value map. Known keys:
present — "true" / "false"
error — error text when present=false
label — filesystem label (ext) or device name (int)
type — filesystem type ("FAT32", "exFAT", "Virtual", ...)
totalSpace — total bytes (decimal)
freeSpace — free bytes (decimal)
device_info does NOT carry storage fields on any fork; this CLI is the canonical source both for the mobile app and /status.
func (*Flipper) StorageFormat ¶ added in v0.16.0
StorageFormat formats the external SD card (/ext). Destructive — the Spec risk band enforces confirmation; this method is a plain wire wrapper with no guard of its own. CLI: storage format /ext
func (*Flipper) StorageList ¶
StorageList lists files and directories at the given path. CLI: storage list <path>
On BLE the CLI is unavailable and the equivalent RPC verb (storage_list_request) is dispatched via the persistent rpc.Client; the response is reformatted into the same `\t[D] name\n` / `\t[F] name <size>b\n` block the firmware emits over USB so downstream parsers (parseStorageList in internal/web) work without knowing which transport produced it.
func (*Flipper) StorageMD5 ¶
StorageMD5 returns the MD5 hash of a file on the SD card. CLI: storage md5 <path>
CLI emits the 32-character lowercase-hex digest followed by a newline; the RPC variant returns the same string and we append the newline so downstream parsers (which trim whitespace) see identical output.
func (*Flipper) StorageMkdir ¶
StorageMkdir creates a directory. CLI: storage mkdir <path>
func (*Flipper) StorageRead ¶
StorageRead reads the contents of a file. CLI: storage read <path>
Over USB the firmware emits "Size: <N>\n" then the raw bytes. stripStorageReadHeader and similar callers parse that shape. On BLE the RPC verb returns just the bytes; we reformat to match.
func (*Flipper) StorageRemove ¶
StorageRemove removes a file or directory. CLI: storage remove <path>
func (*Flipper) StorageRename ¶
StorageRename renames/moves a file or directory on the SD card. CLI: storage rename <src> <dst>
func (*Flipper) StorageStat ¶
StorageStat returns metadata about a file or directory. CLI: storage stat <path>
On BLE the RPC response is reformatted to match the CLI's two canonical shapes that ParseStorageStat recognises:
Directory File, size: <N>
Storage errors map to "Storage error: <msg>" so the parser's error branch fires.
func (*Flipper) StorageTree ¶
StorageTree walks a directory recursively and returns its tree listing. CLI: storage tree <path>
On BLE the firmware exposes no `tree` RPC verb; we recreate the CLI's recursive `storage list` walk by issuing storage_list_request once per directory, depth-first. The CLI emits paths absolute to root (e.g. "\t[D] /ext/subghz/Tesla\n") rather than relative names — so do we, joining the directory path with the entry name and emitting one `\t[D|F] <path> [<size>b]` line per entry.
func (*Flipper) StorageWrite ¶
StorageWrite writes data to a file using the write_chunk protocol.
func (*Flipper) StorageWriteCtx ¶ added in v0.2.5
StorageWriteCtx is the context-aware variant of StorageWrite. On BLE the firmware exposes only RPC, so we dispatch via the persistent rpc.Client (storage_write_request, multi-Main with has_next) instead of the USB-only write_chunk text protocol that WriteFileCtx uses.
func (*Flipper) StreamCtx ¶
func (f *Flipper) StreamCtx(ctx context.Context, command string, onLine func(line string) (stop bool)) error
StreamCtx runs command and invokes onLine for each output line as it arrives. It returns when ctx is done, when onLine returns true (caller asks to stop), or when the Flipper emits its terminating ">: " prompt. A Ctrl+C is always sent to the Flipper on exit so in-flight commands (like `rfid read` or `subghz rx`) are halted.
func (*Flipper) SubGHzChat ¶
SubGHzChat joins an interactive Sub-GHz text chat on the given frequency. Long-running and actively transmits — the caller bounds it with a duration. Xtreme firmware requires the trailing `<device>` arg. CLI: subghz chat <frequency> [<device>]
func (*Flipper) SubGHzChatCtx ¶ added in v0.63.0
func (f *Flipper) SubGHzChatCtx(ctx context.Context, frequency uint32, duration time.Duration) (string, error)
SubGHzChatCtx is the context-aware variant of SubGHzChat.
func (*Flipper) SubGHzChatDevice ¶ added in v0.16.0
func (f *Flipper) SubGHzChatDevice(frequency uint32, duration time.Duration, device int) (string, error)
SubGHzChatDevice is like SubGHzChat but passes the device index explicitly. Long-running; the caller bounds it with a duration. CLI: subghz chat <frequency> -d <device>
func (*Flipper) SubGHzChatDeviceCtx ¶ added in v0.63.0
func (f *Flipper) SubGHzChatDeviceCtx(ctx context.Context, frequency uint32, duration time.Duration, device int) (string, error)
SubGHzChatDeviceCtx is the context-aware variant of SubGHzChatDevice.
Validates frequency against the firmware-permitted bands before TX. Out-of-band requests come back as "Frequency not allowed!" after a slow round-trip — same failure mode as SubGHzTxKey before v0.181.
func (*Flipper) SubGHzDecode ¶
SubGHzDecode decodes a previously captured raw Sub-GHz file. CLI: subghz decode_raw <file_path>
func (*Flipper) SubGHzRx ¶
SubGHzRx receives Sub-GHz signals on the given frequency (Hz). Xtreme firmware's `subghz rx` requires a trailing <device> arg (0=internal CC1101, 1=external); we append "0" when capabilities report that quirk.
Note: withSuccessBuzz is intentionally omitted here. ExecLong returns nil on timeout (streaming semantics), so the buzz would always fire. On firmware that does not honour Ctrl+C (e.g. Momentum's subghz rx), the device may still be executing the command when the vibro Exec is sent, causing the buzz Exec calls to hang for their full safety-net deadline.
func (*Flipper) SubGHzRxCtx ¶ added in v0.62.0
func (f *Flipper) SubGHzRxCtx(ctx context.Context, frequency uint32, duration time.Duration) (string, error)
SubGHzRxCtx is the context-aware variant of SubGHzRx. ctx cancellation propagates via ExecLongCtx so a turn-level Ctrl+C aborts the in-flight capture without waiting for the duration timer.
func (*Flipper) SubGHzRxRaw ¶
SubGHzRxRaw streams raw Sub-GHz pulse data to the caller's return value. Available on Momentum firmware (subghz_cli.c:subghz_cli_command_rx_raw streams pulses to stdout with no file-path argument). On stock/Unleashed/ Xtreme firmware, the rx_raw verb requires a file-path argument that this API no longer accepts — those callers should use SubGHzRx for time-bounded capture, or construct a .sub capture manually via StorageWrite. CLI (Momentum): subghz rx_raw [<frequency>]
func (*Flipper) SubGHzRxRawCtx ¶ added in v0.62.0
func (f *Flipper) SubGHzRxRawCtx(ctx context.Context, frequency uint32, duration time.Duration) (string, error)
SubGHzRxRawCtx is the context-aware variant of SubGHzRxRaw. The same Momentum-only capability gate as the blocking variant applies — non-Momentum forks return the file-path-required error before any wire traffic.
func (*Flipper) SubGHzRxRawStream ¶ added in v0.57.0
func (f *Flipper) SubGHzRxRawStream(ctx context.Context, frequency uint32, duration time.Duration, onLine func(line string) (stop bool)) (string, error)
SubGHzRxRawStream is the line-streaming variant of SubGHzRxRaw. Each pulse line emitted while `subghz rx_raw` is running is delivered to onLine; stop=true ends the capture early. The same firmware-fork capability check as SubGHzRxRaw applies — non-Momentum forks return the file-path-required error before any streaming starts. CLI (Momentum): subghz rx_raw [<frequency>]
func (*Flipper) SubGHzRxStream ¶ added in v0.56.0
func (f *Flipper) SubGHzRxStream(ctx context.Context, frequency uint32, duration time.Duration, onLine func(line string) (stop bool)) (string, error)
SubGHzRxStream is the streaming variant of SubGHzRx. Each line emitted by firmware while `subghz rx` is running is delivered to onLine as it arrives; the callback can return stop=true to terminate the capture early (e.g. once a candidate signal lands). duration bounds the call like SubGHzRx; ctx cancel also terminates early. The accumulated raw output is returned so callers can feed it to ParseSubGHzReceive on the streaming path the same way they would on the blocking path.
func (*Flipper) SubGHzTx ¶
SubGHzTx transmits a Sub-GHz signal from a saved file. CLI: subghz tx_from_file <file_path>
func (*Flipper) SubGHzTxKey ¶
SubGHzTxKey transmits a raw Sub-GHz key. Xtreme firmware requires a trailing <device> arg (0=internal CC1101, 1=external); appended when the detected capability flag is set.
Validates freq/te/repeat before transport: out-of-band frequency either no-ops or returns an opaque firmware banner; te=0 produces a broken signal; repeat<=0 means no TX. Reject up front so the LLM gets a useful diagnostic on its next turn. CLI: subghz tx <key_hex> <frequency> <te> <repeat> [device]
func (*Flipper) SubGHzTxKeyDevice ¶ added in v0.16.0
func (f *Flipper) SubGHzTxKeyDevice(keyHex string, freq uint32, te uint32, repeat int, device int) (string, error)
SubGHzTxKeyDevice is like SubGHzTxKey but sends the device index explicitly via the -d flag rather than relying on the auto-append logic in SubGHzTxKey (which only supports device=0). Use this when device != 0 (i.e. an external CC1101 module is wired to the GPIO header).
Pre-transport validation matches SubGHzTxKey: freq must fall in an allowed band, te > 0, repeat >= 1. CLI: subghz tx <key_hex> <frequency> <te> <repeat> -d <device>
func (*Flipper) Suspend ¶ added in v0.10.0
Suspend marks this handle inactive and closes the underlying transport so a sibling process (e.g. marauder.Connect) can open the same OS-level port. Subsequent CLI calls return ErrFlipperSuspended until the process exits. Suspend is idempotent — the first call's reason wins.
func (*Flipper) SuspensionReason ¶ added in v0.10.0
SuspensionReason returns the string passed to the most recent Suspend call, or "" when not suspended.
func (*Flipper) Transport ¶
Transport returns the underlying byte channel. Exposed read-only so /status output and telemetry can read Identity/Kind without the command-layer mutex.
func (*Flipper) UpdateInstall ¶
UpdateInstall applies a firmware update from an already-staged manifest on the SD card. Long-running — uses a 5-minute deadline. Critical.
Rejects empty/whitespace manifestPath before transport: the firmware command form is `update install <path>` and an empty path produces `update install ` which the loader may treat as either a no-op or a parse error (fork-dependent). On a real update path that took minutes to set up via Updater Builder, sending an empty manifest path is a high-cost LLM mistake; reject up front with a clear nudge. CLI: update install <manifest_path>
func (*Flipper) Vibro ¶
Vibro turns the vibration motor on (true) or off (false). On Momentum, vibro 1 is silently suppressed in two cases:
- stealth mode (FuriHalRtcFlagStealthMode): "Flipper is in stealth mode…"
- vibro disabled in settings: "Vibro is disabled in settings…"
Both return success at the firmware layer, so we detect the banner and return an error so callers know the motor was never activated. CLI: vibro <0|1>
func (*Flipper) WriteFile ¶
WriteFile writes data to a file on the Flipper using the storage write_chunk interactive protocol: send the command with the byte count, then send the raw bytes immediately after. Preserved for backward compatibility; prefer WriteFileCtx so cancellation and reconnect propagate a ctx.
func (*Flipper) WriteFileCtx ¶
WriteFileCtx is the context-aware variant of WriteFile. It reconnects if needed, uses a cancellable sleep between command and payload, and tags any disconnect-class error via markDisconnectedIfRelevant so the next op can recover.
Firmware append behaviour: some firmware builds — notably Momentum dev branch as of mntm-dev 430a3d50 (2026-03-09) — do NOT truncate an existing file when storage write_chunk is called; they append to the existing content instead. Callers that need truncate semantics must issue "storage remove <path>" before writing, or the re-written file will contain concatenated data.
type LoaderApps ¶
LoaderApps is the parsed shape of `loader list`: user-facing apps plus the settings menu entries (which are also launchable via `loader open`).
type NFCDetectResult ¶ added in v0.3.0
type NFCDetectResult struct {
Detected bool `json:"detected"`
Type string `json:"type,omitempty"` // "NTAG215", "MIFARE Classic 1K", ...
Technology string `json:"technology,omitempty"` // "ISO14443-3a (NFC-A)" etc.
UID string `json:"uid,omitempty"`
ATQA string `json:"atqa,omitempty"`
SAK string `json:"sak,omitempty"`
Raw string `json:"raw,omitempty"`
}
NFCDetectResult captures the structured shape of an NFC subshell scanner response. At least one of UID/Type is set when a card was detected.
func ParseNFCDetect ¶ added in v0.3.0
func ParseNFCDetect(raw string) NFCDetectResult
ParseNFCDetect parses the output of the nfc subshell scanner subcommand into a structured result. A successfully parsed card sets Detected=true plus whatever fields the firmware emitted; empty / timeout output sets Detected=false.
type Pipeline ¶ added in v0.13.0
type Pipeline struct {
// CLIRetryAttempts is the number of times ExecCtx will issue the
// command before giving up on a hung CLI. ExecCtx's existing
// per-attempt timeout (ExecTimeout) gates each try.
//
// NOTE: today's serial.go ExecCtx is single-shot — it sends once and
// either returns the response or the "hung" error. We carry this
// field so the auto-tune side can grow per-op retries without a
// second refactor; the current dispatcher reads it but treats values
// > 1 as a no-op until the retry loop is added in a follow-up.
CLIRetryAttempts int
// CLIRetryDelay is the delay between CLI retries when CLIRetryAttempts > 1.
CLIRetryDelay time.Duration
// RPCRetryAttempts is the number of Ping attempts rpc.Client.Open
// will make before giving up. The legacy value was 5.
RPCRetryAttempts int
// RPCRetryDelay is the per-attempt context timeout used by Open's
// Ping. The legacy value was 500ms.
RPCRetryDelay time.Duration
// FileWriteRetryAttempts is the number of times WriteFileCtx will
// re-issue a failed storage write_chunk before giving up. As with
// CLIRetryAttempts, today's WriteFileCtx is single-shot; values > 1
// are reserved for the auto-tune follow-up.
FileWriteRetryAttempts int
// FileWriteRetryDelay is the delay between file-write retries.
FileWriteRetryDelay time.Duration
// Exec is the per-command read deadline used by ExecCtx. Replaces
// the previous f.execTimeout SetExecTimeout setter as the source of
// truth.
Exec time.Duration
// WriteFile is the post-payload read deadline used by WriteFileCtx.
WriteFile time.Duration
// Connect is the budget for the connect/reconnect cycle. ConnectURL
// uses the caller-supplied timeout argument directly today; this
// value is consulted by reconnectIfNeededLocked when the original
// connectTimeout wasn't recorded.
Connect time.Duration
// ReconnectAttemptDelay is the inner sleep between transport
// reconnect attempts in reconnectIfNeededLocked. Legacy value was
// 250ms.
ReconnectAttemptDelay time.Duration
}
Pipeline carries the resolved retry and timeout knobs for one profile. Zero values are not valid; always construct via ProfileSettings (or copy from one and tweak fields explicitly) so missing fields don't silently degrade to no-retry/no-timeout behaviour. Pipeline values are immutable after construction — *Flipper holds them by atomic.Pointer so a live SetPipeline call can swap the whole bundle without partial reads.
func ProfileSettings ¶ added in v0.13.0
func ProfileSettings(p PipelineProfile) Pipeline
ProfileSettings returns the canonical Pipeline bundle for the named profile. An unknown or empty name returns the Balanced bundle so a stale config string can never zero out the timeouts.
type PipelineProfile ¶ added in v0.13.0
type PipelineProfile string
PipelineProfile names a bundled retry/timeout policy applied across the command-dispatch layer (CLI exec, file write, RPC handshake, reconnect). Profiles let operators trade latency for reliability without re-deriving every constant by hand: a flaky USB cable picks "resilient", a known-good dev rig picks "fast", and the default ("balanced") matches the historical hard-coded behaviour byte-for-byte so existing scripts and tests keep their timing.
Inspired by V3SP3R's CommandPipelineAutotuneStatus shape — but the auto-tune feedback loop is intentionally NOT implemented here; profile selection is manual in this round. The struct is deliberately a flat bundle of durations so the future telemetry-driven auto-tuner can swap it atomically via SetPipeline without redoing the wire path.
const ( // ProfileFast favours snappy failure over robustness. Suitable for // known-good USB rigs running CI or interactive dev where a hung // command should fall through fast and surface as an error rather // than waste seconds retrying. ProfileFast PipelineProfile = "fast" // ProfileBalanced is the default. Every value matches the legacy // hard-coded constants from before the pipeline refactor: // - rpc.Open: 5 attempts, 500ms per ping // - ExecCtx: 10s // - WriteFileCtx: 10s // - reconnect inter-attempt sleep: 250ms // Anything depending on the previous timing characteristics // (existing tests, scripts, hand-tuned configs) must observe // identical behaviour under this profile. ProfileBalanced PipelineProfile = "balanced" // ProfileResilient stretches every retry budget so commands ride // through transient cable wobble, BLE link drops, or a busy // firmware. Pays for it with latency on the failure path. ProfileResilient PipelineProfile = "resilient" )
type RouteDecision ¶ added in v0.13.0
type RouteDecision struct {
Route CommandRoute
Reason string
}
RouteDecision is the result of a routing decision. Reason is a short human-readable phrase that explains WHY the route was chosen — it gets wrapped into errors when Route is RouteUSBOnly so the agent layer can show the operator something more actionable than a bare "command failed".
func RouteFor ¶ added in v0.13.0
func RouteFor(operation string, support CommandSupport, transportKind string, caps Capabilities) RouteDecision
RouteFor picks the dispatch path for an operation given the command's declared CommandSupport, the live transport kind, and the detected firmware capabilities. The function is pure — same inputs always produce the same output — so it is straightforward to unit-test with table-driven cases.
Decision matrix (Phase A):
transport | HasRPCVerb | HasCLI | route ----------+------------+--------+------------------ ble | true | * | RouteRPC ble | false | * | RouteUSBOnly (no RPC verb) usb/mock | * | true | RouteTextCLI usb/mock | * | false | RouteUSBOnly (no CLI verb)
FirmwareForkRequired is checked AFTER the transport-based selection: if the live caps.FirmwareFork does not match (case- insensitive), the route is rewritten to RouteUSBOnly with a descriptive reason regardless of what the transport offered.
type State ¶ added in v0.3.0
type State struct {
Connected bool `json:"connected"`
Fork string `json:"fork,omitempty"` // stock/Momentum/Unleashed/RogueMaster/Xtreme
FirmwareVersion string `json:"firmware_version,omitempty"` // version string from device_info
HardwareName string `json:"hardware_name,omitempty"` // user-settable dolphin name
HardwareUID string `json:"hardware_uid,omitempty"`
BatteryPct int `json:"battery_pct,omitempty"` // 0-100, omitted when unknown
ChargeState string `json:"charge_state,omitempty"` // "charging" / "discharging" / ""
// Transport identifies how PromptZero is talking to the Flipper
// ("serial" / "ble" / "mock"). The agent uses it to warn before
// high-throughput operations on the slower BLE path.
Transport string `json:"transport,omitempty"`
// SDPresent reports whether the /ext volume exists at all. When
// false, the SD-space fields are omitted and any storage_* tool
// call will fail — surfacing this early saves the model a turn.
SDPresent bool `json:"sd_present"`
// SDTotalBytes and SDFreeBytes track SD capacity in bytes. Zero
// values are omitted so a failed storage-info probe doesn't
// masquerade as "0 free".
SDTotalBytes int64 `json:"sd_total_bytes,omitempty"`
SDFreeBytes int64 `json:"sd_free_bytes,omitempty"`
CollectedAt time.Time `json:"collected_at"`
}
State is a point-in-time snapshot of the connected Flipper, cheap to render into the model's turn context. Carries only fields that help the agent avoid redundant "what's connected?" round-trips; heavyweight probes (SD walk, loader state, log dump) are deliberately excluded.
Fields honour `omitempty` wherever missing data is better expressed as absence than as a zero sentinel (notably BatteryPct — a partial fetch that couldn't reach power_info must not surface as "battery: 0%").
type StorageStatResult ¶ added in v0.3.0
type StorageStatResult struct {
Exists bool `json:"exists"`
IsDir bool `json:"is_dir"`
SizeBytes int64 `json:"size_bytes,omitempty"`
Error string `json:"error,omitempty"`
Raw string `json:"raw,omitempty"`
}
StorageStatResult captures the structured shape of `storage stat <path>` output. The Flipper firmware emits a short line per attribute: "File, size: 1234" for regular files, "Directory" for directories, "Storage error: <msg>" on failure.
func ParseStorageStat ¶ added in v0.3.0
func ParseStorageStat(raw string) StorageStatResult
ParseStorageStat parses `storage stat <path>` output. Order matters: the "Storage error:" check runs FIRST so interleaved output like "File\nStorage error: not found" (seen on some firmware forks) doesn't produce a false-positive Exists=true. When both markers appear, the error takes precedence — the file-regex matches anywhere on any line (case-insensitive), so a naked File/Directory check without the error gate would misclassify the error path.
type SubGHzCandidate ¶ added in v0.3.0
type SubGHzCandidate struct {
Protocol string `json:"protocol,omitempty"`
Frequency uint32 `json:"frequency,omitempty"`
Key string `json:"key,omitempty"`
Bit int `json:"bit,omitempty"`
TE int `json:"te,omitempty"`
RSSI int `json:"rssi,omitempty"`
}
SubGHzCandidate is one detected protocol / key block.
type SubGHzReceiveResult ¶ added in v0.3.0
type SubGHzReceiveResult struct {
Candidates []SubGHzCandidate `json:"candidates,omitempty"`
Count int `json:"count"`
RawLines []string `json:"raw_lines,omitempty"`
}
SubGHzReceiveResult summarises the output of `subghz rx` / the subghz_receive tool. The Flipper emits detected protocol candidates as blocks like:
[Protocol: Princeton] Frequency: 433920000 Key: 00 00 00 1A 2B 3C 4D 00 Bit: 24
The parser collects one Candidate per block; unstructured noise lines go into RawLines.
func ParseSubGHzReceive ¶ added in v0.3.0
func ParseSubGHzReceive(raw string) SubGHzReceiveResult
ParseSubGHzReceive parses the output of subghz_receive. Detects one or more "Protocol:" blocks and extracts the common fields of each. Lines that don't belong to a block are preserved in RawLines.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package mock provides a pty-backed fake Flipper CLI so serial.go and the command wrappers can be exercised without real hardware.
|
Package mock provides a pty-backed fake Flipper CLI so serial.go and the command wrappers can be exercised without real hardware. |
|
Package rpc implements a typed Flipper Zero RPC client over a transport.Transport.
|
Package rpc implements a typed Flipper Zero RPC client over a transport.Transport. |
|
Package transport defines the byte-channel substrate the Flipper CLI layer operates over.
|
Package transport defines the byte-channel substrate the Flipper CLI layer operates over. |