Real-Time Solar Panel Monitoring via Bluetooth

A native Android app delivering live performance insights with custom-built visualizations and fluid animations — all powered by Jetpack Compose.

Real-Time Solar Panel Monitoring via Bluetooth

Project Overview

RoleAndroid Developer (Contract)
Duration
May 25’Jun 25’
Team SizeSolo Developer
PlatformsAndroid

Designed and shipped a high-fidelity monitoring application for solar installations that connects directly to hardware via Bluetooth. The focus was on turning raw telemetry into clear, actionable insights while creating an interface that feels responsive and delightful to use — even when handling continuous live data streams.

Technical Overview

A modern Android stack built entirely with Jetpack Compose and Kotlin — prioritizing performance, maintainability, and visual polish.

  • UI Layer: Jetpack Compose, custom Canvas drawings, Lottie for micro-interactions
  • Architecture: Clean Architecture + MVVM, StateFlow/SharedFlow, single source of truth
  • Dependency Injection: Hilt
  • Async & Reactive: Kotlin Coroutines, Flow, Channel buffering for BLE packets
  • Bluetooth: Android BLE API with notification characteristics and robust reconnection
  • Persistence: Room for session caching and offline charts
  • Animations: Compose Animation API, spring physics, custom Path interpolators
  • Testing: Unit tests for repository and view-model layers, UI tests for critical flows
  • Build & Delivery: Gradle Kotlin DSL, version catalog, signed release builds

The Challenge

The client needed a reliable way to visualize live solar data on-site without relying on cloud dashboards. The hardware sent frequent Bluetooth updates, so the app had to feel instantaneous while remaining battery-friendly and resilient to connection drops.

  • Real-time fidelity: Show accurate, smooth updates without jank even at high packet rates.
  • Battery consciousness: Avoid excessive CPU/GPU usage despite continuous animations and charting.
  • Connection resilience: Graceful handling of BLE disconnects and reconnections without losing context.
  • Data clarity: Present technical telemetry (voltage, current, temperature, yield) in a way installers and owners can understand at a glance.
  • No third-party charting libraries: Everything custom-built to control performance and appearance precisely.
  • Single codebase maintainability: Clean architecture that scales if more device types are added later.

Approach & Key Decisions

I chose a fully custom Compose implementation to own every pixel and frame. The goal was to make the app feel alive when data flows and calm when idle — using motion intentionally to reinforce information hierarchy.

Architecture & Data Flow

Built on Clean Architecture with MVVM. Bluetooth handling lives in a dedicated repository layer using Kotlin Flows for reactive, cancellable streams.

  • Separated BLE connection logic from UI to survive configuration changes and process death
  • Used shared flows with replay cache to recover recent data after reconnect
  • StateFlow for UI state — single source of truth, easy to test and reason about
  • Hilt for dependency injection — kept modules scoped and replaceable

Real-Time Visualizations

All charts and gauges drawn manually on Canvas — giving full control over interpolation, performance, and visual style.

  • Custom Path-based line charts with cubic bezier smoothing and dynamic window scrolling
  • Radial gauges using arc sweeps and animated value changes with spring physics
  • Sparse sampling for historical data to keep draw calls minimal
  • Off-main-thread preprocessing of incoming packets before emitting to UI

Animation Philosophy

Motion used sparingly and purposefully — always tied to data changes or user interaction.

  • Staggered entrance animations on launch to establish visual hierarchy
  • Spring-based value animations for metrics (fast settle, natural feel)
  • Shared element transitions when drilling into details
  • Subtle breathing pulse on connection status to indicate health without distraction

Performance & Battery

Prioritized efficiency from day one — targeting 60 fps on mid-range devices while connected.

  • Limited Canvas redraws to dirty regions only
  • Throttled UI updates when values change minimally
  • Background service with foreground notification only when actively monitoring
  • Efficient BLE characteristic reading (notification mode, no polling)

Resilience & UX

Designed for the real-world environment of rooftops and inverters — where connections drop and devices reboot.

  • Auto-reconnect with exponential backoff and user-visible status
  • Persisted recent sessions locally (Room) for offline review
  • Clear, non-technical messaging for connection states and errors
  • One-tap refresh and manual scan fallback

Results & Impact

Update Latency< 1s

From hardware reading to screen update — consistently sub-second even during peak packet rates.

Battery ImpactLow

Optimized drawing and BLE usage resulted in minimal drain during active monitoring.

Connection RecoveryAutomatic

App seamlessly resumes data flow after temporary disconnects without user intervention.

Reflection

This project was a reminder of how much impact thoughtful motion and custom drawing can have in technical tools. When data arrives continuously, animation isn’t decoration — it becomes a primary way to communicate change and system health. By owning the rendering pipeline completely, I could make the app feel truly alive while staying performant and reliable in real field conditions.

Key Takeaways

  • Custom beats off-the-shelf: When performance and feel matter, building your own charts pays off.
  • Motion with meaning: The best animations are the ones users don’t notice — until they’re gone.
  • BLE is fragile: Resilience and clear feedback turn a flaky connection into a trustworthy tool.
  • Compose shines for data-heavy UIs: The declarative model makes complex, reactive screens far easier to reason about.
  • Constraints breed creativity: Working within battery, CPU, and bandwidth limits forced decisions that ultimately improved the product.

Share this case study