Fixed BLE Scan activation after Disconect
All checks were successful
Deploy Docs / build-and-deploy (push) Successful in 23s

This commit is contained in:
2026-01-12 16:18:42 +01:00
parent 395d577b78
commit 65688b7b99
10 changed files with 119 additions and 114 deletions

View File

@@ -3,9 +3,9 @@
"appTitle": "Lasertag Mission Control",
"selectLeader": "Leader auswählen",
"searching": "Suche nach Knoten...",
"listTypeLeader": "Gameleadergeräte",
"listTypeLeader": "Game LEader",
"typeWeapon": "Waffe",
"typeVest": "Weste",
"typeBeacon": "Beacon",
"listTypeEquipment": "Ausrüstungsgeräte"
"listTypeEquipment": "Sonstiges"
}

View File

@@ -115,7 +115,7 @@ abstract class AppLocalizations {
/// No description provided for @listTypeLeader.
///
/// In de, this message translates to:
/// **'Gameleadergeräte'**
/// **'Game LEader'**
String get listTypeLeader;
/// No description provided for @typeWeapon.
@@ -139,7 +139,7 @@ abstract class AppLocalizations {
/// No description provided for @listTypeEquipment.
///
/// In de, this message translates to:
/// **'Ausrüstungsgeräte'**
/// **'Sonstiges'**
String get listTypeEquipment;
}

View File

@@ -18,7 +18,7 @@ class AppLocalizationsDe extends AppLocalizations {
String get searching => 'Suche nach Knoten...';
@override
String get listTypeLeader => 'Gameleadergeräte';
String get listTypeLeader => 'Game LEader';
@override
String get typeWeapon => 'Waffe';
@@ -30,5 +30,5 @@ class AppLocalizationsDe extends AppLocalizations {
String get typeBeacon => 'Beacon';
@override
String get listTypeEquipment => 'Ausrüstungsgeräte';
String get listTypeEquipment => 'Sonstiges';
}

View File

@@ -1,14 +1,13 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; // Neu
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/material.dart';
import 'package:lasertag_app/l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'providers/device_provider.dart';
import 'ui/screens/device_selection_screen.dart';
import 'providers/device_provider.dart'; // Neu
void main() {
runApp(
// Den Provider hier für die ganze App bereitstellen
ChangeNotifierProvider(
create: (context) => DeviceProvider(),
child: const LasertagApp(),

View File

@@ -1,4 +1,5 @@
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import '../../constants.dart';
class LasertagDevice {

View File

@@ -1,9 +1,11 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'dart:convert';
import '../models/device_model.dart';
import '../constants.dart';
import '../models/device_model.dart';
class DeviceProvider extends ChangeNotifier {
final List<LasertagDevice> _discoveredLeaders = [];
@@ -13,69 +15,7 @@ class DeviceProvider extends ChangeNotifier {
List<LasertagDevice> get leaders => _discoveredLeaders;
List<LasertagDevice> get peripherals => _discoveredPeripherals;
// 1. HARDWARE LESEN
Future<String> readDeviceNameFromHardware(LasertagDevice ltDevice) async {
try {
if (!ltDevice.btDevice.isConnected) {
await ltDevice.btDevice.connect(
license: License.free,
timeout: const Duration(seconds: 5),
);
}
List<BluetoothService> services = await ltDevice.btDevice.discoverServices();
var service = services.firstWhere((s) => s.uuid == Guid(LasertagUUIDs.provService));
var characteristic = service.characteristics.firstWhere((c) => c.uuid == Guid(LasertagUUIDs.provNameChar));
List<int> value = await characteristic.read();
String hardwareName = utf8.decode(value);
// Den Namen lokal speichern und als verifiziert markieren (für das Styling)
updateDeviceName(ltDevice.id, hardwareName, verified: true);
return hardwareName;
} catch (e) {
debugPrint("Fehler beim Lesen der Hardware: $e");
rethrow;
}
}
// 2. HARDWARE SCHREIBEN
Future<void> updateDeviceNameOnHardware(LasertagDevice ltDevice, String newName) async {
try {
await ltDevice.btDevice.connect(
license: License.free,
autoConnect: false,
timeout: const Duration(seconds: 10),
);
await Future.delayed(const Duration(milliseconds: 500));
List<BluetoothService> services = await ltDevice.btDevice.discoverServices();
var service = services.firstWhere((s) => s.uuid == Guid(LasertagUUIDs.provService));
var characteristic = service.characteristics.firstWhere((c) => c.uuid == Guid(LasertagUUIDs.provNameChar));
await characteristic.write(utf8.encode(newName));
// Lokal aktualisieren und als verifiziert markieren
updateDeviceName(ltDevice.id, newName, verified: true);
await ltDevice.btDevice.disconnect();
} catch (e) {
debugPrint("Hardware-Fehler: $e");
rethrow;
}
}
// 3. LOKALE LISTE AKTUALISIEREN (Hilfsmethode konsolidiert)
void updateDeviceName(String id, String newName, {bool verified = false}) {
_updateDeviceInLists(
id,
(old) => old.copyWith(name: newName, isNameVerified: verified)
);
}
// 4. BLUETOOTH SCAN
// Öffentlicher API-Entry: Scan starten
void startScan() async {
_discoveredLeaders.clear();
_discoveredPeripherals.clear();
@@ -117,6 +57,63 @@ class DeviceProvider extends ChangeNotifier {
}
}
// Öffentlicher API-Entry: Namen von der Hardware lesen
Future<String> readDeviceNameFromHardware(LasertagDevice ltDevice) async {
try {
if (!ltDevice.btDevice.isConnected) {
await ltDevice.btDevice.connect(
license: License.free,
timeout: const Duration(seconds: 5),
);
}
List<BluetoothService> services = await ltDevice.btDevice.discoverServices();
var service = services.firstWhere((s) => s.uuid == Guid(LasertagUUIDs.provService));
var characteristic = service.characteristics.firstWhere((c) => c.uuid == Guid(LasertagUUIDs.provNameChar));
List<int> value = await characteristic.read();
String hardwareName = utf8.decode(value);
updateDeviceName(ltDevice.id, hardwareName, verified: true);
return hardwareName;
} catch (e) {
debugPrint("Fehler beim Lesen der Hardware: $e");
rethrow;
}
}
// Öffentlicher API-Entry: Namen auf Hardware schreiben
Future<void> updateDeviceNameOnHardware(LasertagDevice ltDevice, String newName) async {
try {
await ltDevice.btDevice.connect(
license: License.free,
autoConnect: false,
timeout: const Duration(seconds: 10),
);
await Future.delayed(const Duration(milliseconds: 500));
List<BluetoothService> services = await ltDevice.btDevice.discoverServices();
var service = services.firstWhere((s) => s.uuid == Guid(LasertagUUIDs.provService));
var characteristic = service.characteristics.firstWhere((c) => c.uuid == Guid(LasertagUUIDs.provNameChar));
await characteristic.write(utf8.encode(newName));
updateDeviceName(ltDevice.id, newName, verified: true);
await ltDevice.btDevice.disconnect();
} catch (e) {
debugPrint("Hardware-Fehler: $e");
rethrow;
}
}
// Öffentlicher API-Entry: Lokale Liste aktualisieren
void updateDeviceName(String id, String newName, {bool verified = false}) {
_updateDeviceInLists(id, (old) => old.copyWith(name: newName, isNameVerified: verified));
}
void _addDeviceToLists(LasertagDevice device) {
List<LasertagDevice> list = device.isLeader ? _discoveredLeaders : _discoveredPeripherals;

View File

@@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:lasertag_app/l10n/app_localizations.dart';
import '../../constants.dart';
import '../../models/device_model.dart';
import '../../providers/device_provider.dart';
import '../../constants.dart';
import '../widgets/rename_dialog.dart';
import 'package:lasertag_app/l10n/app_localizations.dart';
class DeviceSelectionScreen extends StatefulWidget {
const DeviceSelectionScreen({super.key});
@@ -84,12 +85,12 @@ class _DeviceSelectionScreenState extends State<DeviceSelectionScreen> {
device.name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontStyle: device.isNameVerified
? FontStyle.normal
: FontStyle.italic, // Kursiv, wenn nicht verifiziert
// fontStyle: device.isNameVerified
// ? FontStyle.normal
// : FontStyle.italic, // Kursiv, wenn nicht verifiziert
color: device.isNameVerified
? Theme.of(context).colorScheme.onSurface
: Theme.of(context).colorScheme.onSurface.withOpacity(0.7),
: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.7),
),
),
subtitle: Text("BTLE-ID: ${device.id}"),

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../models/device_model.dart';
import '../../providers/device_provider.dart';