Розробка мобільного додатку для розумної будівлі (Building Management System)

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Розробка мобільного додатку для розумної будівлі (Building Management System)
Складний
від 2 тижнів до 3 місяців
Часті запитання

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

Етапи розробки

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

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Розробка мобільних додатків для розумного будівлі (BMS)

BMS-проекти починаються однаково: замовник показує схему будівлі з контролерами Siemens Desigo CC, Schneider Electric EcoStruxure або Johnson Controls Metasys та говорить «хочемо видіти все це у телефоні». За цим «все це» скриваються десятки протоколів, polling-цикли від 1 секунди до 15 хвилин, історична база на роки назад та вимога працювати навіть коли основний сервер BMS перезагружається.

Протоколи та шлюзи

Промислові BMS говорять на BACnet/IP, Modbus TCP/RTU, KNX/IP та LonWorks. Напрямку з них не ходять — між контролерами та REST/WebSocket API стоїть шлюз або middleware.

Типовий стек інтеграції:

Рівень Технологія
Контролери BACnet/IP, Modbus TCP, KNX
Шлюз Node-RED, Niagara Framework 4, кастомний Python/Go сервіс
Transport MQTT over TLS, REST, WebSocket
Мобільний клієнт Flutter / Swift / Kotlin

Niagara Framework 4 (Tridium) — де-факто стандарт для великих об'єктів. Він умеє нормалізувати BACnet-об'єкти в єдиний REST API (/haystack/api/read?filter=bacnet) та віддавати WebSocket-стрім змін. Робота з Haystack API через Dart:

class HaystackClient {
  final Dio _dio;
  final String _baseUrl;

  HaystackClient(this._baseUrl, String username, String password) :
    _dio = Dio(BaseOptions(
      baseUrl: _baseUrl,
      headers: {
        'Authorization': 'Basic ${base64Encode(utf8.encode('$username:$password'))}',
        'Accept': 'application/json',
      },
    ));

  Future<List<HaystackRow>> read(String filter) async {
    final response = await _dio.get('/haystack/api/read',
        queryParameters: {'filter': filter});
    final grid = HaystackGrid.fromJson(response.data);
    return grid.rows;
  }

  Future<Map<String, dynamic>> readPoint(String pointId) async {
    final response = await _dio.get('/haystack/api/hisRead',
        queryParameters: {
          'id': '@$pointId',
          'range': 'today',
        });
    return response.data;
  }
}

Для об'єктів з MQTT-шлюзом (Node-RED конвертує BACnet → MQTT JSON) використовуйте mqtt_client у Flutter. Топіки організуйте по ієрархії будівлі: building/{buildingId}/floor/{floor}/zone/{zone}/{parameter}.

Архітектура даних реального часу

Найскладніший момент у BMS-додатку — не підключення, а управління потоком даних. Температура у 200 зонах оновлюється кожні 30 секунд, освітлення — за подією, енергоспоживання — кожну хвилину. Все це неможна переписувати при кожному перерисуванні UI.

Рішення — централізований DataHub на рівні додатка:

class BmsDataHub {
  final MqttClient _mqtt;
  final _streams = <String, BehaviorSubject<BmsPoint>>{};

  Stream<BmsPoint> watchPoint(String pointId) {
    if (!_streams.containsKey(pointId)) {
      _streams[pointId] = BehaviorSubject();
      _mqtt.subscribe('building/+/+/+/$pointId', MqttQos.atLeastOnce);
    }
    return _streams[pointId]!.stream;
  }

  void _onMessage(List<MqttReceivedMessage<MqttMessage>> events) {
    for (final event in events) {
      final topic = event.topic;
      final payload = MqttPublishPayload.bytesToStringAsString(
          (event.payload as MqttPublishMessage).payload.message);
      final point = BmsPoint.fromJson(jsonDecode(payload));
      _streams[point.id]?.add(point);
    }
  }
}

BehaviorSubject з пакета rxdart зберігає останнє значення — віджет, підписаний після приходу даних, одразу отримує актуальний стан без чекання на наступний цикл polling.

Інтерактивний план етажу

Замовники завжди хочуть план будівлі з живими даними. Конвертуйте DXF або SVG-план у SVG (через ODA File Converter для DXF), рендеріть через flutter_svg + InteractiveViewer. Точки датчиків — overlay поверх SVG з позиціонуванням за нормалізованими координатами:

class FloorPlanWidget extends StatelessWidget {
  final FloorPlan plan;
  final Map<String, BmsPoint> liveData;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      return Stack(children: [
        SvgPicture.asset('assets/floors/${plan.id}.svg',
            width: constraints.maxWidth),
        ...plan.sensors.map((sensor) => Positioned(
          left: sensor.x * constraints.maxWidth,
          top: sensor.y * constraints.maxHeight,
          child: SensorMarker(
            point: liveData[sensor.pointId],
            type: sensor.type,
          ),
        )),
      ]);
    });
  }
}

Маркери змінюють колір за порогами: зелений (норма), жовтий (попередження), червоний (аварія). Пороги беруть з BMS-конфігурації, не хардкодять.

Управління: запис значень в BACnet-точки

Читати простіше, ніж писати. Для командування BACnet-точками (setpoint температури, включення/выключення освітлення) через REST-шлюз:

Future<void> writePoint(String pointId, dynamic value) async {
  // Оптимістичне оновлення UI
  _hub.updateLocally(pointId, value);

  try {
    await _api.put('/haystack/api/pointWrite', data: {
      'id': '@$pointId',
      'level': 8,  // приоритет записи BACnet (1-16, нижче = вище приоритет)
      'val': value,
      'who': _authService.currentUser,
      'duration': 'PT0S',  // permanent
    });
  } on DioException catch (e) {
    // Откат при ошибке
    _hub.revertLocally(pointId);
    rethrow;
  }
}

BACnet Priority Array — деталь, яку ігнорують і потім не можуть зрозуміти, чому уставка температури не змінюється: контролер приймає команди, але вони перебиваються більш високим приоритетом з BMS-розписання (рівні 2-4). Рівень 8 — стандартний для ручного оператора.

Алерти та журнал событій

Аварійні события з BMS приходять через MQTT або WebSocket. Локальні push-сповіщення генеруємо через flutter_local_notifications, серверні push (коли додаток закритий) — через FCM з високим приоритетом (priority: high, content_available: true).

Журнал событій: SQLite через drift для офлайн-зберігання 30 днів історії, страничне завантаження з API для більш старих записів.

Розграничення прав

У реальних об'єктах різні користувачі видять різні етажі та зони. Права зберігаються на backend, мобільний клієнт запитує список доступних об'єктів при логіні та не будує маршрути до недоступних ресурсів. Спроба написати в заборонену точку → HTTP 403 → локальний откат + сповіщення користувачу.

Розробка мобільного BMS-клієнта з відображенням плану етажу, real-time даними через MQTT/WebSocket та управлінням setpoints: 8–12 тижнів. Повнофункціональна система з підтримкою кількох об'єктів, історичними графіками, алертами та розграниченням прав: 4–6 місяців. Вартість розраховується індивідуально після аналізу протоколів контролерів та вимог до інтеграції.