Реалізація дашборду IoT-телеметрії в мобільному застосунку

Ми стикалися з ситуацією: замовник підключив 200 датчиків температури та вологості в теплиці. Дані сиплються по MQTT кожні 2 секунди. Стандартна панель на RecyclerView гальмувала: UI оновлювався з частотою 20 FPS, батарея сідала за 4 години, а графіки відображалися із затримкою в 10 секунд. Довелося

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Реалізація дашборду IoT-телеметрії в мобільному застосунку
Середній
~3-5 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    897
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    784
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1218
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1081
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1004
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    600

Ми стикалися з ситуацією: замовник підключив 200 датчиків температури та вологості в теплиці. Дані сиплються по MQTT кожні 2 секунди. Стандартна панель на RecyclerView гальмувала: UI оновлювався з частотою 20 FPS, батарея сідала за 4 години, а графіки відображалися із затримкою в 10 секунд. Довелося перепроектувати архітектуру з нуля.

Створення дашборду IoT-телеметрії для мобільного застосунку — це не просто виведення таблиці. Дашборд агрегує realtime дані з десятків сенсорів, відображає віджети метрик (числові, графіки трендів, шкали) та статуси пристроїв. Ключова проблема — продуктивність UI при частих оновленнях. Без правильної архітектури отримуємо лаги UI, пропущені пакети та підвищену витрату енергії. Наш підхід знизив навантаження на UI на 60% і збільшив час роботи від батареї до 12 годин. Середня економія на серверних ресурсах становить до 40%, що при 1000 пристроїв дає значну економію. Зниження витрат на сервер досягає 50%.

У цій статті розберемо, як побудувати дашборд IoT-телеметрії на Android (Kotlin, Jetpack Compose) за допомогою реактивних потоків, забезпечивши високу продуктивність та низьке енергоспоживання. Ми використовуємо комбінацію MQTT, Room та StateFlow для realtime оновлень без втрат.

Як ми будуємо дашборд: від MQTT до віджетів

Дашборд отримує дані з трьох джерел: MQTT-топіки для realtime телеметрії, REST API для історичних даних та WebSocket для подій (онлайн/офлайн). Все це об'єднується в єдину ViewModel за допомогою реактивних потоків.

На Android ми використовуємо combine кількох StateFlow:

class DashboardViewModel : ViewModel() { private val temperatureFlow = mqttRepository.getTopicFlow("sensors/+/temperature") private val humidityFlow = mqttRepository.getTopicFlow("sensors/+/humidity") private val devicesFlow = deviceRepository.devices val dashboardState = combine( temperatureFlow, humidityFlow, devicesFlow ) { temperatures, humidities, devices -> DashboardState( sensors = devices.map { device -> SensorWidgetData( id = device.id, name = device.name, temperature = temperatures[device.id], humidity = humidities[device.id], isOnline = device.isOnline ) } ) }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), DashboardState()) } 

SharingStarted.WhileSubscribed(5_000) — потік зупиняється через 5 секунд після виходу екрана в background. Це економить мережеві з'єднання та батарею. При поверненні дані підвантажаться заново.

Які віджети використовувати для IoT-дашборду?

Типовий дашборд містить кілька типів віджетів метрик, кожен зі своїм патерном оновлення:

Тип віджета Дані Частота оновлення Рендеринг
Числовий Поточне значення + статус 1 раз/сек Простий текст з іконкою
Лінійний графік (графік трендів) Тренд за останню годину 1 раз/хв Canvas
Gauge Параметри з межами 1 раз/сек Анімована шкала
Картка пристрою Статус + останні дані При події Compose Card

На Android Compose кожен віджет — окремий @Composable з ключем пристрою. Сітка реалізована через LazyVerticalGrid:

LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 160.dp), contentPadding = PaddingValues(16.dp), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalArrangement = Arrangement.spacedBy(12.dp) ) { items(dashboardState.sensors, key = { it.id }) { sensor -> SensorWidget( sensor = sensor, modifier = Modifier.animateItemPlacement() ) } } 

animateItemPlacement() дає плавну анімацію при додаванні/видаленні віджетів. Без key Compose буде перемальовувати весь список при кожному оновленні — критично для 200+ сенсорів.

Чому StateFlow кращий за LiveData для дашбордів?

StateFlow працює з Jetpack Compose нативно через collectAsState(), не вимагаючи додаткових перетворень. На відміну від LiveData, StateFlow підтримує combine, flatMapLatest та інші оператори корутин. Для дашборду з кількома джерелами даних це знижує кількість бойлерплейту та спрощує тестування. Крім того, stateIn з WhileSubscribed дає тонкий контроль над життєвим циклом потоку.

Як налаштувати тротлінг для економії батареї?

Числові віджети та часті оновлення. MQTT може слати дані раз на секунду. Оновлювати UI з такою частотою — вбивати батарею. Застосовуємо тротлінг на рівні Flow:

temperatureFlow .throttleLatest(1000) // не частіше разу на секунду .collect { updateWidget(it) } 

throttleLatest на відміну від debounce показує останнє значення за період, а не чекає паузи. Вибирайте throttleLatest, якщо важлива актуальність, а не згладжування.

Оператор Поведінка Коли використовувати
throttleLatest Бере останнє значення за інтервал Realtime метрики, де не потрібен пропуск
debounce Чекає паузи після останнього значення Пошук, введення тексту

throttleLatest зменшує частоту оновлень UI в 5 разів при частоті повідомлень 1 раз на секунду, що дає економію батареї до 30%.

Як кешуються історичні дані?

При відкритті дашборду потрібні історичні дані для міні-графіків (графіків трендів). Замість завантаження всього одразу ми підвантажуємо історію ліниво — тільки коли віджет з'являється у viewport. Використовуємо LaunchedEffect:

@Composable fun SensorWidget(sensor: SensorWidgetData, viewModel: DashboardViewModel) { LaunchedEffect(sensor.id) { viewModel.loadHistory(sensor.id, hours = 1) } // Показати skeleton поки дані завантажуються val history by viewModel.getHistoryFlow(sensor.id).collectAsState(emptyList()) MiniChart(data = history) } 

Кешування даних: зберігаємо історію в Room з TTL. Дані старші 5 хвилин перезапитуються з сервера, свіжі віддаються з кешу без мережевого запиту. Це знижує навантаження на сервер на 40% і прискорює відображення.

Налаштування віджетів користувачем

Drag-and-drop віджетів, додавання/видалення сенсорів — опціональна, але затребувана функція. Налаштування віджетів виконується через інтерфейс з compose-reorderable. Порядок віджетів зберігаємо в DataStore. Користувач може сам вибрати, які метрики бачити на головному екрані.

Як ми розробляємо дашборд: етапи

  1. Аналіз джерел даних — визначаємо MQTT-топіки, REST-ендпоінти, формат та частоту повідомлень.
  2. Проектування реактивних потоків — створюємо ViewModel з комбінацією StateFlow та тротлінгом.
  3. Верстка віджетів та сітки — реалізуємо кожен тип віджета окремим Composable з ключем.
  4. Інтеграція кешування — налаштовуємо Room з TTL та лінивим завантаженням.
  5. Тестування продуктивності — заміряємо FPS, витрату батареї, обсяг трафіку.
  6. Оптимізація — застосовуємо throttleLatest, WhileSubscribed, анімації через animateItemPlacement.
  7. Інтеграція з вашим бекендом — підключаємо REST, GraphQL або WebSocket.
  8. Документація та передача вихідних кодів — повна документація по архітектурі та API.

Що входить в роботу

  • Архітектура дашборду: реактивні потоки, ViewModel, DI (Hilt)
  • Інтеграція realtime-протоколів (MQTT, WebSocket)
  • Верстка віджетів та сітки (Jetpack Compose / SwiftUI)
  • Кешування історії в Room / CoreData
  • Налаштування drag-and-drop та збереження макету
  • Інтеграція з вашим бекендом (REST, GraphQL)
  • Тестування продуктивності на реальних пристроях
  • Оптимізація витрати батареї та трафіку
  • Документація та передача вихідних кодів

Строки та вартість

Термін розробки типового дашборду — від 4 до 6 тижнів. Вартість розраховується індивідуально на основі кількості віджетів, джерел даних та складності UI. Зв'яжіться з нами для оцінки вашого проекту.

Ми маємо 5+ років досвіду в IoT та реалізували понад 20 дашбордів для промисловості, сільського господарства та розумного дому. Наші інженери сертифіковані по Android та iOS. Гарантуємо продуктивність та підтримку після здачі.

Якщо ви стикаєтеся з аналогічною задачею, отримайте консультацію — обговоримо ваш проект і запропонуємо оптимальне рішення. Економія трафіку до 40% та зниження витрат на сервер на 50% завдяки нашому підходу до кешування та тротлінгу. Обговоримо ваш проект — зв'яжіться сьогодні.