AndroidSCM is an Android app that decodes ERT/SCM smart-meter radio packets directly from an RTL-SDR dongle connected via USB OTG — no PC, no root, no external apps required.
- 📡 Tunes to 912.600 MHz and decodes SCM (Standard Consumption Message) packets in real time
- 🔌 Drives the RTL-SDR dongle natively over USB OTG — no rtl_tcp server needed
- ⚡ Signal processing written in pure C (Manchester matched filter → preamble search → BCH-16 CRC verify)
- 🎯 Dart FFI bridge — zero-copy packet delivery from the C decode thread to the Flutter UI
- 🔁 Duplicate suppression across packet boundaries
- �� Live scrolling packet list with meter ID, type, consumption, tamper flags, and CRC
Flutter UI (Dart)
│ MethodChannel "com.example.androidscm/usb"
▼
MainActivity.kt ← Android UsbManager API
│ returns (fd, devicePath) to Dart after USB permission grant
▼
ScmDecoder (lib/scm_ffi.dart) ← dart:ffi
│ scm_open(fd, path) / scm_start(callback) / scm_stop()
▼
libscm_decoder.so (android/app/src/main/cpp/scm_lib.c)
│ rtlsdr_open2(fd, path) ← librtlsdr (rtl_tcp_andro submodule)
│ rtlsdr_read_sync → Manchester filter → preamble search → BCH CRC
│ NativeCallable → Dart Stream<ScmPacket>
▼
Flutter UI: live scrolling packet list
| Parameter | Value |
|---|---|
| Center frequency | 912,600,155 Hz |
| Sample rate | 2,359,296 sps |
| Symbol rate | 32,768 baud |
| Chip length | 72 samples |
| Modulation | OOK, Manchester coded |
| Preamble | 111110010101001100000 (21 bits) |
| Packet length | 96 bits |
| Error detection | BCH-16, poly=0x6F63 |
- Any Realtek RTL2832U DVB-T USB dongle (VID
0x0BDA) - Android device with USB host (OTG) support, API 24+
- USB OTG adapter cable
The app auto-launches when the dongle is plugged in and prompts for USB permission on first use.
| Tool | Version |
|---|---|
| Flutter | ≥ 3.0 |
| Android NDK | 27+ (via Android Studio → SDK Manager) |
| CMake | 3.18.1+ (via SDK Manager) |
git clone --recurse-submodules https://github.com/SarahRoseLives/AndroidSCM.git
cd AndroidSCMOr if you already cloned without --recurse-submodules:
git submodule update --init --recursiveflutter pub get
flutter runGradle will automatically compile librtlsdr + libscm_decoder.so via CMake/NDK on the first build.
AndroidSCM/
├── lib/
│ ├── main.dart # Flutter UI
│ ├── scm_ffi.dart # Dart FFI bindings
│ └── models/
│ └── scm_packet.dart # Decoded packet data class
├── android/
│ ├── app/src/main/
│ │ ├── cpp/
│ │ │ ├── scm_lib.c # C decoder library (rtlsdr_open2 + signal pipeline)
│ │ │ └── CMakeLists.txt
│ │ ├── kotlin/.../MainActivity.kt # USB MethodChannel bridge
│ │ └── AndroidManifest.xml
│ └── rtl_tcp_andro/ # Git submodule — librtlsdr for Android
└── pubspec.yaml
- rtlamr by bemasher — Go reference implementation, signal parameters, and BCH CRC algorithm
- rtl_tcp_andro by signalwareltd — Android-adapted librtlsdr with
rtlsdr_open2USB fd API