KBA_BT_0515: Bluetooth Mesh Mobile - Import/Export Functionalities Concepts
08/237/2020 | 12:20 PM
KBA_BT_0515: Bluetooth Mesh Mobile - Import/Export Functionalities Concepts
1. Introduction
The Import and Export feature can be regarded as one of the most important ones in the Bluetooth Mesh Silicon Laboratories’ ADK. Introduced in the 2.2.0 release can allow the User to implement completely new approach to control the Mesh Network. One of the use cases examples we suggest, and which is enabled by this functionality, is active usage of multiple data bases or in other words multiple different Mesh networks in the same application. Currently as stated in the AN1200 document the library does not natively support it but it can be worked around by using the Import and Export. Surely there are many other scenarios to be invented by the Users, and knowing the importance of the topic, we have tried to sum up the key steps that need to be followed, in the Document below.
2. Export
First of all, it is necessary for the Developer to understand how and what information exactly need to be exported into an external file to successfully move the Mesh Network structure between the devices. The Silabs’ ADK does not specify what type of file it needs to be, it is up to Developer to choose a specific format for storing the data base. Our API only provides appropriate methods which can be used to extract the necessary information from the Mesh structure which main components are Network, Subnet, Group, Node, Element and Model. As a help for the Developers to get started, we have also prepared a sample implementation of the Export which you can use as a reference or a starting point for your own, in which we have decided to use a JSON string file as a container for our database.
Warning: Due to complexity of the dependencies between the different objects in the Mesh Structure we were not able to gather all the necessary API for export in this document. Below you will find just examples of the methods which can be used to extract the data. The rest of the necessary functions can be found in the class documentation which was attached to the BLE mesh package in the Simplicity Studio directory.
Also, we would highly recommend, after the successful export procedure, to keep the file protected by implementing an appropriate encryption method according to the Customer's requirements.
2.1 Network
Firstly, it would be necessary to get access to the Network type objects available in the data base. It would allow the developer to extract all the necessary information stored inside and will allow you to get the lists of existing Subnets, Provisioners and Scenes in the Mesh Network. Following that, it is going to be needed to extract the data stored in each of the objects of these three types and then the lower layer as well (SubnetSecurity, NetKey, AddressRange). The API samples were listed below for both platforms.
2.1.1. iOS
SBMBluetoothMesh:
networks – use SBMBluetoothMesh.networks
SBMNetwork:
version – use SBMNetwork.version
uuid – use SBMNetwork.uuid
name – use SBMNetwork.name
timestamp – use SBMNetwork.timestamp
subnets – use SBMNetwork.subnets
provisioners – use SBMNetwork.provisioners
scenes – use SBMNetwork.scenes
SBMSubnet
name – use SBMSubnet.name
netKey – use SBMSubnet.netKey
subnetSecurity – use SBMSubnet.subnetSecurity
groups – use SBMSubnet.groups
nodes – use SBMSubnet.nodes
SBMProvisioner
provisionerName – use SBMProvisioner.provisionerName
uuid – use SBMProvisioner.uuid
allocatedUnicastRange – use SBMProvisioner.allocatedUnicastRange
allocatedGroupRange – use SBMProvisioner.allocatedGroupRange
allocatedSceneRange – use SBMProvisioner.allocatedSceneRange
SBMScene
name – use SBMScene.name
number – use SBMScene.number
nodes – use SBMScene.nodes
2.1.2 Android
Bluetoothmesh:
networks – use BluetoothMesh.getNetworks()
Network:
version – use Network.getVersion()
uuid – use Network.getUuid()
name – use Network.getName()
timestamp – use Network.getTimestamp()
subnets – use Network.getSubnets()
provisioners – use Network.getProvisioners()
scenes – use Network.getScenes()
Subnet
name – use Subnet.getName()
netKey – use Subnet.getNetKey()
subnetSecurity – use Subnet.getSubnetSecurity()
groups – use Subnet.getGroups()
nodes – use Subnet.getNodes()
Provisioner
provisionerName – use Provisioner.getName()
uuid – use Provisioner.getUuid()
allocatedUnicastRange – use Provisioner.getAllocatedUnicastRange()
allocatedGroupRange – use Provisioner.getAllocatedGroupRange()
allocatedSceneRange – use Provisioner.getAllocatedSceneRange()
Scene
name – use Scene.getName()
number – use Scene.getNumber()
nodes – use Scene.getNodes()
2.2 Group
Having extracted a list of Group objects from each Subnet instance, you would need to access the data stored in those by using the following API samples.
2.2.1 iOS
SBMGroup:
name – use SBMGroup.name
address – use SBMGroup.address
virtualAddress – use SBMGroup.virtualAddress
parentGroup – use SBMGroup.parentGroup
appKey – use SBMGroup.appKey
subnet – use SBMGroup.subnet
2.2.2 Android
Group:
name – use Group.getName
address – use Group.getAddress
virtualAddress – use Group.getVirtualAddress
parentGroup – use Group.getParentGroup
appKey – use Group.getAppKey
subnet – use Group.getSubnet
2.3 Node
In the next step you would need to extract the data from the above Node class structure for each Node object in the data base.
2.3.1 iOS
SBMNode
uuid – use SBMNode.uuid
name – use SBMNode.name
primaryElementAddress – use SBMNode.primaryElementAddress
devKey – use SBMNode.devKey
deviceCompositionData – use SBMNode.deviceCompositionData
settings – use SBMNode.settings
security – use SBMNode.security
elements – use SBMNode.elements
subnets – use SBMNode.subnets
2.3.2 Android
Node
uuid – use Node.getUuid
name – use Node.getName
primaryElementAddress – use Node.getPrimaryElementAddress
devKey – use Node.getDevKey
deviceCompositionData – use Node.getDeviceCompositionData
settings – use Node.getSettings
security – use Node.getSecurity
elements – use Node.getElements
subnets – use Node.getSubnets
2.4 Element
Next major step would be to extract the Element type objects which were extracted in the previous part.
2.4.1 iOS
SBMElement
name – use SBMElement.name
address - use SBMElement.address
index - use SBMElement.index
location - use SBMElement.location
sigModels - use SBMElement.sigModels
vendorModels - use SBMElement.vendorModels
2.4.2 Android
Element
name – use Element.getName
address – use Element.getAddress
index – use Element.getIndex
location – use Element.getLocation
sigModels – use Element.getSigModels
vendorModels – use Element.getVendormodels
2.5 Model
Having extracted the lists of supported models you would need to also export the Model structures as well.
2.5.1 iOS
SBMModel
identifier – use SBMModel.identifier
settings – use SBMModel.modelSettings
bindedGroups - use SBMModel.bindedGroups
2.5.2 Android
Model
identifier – use Model.getId()
settings – use Model.getModelSettings()
bindedGroups - use Model.getBindedGroups()
3. Import
Having successfully extracted all the necessary structures of a Mesh Network, it is now time to cover the import procedure to transfer it i.e. into another mobile device. It is a more complex in comparison to the export and there are a few challenges the Developer need to think about to come up with a solution. The following description would require at least basic understanding of Bluetooth Mesh Network mechanisms and safety solutions to enable the Developer to come up with an own solution for the given use case. In our implementation or rather code example we have taken a few shortcuts as this was not prepared for any particular real-life solution but rather for testing and reference for the Customers.
In general, the process would contain from a few key points mentioned below:
Firstly, it is important to note that the existing data base in the receiver device needs to be emptied before starting the procedure, which means that to be sure it was correctly prepared we would recommend using the clearDatabase method from the BluetoothMesh/ SBMBluetoothMesh class.
Secondly, the developer needs to take care of creating all the Mesh structure elements and filling them with appropriate data from the source file. For this purpose, we have prepared an implementation of Importer classes which would allow you to use the API to create the objects with specific configurations.
Lastly, it is necessary to initialize the imported Network with the initializeNetwork method from the BluetoothMesh/SBMBluetoothMesh class. At this point it is necessary for the developer to implement a mechanism for handling the unicast addresses of the provisioners and maintaining both the correct sequence number and IV Index for the Mesh Network.
3.1 Importer class
The Importer/SBMImporter class on both platforms provides two methods createNetwork and performImport. The first one is used to create an object of a NetworkImport/SBMNetworkImport class which contains the API to create and fill all the preliminary MeshNetwork structures in the data base on the receiving device. However, the end responsibility of preparing implementation of creating an appropriate logic to make use of the available functions is on the developer’s side. (The methods were listed and briefly described in the Class Documentation available in the Simplicity Studio directory mentioned in section 2 Export.) Once you have prepared the structure, next step you would need to do is to call the second method from the Importer class which would be performImport. It would transfer all the ‘Import’ objects into the default data base classes and clear the previous instances.
To help you better understand the usage of the Importer we have prepared a code sample for both iOS and Android which shows the usage of these methods.
3.1.1 iOS
func import(from json: String) {
let decoder = JSONDecoder()
do {
let meshData = try decoder.decode(JsonMesh.self, from: (json.data(using: .utf8))!)
// clear database to ensure it's ready for import
SBMBluetoothMesh.sharedInstance().clearDatabase()
let importer = meshData.createImporter()
try importer.performImport()
let network = SBMBluetoothMesh.sharedInstance().networks()[0]
let address = 0
let ivi = 0
try SBMBluetoothMesh.sharedInstance().initializeNetwork(item, address: address, ivIndex: ivi)
} catch {
}
}
func createImporter() -> SBMImporter {
let importer = SBMImporter()
let networkImport = importer.createNetwork((uuid.data(using: .hexadecimal))!)
networkImport.name = name
for item in netKeys {
item.performImport(network: networkImport)
}
// AppKeys & Groups
for item in groups {
item.performImport(network: networkImport, appKeys: appKeys)
}
for item in provisioners {
item.performImport(network: networkImport)
}
for node in nodes {
node.performImport(network: networkImport)
}
return importer
}
3.1.2 Android
fun import() {
val bluetoothMesh = BluetoothMesh.getInstance()
val customAddress = 0
val customIvIndex = 0
val importer = createImporter()
bluetoothMesh.clearDatabase()
importer.performImport()
val network = bluetoothMesh.networks.first()
bluetoothMesh.initializeNetwork(network, customAddress, customIvIndex)
}
private fun createImporter(): Importer {
val importer = Importer() importer.createNetwork(Converter.stringToUuid(jsonMesh.meshUUID!!))
.apply { name = jsonMesh.meshName }
.also {
handleAppKeys()
handleSubnets(it)
handleNodes(it)
handleProvisioners(it)
handleScenes(it)
}
return importer
}
3.2 Network initialization
As it can be seen, next step after a successful data import would be the Network initialization which can be done using the initializeNetwork method from the BluetoothMesh/SBMBluetoothMesh class. (In the code examples attached at sections 3.1.1 and 3.1.2 it can be seen how the usage should look like.) At this point, it is important for the Developer to understand the meaning of the three arguments that this function should receive because wrong values of these parameters may have big influence on the ability to control the imported Network by the mobile device.
Network
First of the arguments is relatively easy to define because it is going be a Network/SBMNetwork type instance which was created by the Importer/SBMImporter.performImport call and can be obtained by using the bluetoothMesh.networks.first() on Android side or SBMBluetoothMesh.networks[0] on the iOS platform.
Warning: With the current version of the ADK library which is 2.3.0 it is always going to be the first element of the networks list because it does not support importing multiple Network instances.
Address
According to the Bluetooth Mesh specification, a provisioner device is still regarded as a Node but with capabilities to add new devices to the Network. This implies that it needs to have a unicast address defined to be identifiable in the structure and it should be unique for a mobile device across mesh. One of the reasons why it is so important is that the address is strictly tied with a certain value of Sequence Number (check out section 3.2.1) and in a case when these two would not match, the provisioner the provisioner device would not be able to control the Network.
IV Index
Last but not least important is for the Developer to set a correct IV Index value and because the updates intervals of this value may differ across different Mesh Networks we can not be sure if the value has not changed since the data base has been exported so hard coding the value in the source file would not be a good solution. Luckily, the IV Index can be retrieved from the Secure Network Beacon (for more information please check Bluetooth Mesh Profile Specification rev. 1.0.1 chapter 3.9.3) data so our recommendation would be to implement a mechanism shown in the AN1200: Bluetooth Mesh for iOS and Android ADK section 13.5 Retrieving the IV Index from the Secure Network Beacon (section number valid for a document rev. 1.3) before calling the initializeNetwork method.
The sequence number, a 24-bit value contained in the sequence number field of the Network PDU, is primarily designed to protect against replay attacks. Elements within the same node may or may not share the sequence number space with each other. Having a different sequence number in each new Network PDU for every message source (identified by the unicast address contained in the SRC field) is critical for the security of the mesh network.
With a 24-bit sequence number, an element can transmit 16,777,216 messages before repeating a nonce. If an element transmits a message on average once every five seconds (representing a fairly high frequency message for known use cases), the element can transmit for 2.6 years before the nonce repeats.
Each element shall use strictly increasing sequence numbers for the Network PDUs it generates. Before the sequence number approaches the maximum value (0xFFFFFF), the element shall update the IV Index using the IV Update procedure (see Section 3.10.5). This is done to ensure that the sequence number will never wrap around.
The IV Index is a 32-bit value that is a shared network resource (i.e., all nodes in a mesh network share the same value of the IV Index and use it for all subnets they belong to).
The IV Index starts at 0x00000000 and is incremented during the IV Update procedure as described in Section 3.10.5. The timing when the value is incremented does not have to be exact, since the least significant bit is communicated within every Network PDU. Since the IV Index value is a 32-bit value, a mesh network can function approximately 5 trillion years before the IV Index will wrap.
The IV Index is shared within a network via Secure Network beacons (see Section 3.9.3). IV updates received on a subnet are processed and propagated to that subnet. The propagation happens by the device transmitting Secure Network beacons with the updated IV Index for that particular subnet. If a device on a primary subnet receives an update on the primary subnet, it shall propagate the IV update to all other subnets. If a device on a primary subnet receives an IV update on any other subnet, the update shall be ignored.
If a node is absent from a mesh network for a period of time, it can scan for Secure Network beacons (see Section 3.10.1) or use the IV Index Recovery procedure (see Section 3.10.6), and therefore set the IV Index value autonomously.
4. Conclusion
As stated at the beginning, the above article shows just a concept of using the Import and Export functionalities available in our mobile library. The mentioned sample implementation will be presented in details with the KBA_BT_0516 which should be available soon on our community forum. In case of any questions regarding this document you can create a support ticket at our web page or comment below.
KBA_BT_0515: Bluetooth Mesh Mobile - Import/Export Functionalities Concepts
KBA_BT_0515: Bluetooth Mesh Mobile - Import/Export Functionalities Concepts
1. Introduction
The Import and Export feature can be regarded as one of the most important ones in the Bluetooth Mesh Silicon Laboratories’ ADK. Introduced in the 2.2.0 release can allow the User to implement completely new approach to control the Mesh Network. One of the use cases examples we suggest, and which is enabled by this functionality, is active usage of multiple data bases or in other words multiple different Mesh networks in the same application. Currently as stated in the AN1200 document the library does not natively support it but it can be worked around by using the Import and Export. Surely there are many other scenarios to be invented by the Users, and knowing the importance of the topic, we have tried to sum up the key steps that need to be followed, in the Document below.
2. Export
First of all, it is necessary for the Developer to understand how and what information exactly need to be exported into an external file to successfully move the Mesh Network structure between the devices. The Silabs’ ADK does not specify what type of file it needs to be, it is up to Developer to choose a specific format for storing the data base. Our API only provides appropriate methods which can be used to extract the necessary information from the Mesh structure which main components are Network, Subnet, Group, Node, Element and Model. As a help for the Developers to get started, we have also prepared a sample implementation of the Export which you can use as a reference or a starting point for your own, in which we have decided to use a JSON string file as a container for our database.
Warning: Due to complexity of the dependencies between the different objects in the Mesh Structure we were not able to gather all the necessary API for export in this document. Below you will find just examples of the methods which can be used to extract the data. The rest of the necessary functions can be found in the class documentation which was attached to the BLE mesh package in the Simplicity Studio directory.
Also, we would highly recommend, after the successful export procedure, to keep the file protected by implementing an appropriate encryption method according to the Customer's requirements.
2.1 Network
Firstly, it would be necessary to get access to the Network type objects available in the data base. It would allow the developer to extract all the necessary information stored inside and will allow you to get the lists of existing Subnets, Provisioners and Scenes in the Mesh Network. Following that, it is going to be needed to extract the data stored in each of the objects of these three types and then the lower layer as well (SubnetSecurity, NetKey, AddressRange). The API samples were listed below for both platforms.
2.1.1. iOS
2.1.2 Android
2.2 Group
Having extracted a list of Group objects from each Subnet instance, you would need to access the data stored in those by using the following API samples.
2.2.1 iOS
2.2.2 Android
2.3 Node
In the next step you would need to extract the data from the above Node class structure for each Node object in the data base.
2.3.1 iOS
2.3.2 Android
2.4 Element
Next major step would be to extract the Element type objects which were extracted in the previous part.
2.4.1 iOS
2.4.2 Android
2.5 Model
Having extracted the lists of supported models you would need to also export the Model structures as well.
2.5.1 iOS
2.5.2 Android
3. Import
Having successfully extracted all the necessary structures of a Mesh Network, it is now time to cover the import procedure to transfer it i.e. into another mobile device. It is a more complex in comparison to the export and there are a few challenges the Developer need to think about to come up with a solution. The following description would require at least basic understanding of Bluetooth Mesh Network mechanisms and safety solutions to enable the Developer to come up with an own solution for the given use case. In our implementation or rather code example we have taken a few shortcuts as this was not prepared for any particular real-life solution but rather for testing and reference for the Customers.
In general, the process would contain from a few key points mentioned below:
3.1 Importer class
The Importer/SBMImporter class on both platforms provides two methods createNetwork and performImport. The first one is used to create an object of a NetworkImport/SBMNetworkImport class which contains the API to create and fill all the preliminary MeshNetwork structures in the data base on the receiving device. However, the end responsibility of preparing implementation of creating an appropriate logic to make use of the available functions is on the developer’s side. (The methods were listed and briefly described in the Class Documentation available in the Simplicity Studio directory mentioned in section 2 Export.) Once you have prepared the structure, next step you would need to do is to call the second method from the Importer class which would be performImport. It would transfer all the ‘Import’ objects into the default data base classes and clear the previous instances.
To help you better understand the usage of the Importer we have prepared a code sample for both iOS and Android which shows the usage of these methods.
3.1.1 iOS
3.1.2 Android
3.2 Network initialization
As it can be seen, next step after a successful data import would be the Network initialization which can be done using the initializeNetwork method from the BluetoothMesh/SBMBluetoothMesh class. (In the code examples attached at sections 3.1.1 and 3.1.2 it can be seen how the usage should look like.) At this point, it is important for the Developer to understand the meaning of the three arguments that this function should receive because wrong values of these parameters may have big influence on the ability to control the imported Network by the mobile device.
First of the arguments is relatively easy to define because it is going be a Network/SBMNetwork type instance which was created by the Importer/SBMImporter.performImport call and can be obtained by using the bluetoothMesh.networks.first() on Android side or SBMBluetoothMesh.networks[0] on the iOS platform.
Warning: With the current version of the ADK library which is 2.3.0 it is always going to be the first element of the networks list because it does not support importing multiple Network instances.
Address
According to the Bluetooth Mesh specification, a provisioner device is still regarded as a Node but with capabilities to add new devices to the Network. This implies that it needs to have a unicast address defined to be identifiable in the structure and it should be unique for a mobile device across mesh. One of the reasons why it is so important is that the address is strictly tied with a certain value of Sequence Number (check out section 3.2.1) and in a case when these two would not match, the provisioner the provisioner device would not be able to control the Network.
IV Index
Last but not least important is for the Developer to set a correct IV Index value and because the updates intervals of this value may differ across different Mesh Networks we can not be sure if the value has not changed since the data base has been exported so hard coding the value in the source file would not be a good solution. Luckily, the IV Index can be retrieved from the Secure Network Beacon (for more information please check Bluetooth Mesh Profile Specification rev. 1.0.1 chapter 3.9.3) data so our recommendation would be to implement a mechanism shown in the AN1200: Bluetooth Mesh for iOS and Android ADK section 13.5 Retrieving the IV Index from the Secure Network Beacon (section number valid for a document rev. 1.3) before calling the initializeNetwork method.
3.2.1 Sequence number
Definition taken from Bluetooth Mesh Profile Specification rev. 1.0.1 chapter 3.8.3.
3.2.2 IV Index
Definition taken from Bluetooth Mesh Profile Specification rev. 1.0.1 chapter 3.8.4.
4. Conclusion
As stated at the beginning, the above article shows just a concept of using the Import and Export functionalities available in our mobile library. The mentioned sample implementation will be presented in details with the KBA_BT_0516 which should be available soon on our community forum. In case of any questions regarding this document you can create a support ticket at our web page or comment below.