WIFI connection support added

This commit is contained in:
Constantin Leue
2026-07-31 08:17:12 +02:00
parent b28b1a89bb
commit 8cc9a51a34
11 changed files with 1436 additions and 115 deletions
+29 -1
View File
@@ -5,6 +5,8 @@ import 'package:drift/native.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import '../../transport/connection_type.dart';
part 'app_database.g.dart';
/// Persistenz fuer Missionen (Architektur-Doku 4.15): Drift statt Hive, weil
@@ -61,6 +63,21 @@ class AppSettingsTable extends Table {
BoolColumn get connectionAutoConnect =>
boolean().withDefault(const Constant(true))();
/// Gewaehlte Verbindungsart (Doku 7: "Art: WLAN * USB (spaeter)"),
/// gespeichert als [ConnectionType.name]. Standard bleibt Bluetooth, damit
/// bestehende Installationen ihr bisheriges Verhalten behalten.
TextColumn get connectionType =>
text().withDefault(const Constant('bluetooth'))();
/// Vom Nutzer eingetragene Ziel-IP der mLRS-WLAN-Bruecke (Doku 3:
/// "Zieladresse niemals fest eincodieren") - null, solange keine Vorgabe
/// gesetzt ist und die Gegenstelle erst aus dem Verkehr gelernt wird.
TextColumn get connectionWifiHost => text().nullable()();
/// Lokaler UDP-Port fuer die mLRS-WLAN-Bruecke (Doku 3), Standard 14550.
IntColumn get connectionWifiPort =>
integer().withDefault(const Constant(kDefaultWifiPort))();
@override
Set<Column> get primaryKey => {id};
}
@@ -72,7 +89,7 @@ class AppDatabase extends _$AppDatabase {
AppDatabase.forTesting(super.executor);
@override
int get schemaVersion => 3;
int get schemaVersion => 4;
@override
MigrationStrategy get migration => MigrationStrategy(
@@ -93,6 +110,17 @@ class AppDatabase extends _$AppDatabase {
appSettingsTable.connectionAutoConnect,
);
}
if (from < 4) {
await m.addColumn(appSettingsTable, appSettingsTable.connectionType);
await m.addColumn(
appSettingsTable,
appSettingsTable.connectionWifiHost,
);
await m.addColumn(
appSettingsTable,
appSettingsTable.connectionWifiPort,
);
}
},
);
+237 -3
View File
@@ -1348,6 +1348,40 @@ class $AppSettingsTableTable extends AppSettingsTable
),
defaultValue: const Constant(true),
);
static const VerificationMeta _connectionTypeMeta = const VerificationMeta(
'connectionType',
);
@override
late final GeneratedColumn<String> connectionType = GeneratedColumn<String>(
'connection_type',
aliasedName,
false,
type: DriftSqlType.string,
requiredDuringInsert: false,
defaultValue: const Constant('bluetooth'),
);
static const VerificationMeta _connectionWifiHostMeta =
const VerificationMeta('connectionWifiHost');
@override
late final GeneratedColumn<String> connectionWifiHost =
GeneratedColumn<String>(
'connection_wifi_host',
aliasedName,
true,
type: DriftSqlType.string,
requiredDuringInsert: false,
);
static const VerificationMeta _connectionWifiPortMeta =
const VerificationMeta('connectionWifiPort');
@override
late final GeneratedColumn<int> connectionWifiPort = GeneratedColumn<int>(
'connection_wifi_port',
aliasedName,
false,
type: DriftSqlType.int,
requiredDuringInsert: false,
defaultValue: const Constant(kDefaultWifiPort),
);
@override
List<GeneratedColumn> get $columns => [
id,
@@ -1355,6 +1389,9 @@ class $AppSettingsTableTable extends AppSettingsTable
currentMissionId,
connectionDeviceAddress,
connectionAutoConnect,
connectionType,
connectionWifiHost,
connectionWifiPort,
];
@override
String get aliasedName => _alias ?? actualTableName;
@@ -1407,6 +1444,33 @@ class $AppSettingsTableTable extends AppSettingsTable
),
);
}
if (data.containsKey('connection_type')) {
context.handle(
_connectionTypeMeta,
connectionType.isAcceptableOrUnknown(
data['connection_type']!,
_connectionTypeMeta,
),
);
}
if (data.containsKey('connection_wifi_host')) {
context.handle(
_connectionWifiHostMeta,
connectionWifiHost.isAcceptableOrUnknown(
data['connection_wifi_host']!,
_connectionWifiHostMeta,
),
);
}
if (data.containsKey('connection_wifi_port')) {
context.handle(
_connectionWifiPortMeta,
connectionWifiPort.isAcceptableOrUnknown(
data['connection_wifi_port']!,
_connectionWifiPortMeta,
),
);
}
return context;
}
@@ -1436,6 +1500,18 @@ class $AppSettingsTableTable extends AppSettingsTable
DriftSqlType.bool,
data['${effectivePrefix}connection_auto_connect'],
)!,
connectionType: attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}connection_type'],
)!,
connectionWifiHost: attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}connection_wifi_host'],
),
connectionWifiPort: attachedDatabase.typeMapping.read(
DriftSqlType.int,
data['${effectivePrefix}connection_wifi_port'],
)!,
);
}
@@ -1458,12 +1534,28 @@ class AppSettingsTableData extends DataClass
/// "Beim Wechsel in Fly automatisch verbinden" (Doku 7), Standard an.
final bool connectionAutoConnect;
/// Gewaehlte Verbindungsart (Doku 7: "Art: WLAN * USB (spaeter)"),
/// gespeichert als [ConnectionType.name]. Standard bleibt Bluetooth, damit
/// bestehende Installationen ihr bisheriges Verhalten behalten.
final String connectionType;
/// Vom Nutzer eingetragene Ziel-IP der mLRS-WLAN-Bruecke (Doku 3:
/// "Zieladresse niemals fest eincodieren") - null, solange keine Vorgabe
/// gesetzt ist und die Gegenstelle erst aus dem Verkehr gelernt wird.
final String? connectionWifiHost;
/// Lokaler UDP-Port fuer die mLRS-WLAN-Bruecke (Doku 3), Standard 14550.
final int connectionWifiPort;
const AppSettingsTableData({
required this.id,
this.activeDroneProfileId,
this.currentMissionId,
this.connectionDeviceAddress,
required this.connectionAutoConnect,
required this.connectionType,
this.connectionWifiHost,
required this.connectionWifiPort,
});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
@@ -1481,6 +1573,11 @@ class AppSettingsTableData extends DataClass
);
}
map['connection_auto_connect'] = Variable<bool>(connectionAutoConnect);
map['connection_type'] = Variable<String>(connectionType);
if (!nullToAbsent || connectionWifiHost != null) {
map['connection_wifi_host'] = Variable<String>(connectionWifiHost);
}
map['connection_wifi_port'] = Variable<int>(connectionWifiPort);
return map;
}
@@ -1497,6 +1594,11 @@ class AppSettingsTableData extends DataClass
? const Value.absent()
: Value(connectionDeviceAddress),
connectionAutoConnect: Value(connectionAutoConnect),
connectionType: Value(connectionType),
connectionWifiHost: connectionWifiHost == null && nullToAbsent
? const Value.absent()
: Value(connectionWifiHost),
connectionWifiPort: Value(connectionWifiPort),
);
}
@@ -1517,6 +1619,11 @@ class AppSettingsTableData extends DataClass
connectionAutoConnect: serializer.fromJson<bool>(
json['connectionAutoConnect'],
),
connectionType: serializer.fromJson<String>(json['connectionType']),
connectionWifiHost: serializer.fromJson<String?>(
json['connectionWifiHost'],
),
connectionWifiPort: serializer.fromJson<int>(json['connectionWifiPort']),
);
}
@override
@@ -1530,6 +1637,9 @@ class AppSettingsTableData extends DataClass
connectionDeviceAddress,
),
'connectionAutoConnect': serializer.toJson<bool>(connectionAutoConnect),
'connectionType': serializer.toJson<String>(connectionType),
'connectionWifiHost': serializer.toJson<String?>(connectionWifiHost),
'connectionWifiPort': serializer.toJson<int>(connectionWifiPort),
};
}
@@ -1539,6 +1649,9 @@ class AppSettingsTableData extends DataClass
Value<int?> currentMissionId = const Value.absent(),
Value<String?> connectionDeviceAddress = const Value.absent(),
bool? connectionAutoConnect,
String? connectionType,
Value<String?> connectionWifiHost = const Value.absent(),
int? connectionWifiPort,
}) => AppSettingsTableData(
id: id ?? this.id,
activeDroneProfileId: activeDroneProfileId.present
@@ -1551,6 +1664,11 @@ class AppSettingsTableData extends DataClass
? connectionDeviceAddress.value
: this.connectionDeviceAddress,
connectionAutoConnect: connectionAutoConnect ?? this.connectionAutoConnect,
connectionType: connectionType ?? this.connectionType,
connectionWifiHost: connectionWifiHost.present
? connectionWifiHost.value
: this.connectionWifiHost,
connectionWifiPort: connectionWifiPort ?? this.connectionWifiPort,
);
AppSettingsTableData copyWithCompanion(AppSettingsTableCompanion data) {
return AppSettingsTableData(
@@ -1567,6 +1685,15 @@ class AppSettingsTableData extends DataClass
connectionAutoConnect: data.connectionAutoConnect.present
? data.connectionAutoConnect.value
: this.connectionAutoConnect,
connectionType: data.connectionType.present
? data.connectionType.value
: this.connectionType,
connectionWifiHost: data.connectionWifiHost.present
? data.connectionWifiHost.value
: this.connectionWifiHost,
connectionWifiPort: data.connectionWifiPort.present
? data.connectionWifiPort.value
: this.connectionWifiPort,
);
}
@@ -1577,7 +1704,10 @@ class AppSettingsTableData extends DataClass
..write('activeDroneProfileId: $activeDroneProfileId, ')
..write('currentMissionId: $currentMissionId, ')
..write('connectionDeviceAddress: $connectionDeviceAddress, ')
..write('connectionAutoConnect: $connectionAutoConnect')
..write('connectionAutoConnect: $connectionAutoConnect, ')
..write('connectionType: $connectionType, ')
..write('connectionWifiHost: $connectionWifiHost, ')
..write('connectionWifiPort: $connectionWifiPort')
..write(')'))
.toString();
}
@@ -1589,6 +1719,9 @@ class AppSettingsTableData extends DataClass
currentMissionId,
connectionDeviceAddress,
connectionAutoConnect,
connectionType,
connectionWifiHost,
connectionWifiPort,
);
@override
bool operator ==(Object other) =>
@@ -1598,7 +1731,10 @@ class AppSettingsTableData extends DataClass
other.activeDroneProfileId == this.activeDroneProfileId &&
other.currentMissionId == this.currentMissionId &&
other.connectionDeviceAddress == this.connectionDeviceAddress &&
other.connectionAutoConnect == this.connectionAutoConnect);
other.connectionAutoConnect == this.connectionAutoConnect &&
other.connectionType == this.connectionType &&
other.connectionWifiHost == this.connectionWifiHost &&
other.connectionWifiPort == this.connectionWifiPort);
}
class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
@@ -1607,12 +1743,18 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
final Value<int?> currentMissionId;
final Value<String?> connectionDeviceAddress;
final Value<bool> connectionAutoConnect;
final Value<String> connectionType;
final Value<String?> connectionWifiHost;
final Value<int> connectionWifiPort;
const AppSettingsTableCompanion({
this.id = const Value.absent(),
this.activeDroneProfileId = const Value.absent(),
this.currentMissionId = const Value.absent(),
this.connectionDeviceAddress = const Value.absent(),
this.connectionAutoConnect = const Value.absent(),
this.connectionType = const Value.absent(),
this.connectionWifiHost = const Value.absent(),
this.connectionWifiPort = const Value.absent(),
});
AppSettingsTableCompanion.insert({
this.id = const Value.absent(),
@@ -1620,6 +1762,9 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
this.currentMissionId = const Value.absent(),
this.connectionDeviceAddress = const Value.absent(),
this.connectionAutoConnect = const Value.absent(),
this.connectionType = const Value.absent(),
this.connectionWifiHost = const Value.absent(),
this.connectionWifiPort = const Value.absent(),
});
static Insertable<AppSettingsTableData> custom({
Expression<int>? id,
@@ -1627,6 +1772,9 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
Expression<int>? currentMissionId,
Expression<String>? connectionDeviceAddress,
Expression<bool>? connectionAutoConnect,
Expression<String>? connectionType,
Expression<String>? connectionWifiHost,
Expression<int>? connectionWifiPort,
}) {
return RawValuesInsertable({
if (id != null) 'id': id,
@@ -1637,6 +1785,11 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
'connection_device_address': connectionDeviceAddress,
if (connectionAutoConnect != null)
'connection_auto_connect': connectionAutoConnect,
if (connectionType != null) 'connection_type': connectionType,
if (connectionWifiHost != null)
'connection_wifi_host': connectionWifiHost,
if (connectionWifiPort != null)
'connection_wifi_port': connectionWifiPort,
});
}
@@ -1646,6 +1799,9 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
Value<int?>? currentMissionId,
Value<String?>? connectionDeviceAddress,
Value<bool>? connectionAutoConnect,
Value<String>? connectionType,
Value<String?>? connectionWifiHost,
Value<int>? connectionWifiPort,
}) {
return AppSettingsTableCompanion(
id: id ?? this.id,
@@ -1655,6 +1811,9 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
connectionDeviceAddress ?? this.connectionDeviceAddress,
connectionAutoConnect:
connectionAutoConnect ?? this.connectionAutoConnect,
connectionType: connectionType ?? this.connectionType,
connectionWifiHost: connectionWifiHost ?? this.connectionWifiHost,
connectionWifiPort: connectionWifiPort ?? this.connectionWifiPort,
);
}
@@ -1682,6 +1841,15 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
connectionAutoConnect.value,
);
}
if (connectionType.present) {
map['connection_type'] = Variable<String>(connectionType.value);
}
if (connectionWifiHost.present) {
map['connection_wifi_host'] = Variable<String>(connectionWifiHost.value);
}
if (connectionWifiPort.present) {
map['connection_wifi_port'] = Variable<int>(connectionWifiPort.value);
}
return map;
}
@@ -1692,7 +1860,10 @@ class AppSettingsTableCompanion extends UpdateCompanion<AppSettingsTableData> {
..write('activeDroneProfileId: $activeDroneProfileId, ')
..write('currentMissionId: $currentMissionId, ')
..write('connectionDeviceAddress: $connectionDeviceAddress, ')
..write('connectionAutoConnect: $connectionAutoConnect')
..write('connectionAutoConnect: $connectionAutoConnect, ')
..write('connectionType: $connectionType, ')
..write('connectionWifiHost: $connectionWifiHost, ')
..write('connectionWifiPort: $connectionWifiPort')
..write(')'))
.toString();
}
@@ -2333,6 +2504,9 @@ typedef $$AppSettingsTableTableCreateCompanionBuilder =
Value<int?> currentMissionId,
Value<String?> connectionDeviceAddress,
Value<bool> connectionAutoConnect,
Value<String> connectionType,
Value<String?> connectionWifiHost,
Value<int> connectionWifiPort,
});
typedef $$AppSettingsTableTableUpdateCompanionBuilder =
AppSettingsTableCompanion Function({
@@ -2341,6 +2515,9 @@ typedef $$AppSettingsTableTableUpdateCompanionBuilder =
Value<int?> currentMissionId,
Value<String?> connectionDeviceAddress,
Value<bool> connectionAutoConnect,
Value<String> connectionType,
Value<String?> connectionWifiHost,
Value<int> connectionWifiPort,
});
class $$AppSettingsTableTableFilterComposer
@@ -2376,6 +2553,21 @@ class $$AppSettingsTableTableFilterComposer
column: $table.connectionAutoConnect,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get connectionType => $composableBuilder(
column: $table.connectionType,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get connectionWifiHost => $composableBuilder(
column: $table.connectionWifiHost,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<int> get connectionWifiPort => $composableBuilder(
column: $table.connectionWifiPort,
builder: (column) => ColumnFilters(column),
);
}
class $$AppSettingsTableTableOrderingComposer
@@ -2411,6 +2603,21 @@ class $$AppSettingsTableTableOrderingComposer
column: $table.connectionAutoConnect,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get connectionType => $composableBuilder(
column: $table.connectionType,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get connectionWifiHost => $composableBuilder(
column: $table.connectionWifiHost,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<int> get connectionWifiPort => $composableBuilder(
column: $table.connectionWifiPort,
builder: (column) => ColumnOrderings(column),
);
}
class $$AppSettingsTableTableAnnotationComposer
@@ -2444,6 +2651,21 @@ class $$AppSettingsTableTableAnnotationComposer
column: $table.connectionAutoConnect,
builder: (column) => column,
);
GeneratedColumn<String> get connectionType => $composableBuilder(
column: $table.connectionType,
builder: (column) => column,
);
GeneratedColumn<String> get connectionWifiHost => $composableBuilder(
column: $table.connectionWifiHost,
builder: (column) => column,
);
GeneratedColumn<int> get connectionWifiPort => $composableBuilder(
column: $table.connectionWifiPort,
builder: (column) => column,
);
}
class $$AppSettingsTableTableTableManager
@@ -2488,12 +2710,18 @@ class $$AppSettingsTableTableTableManager
Value<int?> currentMissionId = const Value.absent(),
Value<String?> connectionDeviceAddress = const Value.absent(),
Value<bool> connectionAutoConnect = const Value.absent(),
Value<String> connectionType = const Value.absent(),
Value<String?> connectionWifiHost = const Value.absent(),
Value<int> connectionWifiPort = const Value.absent(),
}) => AppSettingsTableCompanion(
id: id,
activeDroneProfileId: activeDroneProfileId,
currentMissionId: currentMissionId,
connectionDeviceAddress: connectionDeviceAddress,
connectionAutoConnect: connectionAutoConnect,
connectionType: connectionType,
connectionWifiHost: connectionWifiHost,
connectionWifiPort: connectionWifiPort,
),
createCompanionCallback:
({
@@ -2502,12 +2730,18 @@ class $$AppSettingsTableTableTableManager
Value<int?> currentMissionId = const Value.absent(),
Value<String?> connectionDeviceAddress = const Value.absent(),
Value<bool> connectionAutoConnect = const Value.absent(),
Value<String> connectionType = const Value.absent(),
Value<String?> connectionWifiHost = const Value.absent(),
Value<int> connectionWifiPort = const Value.absent(),
}) => AppSettingsTableCompanion.insert(
id: id,
activeDroneProfileId: activeDroneProfileId,
currentMissionId: currentMissionId,
connectionDeviceAddress: connectionDeviceAddress,
connectionAutoConnect: connectionAutoConnect,
connectionType: connectionType,
connectionWifiHost: connectionWifiHost,
connectionWifiPort: connectionWifiPort,
),
withReferenceMapper: (p0) => p0
.map((e) => (e.readTable(table), BaseReferences(db, table, e)))
@@ -1,5 +1,6 @@
import 'package:drift/drift.dart';
import '../../transport/connection_type.dart';
import 'app_database.dart';
/// Zugriff auf die Einzeilen-Einstellungstabelle (Doku 7.5): welches
@@ -18,6 +19,9 @@ class AppSettingsRepository {
int? currentMissionId,
String? connectionDeviceAddress,
bool connectionAutoConnect,
ConnectionType connectionType,
String? connectionWifiHost,
int connectionWifiPort,
})> load() async {
final row = await (_db.select(_db.appSettingsTable)
..where((s) => s.id.equals(_rowId)))
@@ -27,6 +31,12 @@ class AppSettingsRepository {
currentMissionId: row?.currentMissionId,
connectionDeviceAddress: row?.connectionDeviceAddress,
connectionAutoConnect: row?.connectionAutoConnect ?? true,
connectionType: ConnectionType.values.firstWhere(
(t) => t.name == row?.connectionType,
orElse: () => ConnectionType.bluetooth,
),
connectionWifiHost: row?.connectionWifiHost,
connectionWifiPort: row?.connectionWifiPort ?? kDefaultWifiPort,
);
}
@@ -64,6 +74,36 @@ class AppSettingsRepository {
));
}
/// Gewaehlte Verbindungsart (Doku Kommunikationsschicht 7).
Future<void> setConnectionType(ConnectionType type) async {
await _upsert(AppSettingsTableCompanion(
id: const Value(_rowId),
connectionType: Value(type.name),
));
}
/// Vom Nutzer eingetragene Ziel-IP der WLAN-Bruecke (Doku 3), oder null um
/// die Vorgabe zu loeschen und nur noch aus dem Verkehr zu lernen.
Future<String?> loadConnectionWifiHost() async =>
(await load()).connectionWifiHost;
Future<void> setConnectionWifiHost(String? host) async {
await _upsert(AppSettingsTableCompanion(
id: const Value(_rowId),
connectionWifiHost: Value(host),
));
}
Future<int> loadConnectionWifiPort() async =>
(await load()).connectionWifiPort;
Future<void> setConnectionWifiPort(int port) async {
await _upsert(AppSettingsTableCompanion(
id: const Value(_rowId),
connectionWifiPort: Value(port),
));
}
Future<void> _upsert(AppSettingsTableCompanion companion) async {
await _db.into(_db.appSettingsTable).insertOnConflictUpdate(companion);
}