Mobile App Development for BMS Building Management

BMS projects start the same way: the client shows a building diagram with controllers from Siemens Desigo CC, Schneider Electric EcoStruxure, or Johnson Controls Metasys and says, "We want all this on a phone." Behind that "all this" are dozens of protocols, polling cycles from 1 second to 15 minute

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Mobile App Development for BMS Building Management
Complex
from 2 weeks to 3 months

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    897
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    784
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1218
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1081
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1004
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    600

BMS projects start the same way: the client shows a building diagram with controllers from Siemens Desigo CC, Schneider Electric EcoStruxure, or Johnson Controls Metasys and says, "We want all this on a phone." Behind that "all this" are dozens of protocols, polling cycles from 1 second to 15 minutes, a historical database going back years, and the requirement to work even when the main BMS server reboots. We take such projects turnkey: from protocol analysis to publishing in stores. Our experience: 10+ years in BMS integration and over 50 implemented sites. We evaluate the project in 2 days and guarantee stable operation under any load.

Protocols and Gateways

Industrial BMS systems speak BACnet/IP, Modbus TCP/RTU, KNX/IP, and LonWorks. They are not directly accessible from a mobile app—between the controllers and the REST/WebSocket API sits a gateway or middleware.

Typical integration stack:

Layer Technology
Controllers BACnet/IP, Modbus TCP, KNX
Gateway Node-RED, Niagara Framework 4, custom Python/Go service
Transport MQTT over TLS, REST, WebSocket
Mobile client Flutter / Swift / Kotlin

Niagara Framework 4 (Tridium) is the de facto standard for large sites. It normalizes BACnet objects into a unified REST API (/haystack/api/read?filter=bacnet) and provides WebSocket streams of changes. Working with Haystack API via 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; } } 

For sites with an MQTT gateway (Node-RED converts BACnet → MQTT JSON), we use the mqtt_client in Flutter. Topics are organized by building hierarchy: building/{buildingId}/floor/{floor}/zone/{zone}/{parameter}.

How We Integrate with Existing BMS?

The process always starts with an audit of the controllers: we find out which protocols are used, which version of Niagara or other middleware is installed, whether a REST/WebSocket API already exists or a gateway needs to be deployed. Then we design the data flow scheme: which points are read, which are written, and at what interval. Certified engineers configure the gateway and perform integration testing. The result is a unified interface on the phone instead of multiple control panels.

Real-Time Data Architecture: Why a DataHub is Critical?

The most challenging part of a BMS app is not the connection but managing the data stream. Temperature in 200 zones updates every 30 seconds, lighting changes by event, energy consumption every minute. All this cannot be resubscribed on every UI redraw.

The solution is a centralized DataHub at the application level:

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 from the rxdart package retains the last value—so a widget that subscribes after data arrives immediately gets the current state without waiting for the next polling cycle.

Interactive Floor Plan

Customers always want a building floor plan with live data. We convert DXF or SVG plans to SVG (via ODA File Converter for DXF), render them with flutter_svg and InteractiveViewer. Sensor points are overlaid onto the SVG using normalized coordinates:

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, ), )), ]); }); } } 

Markers change color based on thresholds: green (normal), yellow (warning), red (alarm). Thresholds are fetched from the BMS configuration—no hardcoding.

Control: Writing Values to BACnet Points

Reading is easier than writing. To command BACnet points (temperature setpoint, light on/off) via the REST gateway:

Future<void> writePoint(String pointId, dynamic value) async { // Optimistic UI update _hub.updateLocally(pointId, value); try { await _api.put('/haystack/api/pointWrite', data: { 'id': '@$pointId', 'level': 8, // BACnet write priority (1-16, lower = higher priority) 'val': value, 'who': _authService.currentUser, 'duration': 'PT0S', // permanent }); } on DioException catch (e) { // Roll back on error _hub.revertLocally(pointId); rethrow; } } 

BACnet Priority Array is a detail often overlooked—leading to confusion why a setpoint won't change: the controller accepts commands but they are overridden by a higher priority from BMS scheduling (level 2-4). Level 8 is standard for manual operator commands.

Alerts and Event Log

Alarm events from the BMS come via MQTT or WebSocket. Local push notifications are generated with flutter_local_notifications, server push (when the app is closed) via FCM with high priority (priority: high, content_available: true).

Event log: SQLite via drift for offline storage of 30 days of history, paginated loading from the API for older entries.

Access Control

On real sites, different users see different floors and zones. Rights are stored on the backend; the mobile client requests the list of accessible objects on login and does not build routes to inaccessible resources. Attempting to write to a forbidden point returns HTTP 403, triggering a local rollback and user notification.

What Is Included in Development?

  • Analysis of controller protocols and BMS architecture.
  • Design of integration scheme and data flows.
  • Implementation of mobile client (iOS/Android on Flutter or native stack).
  • Gateway configuration and integration testing.
  • Publication in App Store and Google Play.
  • 30 days of technical support after release.
  • API documentation and staff training (optional).

Timeline and Cost

Stage Duration
MVP (floor plan + real-time monitoring) 8–12 weeks
Full system (multiple objects, charts, alerts, rights) 4–6 months
Integration with non-standard protocols +2–4 weeks

Cost is calculated individually after analysis of your controllers and requirements. Contact us for an evaluation—we will prepare a commercial proposal within 2 business days.