feat: grab sensor firmware version for detail sheet
This commit is contained in:
@@ -52,6 +52,9 @@ class PhoenixSensorRepository implements SensorRepository {
|
|||||||
Future<Sensor> unplaceSensor(int id) async =>
|
Future<Sensor> unplaceSensor(int id) async =>
|
||||||
Sensor.fromJson(await client.unplaceSensor(id));
|
Sensor.fromJson(await client.unplaceSensor(id));
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<String?> getVersion(int id) => client.getVersion(id);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<Map<String, dynamic>> sensorEvents() => realtime
|
Stream<Map<String, dynamic>> sensorEvents() => realtime
|
||||||
.channelMessages('sensors')
|
.channelMessages('sensors')
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ abstract class SensorRepository {
|
|||||||
{required int roomId, required double x, required double y});
|
{required int roomId, required double x, required double y});
|
||||||
Future<Sensor> unplaceSensor(int id);
|
Future<Sensor> unplaceSensor(int id);
|
||||||
|
|
||||||
|
Future<String?> getVersion(int id);
|
||||||
|
|
||||||
/// Stream of raw SensorsChannel messages. Each map contains an `event` key
|
/// Stream of raw SensorsChannel messages. Each map contains an `event` key
|
||||||
/// (`sensor_announced` or `sensor_enrollment_timeout`) plus the payload.
|
/// (`sensor_announced` or `sensor_enrollment_timeout`) plus the payload.
|
||||||
Stream<Map<String, dynamic>> sensorEvents();
|
Stream<Map<String, dynamic>> sensorEvents();
|
||||||
|
|||||||
@@ -13,30 +13,46 @@ class SensorClient extends LocaliserdClient {
|
|||||||
await get('/api/sensors/$id') as Map<String, dynamic>;
|
await get('/api/sensors/$id') as Map<String, dynamic>;
|
||||||
|
|
||||||
Future<Map<String, dynamic>> updateSensor(
|
Future<Map<String, dynamic>> updateSensor(
|
||||||
int id, Map<String, dynamic> params) async =>
|
int id,
|
||||||
await put('/api/sensors/$id', params) as Map<String, dynamic>;
|
Map<String, dynamic> params,
|
||||||
|
) async => await put('/api/sensors/$id', params) as Map<String, dynamic>;
|
||||||
|
|
||||||
Future<void> deleteSensor(int id) => delete('/api/sensors/$id');
|
Future<void> deleteSensor(int id) => delete('/api/sensors/$id');
|
||||||
|
|
||||||
Future<Map<String, dynamic>> placeSensor(
|
Future<Map<String, dynamic>> placeSensor(
|
||||||
int id, Map<String, dynamic> params) async =>
|
int id,
|
||||||
|
Map<String, dynamic> params,
|
||||||
|
) async =>
|
||||||
await put('/api/sensors/$id/place', params) as Map<String, dynamic>;
|
await put('/api/sensors/$id/place', params) as Map<String, dynamic>;
|
||||||
|
|
||||||
Future<Map<String, dynamic>> unplaceSensor(int id) async =>
|
Future<Map<String, dynamic>> unplaceSensor(int id) async =>
|
||||||
await deleteBody('/api/sensors/$id/place') as Map<String, dynamic>;
|
await deleteBody('/api/sensors/$id/place') as Map<String, dynamic>;
|
||||||
|
|
||||||
Future<Map<String, dynamic>> createSensor(String sensorId,
|
Future<Map<String, dynamic>> createSensor(
|
||||||
{String? name}) async =>
|
String sensorId, {
|
||||||
|
String? name,
|
||||||
|
}) async =>
|
||||||
await post('/api/sensors', {
|
await post('/api/sensors', {
|
||||||
'sensor_id': sensorId,
|
'sensor_id': sensorId,
|
||||||
if (name != null) 'name': name,
|
if (name != null) 'name': name,
|
||||||
}) as Map<String, dynamic>;
|
})
|
||||||
|
as Map<String, dynamic>;
|
||||||
|
|
||||||
Future<Map<String, dynamic>> startCalibration(
|
Future<Map<String, dynamic>> startCalibration(
|
||||||
int id, double referenceDistance) async =>
|
int id,
|
||||||
await post('/api/sensors/$id/calibration/start',
|
double referenceDistance,
|
||||||
{'reference_distance': referenceDistance}) as Map<String, dynamic>;
|
) async =>
|
||||||
|
await post('/api/sensors/$id/calibration/start', {
|
||||||
|
'reference_distance': referenceDistance,
|
||||||
|
})
|
||||||
|
as Map<String, dynamic>;
|
||||||
|
|
||||||
Future<Map<String, dynamic>> stopCalibration(int id) async =>
|
Future<Map<String, dynamic>> stopCalibration(int id) async =>
|
||||||
await post('/api/sensors/$id/calibration/stop') as Map<String, dynamic>;
|
await post('/api/sensors/$id/calibration/stop') as Map<String, dynamic>;
|
||||||
|
|
||||||
|
Future<String> getVersion(int id) async {
|
||||||
|
final response =
|
||||||
|
(await get('/api/sensors/$id/version') as Map<String, dynamic>);
|
||||||
|
return response['version']!;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Sensor {
|
|||||||
this.roomId,
|
this.roomId,
|
||||||
this.x,
|
this.x,
|
||||||
this.y,
|
this.y,
|
||||||
|
this.version,
|
||||||
});
|
});
|
||||||
|
|
||||||
final int id;
|
final int id;
|
||||||
@@ -16,6 +17,7 @@ class Sensor {
|
|||||||
final int? roomId;
|
final int? roomId;
|
||||||
final double? x; // room relative
|
final double? x; // room relative
|
||||||
final double? y; // room relative
|
final double? y; // room relative
|
||||||
|
final String? version;
|
||||||
|
|
||||||
bool get isPlaced => roomId != null && x != null && y != null;
|
bool get isPlaced => roomId != null && x != null && y != null;
|
||||||
String get displayName => name ?? sensorId;
|
String get displayName => name ?? sensorId;
|
||||||
@@ -28,6 +30,7 @@ class Sensor {
|
|||||||
roomId: json['room_id'] as int?,
|
roomId: json['room_id'] as int?,
|
||||||
x: (json['x'] as num?)?.toDouble(),
|
x: (json['x'] as num?)?.toDouble(),
|
||||||
y: (json['y'] as num?)?.toDouble(),
|
y: (json['y'] as num?)?.toDouble(),
|
||||||
|
version: json['version'] as String?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Sensor copyWith({
|
Sensor copyWith({
|
||||||
@@ -35,7 +38,7 @@ class Sensor {
|
|||||||
int? roomId,
|
int? roomId,
|
||||||
double? x,
|
double? x,
|
||||||
double? y,
|
double? y,
|
||||||
double? rssiRef,
|
String? version,
|
||||||
}) =>
|
}) =>
|
||||||
Sensor(
|
Sensor(
|
||||||
id: id,
|
id: id,
|
||||||
@@ -45,5 +48,6 @@ class Sensor {
|
|||||||
roomId: roomId ?? this.roomId,
|
roomId: roomId ?? this.roomId,
|
||||||
x: x ?? this.x,
|
x: x ?? this.x,
|
||||||
y: y ?? this.y,
|
y: y ?? this.y,
|
||||||
|
version: version ?? this.version,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ class _SensorDetailSheetState extends ConsumerState<SensorDetailSheet> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final sensorAsync = ref.watch(sensorProvider(widget.sensorId));
|
final sensorAsync = ref.watch(sensorProvider(widget.sensorId));
|
||||||
final roomsAsync = ref.watch(roomsProvider);
|
final roomsAsync = ref.watch(roomsProvider);
|
||||||
|
final versionAsync = ref.watch(sensorVersionProvider(widget.sensorId));
|
||||||
|
|
||||||
return sensorAsync.when(
|
return sensorAsync.when(
|
||||||
loading: () => const SizedBox(
|
loading: () => const SizedBox(
|
||||||
@@ -110,9 +111,12 @@ class _SensorDetailSheetState extends ConsumerState<SensorDetailSheet> {
|
|||||||
?.name,
|
?.name,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final version = versionAsync.whenOrNull(data: (v) => v);
|
||||||
|
|
||||||
return _SheetBody(
|
return _SheetBody(
|
||||||
sensor: sensor,
|
sensor: sensor,
|
||||||
roomName: roomName,
|
roomName: roomName,
|
||||||
|
version: version,
|
||||||
editing: _editing,
|
editing: _editing,
|
||||||
nameCtrl: _nameCtrl,
|
nameCtrl: _nameCtrl,
|
||||||
onEditToggle: () => setState(() {
|
onEditToggle: () => setState(() {
|
||||||
@@ -132,6 +136,7 @@ class _SheetBody extends StatelessWidget {
|
|||||||
const _SheetBody({
|
const _SheetBody({
|
||||||
required this.sensor,
|
required this.sensor,
|
||||||
required this.roomName,
|
required this.roomName,
|
||||||
|
required this.version,
|
||||||
required this.editing,
|
required this.editing,
|
||||||
required this.nameCtrl,
|
required this.nameCtrl,
|
||||||
required this.onEditToggle,
|
required this.onEditToggle,
|
||||||
@@ -142,6 +147,7 @@ class _SheetBody extends StatelessWidget {
|
|||||||
|
|
||||||
final Sensor sensor;
|
final Sensor sensor;
|
||||||
final String? roomName;
|
final String? roomName;
|
||||||
|
final String? version;
|
||||||
final bool editing;
|
final bool editing;
|
||||||
final TextEditingController nameCtrl;
|
final TextEditingController nameCtrl;
|
||||||
final VoidCallback onEditToggle;
|
final VoidCallback onEditToggle;
|
||||||
@@ -210,6 +216,7 @@ class _SheetBody extends StatelessWidget {
|
|||||||
? '(${sensor.x!.toStringAsFixed(2)}, ${sensor.y!.toStringAsFixed(2)})'
|
? '(${sensor.x!.toStringAsFixed(2)}, ${sensor.y!.toStringAsFixed(2)})'
|
||||||
: 'Not placed',
|
: 'Not placed',
|
||||||
),
|
),
|
||||||
|
_InfoRow(label: 'Firmware', value: version ?? '—'),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
FilledButton.icon(
|
FilledButton.icon(
|
||||||
icon: Icon(Icons.my_location),
|
icon: Icon(Icons.my_location),
|
||||||
|
|||||||
@@ -145,6 +145,11 @@ final sensorProvider =
|
|||||||
return ref.watch(sensorRepositoryProvider).getSensor(id);
|
return ref.watch(sensorRepositoryProvider).getSensor(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final sensorVersionProvider =
|
||||||
|
FutureProvider.autoDispose.family<String?, int>((ref, id) {
|
||||||
|
return ref.watch(sensorRepositoryProvider).getVersion(id);
|
||||||
|
});
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Tag data
|
// Tag data
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user