IoT Device Grouping by Zones/Rooms in Mobile Applications
With twenty+ devices in the system, without grouping the app becomes a flat list of lamps, sensors, and relays mixed together. Users can't find devices, control slows, complaints grow. Grouping by zones and rooms is not cosmetics but mandatory architecture for any mid-scale IoT app.
Where Grouping Data Lives
First question determining whole architecture: where does "device → room → zone" correspondence live? Two options — on server or locally on device.
Local storage (SharedPreferences, AsyncStorage, Hive) works until user installs second phone or transfers control to family member. Grouping vanishes. Syncing via iCloud/Google Drive — separate headache with version conflicts.
Correct: backend hierarchy. Structure: home → floor → zone → room → device. Each level — separate DB record with parent_id and position (for sorting). Device can only be in one room, but rooms can be grouped into arbitrary zones (e.g., "First Floor" and "Kids Zone" may overlap).
CREATE TABLE locations (
id UUID PRIMARY KEY,
home_id UUID NOT NULL,
parent_id UUID REFERENCES locations(id),
type VARCHAR(20) CHECK (type IN ('floor','zone','room')),
name VARCHAR(100),
position INTEGER DEFAULT 0
);
CREATE TABLE device_locations (
device_id UUID NOT NULL,
location_id UUID NOT NULL,
PRIMARY KEY (device_id, location_id)
);
Many-to-many between device and locations for scenarios like "motion sensor counts as both hallway and security zone".
Grouping UI: What Works in Practice
On Flutter use SliverList with SliverAppBar per group — smooth scroll with sticky room headers without performance loss. ExpansionTile for collapsing/expanding rooms. Drag-and-drop for reassigning devices — via ReorderableListView or flutter_reorderable_list package.
On React Native — SectionList with stickySectionHeadersEnabled. For DnD use react-native-draggable-flatlist or Reanimated 3 with GestureHandler. Don't use standard ScrollView with manual position calculations — guaranteed performance nightmare on Android.
Important UX moment: group status (all on / partially / all off) must aggregate on client from device state cache, not requested via separate API call. Otherwise opening "Living Room" — 20 parallel requests, 200ms lag, visible jitter on iOS.
Aggregation via Riverpod StateProvider (Flutter) or Zustand selector (React Native): group status recalculates reactively when any device in group updates.
Real-Time Synchronization
User renamed room or moved device — change must appear on all logged-in devices. Implement via WebSocket channel with messages:
{ "event": "location_updated", "location_id": "...", "changes": { "name": "Bedroom 2" } }
{ "event": "device_moved", "device_id": "...", "from_location": "...", "to_location": "..." }
Client updates local cache (flutter_riverpod Notifier / Zustand store) without full list reload. Critical for multi-user scenarios — family manages one home from different phones.
Additional Considerations
Custom room icons and colors — user-defined, stored in locations.metadata (JSONB). Quick access to favorite devices — separate favorites section with own order independent of room hierarchy. Search by device name — index on devices.name + pg_trgm extension for fuzzy search.
Process and Timeline
Design hierarchy and API — 3–5 days. UI with grouping and basic DnD — 2 weeks. Real-time sync, multi-user scenarios, search — another 1.5–2 weeks. Total basic functionality — 4–6 weeks depending on platform and hierarchy complexity.







