feat: type remote device models
This commit is contained in:
98
lib/models/ignis_device.dart
Normal file
98
lib/models/ignis_device.dart
Normal file
@@ -0,0 +1,98 @@
|
||||
class IgnisDevice {
|
||||
final String id;
|
||||
final String? mac;
|
||||
final String name;
|
||||
final String? model;
|
||||
final String? ip;
|
||||
|
||||
const IgnisDevice({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.mac,
|
||||
this.model,
|
||||
this.ip,
|
||||
});
|
||||
|
||||
String get groupMemberId => mac ?? id;
|
||||
|
||||
String? get subtitle {
|
||||
final parts = <String>[?mac, ?ip];
|
||||
return parts.isEmpty ? null : parts.join(' - ');
|
||||
}
|
||||
|
||||
static IgnisDevice fromApi(Object? value, {String? fallbackId}) {
|
||||
if (value is Map) {
|
||||
final map = Map<String, dynamic>.from(value);
|
||||
final id =
|
||||
_stringValue(map, const ['id', 'mac', 'mac_address', 'device_id']) ??
|
||||
fallbackId;
|
||||
if (id == null || id.isEmpty) {
|
||||
throw const FormatException('device не содержит id/mac');
|
||||
}
|
||||
|
||||
final mac = _stringValue(map, const ['mac', 'mac_address']);
|
||||
final model = _stringValue(map, const ['model']);
|
||||
final name =
|
||||
_stringValue(map, const ['name', 'label', 'model']) ?? mac ?? id;
|
||||
final ip = _stringValue(map, const ['ip', 'address']);
|
||||
|
||||
return IgnisDevice(id: id, mac: mac, name: name, model: model, ip: ip);
|
||||
}
|
||||
|
||||
final id = value?.toString() ?? fallbackId;
|
||||
if (id == null || id.isEmpty) {
|
||||
throw const FormatException('device должен быть объектом или id');
|
||||
}
|
||||
return IgnisDevice(id: id, mac: id, name: id);
|
||||
}
|
||||
|
||||
static List<IgnisDevice> listFromApi(Object? data) {
|
||||
final values = _collectionValues(data, const ['data', 'devices']);
|
||||
return values
|
||||
.map(
|
||||
(value) => value.entryKey == null
|
||||
? IgnisDevice.fromApi(value.value)
|
||||
: IgnisDevice.fromApi(value.value, fallbackId: value.entryKey),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
String? _stringValue(Map<String, dynamic> map, List<String> keys) {
|
||||
for (final key in keys) {
|
||||
final value = map[key];
|
||||
if (value != null && value.toString().isNotEmpty) {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<_CollectionValue> _collectionValues(Object? data, List<String> wrappers) {
|
||||
if (data is List) {
|
||||
return data.map((value) => _CollectionValue(value)).toList();
|
||||
}
|
||||
|
||||
if (data is Map) {
|
||||
final map = Map<String, dynamic>.from(data);
|
||||
for (final wrapper in wrappers) {
|
||||
final value = map[wrapper];
|
||||
if (value is List) {
|
||||
return value.map((item) => _CollectionValue(item)).toList();
|
||||
}
|
||||
}
|
||||
|
||||
return map.entries
|
||||
.map((entry) => _CollectionValue(entry.value, entryKey: entry.key))
|
||||
.toList();
|
||||
}
|
||||
|
||||
throw const FormatException('ожидался список или объект');
|
||||
}
|
||||
|
||||
class _CollectionValue {
|
||||
final Object? value;
|
||||
final String? entryKey;
|
||||
|
||||
const _CollectionValue(this.value, {this.entryKey});
|
||||
}
|
||||
Reference in New Issue
Block a user