Skip to content

Commit

Permalink
Version 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Thai Dinh Le authored and Thai Dinh Le committed Jun 8, 2021
1 parent 81ce0ce commit 4f1c214
Show file tree
Hide file tree
Showing 42 changed files with 667 additions and 323 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

## 2.0.0

* Reformat code & minor public API changes
* Add secure group communication APIs
* Add documentations
* Update documentations
* Add unit testing & update of dependencies version
* Add tests
* Exposed public APIs
* Update LICENSE
* Update dependencies versions
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,71 @@ The ad hoc library supports the following operations:
- Send encrypted data to an existing secure group
- Provides notifications of specific events related to the library (e.g., connection established, or data received)

### TransferManager

To initialise the library, it is done as follows:
```dart
bool verbose = true;
TransferManager transferManager = TransferManager(verbose);
```

It is also possible to modify the behaviour of the library by configuring a __Config__ object.

```dart
bool verbose = false;
Config config = Config();
config.label = "Example name"; // Use for communication
config.public = true; // Join any group formation
TransferManager transferManager = TransferManager(verbose, config);
```

### Listen to events

As different events can occurs in the ad hoc network, the broadcast stream exposed by __TransferManager__ can be listen to.

```dart
TransferManager transferManager = TransferManager(false);
void _listen() {
_manager.eventStream.listen((event) {
switch (event.type) {
case AdHocType.onDeviceDiscovered:
var device = event.payload as AdHocDevice;
break;
case AdHocType.onDiscoveryStarted:
break;
case AdHocType.onDiscoveryCompleted:
var discovered = event.payload as Map<String, AdHocDevice>
break;
case AdHocType.onDataReceived:
var data = event.payload as Object;
break;
case AdHocType.onForwardData:
var data = event.payload as Object;
break;
case AdHocType.onConnection:
var device = event.payload as AdHocDevice;
break;
case AdHocType.onConnectionClosed:
var device = event.payload as AdHocDevice;
break;
case AdHocType.onInternalException:
var exception = event.payload as Exception;
break;
case AdHocType.onGroupInfo:
var info = event.payload as int;
break;
case AdHocType.onGroupDataReceived:
var data = event.payload as Object;
break;
default:
}
}
}
```

## Application Example

## example
Expand Down
27 changes: 10 additions & 17 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import 'search_bar.dart';

void main() => runApp(AdHocMusicClient());

enum MenuOptions { add, search, display, group }
enum MenuOptions { add, search, display }

const platform = MethodChannel('adhoc.music.player/main');

Expand Down Expand Up @@ -48,7 +48,7 @@ class _AdHocMusicClientState extends State<AdHocMusicClient> {
@override
void initState() {
super.initState();
// _manager.enableBle(3600);
_manager.enableBle(3600);
_manager.eventStream.listen(_processAdHocEvent);
_manager.open = true;
}
Expand Down Expand Up @@ -87,13 +87,6 @@ class _AdHocMusicClientState extends State<AdHocMusicClient> {
case MenuOptions.display:
setState(() => _display = !_display);
break;

case MenuOptions.group:
_manager.createGroup();
Future.delayed(Duration(seconds: 30), () {
_manager.sendMessageToGroup('Hello');
});
break;
}
},
itemBuilder: (context) => <PopupMenuEntry<MenuOptions>>[
Expand All @@ -118,13 +111,6 @@ class _AdHocMusicClientState extends State<AdHocMusicClient> {
title: Text('Switch view'),
),
),
const PopupMenuItem<MenuOptions>(
value: MenuOptions.group,
child: ListTile(
leading: Icon(Icons.create),
title: Text('Create a group'),
),
),
],
),
],
Expand All @@ -146,10 +132,17 @@ class _AdHocMusicClientState extends State<AdHocMusicClient> {
Expanded(
child: ListView(
children: _discovered.map((device) {
var type = device.mac.ble == '' ? 'Wi-Fi' : 'BLE';
var mac = device.mac.ble == '' ? device.mac.wifi : device.mac.ble;
if (device.mac.ble != '' && device.mac.wifi != '') {
type = 'Wi-Fi/BLE';
mac = '${device.mac.wifi}/${device.mac.ble}';
}

return Card(
child: ListTile(
title: Center(child: Text(device.name)),
subtitle: Center(child: Text('${device.mac}')),
subtitle: Center(child: Text('$type: $mac')),
onTap: () async {
await _manager.connect(device);
setState(() => _discovered.removeWhere((element) => (element.mac == device.mac)));
Expand Down
2 changes: 1 addition & 1 deletion lib/adhoc_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ library adhoc_plugin;
export 'src/appframework/export.dart';
export 'src/datalink/export.dart';
export 'src/network/export.dart';
export 'src/presentation/export.dart';
export 'src/presentation/export.dart';
14 changes: 5 additions & 9 deletions lib/src/appframework/config.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import 'package:adhoc_plugin/src/appframework/constants.dart';
import 'package:adhoc_plugin/src/appframework/exceptions/bad_server_port.dart';
import 'package:uuid/uuid.dart';


/// Class allowing to modify the library's behaviour via parameters.
class Config {
/// Minimum value allowed for the socket port (Wi-Fi Direct)
static const MIN_PORT = 1023;
/// Maximum value allowed for the socket port (Wi-Fi Direct)
static const MAX_PORT = 65535;

late int _serverPort;

late String label;
late bool flood;
late bool open;
late bool public;
late int timeOut;
late int expiryTime;
late int validityPeriod;
Expand All @@ -27,7 +23,7 @@ class Config {
/// If [flood] is set to true, then internal flooding mechanisms are activated,
/// e.g., flood new connection events.
///
/// If [open] is set to true, then the current device will always join the
/// If [public] is set to true, then the current device will always join the
/// first group formation message received.
///
/// If [serverPort] is given, then it is used instead of the default one
Expand All @@ -43,13 +39,13 @@ class Config {
/// If [validityCheck] is given, then it is used instead of the default one
/// (7200 seconds).
Config({
String label = '', bool flood = false, bool open = false,
String label = '', bool flood = false, bool public = false,
int serverPort = 52000, int expiryTime = 10, int validityPeriod = 7200,
int validityCheck = 7200
}) {
this.label = (label == '') ? Uuid().v4() : label;
this.flood = flood;
this.open = open;
this.public = public;
this.serverPort = serverPort;
this.expiryTime = expiryTime;
this.validityPeriod = validityPeriod;
Expand Down
6 changes: 6 additions & 0 deletions lib/src/appframework/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ enum AdHocType {
onGroupInfo,
onGroupDataReceived,
}

/// Minimum value allowed for the socket port (Wi-Fi Direct)
const MIN_PORT = 1023;

/// Maximum value allowed for the socket port (Wi-Fi Direct)
const MAX_PORT = 65535;
6 changes: 5 additions & 1 deletion lib/src/appframework/event.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import 'package:adhoc_plugin/src/appframework/constants.dart';
import 'package:adhoc_plugin/src/datalink/service/adhoc_device.dart';


/// Class encapsulating the data received from lower layers of the library.
class Event {
late final AdHocType type;
late AdHocDevice? device;
late Object? data;

/// Creates an [Event] object.
///
/// The event is determined by its [type], which in turn indicates if this
/// object has a payload [data] or a sender ad hoc device representation [device].
Event(this.type, {this.device, this.data});
}
24 changes: 18 additions & 6 deletions lib/src/appframework/transfer_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,33 +74,39 @@ class TransferManager {
}

/// Stance about joining group formation
set open(bool open) => _presentationManager.groupController.open = open;
set open(bool state) => _presentationManager.groupController.public = state;

/*-------------------------------Group Methods--------------------------------*/

/// Creates a secure group.
///
/// If [labels] is given, then the group init request message is sent to those
/// particular addresses. Otherwise, the message is broadcasted.
///
/// Throws a [DeviceFailureException] if the Wi-Fi/Bluetooth adapter is not
/// enabled.
void createGroup() {
void createGroup([List<String>? labels]) {
if (_datalinkManager.checkState() == 0) {
throw DeviceFailureException('No wifi and bluetooth connectivity');
}

_presentationManager.groupController.createGroup();
_presentationManager.groupController.createGroup(labels);
}


/// Joins an existing secure group.
///
/// If [label] is given, then the group join request message is sent to that
/// particular address. Otherwise, the join request message is broadcasted.
///
/// Throws a [DeviceFailureException] if the Wi-Fi/Bluetooth adapter is not
/// enabled.
void joinGroup() {
void joinGroup([String? label]) {
if (_datalinkManager.checkState() == 0) {
throw DeviceFailureException('No wifi and bluetooth connectivity');
}

_presentationManager.groupController.joinSecureGroup();
_presentationManager.groupController.joinSecureGroup(label);
}


Expand Down Expand Up @@ -309,7 +315,10 @@ class TransferManager {
}


/// Enables the Wi-Fi adapter.
/// Initialises the underlying Wi-Fi data structures.
///
/// Note: It is not possible to enable/disable Wi-Fi starting with Build.VERSION_CODES#Q.
/// https://developer.android.com/reference/android/net/wifi/WifiManager#setWifiEnabled(boolean)
///
/// The device is set into discovery mode for [duration] ms.
///
Expand Down Expand Up @@ -372,6 +381,9 @@ class TransferManager {

/*------------------------------Private Methods------------------------------*/

/// Listens to lower layers event stream.
///
/// Its main purpose is to encapsulate the data into Event object.
void _initialize() {
_presentationManager.eventStream.listen((event) {
AdHocDevice? device;
Expand Down
17 changes: 10 additions & 7 deletions lib/src/datalink/ble/ble_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class BleClient extends ServiceClient {

late final BleAdHocDevice _device;
late FlutterReactiveBle _reactiveBle;
late bool _isInitialized;
late bool _isInitialised;

/// Creates a [BleClient] object.
///
Expand All @@ -26,10 +26,13 @@ class BleClient extends ServiceClient {
///
/// Connection attempts to a remote device are done at most [attempts] times.
/// A connection attempt waiting time is set to [timeOut] ms.
BleClient(bool verbose, this._device, int attempts, int timeOut)
: super(verbose, attempts, timeOut) {
BleClient(
bool verbose, this._device, int attempts, int timeOut
) : super(
verbose, attempts, timeOut
) {
_reactiveBle = FlutterReactiveBle();
_isInitialized = false;
_isInitialised = false;
}

/*-------------------------------Public methods-------------------------------*/
Expand Down Expand Up @@ -70,7 +73,7 @@ class BleClient extends ServiceClient {

/// Cancels the connection with the remote device.
@override
void disconnect() {
Future<void> disconnect() async {
stopListening();
if (_connectionSub != null) {
// Abort connection with the remote host
Expand Down Expand Up @@ -161,7 +164,7 @@ class BleClient extends ServiceClient {

/// Initializes the environment upon a successful connection performed.
Future<void> _initEnvironment() async {
if (_isInitialized) {
if (_isInitialised) {
return;
}

Expand All @@ -175,6 +178,6 @@ class BleClient extends ServiceClient {
controller.add(AdHocEvent(CONNECTION_PERFORMED, [_device.mac.ble, _device.address, CLIENT]));

state = STATE_CONNECTED;
_isInitialized = true;
_isInitialised = true;
}
}
11 changes: 0 additions & 11 deletions lib/src/datalink/ble/ble_server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ class BleServer extends ServiceServer {
static int id = 0;

late HashMap<String, int> _mapMacMTU;
late HashMap<String, Set<int>> _duplicate;

/// Creates a [BleServer] object.
///
/// The debug/verbose mode is set if [verbose] is true.
BleServer(bool verbose) : super(verbose) {
_mapMacMTU = HashMap();
_duplicate = HashMap();
}

/*-------------------------------Public methods-------------------------------*/
Expand Down Expand Up @@ -54,14 +52,12 @@ class BleServer extends ServiceServer {
if (state) {
addActiveConnection(mac);
_mapMacMTU.putIfAbsent(mac, () => MIN_MTU);
_duplicate.putIfAbsent(mac, () => <int>{});

// Notify upper layer of a connection performed
controller.add(AdHocEvent(CONNECTION_PERFORMED, [mac, uuid, SERVER]));
} else {
removeConnection(mac);
_mapMacMTU.remove(mac);
_duplicate.remove(mac);

// Notify upper layer of a connection aborted
controller.add(AdHocEvent(CONNECTION_ABORTED, mac));
Expand All @@ -77,13 +73,6 @@ class BleServer extends ServiceServer {
json.decode(Utf8Decoder().convert(bytes)) as Map<String, dynamic>
);

var seqNum = message.header.seqNum!;
if (_duplicate[map['mac'] as String]!.contains(seqNum)) {
break;
} else {
_duplicate[map['mac'] as String]!.add(seqNum);
}

// Update the header of the message
if (message.header.mac.ble == '') {
var uuid = BLUETOOTHLE_UUID + (map['mac'] as String)
Expand Down
Loading

0 comments on commit 4f1c214

Please sign in to comment.