藍(lán)牙m(xù)esh network management
1.mesh網(wǎng)絡(luò)創(chuàng)建步驟
要?jiǎng)?chuàng)建一個(gè)mesh網(wǎng)絡(luò),必須要?jiǎng)?chuàng)建一個(gè)配網(wǎng)器。配網(wǎng)器應(yīng)該生成一個(gè)網(wǎng)絡(luò)密鑰,提供IV Index(也叫IV 索引),并分配單播地址。
網(wǎng)絡(luò)密鑰應(yīng)使用符合要求的隨機(jī)數(shù)生成器生成。
IV 索引應(yīng)設(shè)置為 0x00000000。
單播地址的設(shè)置應(yīng)由 配網(wǎng)器分配完成。
使用上述信息創(chuàng)建mesh網(wǎng)絡(luò),配網(wǎng)器的主元素應(yīng)分配單播地址。配網(wǎng)器的其他元素應(yīng)分配在單播地址之后的順序地址。
配網(wǎng)器可以通過(guò)使用主動(dòng)或被動(dòng)掃描掃描未配置設(shè)備信標(biāo)來(lái)找到未配置設(shè)備。然后,配網(wǎng)器可以將這些設(shè)備配置為mesh網(wǎng)絡(luò)中的節(jié)點(diǎn)。一旦這些設(shè)備被配置成功,配置客戶(hù)端就可以通過(guò)向它們提供應(yīng)用程序密鑰并設(shè)置發(fā)布和訂閱地址來(lái)配置節(jié)點(diǎn),以便節(jié)點(diǎn)可以相互通信。
注意:Provisioner 的設(shè)備密鑰僅在一個(gè) Provisioner 直接與另一個(gè) Provisioner 通信并且此設(shè)備密鑰已通過(guò) OOB 通信時(shí)使用。 Provisioner 的設(shè)備密鑰應(yīng)該在多個(gè) Provisioner 之間進(jìn)行協(xié)調(diào)。
2.臨時(shí)訪(fǎng)客訪(fǎng)問(wèn)(Temporary guest access)
可以為節(jié)點(diǎn)提供對(duì)mesh網(wǎng)絡(luò)的臨時(shí)訪(fǎng)客訪(fǎng)問(wèn)。 這是通過(guò)創(chuàng)建單獨(dú)的客人子網(wǎng),向客人提供單獨(dú)的網(wǎng)絡(luò)密鑰,來(lái)訪(fǎng)問(wèn)客人需要訪(fǎng)問(wèn)的節(jié)點(diǎn)。
向客人提供單獨(dú)的應(yīng)用程序密鑰,以限制客人在訪(fǎng)問(wèn)層可以訪(fǎng)問(wèn)的模型。
訪(fǎng)客永遠(yuǎn)不會(huì)獲得被排除在訪(fǎng)客訪(fǎng)問(wèn)之外的節(jié)點(diǎn)和模型使用的應(yīng)用程序密鑰或網(wǎng)絡(luò)密鑰。 只有屬于來(lái)賓子網(wǎng)的節(jié)點(diǎn)才會(huì)與來(lái)賓節(jié)點(diǎn)通信; 在這些節(jié)點(diǎn)中,客人只能使用綁定到客人應(yīng)用程序密鑰的模型。 這允許對(duì)特定節(jié)點(diǎn)和功能的訪(fǎng)客訪(fǎng)問(wèn)進(jìn)行非常精細(xì)的控制。
訪(fǎng)客無(wú)法在主子網(wǎng)上啟動(dòng) IV 索引更新。 這可以保護(hù)作為網(wǎng)絡(luò)共享資源的 IV 索引免受潛在惡意行為的影響。
訪(fǎng)客訪(fǎng)問(wèn)由配置客戶(hù)端使用由設(shè)備密鑰保護(hù)的配置服務(wù)器模型(Configuration Server model)配置。 可以為多個(gè)來(lái)賓提供來(lái)賓訪(fǎng)問(wèn)權(quán)限,每個(gè)來(lái)賓都在他們自己的來(lái)賓子網(wǎng)和模型域中。通過(guò)密鑰刷新程序刷新應(yīng)用程序和網(wǎng)絡(luò)密鑰,來(lái)撤銷(xiāo)訪(fǎng)客訪(fǎng)問(wèn)。
配網(wǎng)器在程序中的本質(zhì)
- 配網(wǎng)器的deviceKey是創(chuàng)建配網(wǎng)器時(shí),生辰改的128位隨機(jī)數(shù)。
- 配網(wǎng)器的NetworkKey是在創(chuàng)建配網(wǎng)器時(shí),將網(wǎng)絡(luò)中所有的networkKey的index賦值給配網(wǎng)器的NetKey屬性。
藍(lán)牙m(xù)esh中網(wǎng)絡(luò)信息需要導(dǎo)入導(dǎo)出,SIG確定了數(shù)據(jù)格式是Json。配網(wǎng)器是導(dǎo)出數(shù)據(jù)中的一部分。配網(wǎng)器在程序中是一個(gè)數(shù)據(jù)模型,配網(wǎng)器類(lèi)必須支持從JSon數(shù)據(jù)構(gòu)建模型和將數(shù)據(jù)模型歸檔為Json數(shù)據(jù)。在iOS Swift中,Provisioner繼承自Codable,在安卓Java中,Provisioner繼承自Parcelable。
配網(wǎng)器有哪些成員屬性和成員方法
如果沒(méi)有特別指出,說(shuō)明iOS和Android命名相同。
provisionerUuid:128-bit Device UUID,128位的設(shè)備UUID。
provisionerName:UTF-8 string, which should be a human readable name of the Provisioner. UTF8字符串,一個(gè)具有可閱讀性的名稱(chēng)。
allocatedUnicastRange:An array of unicast range objects.可供分配的單播地址范圍對(duì)象的數(shù)組。
allocatedGroupRange:An array of group range objects.可供分配的組播地址范圍對(duì)象的數(shù)組
allocatedSceneRange:An array of scene range objects.可供分配的虛擬地址范圍對(duì)象的數(shù)組。
安卓端:globalTtl,iOS端放在MeshNetworkManager.swift:defaultTtl :The Default TTL will be used for sending messages, if the value has not been set in the Provisioner's Node. By default it is set to 5, which is a reasonable value. The TTL shall be in range 2...127.用于設(shè)置配網(wǎng)器傳遞消息中可以轉(zhuǎn)發(fā)的次數(shù),默認(rèn)為5,取值范圍最好在2到127之間。
安卓端:sequenceNumber:配網(wǎng)器的序列號(hào)。
安卓端:provisionerAddress:給配網(wǎng)器分配的單播地址。
安卓端:lastSelected:是否是最后操作的配網(wǎng)器。
iOS端構(gòu)造方法
有三種
public init(name: String,
uuid: UUID,
allocatedUnicastRange: [AddressRange],
allocatedGroupRange: [AddressRange],
allocatedSceneRange: [SceneRange]) {
self.provisionerName = name
self.provisionerUuid = MeshUUID(uuid)
self.allocatedUnicastRange = allocatedUnicastRange.merged()
self.allocatedGroupRange = allocatedGroupRange.merged()
self.allocatedSceneRange = allocatedSceneRange.merged()
}
public convenience init(name: String,
allocatedUnicastRange: [AddressRange],
allocatedGroupRange: [AddressRange],
allocatedSceneRange: [SceneRange]) {
self.init(name: name,
uuid: UUID(),
allocatedUnicastRange: allocatedUnicastRange,
allocatedGroupRange: allocatedGroupRange,
allocatedSceneRange: allocatedSceneRange
)
}
public convenience init(name: String) {
self.init(name: name,
uuid: UUID(),
allocatedUnicastRange: [AddressRange.allUnicastAddresses],
allocatedGroupRange: [AddressRange.allGroupAddresses],
allocatedSceneRange: [SceneRange.allScenes]
)
}
配網(wǎng)器就是一個(gè)典型的智能手機(jī)或者其他移動(dòng)計(jì)算設(shè)備。盡管在一個(gè)網(wǎng)絡(luò)中只允許使用一個(gè)配網(wǎng)器,但是可能在配網(wǎng)設(shè)備上存在多個(gè)配網(wǎng)器。分享緩存數(shù)據(jù)和合并多個(gè)配網(wǎng)器的數(shù)據(jù)是必須實(shí)現(xiàn)的功能。
To provision a device, the provisioning bearer must be established between a Provisioner and a device. A device can be identified to a Provisioner by its Device UUID and other supplementary information that may also be provided.
After the provisioning bearer is established, the Provisioner establishes a shared secret with the device using an Elliptic Curve Diffie-Hellman (ECDH) protocol. It then authenticates the device using OOB information that is specific to that device. Such OOB information may include a public key of the device, a long secret, the requirement to input a value into the device, or the requirement to output a value on that device. Such OOB information also enables the authentication of that device. Once the device has been authenticated, the provisioning data is transmitted to the device encrypted with a key derived from that shared secret. The device key is derived from the ECDHSecret and ProvisioningSalt.
在安卓端的構(gòu)造方法
/**
* Constructs {@link Provisioner}
*/
public Provisioner(@NonNull final String provisionerUuid,
@NonNull final List<AllocatedUnicastRange> allocatedUnicastRanges,
@NonNull final List<AllocatedGroupRange> allocatedGroupRanges,
@NonNull final List<AllocatedSceneRange> allocatedSceneRanges,
@NonNull final String meshUuid) {
this.provisionerUuid = provisionerUuid.toUpperCase(Locale.US);
this.allocatedUnicastRanges = allocatedUnicastRanges;
this.allocatedGroupRanges = allocatedGroupRanges;
this.allocatedSceneRanges = allocatedSceneRanges;
this.meshUuid = meshUuid;
}
protected Provisioner(Parcel in) {
meshUuid = in.readString();
provisionerUuid = in.readString();
provisionerName = in.readString();
in.readTypedList(allocatedUnicastRanges, AllocatedUnicastRange.CREATOR);
in.readTypedList(allocatedGroupRanges, AllocatedGroupRange.CREATOR);
in.readTypedList(allocatedSceneRanges, AllocatedSceneRange.CREATOR);
sequenceNumber = in.readInt();
provisionerAddress = in.readInt();
globalTtl = in.readInt();
lastSelected = in.readByte() != 0;
}
public static final Creator<Provisioner> CREATOR = new Creator<Provisioner>() {
@Override
public Provisioner createFromParcel(Parcel in) {
return new Provisioner(in);
}
@Override
public Provisioner[] newArray(int size) {
return new Provisioner[size];
}
};