Skip to content

A Flutter plugin to enable mesh network management and communication using Nordic Semiconductor's SDKs.

License

Notifications You must be signed in to change notification settings

OZEO-DOOZ/nrf_mesh_plugin

Repository files navigation

nordic_nrf_mesh

pub version pub points pub likes pub popularity

A Flutter plugin to enable mesh network management and communication using Nordic Semiconductor's SDKs.

Features

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)

How to use

Installation

Plugin development :

  • clone repository
  • execute git submodule update --init

Install in Flutter App :

Install plugin
  • add nordic_nrf_mesh to your pubspec.yaml and execute flutter pub get
  • go to path/to/flutter/.pub-cache/hosted/pub.dartlang.org/nrf_mesh_plugin-<plugin_version>
  • execute git submodule update --init
Update build scripts
Android
iOS
  • copy plugin's example Podfile script in ios/Podfile
  • paste it in your own app's file

Initialization

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.

Mesh network features

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 on MeshManagerApi.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)

(de)provisioning

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.

Bluetooth features

(Note: the Bluetooth scanning and connecting features are done with flutter_reactive_ble)

Scan devices :

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.

Connect to a device :

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);

Custom BLE features :

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 ! :)

Example app

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

Related links

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