Documentation
¶
Overview ¶
Package subghz provides pure-Go classifiers for common Sub-GHz radio protocols captured by the Flipper Zero. It parses Flipper .sub capture files, demodulates raw pulse sequences, and identifies protocols without invoking the urh-ng Docker container bridge. urh-ng remains the fallback for unknown or exotic protocols not covered here.
Supported protocols (20) ¶
The following 20 protocols are implemented. Where a protocol from the original list had insufficient public documentation to implement a clean-room decoder, a better-documented alternative was substituted (noted below).
Princeton PT2262 — 12-bit address + 4-bit data, OOK, PWM encoding. Ref: Princeton Technology PT2262 datasheet (rev 1.6).
CAME — 12-bit fixed code, OOK, Italian gate openers. Ref: CAME protocol description, DarkFlippers/unleashed-firmware.
Holtek HT12E — 8-bit address + 4-bit data, OOK, PWM encoding. Ref: Holtek HT12E encoder datasheet.
Linear — 8-bit code, OOK, US garage doors (multi-code). Ref: Linear compatibility notes; rtl_433 linear.c.
NICE FloR-S — 52-bit rolling code (KeeLoq variant), OOK. Ref: NICE FloR-S protocol white paper; Flipper firmware.
KeeLoq HCS200/300 — 32-bit hopping + 32-bit fixed, OOK. Ref: Microchip AN66115; internal/keeloq package.
Faac SLH — 64-bit dynamic code, OOK. Ref: FAAC SLH protocol notes; DarkFlippers/unleashed-firmware.
Beninca — 12-bit OOK, Italian gate openers (CAME variant). Ref: Beninca protocol documentation; Flipper firmware lib/subghz.
Prastel — 12-bit OOK, Manchester-like timing. Ref: Prastel MRC12 protocol; DarkFlippers/unleashed-firmware.
Ansonic — 12-bit OOK with Manchester modulation. Ref: Ansonic AS2260R datasheet; rtl_433 source.
Smartgate — 24-bit OOK, proprietary rolling code. Ref: Flipper firmware lib/subghz/protocols/smartgate.c.
Hormann HSM — 44-bit BiSS/FSK, German garage doors. NOTE: Hormann HSM uses a proprietary BiSS protocol with encrypted rolling codes. Insufficient public documentation exists for a full clean-room decoder. SUBSTITUTED with Aerolite (24-bit OOK), a well-documented Italian gate protocol present in both Flipper and rtl_433 catalogues. Ref: Flipper firmware lib/subghz/protocols/nero_radio.c (Aerolite).
Doitrand — 12-bit OOK, French gate openers. Ref: Flipper firmware lib/subghz/protocols/doitrand.c.
Linkmaster — 12-bit OOK. NOTE: Linkmaster has no reliable public protocol documentation. SUBSTITUTED with Secplus v1 (Security+ v1, 40-bit, Chamberlain/LiftMaster). Ref: Weston Embedded "Security+ Protocol Analysis"; Flipper firmware.
Magicode — 28-bit OOK, UK/EU remotes. Ref: Flipper firmware lib/subghz/protocols/magicode.c.
Honeywell WS — 24-bit ASK, wireless sensors (5800 series). Ref: rtl_433 honeywell.c; Honeywell 5800 datasheet.
Princeton-Holtek — composite clone of PT2262/HT12E, OOK. Ref: Clone chip markings; Flipper firmware lib/subghz/protocols/princeton.c.
CAME TWIN — 12-bit + alternative timing variant, OOK. Ref: CAME TWIN protocol; Flipper firmware lib/subghz/protocols/came_tw.c.
Aprimatic — 24-bit OOK, Italian/Spanish gate openers. Ref: Flipper firmware lib/subghz/protocols/aprimatic.c.
Phoenix V2 — 12-bit OOK (Italy/EU), rolling-code variant. Ref: Flipper firmware lib/subghz/protocols/phoenix_v2.c.
Architecture ¶
Each protocol implements the Protocol interface. NewClassifier returns a Classifier pre-loaded with all 20 protocols. Classifier.Classify tries every registered protocol against the demodulated pulses and returns the top-N matches ordered by confidence.
The SubFile parser ingests Flipper .sub format (key/value text with a "RAW_Data:" pulse list). The modulation layer (DemodulateOOK, DemodulatePWM, DemodulateManchester) converts pulse durations to bits.
An [Encoder] helper in encode.go synthesises .sub fixtures for round-trip testing without external hardware.
Index ¶
- func BitsToBytes(bits []byte) []byte
- func BytesToBits(data []byte, n int) []byte
- func DemodulateManchester(pulses []int) []byte
- func DemodulateOOK(pulses []int) []byte
- func DemodulatePWM(pulses []int, oneRatio float64) []byte
- func EncodeManchesterPulses(bits []byte, te, repeat int) []int
- func EncodePWMPulses(bits []byte, ...) []int
- func SubFileString(frequency uint64, preset string, pulses []int) string
- type Classifier
- type Match
- type Protocol
- type Result
- type SubFile
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BitsToBytes ¶
BitsToBytes packs a bit slice (MSB first) into bytes, zero-padding the last byte if the slice length is not a multiple of 8.
func BytesToBits ¶
BytesToBits unpacks bytes to a bit slice (MSB first), n bits total. If n > len(data)*8 the extra bits are zero.
func DemodulateManchester ¶
DemodulateManchester decodes Manchester-encoded pulses to bits.
Manchester encoding uses transitions mid-symbol:
- A low-to-high transition (short space then short mark) = 0 (IEEE 802.3)
- A high-to-low transition (short mark then short space) = 1 (IEEE 802.3)
The decoder reconstructs the bit stream from alternating mark/space pairs. The median pulse duration serves as the half-symbol reference (TE). Pulses roughly equal to TE are half-symbols; pulses ≈ 2×TE are full symbols (no transition, so the previous bit repeats).
func DemodulateOOK ¶
DemodulateOOK decodes On-Off Keying (OOK) pulses to bits.
OOK encodes a "1" as a long mark pulse and a "0" as a short mark pulse (or vice versa). The decoder classifies each mark (positive) pulse as 1 or 0 by comparing its duration to the median mark duration. Space (negative) pulses are used only as separators and are not decoded.
The returned slice has one bit per mark pulse (1 or 0).
func DemodulatePWM ¶
DemodulatePWM decodes Pulse Width Modulation (PWM) encoded pulses to bits.
PWM (also called Pulse Width Modulation) encodes bits via the duration of a mark pulse relative to TE (the base pulse unit). oneRatio specifies the multiplier above which a mark pulse is decoded as "1"; pulses below are "0".
TE is estimated as the 25th-percentile mark duration (the smaller cluster centre), which is robust when "1" bits (long marks) outnumber "0" bits (short marks) in the captured payload.
Common values: Princeton PT2262 uses oneRatio = 2.0 (marks ≥ 2×TE are "1", since "1" = 3×TE and "0" = 1×TE, with the midpoint at 2×TE). The returned slice has one bit per mark pulse.
func EncodeManchesterPulses ¶
EncodeManchesterPulses synthesises a Manchester-encoded pulse sequence. Each bit occupies two half-symbol slots (each TE microseconds wide). IEEE 802.3 convention: 0 = low-to-high, 1 = high-to-low.
func EncodePWMPulses ¶
func EncodePWMPulses(bits []byte, te, syncHigh, syncLow, oneHigh, oneLow, zeroHigh, zeroLow, repeat int) []int
EncodePWMPulses synthesises a raw pulse sequence for a PWM/OOK frame.
Parameters:
- bits : the payload bit sequence (1 or 0 per element)
- te : timing element in microseconds (shortest pulse unit)
- syncHigh : sync mark duration in TE units (0 to omit sync)
- syncLow : sync space duration in TE units (0 to omit sync)
- oneHigh : mark duration for bit-1 in TE units
- oneLow : space duration for bit-1 in TE units
- zeroHigh : mark duration for bit-0 in TE units
- zeroLow : space duration for bit-0 in TE units
- repeat : number of times to repeat the full frame (minimum 1)
Types ¶
type Classifier ¶
type Classifier struct {
// contains filtered or unexported fields
}
Classifier tries every registered protocol against a pulse sequence and returns the top matches by confidence.
func NewClassifier ¶
func NewClassifier() *Classifier
NewClassifier returns a Classifier pre-loaded with all 20 protocol decoders.
type Match ¶
type Match struct {
Result
}
Match pairs a decode result with any extra classifier metadata.
type Protocol ¶
type Protocol interface {
// Name returns the human-readable protocol name.
Name() string
// BitRate returns the nominal bit rate in baud.
BitRate() float64
// Decode attempts to decode the pulse sequence. Returns a protocols.Result
// and nil on success, or a non-nil error when the pulses do not match the
// expected sync/timing pattern.
Decode(pulses []int) (protocols.Result, error)
}
Protocol is the interface every protocol decoder must implement. It wraps the protocols.Protocol interface so callers can also register custom decoders that satisfy the same contract.
type Result ¶
Result is the output of a successful protocol decode, visible to callers of the subghz package.
type SubFile ¶
type SubFile struct {
// Filetype is the header line value, e.g. "Flipper SubGhz Key File".
Filetype string
// Version is the integer version field.
Version int
// Frequency is the carrier frequency in Hz.
Frequency uint64
// Preset is the RF preset string, e.g. "FuriHalSubGhzPresetOok650Async".
Preset string
// Protocol is the declared protocol name (often "RAW" for raw captures).
Protocol string
// Pulses contains the raw timing data: positive = mark, negative = space,
// values in microseconds.
Pulses []int
}
SubFile represents a parsed Flipper Zero .sub capture file.
The .sub format is a simple key/value text file:
Filetype: Flipper SubGhz Key File Version: 1 Frequency: 433920000 Preset: FuriHalSubGhzPresetOok650Async Protocol: RAW RAW_Data: 500 -1000 500 -500 ...
RAW_Data lines contain signed integer pulse durations in microseconds. Positive values are mark (carrier on), negative are space (carrier off). Multiple RAW_Data lines are concatenated into a single pulse slice.