Initial commit

This commit is contained in:
2026-01-19 10:20:45 +01:00
commit dd6d0b6e7b
144 changed files with 7016 additions and 0 deletions

35
lib/models/cluster.dart Normal file
View File

@@ -0,0 +1,35 @@
class Cluster {
final int? id;
final int? masterId;
final String? clusterName;
final int? talkgroup;
final bool? repeatersOnly;
Cluster({
this.id,
this.masterId,
this.clusterName,
this.talkgroup,
this.repeatersOnly,
});
factory Cluster.fromJson(Map<String, dynamic> json) {
return Cluster(
id: json['id'] as int?,
masterId: json['masterId'] as int?,
clusterName: json['clusterName'] as String?,
talkgroup: json['talkgroup'] as int?,
repeatersOnly: json['repeatersOnly'] as bool?,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'masterId': masterId,
'clusterName': clusterName,
'talkgroup': talkgroup,
'repeatersOnly': repeatersOnly,
};
}
}

129
lib/models/device.dart Normal file
View File

@@ -0,0 +1,129 @@
class Device {
final int id;
final String? callsign;
final String? name;
final String? city;
final String? state;
final String? country;
final String? surname;
final String? linkname;
final String? hardware;
final String? firmware;
final String? tx;
final String? rx;
final int? colorcode;
final int? status;
final int? lastKnownMaster;
final double? lat;
final double? lng;
final String? website;
final int? pep;
final int? agl;
final String? description;
final String? createdAt;
final String? updatedAt;
final String? lastSeen;
final List<String>? permissions;
Device({
required this.id,
this.callsign,
this.name,
this.city,
this.state,
this.country,
this.surname,
this.linkname,
this.hardware,
this.firmware,
this.tx,
this.rx,
this.colorcode,
this.status,
this.lastKnownMaster,
this.lat,
this.lng,
this.website,
this.pep,
this.agl,
this.description,
this.createdAt,
this.updatedAt,
this.lastSeen,
this.permissions,
});
factory Device.fromJson(Map<String, dynamic> json) {
return Device(
id: json['id'] as int,
callsign: json['callsign'] as String?,
name: json['name'] as String?,
city: json['city'] as String?,
state: json['state'] as String?,
country: json['country'] as String?,
surname: json['surname'] as String?,
linkname: json['linkname'] as String?,
hardware: json['hardware'] as String?,
firmware: json['firmware'] as String?,
tx: json['tx'] as String?,
rx: json['rx'] as String?,
colorcode: json['colorcode'] as int?,
status: json['status'] as int?,
lastKnownMaster: json['last_known_master'] as int?,
lat: json['lat'] as double?,
lng: json['lng'] as double?,
website: json['website'] as String?,
pep: json['pep'] as int?,
agl: json['agl'] as int?,
description: json['description'] as String?,
createdAt: json['created_at'] as String?,
updatedAt: json['updated_at'] as String?,
lastSeen: json['last_seen'] as String?,
permissions: (json['permissions'] as List<dynamic>?)
?.map((e) => e as String)
.toList(),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'callsign': callsign,
'name': name,
'city': city,
'state': state,
'country': country,
'surname': surname,
'linkname': linkname,
'hardware': hardware,
'firmware': firmware,
'tx': tx,
'rx': rx,
'colorcode': colorcode,
'status': status,
'last_known_master': lastKnownMaster,
'lat': lat,
'lng': lng,
'website': website,
'pep': pep,
'agl': agl,
'description': description,
'created_at': createdAt,
'updated_at': updatedAt,
'last_seen': lastSeen,
'permissions': permissions,
};
}
String get displayLocation {
final parts = <String>[];
if (city != null && city!.isNotEmpty) parts.add(city!);
if (state != null && state!.isNotEmpty) parts.add(state!);
if (country != null && country!.isNotEmpty) parts.add(country!);
return parts.isEmpty ? 'Unknown Location' : parts.join(', ');
}
String get displayName {
return name ?? callsign ?? 'Unknown Device';
}
}

View File

@@ -0,0 +1,54 @@
import 'static_talkgroup.dart';
import 'cluster.dart';
class DeviceProfile {
final List<StaticTalkgroup> blockedGroups;
final List<StaticTalkgroup> staticSubscriptions;
final List<StaticTalkgroup> dynamicSubscriptions;
final List<StaticTalkgroup> timedSubscriptions;
final List<Cluster> clusters;
DeviceProfile({
this.blockedGroups = const [],
this.staticSubscriptions = const [],
this.dynamicSubscriptions = const [],
this.timedSubscriptions = const [],
this.clusters = const [],
});
factory DeviceProfile.fromJson(Map<String, dynamic> json) {
return DeviceProfile(
blockedGroups: (json['blockedGroups'] as List<dynamic>?)
?.map((e) => StaticTalkgroup.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
staticSubscriptions: (json['staticSubscriptions'] as List<dynamic>?)
?.map((e) => StaticTalkgroup.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
dynamicSubscriptions: (json['dynamicSubscriptions'] as List<dynamic>?)
?.map((e) => StaticTalkgroup.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
timedSubscriptions: (json['timedSubscriptions'] as List<dynamic>?)
?.map((e) => StaticTalkgroup.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
clusters: (json['clusters'] as List<dynamic>?)
?.map((e) => Cluster.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
);
}
Map<String, dynamic> toJson() {
return {
'blockedGroups': blockedGroups.map((e) => e.toJson()).toList(),
'staticSubscriptions': staticSubscriptions.map((e) => e.toJson()).toList(),
'dynamicSubscriptions':
dynamicSubscriptions.map((e) => e.toJson()).toList(),
'timedSubscriptions': timedSubscriptions.map((e) => e.toJson()).toList(),
'clusters': clusters.map((e) => e.toJson()).toList(),
};
}
}

View File

@@ -0,0 +1,35 @@
class StaticTalkgroup {
final String? talkgroup;
final String? repeaterId;
final String? slot;
StaticTalkgroup({
this.talkgroup,
this.repeaterId,
this.slot,
});
factory StaticTalkgroup.fromJson(Map<String, dynamic> json) {
return StaticTalkgroup(
talkgroup: json['talkgroup']?.toString(),
repeaterId: json['repeaterId']?.toString(),
slot: json['slot']?.toString(),
);
}
Map<String, dynamic> toJson() {
return {
'talkgroup': talkgroup,
'repeaterId': repeaterId,
'slot': slot,
};
}
String get displaySlot {
return slot != null ? 'TS$slot' : 'TS?';
}
String get displayId {
return talkgroup ?? 'Unknown';
}
}

37
lib/models/user_info.dart Normal file
View File

@@ -0,0 +1,37 @@
class UserInfo {
final int id;
final String? name;
final String? username;
UserInfo({
required this.id,
this.name,
this.username,
});
factory UserInfo.fromJson(Map<String, dynamic> json) {
return UserInfo(
id: json['id'] as int,
name: json['name'] as String?,
username: json['username'] as String?,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'username': username,
};
}
String get displayName {
if (username != null && username!.isNotEmpty) {
if (name != null && name!.isNotEmpty) {
return '$username ($name)';
}
return username!;
}
return name ?? 'User $id';
}
}