A Flutter plugin to enable mesh network management and communication using Nordic Semiconductor's SDKs.
This plugin wraps both IOS-nRF-Mesh-Library and Android-nRF-Mesh-Library to provide a Dart-only API and has the following features :
- Create, load and manage a mesh network model
- (de)provision a BLE mesh node
- Scan for BLE devices in range
- Connect to a BLE mesh node and use it as a proxy to communicate in a mesh network
- Encrypt and decrypt mesh PDUs (not all mesh message types are supported)
- Event based API using StreamControllers
- Manage mesh groups
- Manage nodes' publications and subscriptions
- Manage mesh provisioners
- Key Refresh Procedure (partial support on Android)
(Note: the Bluetooth scanning and connecting features are done with flutter_reactive_ble)
- clone repository
- execute
git submodule update --init
- add
nordic_nrf_mesh
to your pubspec.yaml and executeflutter pub get
- go to
path/to/flutter/.pub-cache/hosted/pub.dartlang.org/nrf_mesh_plugin-<plugin_version>
- execute
git submodule update --init
- copy plugin's example app gradle script in android/settings.gradle
- paste it in your own app's file
- copy plugin's example Podfile script in ios/Podfile
- paste it in your own app's file
To begin to use the plugin, one should instantiate the NordicNrfMesh
instance like so :
final nordicNrfMesh = NordicNrfMesh();
It's via this singleton that one may have access to the main API.
To be able to use the mesh features, please make sure to load a mesh network at each run like so :
final MeshManagerApi meshManager = nordicNrfMesh.meshManagerApi;
final MeshNetwork meshNetwork = await meshManager.loadMeshNetwork();
or
final String networkAsJson = '{"mesh": "network"}';
final MeshManagerApi meshManager = nordicNrfMesh.meshManagerApi;
final MeshNetwork meshNetwork = await meshManager.importMeshNetworkJson(networkAsJson);
Getting the network via the result of these two methods is the easy way. However it won't be updated on events and so we strongly advise users to use the event streams like so :
class MyPluginWrapper{
late IMeshNetwork? _meshNetwork;
late final NordicNrfMesh _nordicNrfMesh;
late final MeshManagerApi _meshManagerApi;
late final StreamSubscription<IMeshNetwork?> onNetworkUpdateSubscription;
late final StreamSubscription<IMeshNetwork?> onNetworkImportSubscription;
late final StreamSubscription<IMeshNetwork?> onNetworkLoadingSubscription;
void init() {
_nordicNrfMesh = NordicNrfMesh();
_meshManagerApi = _nordicNrfMesh.meshManagerApi;
_meshNetwork = _meshManagerApi.meshNetwork;
onNetworkUpdateSubscription = _meshManagerApi.onNetworkUpdated.listen((event) {
_meshNetwork = event;
});
onNetworkImportSubscription = _meshManagerApi.onNetworkImported.listen((event) {
_meshNetwork = event;
});
onNetworkLoadingSubscription = _meshManagerApi.onNetworkLoaded.listen((event) {
_meshNetwork = event;
});
}
void dispose() {
onNetworkUpdateSubscription.cancel();
onNetworkLoadingSubscription.cancel();
onNetworkImportSubscription.cancel();
}
}
Basically these two ways to get a result tend to be there in each methods of the plugin. For example :
- you can await a call to
MeshManagerApi.sendGenericLevelSet
, but also just call it, and having a stream subscription onMeshManagerApi.onGenericLevelStatus
running in the background. - you can await a connection or ask for it and listen to resulting events in the given
BleManagerCallbacks
(If it's not the case and you'd want it implemented, feel free to open an Issue or a Pull Request)
For a node to be part of a network, it must be provisioned. This critical feature is available via the NordicNrfMesh
instance.
Here are the signatures :
Future<ProvisionedMeshNode> provisioning(
final MeshManagerApi meshManagerApi,
final BleMeshManager bleMeshManager,
final DiscoveredDevice device,
final String serviceDataUuid, {
final ProvisioningEvent? events,
})
Future<ConfigNodeResetStatus> deprovision(
final MeshManagerApi meshManagerApi,
final ProvisionedMeshNode meshNode,
)
For example usage, please refer to example app.
(Note: the Bluetooth scanning and connecting features are done with flutter_reactive_ble)
The different scanners are available via the NordicNrfMesh
instance. The API is mesh oriented so you can easily get the mesh devices around the phone, but you can still have custom scanning via NordicNrfMesh.scanWithServices
.
In order to implement connection features, one must use the BleManager
and BleManagerCallbacks
abstract classes.
For convenience, we ship this plugin with an implementation specific to mesh nodes. To be able to handle BLE connection with a mesh proxy node, one shall create and initialize a BleMeshManager
instance.
final bleMeshManager = BleMeshManager();
bleMeshManager.callbacks = MyBleCallbacks(meshManager); // must be set
(The MyBleCallbacks
in the snippet above must extends BleMeshManagerCallbacks
.)
After that, you will have to scan for devices, and then call the connect
method like so :
DiscoveredDevice device;
// scan for device in range
[...]
// connect if found
bleMeshManager.connect(device);
If your use case is not implemented, you should prioritize opening an Issue for a feature request. However you can still get access to other features of the flutter_reactive_ble plugin by getting its singleton instance using the following snippet :
final blePlugin = FlutterReactiveBle();
Again, this should not be done by you, feel free to ask us to implement a new method/feature ! :)
For more in depth use, please refer to example app which shows some of the most used features. In a tab based layout, it provides example usage on :
- basic mesh network management
- scanning and provisioning a new node with some event based ui
- scanning, connecting and sending messages to provisioned nodes
- Android-nRF-Mesh-Library (fork)
- iOS-nRF-Mesh-Library (fork)
- Bluetooth Mesh Profile v1.0.1
- flutter_reactive_ble
(Note: This plugin uses forks of Nordic Semiconductor's libraries. This has been done to be able to extend these libraries with some DooZ specific API, but doesn't change the source code)