mirror of
https://github.com/jonasbark/swiftcontrol.git
synced 2026-02-18 00:17:40 +01:00
fix BT connection issues
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user