From 06267244229ae581ceb14fd59c61f5f46aa9d802 Mon Sep 17 00:00:00 2001 From: hariharasudhanPerumalSamy Date: Wed, 29 Dec 2021 11:42:05 +0100 Subject: [PATCH 1/5] added 'name' as one of the param for addProvisioner (#211) * added 'name' as one of the param for addProvisioner * document changes + bump pkg version Co-authored-by: R0m4in-dooz --- CHANGELOG.md | 4 ++++ example/pubspec.lock | 2 +- .../Channels/Arguments/AddProvisionerArguments.swift | 1 + pubspec.yaml | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b93f8e607..e0baa9b1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.1 + +- fix bug in adding a provisioner on iOS device + ## 0.5.0 - expose some of the API needed to execute a Key Refresh Procedure on Android using [this](https://github.com/NordicSemiconductor/Android-nRF-Mesh-Library/pull/381) Pull Request as reference diff --git a/example/pubspec.lock b/example/pubspec.lock index 4cd9ea8b5..c8f9dabb4 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -326,7 +326,7 @@ packages: path: ".." relative: true source: path - version: "0.5.0" + version: "0.5.1" package_config: dependency: transitive description: diff --git a/ios/Classes/DoozMeshNetwork/Channels/Arguments/AddProvisionerArguments.swift b/ios/Classes/DoozMeshNetwork/Channels/Arguments/AddProvisionerArguments.swift index 1a610ddc9..b1c96d51a 100644 --- a/ios/Classes/DoozMeshNetwork/Channels/Arguments/AddProvisionerArguments.swift +++ b/ios/Classes/DoozMeshNetwork/Channels/Arguments/AddProvisionerArguments.swift @@ -6,6 +6,7 @@ // struct AddProvisionerArguments: BaseFlutterArguments { + let name: String let unicastAddressRange: Int let groupAddressRange: Int let sceneAddressRange: Int diff --git a/pubspec.yaml b/pubspec.yaml index 8ef204857..bdf97c811 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: nordic_nrf_mesh description: A Flutter plugin to enable mesh network management and communication using Nordic's SDKs. It also provides the ability to open BLE connection with mesh nodes using some other flutter package. -version: 0.5.0 +version: 0.5.1 environment: sdk: ">=2.12.0 <3.0.0" From 141baa5c35da9bd548ea1423ba7806aa7db44b48 Mon Sep 17 00:00:00 2001 From: R0m4in-dooz <72380352+R0m4in-dooz@users.noreply.github.com> Date: Thu, 13 Jan 2022 18:30:48 +0100 Subject: [PATCH 2/5] Feature : config beacon msg (#212) --- CHANGELOG.md | 3 +- .../nordic_nrf_mesh/DoozMeshManagerApi.kt | 13 ++ .../DoozMeshStatusCallbacks.kt | 11 + example/pubspec.lock | 2 +- .../Arguments/ConfigBeaconGetArguments.swift | 10 + .../Arguments/ConfigBeaconSetArguments.swift | 11 + .../Channels/DoozMeshManagerApiChannel.swift | 6 + ...ozMeshManagerApi+MeshNetworkDelegate.swift | 81 +------- .../DoozMeshManagerApi.swift | 22 ++ ios/Classes/Utils/Constants.swift | 3 + lib/src/ble/ble_manager_callbacks.dart | 1 + lib/src/ble/ble_mesh_manager.dart | 1 + .../config_beacon_status.dart | 11 + .../config_beacon_status.freezed.dart | 189 ++++++++++++++++++ .../config_beacon_status.g.dart | 21 ++ lib/src/events/data/event_data.dart | 1 + lib/src/events/mesh_manager_api_events.dart | 1 + lib/src/mesh_manager_api.dart | 47 ++++- pubspec.yaml | 2 +- 19 files changed, 359 insertions(+), 77 deletions(-) create mode 100644 ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconGetArguments.swift create mode 100644 ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconSetArguments.swift create mode 100644 lib/src/events/data/config_beacon_status/config_beacon_status.dart create mode 100644 lib/src/events/data/config_beacon_status/config_beacon_status.freezed.dart create mode 100644 lib/src/events/data/config_beacon_status/config_beacon_status.g.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index e0baa9b1a..6d9585066 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ -## 0.5.1 +## 0.6.0 - fix bug in adding a provisioner on iOS device +- expose ConfigBeacon API ## 0.5.0 diff --git a/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshManagerApi.kt b/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshManagerApi.kt index b1784b29f..d4ae714e0 100644 --- a/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshManagerApi.kt +++ b/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshManagerApi.kt @@ -176,6 +176,19 @@ class DoozMeshManagerApi(context: Context, binaryMessenger: BinaryMessenger) : S mMeshManagerApi.createMeshPdu(address, meshMessage) result.success(null) } + "getSNBeacon" -> { + val address = call.argument("address")!! + val meshMessage: MeshMessage = ConfigBeaconGet() + mMeshManagerApi.createMeshPdu(address, meshMessage) + result.success(null) + } + "setSNBeacon" -> { + val address = call.argument("address")!! + val enable = call.argument("enable")!! + val meshMessage: MeshMessage = ConfigBeaconSet(enable) + mMeshManagerApi.createMeshPdu(address, meshMessage) + result.success(null) + } "setNetworkTransmitSettings" -> { val address = call.argument("address")!! val transmitCount = call.argument("transmitCount")!! diff --git a/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshStatusCallbacks.kt b/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshStatusCallbacks.kt index 37b07a644..c8256a7eb 100644 --- a/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshStatusCallbacks.kt +++ b/android/src/main/kotlin/fr/dooz/nordic_nrf_mesh/DoozMeshStatusCallbacks.kt @@ -231,6 +231,17 @@ class DoozMeshStatusCallbacks(var eventSink: EventChannel.EventSink?): MeshStatu )) } } + is ConfigBeaconStatus -> { + Log.d(tag, "received a ConfigBeaconStatus") + Handler(Looper.getMainLooper()).post { + eventSink?.success(mapOf( + "eventName" to "onConfigBeaconStatus", + "source" to meshMessage.src, + "destination" to meshMessage.dst, + "enable" to meshMessage.isEnable() + )) + } + } else -> { Log.d(tag, "Unknown message received :" + meshMessage.javaClass.toString()) } diff --git a/example/pubspec.lock b/example/pubspec.lock index c8f9dabb4..99d7634dd 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -326,7 +326,7 @@ packages: path: ".." relative: true source: path - version: "0.5.1" + version: "0.6.0" package_config: dependency: transitive description: diff --git a/ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconGetArguments.swift b/ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconGetArguments.swift new file mode 100644 index 000000000..714295857 --- /dev/null +++ b/ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconGetArguments.swift @@ -0,0 +1,10 @@ +// +// ConfigBeaconGetArguments.swift +// nordic_nrf_mesh +// +// Created by OZEO DOOZ on 07/01/2022. +// + +struct ConfigBeaconGetArguments: BaseFlutterArguments { + let address: Int +} diff --git a/ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconSetArguments.swift b/ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconSetArguments.swift new file mode 100644 index 000000000..7bad9af18 --- /dev/null +++ b/ios/Classes/DoozMeshManagerApi/Channels/Arguments/ConfigBeaconSetArguments.swift @@ -0,0 +1,11 @@ +// +// ConfigBeaconSetArguments.swift +// nordic_nrf_mesh +// +// Created by OZEO DOOZ on 07/01/2022. +// + +struct ConfigBeaconSetArguments: BaseFlutterArguments { + let address: Int + let enable: Bool +} diff --git a/ios/Classes/DoozMeshManagerApi/Channels/DoozMeshManagerApiChannel.swift b/ios/Classes/DoozMeshManagerApi/Channels/DoozMeshManagerApiChannel.swift index dc5d37f78..660a9844b 100644 --- a/ios/Classes/DoozMeshManagerApi/Channels/DoozMeshManagerApiChannel.swift +++ b/ios/Classes/DoozMeshManagerApi/Channels/DoozMeshManagerApiChannel.swift @@ -33,6 +33,8 @@ enum DoozMeshManagerApiChannel { case getNetworkTransmitSettings(_ data: GetNetworkTransmitSettingsArguments) case getDefaultTtl(_ data: GetDefaultTtlArguments) case setDefaultTtl(_ data: SetDefaultTtlArguments) + case getSNBeacon(_ data: ConfigBeaconGetArguments) + case setSNBeacon(_ data: ConfigBeaconSetArguments) case sendConfigModelSubscriptionDeleteAll(_ data: SendConfigModelSubscriptionDeleteAllArguments) case sendConfigModelPublicationSet(_ data: SendConfigModelPublicationSetArguments) case sendLightLightness(_ data: SendLightLightnessArguments) @@ -101,6 +103,10 @@ enum DoozMeshManagerApiChannel { self = .getDefaultTtl(try GetDefaultTtlArguments(arguments)) case "setDefaultTtl": self = .setDefaultTtl(try SetDefaultTtlArguments(arguments)) + case "getSNBeacon": + self = .getSNBeacon(try ConfigBeaconGetArguments(arguments)) + case "setSNBeacon": + self = .setSNBeacon(try ConfigBeaconSetArguments(arguments)) case "sendConfigModelSubscriptionDeleteAll": self = .sendConfigModelSubscriptionDeleteAll(try SendConfigModelSubscriptionDeleteAllArguments(arguments)) case "sendConfigModelPublicationSet": diff --git a/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi+MeshNetworkDelegate.swift b/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi+MeshNetworkDelegate.swift index 7a6e3b2a0..47ae67d9a 100644 --- a/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi+MeshNetworkDelegate.swift +++ b/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi+MeshNetworkDelegate.swift @@ -12,65 +12,47 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ func meshNetworkManager(_ manager: MeshNetworkManager, didReceiveMessage message: MeshMessage, sentFrom source: Address, to destination: Address) { print("📣 didReceiveMessage : \(message) from \(source) to \(destination)") - // Handle the message based on its type. switch message { - case let status as ConfigModelAppStatus: - if status.isSuccess { let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue: MessageEvent.onConfigModelAppStatus.rawValue, EventSinkKeys.message.elementAddress.rawValue: status.elementAddress, EventSinkKeys.message.modelId.rawValue: status.modelId, EventSinkKeys.message.appKeyIndex.rawValue: status.applicationKeyIndex, ] - _sendFlutterMessage(message) - } else { break } - case is ConfigCompositionDataStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onConfigCompositionDataStatus.rawValue, EventSinkKeys.source.rawValue : source, EventSinkKeys.message.meshMessage.rawValue : [ EventSinkKeys.message.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination ] - ] - _sendFlutterMessage(message) - case let status as ConfigAppKeyStatus: if status.isSuccess { let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onConfigAppKeyStatus.rawValue, EventSinkKeys.source.rawValue : source, EventSinkKeys.message.meshMessage.rawValue : [ EventSinkKeys.message.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination ] - ] - _sendFlutterMessage(message) }else { break } - case let status as GenericLevelStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onGenericLevelStatus.rawValue, EventSinkKeys.message.level.rawValue : status.level, EventSinkKeys.message.targetLevel.rawValue : status.targetLevel ?? 0, @@ -78,30 +60,20 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.message.destination.rawValue : destination, EventSinkKeys.message.transitionResolution.rawValue : status.remainingTime?.stepResolution.rawValue ?? 0, EventSinkKeys.message.transitionSteps.rawValue : status.remainingTime?.steps ?? 0, - ] - _sendFlutterMessage(message) - case let status as GenericOnOffStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onGenericOnOffStatus.rawValue, EventSinkKeys.source.rawValue : source, EventSinkKeys.message.presentState.rawValue : status.isOn, EventSinkKeys.message.targetState.rawValue : status.targetState ?? false, EventSinkKeys.message.transitionResolution.rawValue : status.remainingTime?.stepResolution.rawValue ?? 0, EventSinkKeys.message.transitionSteps.rawValue : status.remainingTime?.steps ?? 0, - ] - _sendFlutterMessage(message) - case let status as ConfigModelSubscriptionStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onConfigModelSubscriptionStatus.rawValue, EventSinkKeys.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination, @@ -109,15 +81,10 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.message.subscriptionAddress.rawValue : status.address, EventSinkKeys.message.modelIdentifier.rawValue : status.modelIdentifier, EventSinkKeys.message.isSuccessful.rawValue : status.isSuccess, - ] - _sendFlutterMessage(message) - case let status as ConfigModelPublicationStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onConfigModelPublicationStatus.rawValue, EventSinkKeys.message.elementAddress.rawValue: status.elementAddress, EventSinkKeys.message.publishAddress.rawValue : status.publish.publicationAddress.address, @@ -130,15 +97,10 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.message.retransmitIntervalSteps.rawValue : status.publish.retransmit.steps, EventSinkKeys.message.modelIdentifier.rawValue : status.modelIdentifier, EventSinkKeys.message.isSuccessful.rawValue : status.isSuccess, - ] - _sendFlutterMessage(message) - case let status as LightLightnessStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onLightLightnessStatus.rawValue, EventSinkKeys.message.presentLightness.rawValue : status.lightness, EventSinkKeys.message.targetLightness.rawValue : status.targetLightness ?? 0, @@ -146,15 +108,10 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.message.destination.rawValue : destination, EventSinkKeys.message.transitionResolution.rawValue : status.remainingTime?.stepResolution.rawValue ?? 0, EventSinkKeys.message.transitionSteps.rawValue : status.remainingTime?.steps ?? 0, - ] - _sendFlutterMessage(message) - case let status as LightCTLStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onLightCtlStatus.rawValue, EventSinkKeys.message.presentLightness.rawValue : status.lightness, EventSinkKeys.message.targetLightness.rawValue : status.targetLightness ?? 0, @@ -164,15 +121,10 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.message.destination.rawValue : destination, EventSinkKeys.message.transitionResolution.rawValue : status.remainingTime?.stepResolution.rawValue ?? 0, EventSinkKeys.message.transitionSteps.rawValue : status.remainingTime?.steps ?? 0, - ] - _sendFlutterMessage(message) - case let status as LightHSLStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onLightHslStatus.rawValue, EventSinkKeys.message.presentLightness.rawValue : status.lightness, EventSinkKeys.message.presentHue.rawValue : status.hue, @@ -181,28 +133,18 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.message.destination.rawValue : destination, EventSinkKeys.message.transitionResolution.rawValue : status.remainingTime?.stepResolution.rawValue ?? 0, EventSinkKeys.message.transitionSteps.rawValue : status.remainingTime?.steps ?? 0, - ] - _sendFlutterMessage(message) - case _ as ConfigNodeResetStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onConfigNodeResetStatus.rawValue, EventSinkKeys.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination, EventSinkKeys.message.success.rawValue : true, - ] - _sendFlutterMessage(message) - case let status as ConfigNetworkTransmitStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onConfigNetworkTransmitStatus.rawValue, EventSinkKeys.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination, @@ -210,23 +152,24 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.message.transmitIntervalSteps.rawValue : status.steps, ] - _sendFlutterMessage(message) - case let status as ConfigDefaultTtlStatus: - let message: FlutterMessage = [ - EventSinkKeys.eventName.rawValue : MessageEvent.onConfigDefaultTtlStatus.rawValue, EventSinkKeys.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination, EventSinkKeys.message.ttl.rawValue : status.ttl, - ] - + _sendFlutterMessage(message) + case let status as ConfigBeaconStatus: + let message: FlutterMessage = [ + EventSinkKeys.eventName.rawValue : MessageEvent.onConfigBeaconStatus.rawValue, + EventSinkKeys.source.rawValue : source, + EventSinkKeys.message.destination.rawValue : destination, + EventSinkKeys.message.enable.rawValue : status.isEnabled, + ] _sendFlutterMessage(message) case let status as MagicLevelSetStatus: - let message: FlutterMessage = [ EventSinkKeys.eventName.rawValue : MessageEvent.onMagicLevelSetStatus.rawValue, EventSinkKeys.message.io.rawValue : status.mIO, @@ -236,7 +179,6 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination, ] - _sendFlutterMessage(message) case let status as MagicLevelGetStatus: let message: FlutterMessage = [ @@ -248,14 +190,7 @@ extension DoozMeshManagerApi: MeshNetworkDelegate{ EventSinkKeys.source.rawValue : source, EventSinkKeys.message.destination.rawValue : destination, ] - _sendFlutterMessage(message) - // case let list as ConfigModelAppList: - // break - // - // case let status as ConfigModelSubscriptionList: - // break - default: break } diff --git a/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi.swift b/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi.swift index 56ef80bac..beb71f740 100644 --- a/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi.swift +++ b/ios/Classes/DoozMeshManagerApi/DoozMeshManagerApi.swift @@ -421,6 +421,28 @@ private extension DoozMeshManagerApi { result(FlutterError(code: String(nsError.code), message: nsError.localizedDescription, details: nil)) } break + case .getSNBeacon(let data): + let message = ConfigBeaconGet() + let _node = doozMeshNetwork?.meshNetwork.node(withAddress: Address(exactly: data.address)!) + do { + _ = try meshNetworkManager.send(message, to: _node!) + result(nil) + } catch { + let nsError = error as NSError + result(FlutterError(code: String(nsError.code), message: nsError.localizedDescription, details: nil)) + } + break + case .setSNBeacon(let data): + let message = ConfigBeaconSet(enable: Bool(data.enable)) + let _node = doozMeshNetwork?.meshNetwork.node(withAddress: Address(exactly: data.address)!) + do { + _ = try meshNetworkManager.send(message, to: _node!) + result(nil) + } catch { + let nsError = error as NSError + result(FlutterError(code: String(nsError.code), message: nsError.localizedDescription, details: nil)) + } + break case .sendConfigModelSubscriptionDeleteAll(let data): if diff --git a/ios/Classes/Utils/Constants.swift b/ios/Classes/Utils/Constants.swift index 442088176..a5322b3d5 100644 --- a/ios/Classes/Utils/Constants.swift +++ b/ios/Classes/Utils/Constants.swift @@ -114,6 +114,7 @@ enum MessageEvent: String{ case onConfigNodeResetStatus case onConfigNetworkTransmitStatus case onConfigDefaultTtlStatus + case onConfigBeaconStatus case onMagicLevelSetStatus case onMagicLevelGetStatus } @@ -167,6 +168,8 @@ enum EventSinkKeys: String{ case index case value case correlation + + case enable } enum network: String{ diff --git a/lib/src/ble/ble_manager_callbacks.dart b/lib/src/ble/ble_manager_callbacks.dart index c45ac163c..f7dc3253a 100644 --- a/lib/src/ble/ble_manager_callbacks.dart +++ b/lib/src/ble/ble_manager_callbacks.dart @@ -49,6 +49,7 @@ abstract class BleManagerCallbacks { // Stream onDeviceNotSupported; + /// A method that should be used to update the stored MTU so the native code properly constructs the PDUs Future sendMtuToMeshManagerApi(int mtu); bool shouldEnableBatteryLevelNotifications(DiscoveredDevice device) => false; diff --git a/lib/src/ble/ble_mesh_manager.dart b/lib/src/ble/ble_mesh_manager.dart index e7e34fd54..de56861c7 100644 --- a/lib/src/ble/ble_mesh_manager.dart +++ b/lib/src/ble/ble_mesh_manager.dart @@ -48,6 +48,7 @@ class BleMeshManager extends BleManager { @override Future isRequiredServiceSupported(bool shouldCheckDoozCustomService) async { _discoveredServices = await bleInstance.discoverServices(device!.id); + _log('services $_discoveredServices'); isProvisioningCompleted = false; if (hasExpectedService(meshProxyUuid)) { isProvisioningCompleted = true; diff --git a/lib/src/events/data/config_beacon_status/config_beacon_status.dart b/lib/src/events/data/config_beacon_status/config_beacon_status.dart new file mode 100644 index 000000000..cd9c1e923 --- /dev/null +++ b/lib/src/events/data/config_beacon_status/config_beacon_status.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'config_beacon_status.freezed.dart'; +part 'config_beacon_status.g.dart'; + +@freezed +class ConfigBeaconStatus with _$ConfigBeaconStatus { + const factory ConfigBeaconStatus(int source, int destination, bool enable) = _ConfigBeaconStatus; + + factory ConfigBeaconStatus.fromJson(Map json) => _$ConfigBeaconStatusFromJson(json); +} diff --git a/lib/src/events/data/config_beacon_status/config_beacon_status.freezed.dart b/lib/src/events/data/config_beacon_status/config_beacon_status.freezed.dart new file mode 100644 index 000000000..cf1dfb304 --- /dev/null +++ b/lib/src/events/data/config_beacon_status/config_beacon_status.freezed.dart @@ -0,0 +1,189 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides + +part of 'config_beacon_status.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + +ConfigBeaconStatus _$ConfigBeaconStatusFromJson(Map json) { + return _ConfigBeaconStatus.fromJson(json); +} + +/// @nodoc +class _$ConfigBeaconStatusTearOff { + const _$ConfigBeaconStatusTearOff(); + + _ConfigBeaconStatus call(int source, int destination, bool enable) { + return _ConfigBeaconStatus( + source, + destination, + enable, + ); + } + + ConfigBeaconStatus fromJson(Map json) { + return ConfigBeaconStatus.fromJson(json); + } +} + +/// @nodoc +const $ConfigBeaconStatus = _$ConfigBeaconStatusTearOff(); + +/// @nodoc +mixin _$ConfigBeaconStatus { + int get source => throw _privateConstructorUsedError; + int get destination => throw _privateConstructorUsedError; + bool get enable => throw _privateConstructorUsedError; + + Map toJson() => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $ConfigBeaconStatusCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $ConfigBeaconStatusCopyWith<$Res> { + factory $ConfigBeaconStatusCopyWith(ConfigBeaconStatus value, $Res Function(ConfigBeaconStatus) then) = + _$ConfigBeaconStatusCopyWithImpl<$Res>; + $Res call({int source, int destination, bool enable}); +} + +/// @nodoc +class _$ConfigBeaconStatusCopyWithImpl<$Res> implements $ConfigBeaconStatusCopyWith<$Res> { + _$ConfigBeaconStatusCopyWithImpl(this._value, this._then); + + final ConfigBeaconStatus _value; + // ignore: unused_field + final $Res Function(ConfigBeaconStatus) _then; + + @override + $Res call({ + Object? source = freezed, + Object? destination = freezed, + Object? enable = freezed, + }) { + return _then(_value.copyWith( + source: source == freezed + ? _value.source + : source // ignore: cast_nullable_to_non_nullable + as int, + destination: destination == freezed + ? _value.destination + : destination // ignore: cast_nullable_to_non_nullable + as int, + enable: enable == freezed + ? _value.enable + : enable // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +abstract class _$ConfigBeaconStatusCopyWith<$Res> implements $ConfigBeaconStatusCopyWith<$Res> { + factory _$ConfigBeaconStatusCopyWith(_ConfigBeaconStatus value, $Res Function(_ConfigBeaconStatus) then) = + __$ConfigBeaconStatusCopyWithImpl<$Res>; + @override + $Res call({int source, int destination, bool enable}); +} + +/// @nodoc +class __$ConfigBeaconStatusCopyWithImpl<$Res> extends _$ConfigBeaconStatusCopyWithImpl<$Res> + implements _$ConfigBeaconStatusCopyWith<$Res> { + __$ConfigBeaconStatusCopyWithImpl(_ConfigBeaconStatus _value, $Res Function(_ConfigBeaconStatus) _then) + : super(_value, (v) => _then(v as _ConfigBeaconStatus)); + + @override + _ConfigBeaconStatus get _value => super._value as _ConfigBeaconStatus; + + @override + $Res call({ + Object? source = freezed, + Object? destination = freezed, + Object? enable = freezed, + }) { + return _then(_ConfigBeaconStatus( + source == freezed + ? _value.source + : source // ignore: cast_nullable_to_non_nullable + as int, + destination == freezed + ? _value.destination + : destination // ignore: cast_nullable_to_non_nullable + as int, + enable == freezed + ? _value.enable + : enable // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$_ConfigBeaconStatus implements _ConfigBeaconStatus { + const _$_ConfigBeaconStatus(this.source, this.destination, this.enable); + + factory _$_ConfigBeaconStatus.fromJson(Map json) => _$_$_ConfigBeaconStatusFromJson(json); + + @override + final int source; + @override + final int destination; + @override + final bool enable; + + @override + String toString() { + return 'ConfigBeaconStatus(source: $source, destination: $destination, enable: $enable)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is _ConfigBeaconStatus && + (identical(other.source, source) || const DeepCollectionEquality().equals(other.source, source)) && + (identical(other.destination, destination) || + const DeepCollectionEquality().equals(other.destination, destination)) && + (identical(other.enable, enable) || const DeepCollectionEquality().equals(other.enable, enable))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ + const DeepCollectionEquality().hash(source) ^ + const DeepCollectionEquality().hash(destination) ^ + const DeepCollectionEquality().hash(enable); + + @JsonKey(ignore: true) + @override + _$ConfigBeaconStatusCopyWith<_ConfigBeaconStatus> get copyWith => + __$ConfigBeaconStatusCopyWithImpl<_ConfigBeaconStatus>(this, _$identity); + + @override + Map toJson() { + return _$_$_ConfigBeaconStatusToJson(this); + } +} + +abstract class _ConfigBeaconStatus implements ConfigBeaconStatus { + const factory _ConfigBeaconStatus(int source, int destination, bool enable) = _$_ConfigBeaconStatus; + + factory _ConfigBeaconStatus.fromJson(Map json) = _$_ConfigBeaconStatus.fromJson; + + @override + int get source => throw _privateConstructorUsedError; + @override + int get destination => throw _privateConstructorUsedError; + @override + bool get enable => throw _privateConstructorUsedError; + @override + @JsonKey(ignore: true) + _$ConfigBeaconStatusCopyWith<_ConfigBeaconStatus> get copyWith => throw _privateConstructorUsedError; +} diff --git a/lib/src/events/data/config_beacon_status/config_beacon_status.g.dart b/lib/src/events/data/config_beacon_status/config_beacon_status.g.dart new file mode 100644 index 000000000..256ccd860 --- /dev/null +++ b/lib/src/events/data/config_beacon_status/config_beacon_status.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'config_beacon_status.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$_ConfigBeaconStatus _$_$_ConfigBeaconStatusFromJson(Map json) { + return _$_ConfigBeaconStatus( + json['source'] as int, + json['destination'] as int, + json['enable'] as bool, + ); +} + +Map _$_$_ConfigBeaconStatusToJson(_$_ConfigBeaconStatus instance) => { + 'source': instance.source, + 'destination': instance.destination, + 'enable': instance.enable, + }; diff --git a/lib/src/events/data/event_data.dart b/lib/src/events/data/event_data.dart index 5439c921e..f5eac1e5f 100644 --- a/lib/src/events/data/event_data.dart +++ b/lib/src/events/data/event_data.dart @@ -1,4 +1,5 @@ export 'config_app_key_status/config_app_key_status.dart'; +export 'config_beacon_status/config_beacon_status.dart'; export 'config_composition_data_status/config_composition_data_status.dart'; export 'config_default_ttl_status/config_default_ttl_status.dart'; export 'config_key_refresh_phase_status/config_key_refresh_phase_status.dart'; diff --git a/lib/src/events/mesh_manager_api_events.dart b/lib/src/events/mesh_manager_api_events.dart index 5f3e8cf5b..5e46580ab 100644 --- a/lib/src/events/mesh_manager_api_events.dart +++ b/lib/src/events/mesh_manager_api_events.dart @@ -44,4 +44,5 @@ class MeshManagerApiEvent { static const configNetworkTransmitStatus = MeshManagerApiEvent._('onConfigNetworkTransmitStatus'); static const configDefaultTtlStatus = MeshManagerApiEvent._('onConfigDefaultTtlStatus'); static const configKeyRefreshPhaseStatus = MeshManagerApiEvent._('onConfigKeyRefreshPhaseStatus'); + static const configBeaconStatus = MeshManagerApiEvent._('onConfigBeaconStatus'); } diff --git a/lib/src/mesh_manager_api.dart b/lib/src/mesh_manager_api.dart index 715754e5d..02bcab6fb 100644 --- a/lib/src/mesh_manager_api.dart +++ b/lib/src/mesh_manager_api.dart @@ -38,6 +38,7 @@ class MeshManagerApi { late final _onConfigNodeResetStatusController = StreamController.broadcast(); late final _onConfigNetworkTransmitStatusController = StreamController.broadcast(); late final _onConfigDefaultTtlStatusController = StreamController.broadcast(); + late final _onConfigBeaconStatusController = StreamController.broadcast(); late final _onLightLightnessStatusController = StreamController.broadcast(); late final _onLightCtlStatusController = StreamController.broadcast(); @@ -66,6 +67,7 @@ class MeshManagerApi { late StreamSubscription _onConfigNodeResetStatusSubscription; late StreamSubscription _onConfigNetworkTransmitStatusSubscription; late StreamSubscription _onConfigDefaultTtlStatusSubscription; + late StreamSubscription _onConfigBeaconStatusSubscription; late StreamSubscription _onLightLightnessStatusSubscription; late StreamSubscription _onLightCtlStatusSubscription; @@ -187,7 +189,12 @@ class MeshManagerApi { .where((event) => event['eventName'] == MeshManagerApiEvent.configKeyRefreshPhaseStatus.value) .map((event) => ConfigKeyRefreshPhaseStatus.fromJson(event)) .listen(_onConfigKeyRefreshPhaseStatusController.add); + _onConfigBeaconStatusSubscription = _eventChannelStream + .where((event) => event['eventName'] == MeshManagerApiEvent.configBeaconStatus.value) + .map((event) => ConfigBeaconStatus.fromJson(event)) + .listen(_onConfigBeaconStatusController.add); } + Stream get onConfigBeaconStatus => _onConfigBeaconStatusController.stream; Stream get onConfigNetworkTransmitStatus => _onConfigNetworkTransmitStatusController.stream; @@ -328,7 +335,9 @@ class MeshManagerApi { _onConfigNetworkTransmitStatusController.close(), _onConfigDefaultTtlStatusController.close(), _onConfigKeyRefreshPhaseStatusSubscription.cancel(), - _onConfigKeyRefreshPhaseStatusController.close() + _onConfigKeyRefreshPhaseStatusController.close(), + _onConfigBeaconStatusSubscription.cancel(), + _onConfigBeaconStatusController.close() ]); Future loadMeshNetwork() async { @@ -740,6 +749,42 @@ class MeshManagerApi { } } + /// Will get the current beacon configuration + Future getSNBeacon(int address) async { + if (Platform.isAndroid || Platform.isIOS) { + final status = _onConfigBeaconStatusController.stream.firstWhere( + (element) => element.source == address, + orElse: () => const ConfigBeaconStatus(-1, -1, false), + ); + await _methodChannel.invokeMethod('getSNBeacon', {'address': address}); + return status; + } else { + throw UnimplementedError('${Platform.environment} not supported'); + } + } + + /// Will set the beacon configuration. + /// + /// If [enable] is true, the node that receives this message will periodically send Secure Network Beacons. + Future setSNBeacon({ + int address = 0xFFFF, + bool enable = false, + }) async { + if (Platform.isAndroid || Platform.isIOS) { + final status = _onConfigBeaconStatusController.stream.firstWhere( + (element) => element.source == address, + orElse: () => const ConfigBeaconStatus(-1, -1, false), + ); + await _methodChannel.invokeMethod('setSNBeacon', { + 'address': address, + 'enable': enable, + }); + return status; + } else { + throw UnimplementedError('${Platform.environment} not supported'); + } + } + String getDeviceUuid(List serviceData) { var msb = 0; var lsb = 0; diff --git a/pubspec.yaml b/pubspec.yaml index bdf97c811..2e3e08ede 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: nordic_nrf_mesh description: A Flutter plugin to enable mesh network management and communication using Nordic's SDKs. It also provides the ability to open BLE connection with mesh nodes using some other flutter package. -version: 0.5.1 +version: 0.6.0 environment: sdk: ">=2.12.0 <3.0.0" From 3c531e758366fb4606645f9c4cc686d7ee4c534c Mon Sep 17 00:00:00 2001 From: R0m4in-dooz <72380352+R0m4in-dooz@users.noreply.github.com> Date: Fri, 14 Jan 2022 12:44:53 +0100 Subject: [PATCH 3/5] Bug : truncated Secure Network Beacon upon connection & SecureNetworkBeacon.canOverwrite always returning false (#214) * MTU negociation is now done in initGatt method, rename BleManagerFailureCode.negociation to BleManagerFailureCode.initGatt * update submodule * remove unused enableNotificationValue + rename kConnectionTimeout to _kConnectionTimeout * update CHANGELOG.md --- Android-nRF-Mesh-Library-1 | 2 +- CHANGELOG.md | 2 ++ lib/src/ble/ble_manager.dart | 28 +++++++++++----------------- lib/src/ble/ble_mesh_manager.dart | 7 +++++++ lib/src/contants.dart | 4 ++-- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Android-nRF-Mesh-Library-1 b/Android-nRF-Mesh-Library-1 index c044559a1..866a56ae3 160000 --- a/Android-nRF-Mesh-Library-1 +++ b/Android-nRF-Mesh-Library-1 @@ -1 +1 @@ -Subproject commit c044559a1caf8c004f5401e2b3570dfc00e4eb02 +Subproject commit 866a56ae3ca93eb978f54c6d74266f110d917281 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9585066..573496b9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ - fix bug in adding a provisioner on iOS device - expose ConfigBeacon API +- negociate MTU before enabling notifications (Fix bug on Android where Secure Network Beacons were truncated) +- Ignore timing criterias to accept an incoming Secure Network Beacon (useful when network has just been loaded from its JSON representation in which the IV Index last transition date is not stored) ## 0.5.0 diff --git a/lib/src/ble/ble_manager.dart b/lib/src/ble/ble_manager.dart index 6eec6c9b3..186acb1e9 100644 --- a/lib/src/ble/ble_manager.dart +++ b/lib/src/ble/ble_manager.dart @@ -23,8 +23,7 @@ final meshProvisioningDataOut = Platform.isAndroid ? Uuid.parse('00002ADC-0000-1000-8000-00805F9B34FB') : Uuid.parse('2ADC'); final clientCharacteristicConfigDescriptorUuid = Platform.isAndroid ? Uuid.parse('00002902-0000-1000-8000-00805f9b34fb') : Uuid.parse('2902'); -final enableNotificationValue = [0x01, 0x00]; -const Duration kConnectionTimeout = Duration(seconds: 30); +const Duration _kConnectionTimeout = Duration(seconds: 30); abstract class BleManager { /// The current BLE device being managed if any @@ -69,6 +68,9 @@ abstract class BleManager { @visibleForOverriding Future isRequiredServiceSupported(bool shouldCheckDoozCustomService); + /// A method that should implement the GATT initialization. + /// + /// In our case, it means requesting the highest possible MTU size and subcribing to notifications @visibleForOverriding Future initGatt(); @@ -104,7 +106,7 @@ abstract class BleManager { /// (because this is a DooZ application specific flow, we made these parameters optional) Future connect( final DiscoveredDevice discoveredDevice, { - Duration connectionTimeout = kConnectionTimeout, + Duration connectionTimeout = _kConnectionTimeout, List? whitelist, bool shouldCheckDoozCustomService = false, }) async { @@ -260,23 +262,15 @@ abstract class BleManager { } if (service != null) { // valid mesh node + if (!_callbacks.onServicesDiscoveredController.isClosed && + _callbacks.onServicesDiscoveredController.hasListener) { + _callbacks.onServicesDiscoveredController.add(BleManagerCallbacksDiscoveredServices(_device!, service)); + } try { - await _callbacks.sendMtuToMeshManagerApi(isProvisioningCompleted ? 22 : mtuSize); - if (!_callbacks.onServicesDiscoveredController.isClosed && - _callbacks.onServicesDiscoveredController.hasListener) { - _callbacks.onServicesDiscoveredController.add(BleManagerCallbacksDiscoveredServices(_device!, service)); - } await initGatt(); - final negotiatedMtu = await _bleInstance.requestMtu(deviceId: _device!.id, mtu: 517); - if (Platform.isAndroid) { - mtuSize = negotiatedMtu - 3; - } else if (Platform.isIOS) { - mtuSize = negotiatedMtu; - } - await _callbacks.sendMtuToMeshManagerApi(mtuSize); } catch (e) { - _log('caught error during negociation : $e'); - throw BleManagerException(BleManagerFailureCode.negociation, '$e'); + _log('caught error during GATT initialization : $e'); + throw BleManagerException(BleManagerFailureCode.initGatt, '$e'); } } else { // invalid BLE device diff --git a/lib/src/ble/ble_mesh_manager.dart b/lib/src/ble/ble_mesh_manager.dart index de56861c7..464c49161 100644 --- a/lib/src/ble/ble_mesh_manager.dart +++ b/lib/src/ble/ble_mesh_manager.dart @@ -88,6 +88,13 @@ class BleMeshManager extends BleManager { @override Future initGatt() async { + final negotiatedMtu = await bleInstance.requestMtu(deviceId: device!.id, mtu: mtuSizeMax); + if (Platform.isAndroid) { + mtuSize = negotiatedMtu - 3; + } else if (Platform.isIOS) { + mtuSize = negotiatedMtu; + } + await callbacks!.sendMtuToMeshManagerApi(mtuSize); DiscoveredService? discoveredService; if (isProvisioningCompleted) { discoveredService = _discoveredServices.firstWhere((service) => service.serviceId == meshProxyUuid); diff --git a/lib/src/contants.dart b/lib/src/contants.dart index 4ed55c727..6cc8659f4 100644 --- a/lib/src/contants.dart +++ b/lib/src/contants.dart @@ -41,8 +41,8 @@ enum BleManagerFailureCode { /// when the connected device does not broadcast the DooZ custom service doozServiceNotFound, - /// negociation failure - negociation, + /// init GATT failure (MTU size negociation and notification subscription) + initGatt, /// missing callbacks (Flutter layer) callbacks, From 488e7620588184bb45b3e936c2582a18cb37326a Mon Sep 17 00:00:00 2001 From: hariharasudhanPerumalSamy Date: Fri, 14 Jan 2022 14:13:02 +0100 Subject: [PATCH 4/5] connect to specific node using device name (#213) * connect to specific node using device name * removed custom service uuid removed mac id list removed related constants * provision, connect, control the modules with the version of FW below 1.1.7 and above 1.1.8 * connect to specific node using device name or uuid flutter formatted * edit documentation for searchForSpecificNode Co-authored-by: R0m4in-dooz --- lib/src/ble/ble_scanner.dart | 8 ++++---- lib/src/nrf_mesh.dart | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/src/ble/ble_scanner.dart b/lib/src/ble/ble_scanner.dart index c33d3983b..107b20fb0 100644 --- a/lib/src/ble/ble_scanner.dart +++ b/lib/src/ble/ble_scanner.dart @@ -86,7 +86,7 @@ class BleScanner { } Future searchForSpecificNode( - String uid, + String deviceNameOrId, Duration scanTimeout, bool forProxy, ) async { @@ -94,11 +94,11 @@ class BleScanner { try { result = await _scanWithParamsAsStream( withServices: [forProxy ? meshProxyUuid : meshProvisioningUuid], - ).firstWhere((s) => s.id == uid).timeout(scanTimeout); + ).firstWhere((s) => s.name == deviceNameOrId || s.id == deviceNameOrId).timeout(scanTimeout); } on StateError catch (e) { - debugPrint('[NordicNrfMesh] StateError -- no device found with UUID : $uid\n$e\n${e.message}'); + debugPrint('[NordicNrfMesh] no device found with given deviceNameOrId : $deviceNameOrId\n$e'); } on TimeoutException catch (e) { - debugPrint('[NordicNrfMesh] TimeoutException -- no device found with UUID : $uid\n$e\n${e.message}'); + debugPrint('[NordicNrfMesh] no device found with given deviceNameOrId : $deviceNameOrId\n$e'); } return result; } diff --git a/lib/src/nrf_mesh.dart b/lib/src/nrf_mesh.dart index 437bfda3c..9c2b745b9 100644 --- a/lib/src/nrf_mesh.dart +++ b/lib/src/nrf_mesh.dart @@ -115,7 +115,7 @@ class NordicNrfMesh { /// Throws an [UnsupportedError] if the current OS is not supported. Stream scanWithServices(List services) => _bleScanner.scanWithServices(services); - /// Will scan for the given node uid. + /// Will scan for the given device using name or id (MAC on Android or UUID on iOS). /// /// It will scan by default for **unprovisioned** nodes, but one can switch to proxy candidates using the [isProxy] bool flag. /// @@ -123,11 +123,11 @@ class NordicNrfMesh { /// /// Throws an [UnsupportedError] if the current OS is not supported. Future searchForSpecificNode( - String uid, { + String deviceNameOrId, { bool isProxy = false, Duration timeoutDuration = defaultScanDuration, }) => - _bleScanner.searchForSpecificNode(uid, timeoutDuration, isProxy); + _bleScanner.searchForSpecificNode(deviceNameOrId, timeoutDuration, isProxy); /// Provide a [Stream] of the current [BleStatus] of the host device. Stream get bleStatus => _bleScanner.bleStatus; From 362d714ac84a23a2690e25e7422913727e438b04 Mon Sep 17 00:00:00 2001 From: R0m4in-dooz <72380352+R0m4in-dooz@users.noreply.github.com> Date: Fri, 14 Jan 2022 14:16:31 +0100 Subject: [PATCH 5/5] update CHANGELOG.md (#215) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 573496b9c..a58d71dbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - expose ConfigBeacon API - negociate MTU before enabling notifications (Fix bug on Android where Secure Network Beacons were truncated) - Ignore timing criterias to accept an incoming Secure Network Beacon (useful when network has just been loaded from its JSON representation in which the IV Index last transition date is not stored) +- `searchForSpecificNode` will now return a result if the given String matches the device's id **or** name ## 0.5.0