tcamViewerDesktop
A Linux/desktop viewer for the tCam thermal imaging camera — a Compose Multiplatform Desktop port of tcamViewer2.
tcamViewerDesktop
Linux/desktop viewer for the tCam thermal imaging camera — a Compose Multiplatform Desktop port of tcamViewer2 (the Android app).
Connects to a tCam over WiFi/TCP (port 5001), decodes its JSON-framed radiometric + telemetry frames, applies a color palette, and displays live thermal video with spotmeter/region temperature readout.
Build & run
./gradlew run
Package a native installer (.deb / AppImage)
./gradlew packageDeb
./gradlew packageAppImage
Status
Ported from tcamViewer2’s Android source: the TCP protocol layer (net/CameraService.kt),
radiometric/telemetry decode + palette mapping (util/CameraUtils.kt, model/ImageDto.kt),
and the full view-model (model/CameraViewModel.kt) — connect/disconnect with auto-reconnect,
live streaming, point spotmeter + region measurement, AGC/manual-range/palette/units control,
temperature-over-time history, temperature alerts, single-frame save, recording (.mtjsn), and
time-lapse capture (.tltjsn).
The UI has four tabs behind a NavigationRail (ui/App.kt):
- Camera (
ui/CameraScreen.kt) — connect/Get/Stream/Record/Save, a flat field correction (FFC) button that sends arun_ffccommand to manually trigger the Lepton’s calibration, the live thermal image with spotmeter tap-to-move / region drag-to-move-or-resize overlay, temperature readouts, and the temperature-history chart. - Settings (
ui/SettingsScreen.kt) — staged Save/Cancel editing (mirrors the Android app’s pattern) over camera IP (with an mDNS “Find tCam Devices” search button), palette, units, manual range, shutter sound, spotmeter/region toggle, temperature alerts, and — while connected — AGC/emissivity/gain mode and a WiFi config dialog with SSID scanning (nmcli). - Library (
ui/LibraryScreen.kt) — browses saved.tjsnframes,.mtjsnrecordings, and.tltjsntime lapses grouped by date folder, multi-select delete, a date-range filter, a full-size browse view with Export-to-PNG, and frame-by-frame video playback (ui/VideoPlayerWindow.kt) with skip ±5, play/pause, and speed control for time lapses. - Charts (
ui/ChartsScreen.kt) — browses saved.tcharttemperature-history files the same way, with a full chart view on browse.
mDNS discovery (net/CameraDiscovery.kt) uses JmDNS — the
desktop JVM has no built-in mDNS/DNS-SD client the way Android’s NsdManager provides one. On a
multi-homed machine (wired + WiFi both up), a plain JmDNS.create() picks one interface and can
silently miss cameras reachable only on the other, so discovery binds a separate JmDNS instance
to every active non-loopback IPv4 interface and merges the results. It’s also wired into
CameraViewModel’s auto-reconnect: after retrying the last-known IP a few times, it falls back
to a fresh mDNS scan in case the camera’s DHCP lease changed. WiFi SSID scanning
(util/WifiScanner.kt) shells out to nmcli for the same reason — no portable desktop WiFi-scan
API exists the way Android’s WifiManager provides one.
Composite image export (util/CompositeExport.kt) — the colorized image plus header/sidebar
(color bar, spotmeter arrow, max/min)/footer (gain, emissivity, date/time) chrome — is ported
from Android’s buildShareBitmap(), saving to ~/tCamViewer/Exports/ instead of Android’s
gallery share sheet (no desktop equivalent of Intent.ACTION_SEND).
Not yet ported from the Android app:
- MP4 export/share for recordings and time lapses (Android’s
VideoExporterusesMediaCodec; no portable desktop video encoder wired up) - Fullscreen toggle in the video player
Saved files land under ~/tCamViewer/{Pictures,Movies,Charts,Exports}/MM_DD_YYYY/.