Skip to content

Commit

Permalink
Services and characteristics list (#92)
Browse files Browse the repository at this point in the history
Added displaying list of services and characteristics 

Co-authored-by: Tomasz Bogusz <[email protected]>
  • Loading branch information
martawoldanska and TomoLV authored Feb 5, 2020
1 parent c7c7477 commit f3f30be
Show file tree
Hide file tree
Showing 14 changed files with 481 additions and 41 deletions.
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 =
await service.characteristics();
List<BleCharacteristic> bleCharacteristics = serviceCharacteristics
.map(
(characteristic) =>
BleCharacteristic.fromCharacteristic(characteristic),
)
.toList();
bleServices.add(BleService(service.uuid, bleCharacteristics));
}

// TODO remove when connectivity handling is implemented
_scannedPeripherals[peripheralId].disconnectOrCancelConnection();

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',
),
],
);

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
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(
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

0 comments on commit f3f30be

Please sign in to comment.