Skip to content

Commit

Permalink
Added toMac() to Guid. Emitting a disconnected state change from doOn…
Browse files Browse the repository at this point in the history
…Completed. Added KnownServices.
  • Loading branch information
pauldemarco committed Jun 30, 2017
1 parent 157f385 commit c419bef
Show file tree
Hide file tree
Showing 12 changed files with 117 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.pauldemarco.flutterblue.concrete;

import android.bluetooth.BluetoothGattCharacteristic;
import android.util.Log;

import com.pauldemarco.flutterblue.ChannelPaths;
import com.pauldemarco.flutterblue.Characteristic;
Expand Down Expand Up @@ -36,7 +37,7 @@ public CharacteristicImpl(Registrar registrar, Guid guid, String name, int prope

public static CharacteristicImpl fromGattCharacteristic(Registrar registrar, BluetoothGattCharacteristic c, Service service, Device device) {
Guid guid = new Guid(c.getUuid());
String name = null; // TODO: Get name if UUID is a known characteristic
String name = null; // TODO: Get name if UUID is a known characteristic (do this on dart side instead?)
int properties = c.getProperties();
int writeTypeInt = c.getWriteType();
CharacteristicWriteType writeType = CharacteristicWriteType.DEFAULT;
Expand All @@ -48,6 +49,7 @@ public static CharacteristicImpl fromGattCharacteristic(Registrar registrar, Blu
writeType = CharacteristicWriteType.WITH_RESPONSE;
break;
}
// Permissions will always be zero, see issue #6
int permissions = c.getPermissions();
boolean canRead = (permissions & BluetoothGattCharacteristic.PERMISSION_READ) == BluetoothGattCharacteristic.PERMISSION_READ;
boolean canReadEncrypted = (permissions & BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED) == BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public Completable connect(boolean autoConnect) {
nativeDevice.observeConnectionStateChanges()
.takeUntil(disconnectTriggerSubject)
.map((s) -> toState(s))
.doOnCompleted(() -> stateChanged(State.DISCONNECTED))
.subscribe(
this::stateChanged,
this::onConnectionStateFailure
Expand Down
35 changes: 25 additions & 10 deletions example/lib/device_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,26 @@ class _DevicePageState extends State<DevicePage> {
onPressed: _connect
);
}
}

_buildServiceList(BuildContext context) {
var children = <Widget>[];
for(IService s in _device.services) {
var sChildren = <Widget>[];
if(s.characteristics.length > 0) {
for(ICharacteristic c in s.characteristics){
sChildren.add(new ListTile(title: new Text(c.name)));
}
} else {
sChildren.add(const Text('The service is empty.'));
}
children.add(new ExpansionTile(
title: new Text(s.name),
backgroundColor: Theme.of(context).accentColor.withOpacity(0.025),
children: sChildren,
));
}
return children;
}

@override
Expand All @@ -72,15 +91,8 @@ class _DevicePageState extends State<DevicePage> {
appBar: new AppBar(
title: new Text(_device.name)
),
body: new SingleChildScrollView(
child: new Container(
margin: const EdgeInsets.all(20.0),
child: new Card(
child: new Text(
_deviceState.toString()
)
)
)
body: new ListView(
children: _buildServiceList(context),
),
floatingActionButton: _buildFloatingActionButton(context),
);
Expand All @@ -90,6 +102,9 @@ class _DevicePageState extends State<DevicePage> {
String result = await _flutterBlue.ble.adapter.connectToDevice(_device);
print(result);
Set<IService> services = await _device.getServices();
setState(() {

});
for(IService s in services) {
printService(s);
}
Expand All @@ -101,7 +116,7 @@ class _DevicePageState extends State<DevicePage> {
printService(q);
}
for(ICharacteristic c in s.characteristics) {
print("Characteristic id: ${c.id} canRead: ${c.canRead} canReadEncrypted: ${c.canReadEncrypted} canWrite: ${c.canWrite} canWriteEncrypted: ${c.canWriteEncrypted}");
print("Characteristic id: ${c.id} properties: ${c.properties} canRead: ${c.canRead} canReadEncrypted: ${c.canReadEncrypted} canWrite: ${c.canWrite} canWriteEncrypted: ${c.canWriteEncrypted}");
}
}

Expand Down
2 changes: 1 addition & 1 deletion example/lib/device_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class DeviceTile extends StatelessWidget {
return new ListTile(
leading: new AnimatedRssi(device.rssi),
title: new Text(device.name),
subtitle: new Text(device.id.toString()),
subtitle: new Text(device.id.toMac()),
onTap: _handleTap,
);;
}
Expand Down
8 changes: 8 additions & 0 deletions lib/abstractions/known_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:flutter_blue/utils/guid.dart';

class KnownService {
final String name;
final Guid id;

const KnownService(this.name, this.id);
}
48 changes: 48 additions & 0 deletions lib/abstractions/known_services.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import 'package:flutter_blue/utils/guid.dart';
import 'package:flutter_blue/abstractions/known_service.dart';

class KnownServices {

static final lookupTable = new Map<Guid, KnownService>.fromIterable(_services, key: (i) => i.id);

static KnownService lookup(Guid guid) {
return lookupTable.containsKey(guid) ? lookupTable[guid] : new KnownService("Unknown service", new Guid.empty());
}

static final _services = [
new KnownService("Alert Notification Service", new Guid("00001811-0000-1000-8000-00805f9b34fb")),
new KnownService("Battery Service", new Guid("0000180f-0000-1000-8000-00805f9b34fb")),
new KnownService("Blood Pressure", new Guid("00001810-0000-1000-8000-00805f9b34fb")),
new KnownService("Current Time Service", new Guid("00001805-0000-1000-8000-00805f9b34fb")),
new KnownService("Cycling Power", new Guid("00001818-0000-1000-8000-00805f9b34fb")),
new KnownService("Cycling Speed and Cadence", new Guid("00001816-0000-1000-8000-00805f9b34fb")),
new KnownService("Device Information", new Guid("0000180a-0000-1000-8000-00805f9b34fb")),
new KnownService("Generic Access", new Guid("00001800-0000-1000-8000-00805f9b34fb")),
new KnownService("Generic Attribute", new Guid("00001801-0000-1000-8000-00805f9b34fb")),
new KnownService("Glucose", new Guid("00001808-0000-1000-8000-00805f9b34fb")),
new KnownService("Health Thermometer", new Guid("00001809-0000-1000-8000-00805f9b34fb")),
new KnownService("Heart Rate", new Guid("0000180d-0000-1000-8000-00805f9b34fb")),
new KnownService("Human Interface Device", new Guid("00001812-0000-1000-8000-00805f9b34fb")),
new KnownService("Immediate Alert", new Guid("00001802-0000-1000-8000-00805f9b34fb")),
new KnownService("Link Loss", new Guid("00001803-0000-1000-8000-00805f9b34fb")),
new KnownService("Location and Navigation", new Guid("00001819-0000-1000-8000-00805f9b34fb")),
new KnownService("Next DST Change Service", new Guid("00001807-0000-1000-8000-00805f9b34fb")),
new KnownService("Phone Alert Status Service", new Guid("0000180e-0000-1000-8000-00805f9b34fb")),
new KnownService("Reference Time Update Service", new Guid("00001806-0000-1000-8000-00805f9b34fb")),
new KnownService("Running Speed and Cadence", new Guid("00001814-0000-1000-8000-00805f9b34fb")),
new KnownService("Scan Parameters", new Guid("00001813-0000-1000-8000-00805f9b34fb")),
new KnownService("TX Power", new Guid("00001804-0000-1000-8000-00805f9b34fb")),
new KnownService("TI SensorTag Smart Keys", new Guid("0000ffe0-0000-1000-8000-00805f9b34fb")),
new KnownService("TI SensorTag Infrared Thermometer", new Guid("f000aa00-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag Accelerometer", new Guid("f000aa10-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag Humidity", new Guid("f000aa20-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag Magnometer", new Guid("f000aa30-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag Barometer", new Guid("f000aa40-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag Gyroscope", new Guid("f000aa50-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag Test", new Guid("f000aa60-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag Connection Control", new Guid("f000ccc0-0451-4000-b000-000000000000")),
new KnownService("TI SensorTag OvertheAir Download", new Guid("f000ffc0-0451-4000-b000-000000000000")),
new KnownService("TXRX_SERV_UUID RedBearLabs Biscuit Service", new Guid("713d0000-503e-4c75-ba94-3148f18d941e")),
];

}
11 changes: 6 additions & 5 deletions lib/concrete/characteristic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@ import 'package:flutter_blue/abstractions/contracts/i_characteristic.dart';
import 'package:flutter_blue/abstractions/contracts/i_descriptor.dart';
import 'package:flutter_blue/abstractions/contracts/i_service.dart';
import 'package:flutter_blue/abstractions/eventargs/characteristic_updated_args.dart';
import 'package:flutter_blue/abstractions/known_characteristics.dart';
import 'package:flutter_blue/utils/guid.dart';

class Characteristic implements ICharacteristic{

Characteristic._internal({this.id, this.name, this.value, this.stringValue, this.properties, this.writeType, this.canRead, this.canReadEncrypted, this.canWrite, this.canWriteEncrypted, this.service})
Characteristic._internal({this.id, this.value, this.stringValue, this.properties, this.writeType, this.canRead, this.canReadEncrypted, this.canWrite, this.canWriteEncrypted, this.service})
: _methodChannel = new MethodChannel(
"flutterblue.pauldemarco.com/devices/${service.device.id.toString()}/services/${service.id.toString()}/characteristics/${id.toString()}/methods");
"flutterblue.pauldemarco.com/devices/${service.device.id.toString()}/services/${service.id.toString()}/characteristics/${id.toString()}/methods"),
name = KnownCharacteristics.lookup(id).name;

Characteristic({id, name, value, stringValue, properties, writeType, canRead, canReadEncrypted, canWrite, canWriteEncrypted, service})
Characteristic({id, value, stringValue, properties, writeType, canRead, canReadEncrypted, canWrite, canWriteEncrypted, service})
: this._internal(
id: id, name: name, value: value, stringValue: stringValue, properties: properties, writeType: writeType, canRead: canRead, canReadEncrypted: canReadEncrypted, canWrite: canWrite, canWriteEncrypted: canWriteEncrypted, service: service);
id: id, value: value, stringValue: stringValue, properties: properties, writeType: writeType, canRead: canRead, canReadEncrypted: canReadEncrypted, canWrite: canWrite, canWriteEncrypted: canWriteEncrypted, service: service);

Characteristic.fromMap(map)
: this._internal(
id: new Guid(map['id']),
name: null,
properties: map['properties'],
writeType: CharacteristicWriteType.values[map['writeType']],
canRead: map['canRead'],
Expand Down
12 changes: 7 additions & 5 deletions lib/concrete/service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import 'package:flutter/services.dart';
import 'package:flutter_blue/abstractions/contracts/i_characteristic.dart';
import 'package:flutter_blue/abstractions/contracts/i_device.dart';
import 'package:flutter_blue/abstractions/contracts/i_service.dart';
import 'package:flutter_blue/abstractions/known_services.dart';
import 'package:flutter_blue/concrete/characteristic.dart';
import 'package:flutter_blue/utils/guid.dart';

class Service implements IService {
Service._internal({this.id, this.device, this.isPrimary, this.name, List<Map<String,Object>> includedServices, List<Map<String,Object>> characteristics})
Service._internal({this.id, this.device, this.isPrimary, List<Map<String,Object>> includedServices, List<Map<String,Object>> characteristics})
: _methodChannel = new MethodChannel(
"flutterblue.pauldemarco.com/devices/${device.id.toString()}/services/${id.toString()}/methods") {
"flutterblue.pauldemarco.com/devices/${device.id.toString()}/services/${id.toString()}/methods"),
name = KnownServices.lookup(id).name
{
if(includedServices != null) {
var s = includedServices.map((m) {
m.putIfAbsent("device", () => this.device);
Expand All @@ -27,14 +30,13 @@ class Service implements IService {
}
}

Service({id, device, isPrimary, name})
Service({id, device, isPrimary})
: this._internal(
id: id, device: device, isPrimary: isPrimary, name: name);
id: id, device: device, isPrimary: isPrimary);

Service.fromMap(map)
: this._internal(
id: new Guid(map['id']),
name: (map['name'] != null) ? map['name'] : 'Unknown',
device: map['device'],
isPrimary: map['isPrimary'],
includedServices: map['includedServices'],
Expand Down
10 changes: 10 additions & 0 deletions lib/utils/guid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ class Guid {
return "$one-$two-$three-$four-$five";
}

String toMac() {
String one = hex.encode(_bytes.sublist(0,1));
String two = hex.encode(_bytes.sublist(1,2));
String three = hex.encode(_bytes.sublist(2,3));
String four = hex.encode(_bytes.sublist(3,4));
String five = hex.encode(_bytes.sublist(4,5));
String six = hex.encode(_bytes.sublist(5,6));
return "$one:$two:$three:$four:$five:$six".toUpperCase();
}

List<int> toByteArray() {
return _bytes;
}
Expand Down
9 changes: 3 additions & 6 deletions test/device_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,17 @@ main() {
var device = new Device(
id: new Guid.fromMac("01:02:03:04:05:06"),
name: "Test Device",
rssi: 123,
state: DeviceState.disconnected);
rssi: 123,);

var device2 = new Device(
id: new Guid.fromMac("01:02:03:04:05:06"),
name: "Test Device",
rssi: 123,
state: DeviceState.disconnected);
rssi: 123,);

var device3 = new Device(
id: new Guid.fromMac("02:02:03:04:05:07"),
name: "Test Device",
rssi: 123,
state: DeviceState.disconnected);
rssi: 123,);

test('equality', (){
expect(device, device2);
Expand Down
5 changes: 5 additions & 0 deletions test/guid_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ main() {
expect("[36, 10, 100, 80, 164, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]", guid.toByteArray().toString());
});

test('fromMac()', (){
var guid = new Guid.fromMac("24:0A:64:50:A4:67");
expect("24:0A:64:50:A4:67", guid.toMac());
});

test('hashCode', (){
var guid = new Guid.fromMac("24:0A:64:50:A4:67");
var guid2 = new Guid.fromMac("24:0A:64:50:A4:67");
Expand Down
2 changes: 0 additions & 2 deletions test/utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ main() {
var min = -90.0;
var max = -60.0;
var value = -66.0;
print(inverseLerp(min, max, value));
print(inverseLerp(min, max, value).clamp(0.0,1.0));
expect(inverseLerp(min,max,value), 0.8);
});
}
Expand Down

0 comments on commit c419bef

Please sign in to comment.