- Kotlin 98.2%
- Shell 1.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .agents/skills/dual-variant-deployment | ||
| app | ||
| docs/playstore | ||
| gradle | ||
| .gitignore | ||
| build.gradle.kts | ||
| GEMINI.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| LICENSE | ||
| README.md | ||
| settings.gradle.kts | ||
Revasri Thermal Vision (Android)
An open-source Android application and USB driver for the REVASRI R-T160, NOHAWK N-T160, and ThermPal USB-C thermal imaging cameras (0x04b4:0x000a).
Why This Project Exists
Budget USB-C thermal cameras like the REVASRI R-T160 (and OEM variants from Nohawk and Inreii) offer outstanding sensor performance for their price, but their official companion app (Camera+ / com.inreii.neutralapp):
- Is not readily available on Google Play.
- Bundles legacy 32-bit (
armeabi-v7a) native.solibraries that fail to run on modern 64-bit-only phones (Pixel 7/8/9/10, Galaxy S23/S24/S25). - Lacks 16 KB ELF segment alignment, triggering immediate OS memory-fault aborts on Android 15, 16, and 17 beta.
- Standard UVC (USB Video Class) camera viewers cannot stream from this device because it communicates over a vendor-specific bulk endpoint protocol.
This project provides a 100% pure Kotlin implementation using Android's native android.hardware.usb API:
- Zero NDK or C/C++ libraries (
.so): Immune to 32/64-bit ABI conflicts and 16 KB page-size enforcement. - Runs natively on Android 15, 16, and 17 beta.
- Modern, responsive Jetpack Compose interface with hardware-accelerated rendering.
Hardware & Protocol Specifications
Through protocol reverse-engineering of USB descriptors and bus packets:
| Attribute | Specification |
|---|---|
| USB Identifiers | Vendor ID: 0x04b4 (Cypress), Product ID: 0x000a |
| USB Class | Class 255 (Vendor Specific), Subclass 240, Protocol 1 (com.white.ThermPalProtocol) |
| Interface & AltSetting | Interface 0, Alternate Setting 1 (AltSetting 0 contains 0 endpoints) |
| Bulk IN Endpoint | 0x82 (Packet size 512 bytes) |
| Bulk OUT Endpoint | 0x06 (Packet size 512 bytes) |
| Stream Frame Rate | ~24.0 – 25.6 FPS (~41.6 ms period) |
| Readout Matrix | 256 columns × 196 rows (192 sensor rows + 4 telemetry rows) |
| Active Sensor Area | 160 × 120 pixels (Centered at Rows 36..155, Columns 48..207) |
Control Commands (Bulk OUT to 0x06)
- Init Handshake:
0x80 0x81(Sent once upon connection to start bulk streaming) - Mechanical Shutter Trigger:
0x80 0x00(Actuates internal solenoid for NUC dark-frame calibration) - High Gain Mode (-20°C to 150°C):
0x80 0x21 - Low Gain Mode (Up to 450°C):
0x80 0x20
Framing Protocol
Each video frame is transmitted across 7 sequential bulk packets of 14,348 bytes each:
- 12-byte header: Contains magic (
0x0c8c/0x0c8d), timestamp, and line offset (1, 29, 57, 85, 113, 141, 169). - 14,336-byte payload: 28 lines × 256 pixels of 16-bit little-endian raw bolometer ADU readings.
- Telemetry (Rows 192..195): Serial number, model identifier (
R-T160), firmware version, and real-time die/shutter temperature sensors (Row 193).
Calibration & Radiometry Engine
Verified Two-Phase Shutter Calibration
Unlike standard consumer apps that merely click the shutter mechanically without synchronizing software, Revasri Thermal Vision executes a closed-loop calibration pipeline:
- Solenoid Transit Handling: When
Calibrateis tapped, the hardware shutter command is dispatched, and transient transit frames (~80 ms) are automatically bypassed. - Phase 1: Stabilization & Temperature Calibration:
- Observes consecutive frame mean delta (
\le 12ADU). - Verifies stability across 3 consecutive readings with the shutter paddle fully seated.
- Anchors the radiometric baseline reference to the internal unit die temperature (
T_{\text{unit}} = \text{fpaTemperatureC}).
- Observes consecutive frame mean delta (
- Phase 2: Video Calibration:
- Accumulates closed-shutter frames to compute a 2D spatial Fixed-Pattern Noise (FPN) matrix.
- Eliminates microbolometer vertical stripes, column offsets, and static grain.
- Verification & Persistence:
- Verifies consistency between video mean and temperature baseline (
|\Delta| < 150ADU), verifies bolometer noise spread, and validates temperature sanity before committing. - Saves verified baseline to
thermal_fpn_baseline.binacross app launches.
- Verifies consistency between video mean and temperature baseline (
Radiometric Temperature Calculation
Pixel temperature is calculated via linear microbolometer radiometry:
T_i = baselineTempC + (pixelAdu_i - baselineMeanAdu) / (Sensitivity * Emissivity) + userOffsetC
- Default Offset Constant: Includes a defined constant
DEFAULT_CAMERA_TEMP_OFFSET_FAHRENHEIT = +22.0°F(+12.22°C) to align baseline radiometry with ambient environmental readings. - Material Emissivity: Configurable from 0.10 to 1.00 (defaults to 0.95 for skin, wood, drywall, and matte surfaces).
App Features
- Fluid Live Thermal Stream: 24+ FPS real-time rendering via Jetpack Compose.
- Spot Tracking HUD:
- Red crosshair on hottest point with peak temperature readout badge.
- Cyan crosshair on coldest point with minimum temperature readout badge.
- Green crosshair on center point with live temperature badge.
- Orientation: Defaults to 90° orientation; one-tap rotation cycling (0°, 90°, 180°, 270°).
- Temperature Units: Automatic locale detection (Celsius / Fahrenheit) with one-tap toggle.
- Color Palettes:
- Inferno
- Ironbow
- Rainbow
- White Hot (Grayscale)
- Black Hot (Inverted Grayscale)
- 1-Tap Calibrate & Options:
- Tapping Calibrate immediately fires the verified shutter calibration.
- Dropdown arrow provides quick access to Fine-Tune Temperature, Guide, and Calibration Reset.
- Interactive Guide: Built-in explainer dialog (
?) covering calibration, emissivity, and thermal tips. - Screen Wake-Lock: Automatically holds screen awake (
FLAG_KEEP_SCREEN_ON) while the camera is active. - Persistent Preferences: Automatically saves palette, rotation, gain mode, temperature units, emissivity, and calibration to
SharedPreferences. - Snapshot Capture: Exports uncompressed PNG captures directly to device gallery (
Pictures/RevasriThermal).
Building & Installing
Prerequisites
- JDK 17+
- Android SDK 35 (Android 15)
Build Debug APK
./gradlew assembleDebug
Output APK: app/build/outputs/apk/debug/app-debug.apk
Install via ADB
adb install -r app/build/outputs/apk/debug/app-debug.apk
Launch App
adb shell am start -n com.adamoutler.revasri/.MainActivity
License
Developed by Adam Outler (adamoutler@gmail.com).
Licensed under the Apache License, Version 2.0. See LICENSE for details.