Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Services and characteristics list #92

Merged
merged 13 commits into from
Feb 5, 2020
46 changes: 39 additions & 7 deletions example/lib/adapter/ble_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:async';
import 'package:blemulator_example/example_peripherals/generic_peripheral.dart';
import 'package:blemulator_example/model/ble_peripheral.dart';
import 'package:blemulator_example/example_peripherals/sensor_tag.dart';
import 'package:blemulator_example/model/ble_service.dart';
import 'package:flutter_ble_lib/flutter_ble_lib.dart';
import 'package:blemulator/blemulator.dart';

Expand Down Expand Up @@ -30,6 +31,8 @@ class BleAdapter {

Stream<BlePeripheral> get blePeripherals => _blePeripheralsController.stream;

Map<String, Peripheral> _scannedPeripherals = Map();

factory BleAdapter(BleManager bleManager, Blemulator blemulator) {
if (_instance == null) {
_instance = BleAdapter._internal(bleManager, blemulator);
Expand Down Expand Up @@ -58,14 +61,16 @@ class BleAdapter {

Stream<BlePeripheral> _startPeripheralScan() {
return _bleManager.startPeripheralScan().map((scanResult) {
_scannedPeripherals.putIfAbsent(
scanResult.peripheral.identifier, () => scanResult.peripheral);
return BlePeripheral(
scanResult.peripheral.name ??
scanResult.advertisementData.localName ??
'Unknown',
scanResult.peripheral.identifier,
scanResult.rssi,
false,
BlePeripheralCategoryResolver.categoryForScanResult(scanResult),
scanResult.peripheral.name ??
scanResult.advertisementData.localName ??
'Unknown',
scanResult.peripheral.identifier,
scanResult.rssi,
false,
BlePeripheralCategoryResolver.categoryForScanResult(scanResult),
);
});
}
Expand All @@ -82,4 +87,31 @@ class BleAdapter {
_blemulator.addSimulatedPeripheral(GenericPeripheral());
_blemulator.simulate();
}

Future<List<BleService>> discoverAndGetServicesCharacteristics(
String peripheralId) async {
// TODO remove connect() call when connectivity handling is implemented
await _scannedPeripherals[peripheralId].connect();
await _scannedPeripherals[peripheralId]
.discoverAllServicesAndCharacteristics();

List<BleService> bleServices = [];
for (Service service
in await _scannedPeripherals[peripheralId].services()) {
List<Characteristic> serviceCharacteristics =
martawoldanska marked this conversation as resolved.
Show resolved Hide resolved
await service.characteristics();
List<BleCharacteristic> bleCharacteristics = serviceCharacteristics
.map(
(characteristic) =>
martawoldanska marked this conversation as resolved.
Show resolved Hide resolved
BleCharacteristic.fromCharacteristic(characteristic),
)
.toList();
bleServices.add(BleService(service.uuid, bleCharacteristics));
}

// TODO remove when connectivity handling is implemented
_scannedPeripherals[peripheralId].disconnectOrCancelConnection();
martawoldanska marked this conversation as resolved.
Show resolved Hide resolved

return bleServices;
}
}
6 changes: 4 additions & 2 deletions example/lib/common/components/property_row.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class PropertyRow extends StatelessWidget {
final Widget titleIcon;
final Color titleColor;
final String valueCompanion;
final TextStyle valueTextStyle;
final Widget rowAccessory;
final Widget titleAccessory;
final Widget valueAccessory;
Expand All @@ -17,6 +18,7 @@ class PropertyRow extends StatelessWidget {
this.titleIcon,
this.titleColor,
@required this.value,
this.valueTextStyle = CustomTextStyle.cardValue,
this.valueCompanion,
this.rowAccessory,
this.titleAccessory,
Expand Down Expand Up @@ -113,7 +115,7 @@ class PropertyRow extends StatelessWidget {
child: Text(
value ?? '',
textWidthBasis: TextWidthBasis.longestLine,
style: CustomTextStyle.cardValue,
style: valueTextStyle,
),
),
),
Expand All @@ -129,7 +131,7 @@ class PropertyRow extends StatelessWidget {
return Expanded(
child: Text(
value ?? '',
style: CustomTextStyle.cardValue,
style: valueTextStyle,
),
);
}
Expand Down
2 changes: 1 addition & 1 deletion example/lib/device_details/device_detail_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class DeviceDetailsViewState extends State<DeviceDetailsView> {
child: Scaffold(
backgroundColor: Colors.grey[300],
appBar: AppBar(
title: Text('Devicie Details'),
title: Text('Device Details'),
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.autorenew), text: "Automatic",),
Expand Down
52 changes: 43 additions & 9 deletions example/lib/example_peripherals/generic_peripheral.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,49 @@ class GenericPeripheral extends SimulatedPeripheral {
advertisementInterval: Duration(milliseconds: milliseconds),
services: [
SimulatedService(
uuid: 'F000AA00-0001-4000-B000-000000000000',
isAdvertised: true,
characteristics: [
SimulatedCharacteristic(
uuid: 'F000AA10-0001-4000-B000-000000000000',
value: Uint8List.fromList([0]),
convenienceName: 'Generic characteristic'),
],
convenienceName: 'Generic service'),
uuid: 'F000AA00-0001-4000-B000-000000000000',
isAdvertised: true,
characteristics: [
SimulatedCharacteristic(
uuid: 'F000AA10-0001-4000-B000-000000000000',
value: Uint8List.fromList([0]),
convenienceName: 'Generic characteristic 1'),
],
convenienceName: 'Generic service 1',
),
SimulatedService(
uuid: 'F000AA01-0001-4000-B000-000000000000',
isAdvertised: true,
characteristics: [
SimulatedCharacteristic(
uuid: 'F000AA11-0001-4000-B000-000000000000',
value: Uint8List.fromList([0]),
convenienceName: 'Generic characteristic 2'),
],
convenienceName: 'Generic service 2',
),
SimulatedService(
uuid: 'F000AA02-0001-4000-B000-000000000000',
isAdvertised: true,
characteristics: [
SimulatedCharacteristic(
uuid: 'F000AA12-0001-4000-B000-000000000000',
value: Uint8List.fromList([0]),
convenienceName: 'Generic characteristic 3'),
],
convenienceName: 'Generic service 3',
),
SimulatedService(
uuid: 'F000AA03-0001-4000-B000-000000000000',
isAdvertised: true,
characteristics: [
SimulatedCharacteristic(
uuid: 'F000AA13-0001-4000-B000-000000000000',
value: Uint8List.fromList([0]),
convenienceName: 'Generic characteristic 4'),
],
convenienceName: 'Generic service 4',
),
],
martawoldanska marked this conversation as resolved.
Show resolved Hide resolved
);

Expand Down
54 changes: 54 additions & 0 deletions example/lib/model/ble_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import 'dart:typed_data';

import 'package:equatable/equatable.dart';
import 'package:flutter_ble_lib/flutter_ble_lib.dart';

class BleService extends Equatable {
final String uuid;
final List<BleCharacteristic> characteristics;

BleService(this.uuid, this.characteristics);

@override
martawoldanska marked this conversation as resolved.
Show resolved Hide resolved
List<Object> get props => [uuid, characteristics];
}

class BleCharacteristic extends Equatable {
final String uuid;
final Uint8List value;
final bool isReadable;
final bool isWritableWithResponse;
final bool isWritableWithoutResponse;
final bool isNotifiable;
final bool isIndicatable;

BleCharacteristic(
this.uuid,
this.value,
this.isReadable,
this.isWritableWithResponse,
this.isWritableWithoutResponse,
this.isNotifiable,
this.isIndicatable,
);

@override
List<Object> get props => [
uuid,
value,
isReadable,
isWritableWithResponse,
isWritableWithoutResponse,
isNotifiable,
isIndicatable
];

BleCharacteristic.fromCharacteristic(Characteristic characteristic)
: uuid = characteristic.uuid,
value = null,
isReadable = characteristic.isReadable,
isWritableWithResponse = characteristic.isWritableWithResponse,
isWritableWithoutResponse = characteristic.isWritableWithoutResponse,
isNotifiable = characteristic.isNotifiable,
isIndicatable = characteristic.isIndicatable;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'package:blemulator_example/model/ble_service.dart';
import 'package:blemulator_example/styles/custom_text_style.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';

class CharacteristicsView extends StatelessWidget {
final BleCharacteristic _characteristic;

CharacteristicsView(this._characteristic);

@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"UUID: ${_characteristic.uuid}",
style: CustomTextStyle.characteristicsStyle,
),
Text(
"Properties: ${_getCharacteristicProperties(_characteristic).toString()}",
style: CustomTextStyle.characteristicsStyle,
),
],
),
),
);
}

static List<String> _getCharacteristicProperties(
BleCharacteristic characteristic) {
List<String> properties = new List<String>();

if (characteristic.isWritableWithResponse ||
characteristic.isWritableWithoutResponse) {
properties.add("write");
}
if (characteristic.isReadable) {
properties.add("read");
}
if (characteristic.isIndicatable || characteristic.isNotifiable) {
properties.add("notify");
}

return properties;
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
import 'package:blemulator_example/peripheral_details/bloc.dart';
import 'package:blemulator_example/common/components/property_row.dart';
import 'package:blemulator_example/peripheral_details/bloc.dart';
import 'package:blemulator_example/peripheral_details/components/services_sliver.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class PeripheralDetailsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
SliverSafeArea(
top: false,
sliver: SliverPadding(
padding: const EdgeInsets.all(8.0),
sliver: SliverToBoxAdapter(
child: BlocBuilder<PeripheralDetailsBloc, PeripheralDetailsState>(
builder: (context, state) {
return PropertyRow(
title: 'Identifier',
titleIcon: Icon(Icons.perm_device_information),
titleColor: Theme.of(context).primaryColor,
value: state.peripheral.id,
);
},
),
SliverPadding(
padding: const EdgeInsets.all(8.0),
sliver: SliverToBoxAdapter(
child: BlocBuilder<PeripheralDetailsBloc, PeripheralDetailsState>(
builder: (context, state) {
return Column(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it redrawn when any of serviceState.expanded has been changed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand it, only the changed view will be redrawn. Whole column view would be rebuilt each time expanded state changes, but only changed part would be actually redrawn.

mainAxisSize: MainAxisSize.min,
children: <Widget>[
PropertyRow(
title: 'Identifier',
titleIcon: Icon(Icons.perm_device_information),
titleColor: Theme.of(context).primaryColor,
value: state.peripheral.id,
),
],
);
},
),
),
),
BlocBuilder<PeripheralDetailsBloc, PeripheralDetailsState>(
builder: (context, state) {
return ServicesSliver(state.bleServiceStates);
},
)
],
);
}
Expand Down
Loading