fix BT connection issues

This commit is contained in:
Jonas Bark
2025-10-08 13:08:40 +02:00
parent 7a8c7c963b
commit e008dea61e
2 changed files with 130 additions and 133 deletions

View File

@@ -32,7 +32,7 @@ class _ChangelogPageState extends State<MarkdownPage> {
// load latest version
final response = await http.get(
Uri.parse('https://raw.githubusercontent.com/jonasbark/swiftcontrol/refs/heads/ios/${widget.assetPath}'),
Uri.parse('https://raw.githubusercontent.com/jonasbark/swiftcontrol/refs/heads/main/${widget.assetPath}'),
);
if (response.statusCode == 200) {
final latestMd = response.body;

View File

@@ -12,7 +12,7 @@ import '../../pages/markdown.dart';
final peripheralManager = PeripheralManager();
bool _isAdvertising = false;
bool _isSubscribedToEvents = false;
bool _isServiceAdded = false;
class RemoteRequirement extends PlatformRequirement {
RemoteRequirement() : super('Connect to your other device');
@@ -35,6 +35,10 @@ class RemoteRequirement extends PlatformRequirement {
],
);
peripheralManager.stateChanged.forEach((state) {
print('Peripheral manager state: ${state.state}');
});
if (!kIsWeb && Platform.isAndroid) {
if (Platform.isAndroid) {
peripheralManager.connectionStateChanged.forEach((state) {
@@ -48,9 +52,6 @@ class RemoteRequirement extends PlatformRequirement {
onUpdate();
}
});
peripheralManager.stateChanged.forEach((state) {
print('Peripheral manager state: ${state.state}');
});
}
final status = await Permission.bluetoothAdvertise.request();
@@ -59,128 +60,122 @@ class RemoteRequirement extends PlatformRequirement {
_isAdvertising = false;
onUpdate();
return;
} else {
while (peripheralManager.state != BluetoothLowEnergyState.poweredOn) {
print('Waiting for peripheral manager to be powered on...');
await Future.delayed(Duration(seconds: 1));
}
}
}
if (_isSubscribedToEvents) {
//await peripheralManager.removeAllServices();
while (peripheralManager.state != BluetoothLowEnergyState.poweredOn) {
print('Waiting for peripheral manager to be powered on...');
await Future.delayed(Duration(seconds: 1));
}
final reportMapDataAbsolute = Uint8List.fromList([
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Min (1)
0x29, 0x03, // Usage Max (3)
0x15, 0x00, // Logical Min (0)
0x25, 0x01, // Logical Max (1)
0x95, 0x03, // Report Count (3)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs) // buttons
0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5)
0x81, 0x03, // Input (Const,Var,Abs) // padding
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Min (0)
0x25, 0x64, // Logical Max (100)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs)
0xC0,
0xC0,
]);
if (!_isServiceAdded) {
final reportMapDataAbsolute = Uint8List.fromList([
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x85, 0x01, // Report ID (1)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Min (1)
0x29, 0x03, // Usage Max (3)
0x15, 0x00, // Logical Min (0)
0x25, 0x01, // Logical Max (1)
0x95, 0x03, // Report Count (3)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs) // buttons
0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5)
0x81, 0x03, // Input (Const,Var,Abs) // padding
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Min (0)
0x25, 0x64, // Logical Max (100)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs)
0xC0,
0xC0,
]);
// 1) Build characteristics
final hidInfo = GATTCharacteristic.immutable(
uuid: UUID.fromString('2A4A'),
value: Uint8List.fromList([0x11, 0x01, 0x00, 0x02]),
descriptors: [], // HID v1.11, country=0, flags=2
);
// 1) Build characteristics
final hidInfo = GATTCharacteristic.immutable(
uuid: UUID.fromString('2A4A'),
value: Uint8List.fromList([0x11, 0x01, 0x00, 0x02]),
descriptors: [], // HID v1.11, country=0, flags=2
);
final reportMap = GATTCharacteristic.immutable(
uuid: UUID.fromString('2A4B'),
//properties: [GATTCharacteristicProperty.read],
//permissions: [GATTCharacteristicPermission.read],
value: reportMapDataAbsolute,
descriptors: [
GATTDescriptor.immutable(uuid: UUID.fromString('2908'), value: Uint8List.fromList([0x0, 0x0])),
],
);
final reportMap = GATTCharacteristic.immutable(
uuid: UUID.fromString('2A4B'),
//properties: [GATTCharacteristicProperty.read],
//permissions: [GATTCharacteristicPermission.read],
value: reportMapDataAbsolute,
descriptors: [
GATTDescriptor.immutable(uuid: UUID.fromString('2908'), value: Uint8List.fromList([0x0, 0x0])),
],
);
final protocolMode = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4E'),
properties: [GATTCharacteristicProperty.read, GATTCharacteristicProperty.writeWithoutResponse],
permissions: [GATTCharacteristicPermission.read, GATTCharacteristicPermission.write],
descriptors: [],
);
final protocolMode = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4E'),
properties: [GATTCharacteristicProperty.read, GATTCharacteristicProperty.writeWithoutResponse],
permissions: [GATTCharacteristicPermission.read, GATTCharacteristicPermission.write],
descriptors: [],
);
final hidControlPoint = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4C'),
properties: [GATTCharacteristicProperty.writeWithoutResponse],
permissions: [GATTCharacteristicPermission.write],
descriptors: [],
);
final hidControlPoint = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4C'),
properties: [GATTCharacteristicProperty.writeWithoutResponse],
permissions: [GATTCharacteristicPermission.write],
descriptors: [],
);
// Input report characteristic (notify)
final keyboardInputReport = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4D'),
permissions: [GATTCharacteristicPermission.read],
properties: [GATTCharacteristicProperty.notify, GATTCharacteristicProperty.read],
descriptors: [
GATTDescriptor.immutable(
// Report Reference: ID=1, Type=Input(1)
uuid: UUID.fromString('2908'),
value: Uint8List.fromList([0x02, 0x01]),
),
],
);
// Input report characteristic (notify)
final keyboardInputReport = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4D'),
permissions: [GATTCharacteristicPermission.read],
properties: [GATTCharacteristicProperty.notify, GATTCharacteristicProperty.read],
descriptors: [
GATTDescriptor.immutable(
// Report Reference: ID=1, Type=Input(1)
uuid: UUID.fromString('2908'),
value: Uint8List.fromList([0x02, 0x01]),
),
],
);
final outputReport = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4D'),
permissions: [GATTCharacteristicPermission.read, GATTCharacteristicPermission.write],
properties: [
GATTCharacteristicProperty.read,
GATTCharacteristicProperty.write,
GATTCharacteristicProperty.writeWithoutResponse,
],
descriptors: [
GATTDescriptor.immutable(
// Report Reference: ID=1, Type=Input(1)
uuid: UUID.fromString('2908'),
value: Uint8List.fromList([0x02, 0x02]),
),
],
);
final outputReport = GATTCharacteristic.mutable(
uuid: UUID.fromString('2A4D'),
permissions: [GATTCharacteristicPermission.read, GATTCharacteristicPermission.write],
properties: [
GATTCharacteristicProperty.read,
GATTCharacteristicProperty.write,
GATTCharacteristicProperty.writeWithoutResponse,
],
descriptors: [
GATTDescriptor.immutable(
// Report Reference: ID=1, Type=Input(1)
uuid: UUID.fromString('2908'),
value: Uint8List.fromList([0x02, 0x02]),
),
],
);
// 2) HID service
final hidService = GATTService(
uuid: UUID.fromString('00001812-0000-1000-8000-00805F9B34FB'),
isPrimary: true,
characteristics: [
hidInfo,
reportMap,
protocolMode,
outputReport,
hidControlPoint,
keyboardInputReport,
inputReport,
],
includedServices: [],
);
// 2) HID service
final hidService = GATTService(
uuid: UUID.fromString(Platform.isIOS ? '1812' : '00001812-0000-1000-8000-00805F9B34FB'),
isPrimary: true,
characteristics: [
hidInfo,
reportMap,
protocolMode,
outputReport,
hidControlPoint,
keyboardInputReport,
inputReport,
],
includedServices: [],
);
if (!_isSubscribedToEvents) {
_isSubscribedToEvents = true;
peripheralManager.characteristicReadRequested.forEach((char) {
print('Read request for characteristic: ${char}');
// You can respond to read requests here if needed
@@ -199,24 +194,26 @@ class RemoteRequirement extends PlatformRequirement {
'Notify state changed for characteristic: ${char.characteristic.uuid} vs ${char.characteristic.uuid == inputReport.uuid}: ${char.state}',
);
});
}
await peripheralManager.addService(hidService);
await peripheralManager.addService(hidService);
// 3) Optional Battery service
await peripheralManager.addService(
GATTService(
uuid: UUID.fromString('180F'),
isPrimary: true,
characteristics: [
GATTCharacteristic.immutable(
uuid: UUID.fromString('2A19'),
value: Uint8List.fromList([100]),
descriptors: [],
),
],
includedServices: [],
),
);
// 3) Optional Battery service
await peripheralManager.addService(
GATTService(
uuid: UUID.fromString('180F'),
isPrimary: true,
characteristics: [
GATTCharacteristic.immutable(
uuid: UUID.fromString('2A19'),
value: Uint8List.fromList([100]),
descriptors: [],
),
],
includedServices: [],
),
);
print('Added services');
_isServiceAdded = true;
}
final advertisement = Advertisement(
name:
@@ -225,7 +222,7 @@ class RemoteRequirement extends PlatformRequirement {
: Platform.isAndroid
? 'Android'
: ''}',
serviceUUIDs: [UUID.fromString('00001812-0000-1000-8000-00805F9B34FB')],
serviceUUIDs: [UUID.fromString(Platform.isIOS ? '1812' : '00001812-0000-1000-8000-00805F9B34FB')],
);
/*pm.connectionStateChanged.forEach((state) {
print('Peripheral connection state: $state');