feat: implement watchPositions() tag position stream
This commit is contained in:
@@ -38,19 +38,42 @@ class PhoenixTagRepository implements TagRepository {
|
|||||||
Future<void> deleteTag(int id) => tagClient.deleteTag(id);
|
Future<void> deleteTag(int id) => tagClient.deleteTag(id);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<List<TagPosition>> watchPositions() =>
|
Stream<List<TagPosition>> watchPositions() async* {
|
||||||
realtime.channel('tags').map((payload) {
|
var tagMap = await _fetchTagMap();
|
||||||
final list = payload['positions'] as List<dynamic>? ?? [];
|
|
||||||
return list.map((j) {
|
await for (final occupancy in watchRoomOccupancy()) {
|
||||||
final m = j as Map<String, dynamic>;
|
// Re-fetch on every occupancy change so name/color edits and new tags
|
||||||
return TagPosition(
|
// are reflected without restarting the stream.
|
||||||
tagId: m['tag_id'] as String,
|
tagMap = await _fetchTagMap();
|
||||||
name: m['name'] as String,
|
|
||||||
color: m['color'] as String,
|
final positions = <TagPosition>[];
|
||||||
roomId: m['room_id'] as int?,
|
for (final entry in occupancy.entries) {
|
||||||
);
|
for (final tagId in entry.value) {
|
||||||
}).toList();
|
final tag = tagMap[tagId];
|
||||||
});
|
positions.add(TagPosition(
|
||||||
|
tagId: tagId,
|
||||||
|
name: tag?.name ?? tagId,
|
||||||
|
color: tag?.color ?? _colorForTagId(tagId),
|
||||||
|
roomId: entry.key,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yield positions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, Tag>> _fetchTagMap() async {
|
||||||
|
final raw = await tagClient.getTags();
|
||||||
|
return {
|
||||||
|
for (final j in raw.cast<Map<String, dynamic>>())
|
||||||
|
j['tag_id'] as String: Tag.fromJson(j),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static String _colorForTagId(String tagId) {
|
||||||
|
final hash = tagId.codeUnits.fold(0, (h, c) => (h * 31 + c) & 0xFFFFFF);
|
||||||
|
return '#${hash.toRadixString(16).padLeft(6, '0')}';
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<ParticleSnapshot> watchParticleCloud(String tagId) =>
|
Stream<ParticleSnapshot> watchParticleCloud(String tagId) =>
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ class Tag {
|
|||||||
this.currentRoomId,
|
this.currentRoomId,
|
||||||
this.lastPosition,
|
this.lastPosition,
|
||||||
this.lastSeen,
|
this.lastSeen,
|
||||||
|
this.color,
|
||||||
});
|
});
|
||||||
|
|
||||||
final int id;
|
final int id;
|
||||||
final String tagId; // BLE beacon advertised identifier
|
final String tagId; // BLE beacon advertised identifier
|
||||||
final String name;
|
final String name;
|
||||||
|
final String? color;
|
||||||
final String? currentRoomId;
|
final String? currentRoomId;
|
||||||
final Position? lastPosition;
|
final Position? lastPosition;
|
||||||
final DateTime? lastSeen;
|
final DateTime? lastSeen;
|
||||||
@@ -34,6 +36,7 @@ class Tag {
|
|||||||
'current_room_id': currentRoomId,
|
'current_room_id': currentRoomId,
|
||||||
'last_position': lastPosition?.toJson(),
|
'last_position': lastPosition?.toJson(),
|
||||||
'last_seen': lastSeen?.toIso8601String(),
|
'last_seen': lastSeen?.toIso8601String(),
|
||||||
|
'color': color,
|
||||||
};
|
};
|
||||||
|
|
||||||
factory Tag.fromJson(Map<String, dynamic> json) => Tag(
|
factory Tag.fromJson(Map<String, dynamic> json) => Tag(
|
||||||
@@ -41,6 +44,7 @@ class Tag {
|
|||||||
tagId: json['tag_id'] as String,
|
tagId: json['tag_id'] as String,
|
||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
currentRoomId: json['current_room_id'] as String?,
|
currentRoomId: json['current_room_id'] as String?,
|
||||||
|
color: json['color'] as String?,
|
||||||
lastPosition: json['last_position'] == null
|
lastPosition: json['last_position'] == null
|
||||||
? null
|
? null
|
||||||
: Position.fromJson(json['last_position'] as Map<String, dynamic>),
|
: Position.fromJson(json['last_position'] as Map<String, dynamic>),
|
||||||
|
|||||||
Reference in New Issue
Block a user