From 7bb7a67a22a8c0d94ba7ef5e1721c58c854d0ef3 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Fri, 13 May 2022 14:35:11 +0200 Subject: [PATCH 1/2] setDeviceSidePacketMergingSupported -> setMaxPacketLength --- .../mcumgr/ble/McuMgrBleTransport.java | 47 +++++++++++++++---- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/mcumgr-ble/src/main/java/io/runtime/mcumgr/ble/McuMgrBleTransport.java b/mcumgr-ble/src/main/java/io/runtime/mcumgr/ble/McuMgrBleTransport.java index 3ab4bf0d..b3eb4cf7 100644 --- a/mcumgr-ble/src/main/java/io/runtime/mcumgr/ble/McuMgrBleTransport.java +++ b/mcumgr-ble/src/main/java/io/runtime/mcumgr/ble/McuMgrBleTransport.java @@ -44,6 +44,7 @@ import io.runtime.mcumgr.exception.McuMgrErrorException; import io.runtime.mcumgr.exception.McuMgrException; import io.runtime.mcumgr.exception.McuMgrTimeoutException; +import io.runtime.mcumgr.managers.DefaultManager; import io.runtime.mcumgr.response.McuMgrResponse; import io.runtime.mcumgr.response.dflt.McuMgrParamsResponse; import io.runtime.mcumgr.util.CBOR; @@ -211,30 +212,56 @@ protected BleManagerGattCallback getGattCallback() { return new McuMgrGattCallback(); } + //******************************************************************************************* + // Maximum SMP packet length. + //******************************************************************************************* + /** - * In order to send packets longer than MTU size, this library supports automatic splitting + * In order to send packets longer than MTU size, this library supports automatic segmentation * of packets into at-most-MTU size chunks. This feature must be also supported by the target - * device, as it must merge received chunks into a single packet, based on the length field - * from the {@link io.runtime.mcumgr.McuMgrHeader}, included in the first chunk. - *

- * {@link io.runtime.mcumgr.managers.ImageManager} and - * {@link io.runtime.mcumgr.managers.FsManager} will automatically split the file into multiple - * SMP packets. This feature is about splitting SMP packet into chunks, not splitting data into - * SMP packets. + * device, as it must reassembly received chunks into full SMP packet, based on the length field + * from the {@link io.runtime.mcumgr.McuMgrHeader}, included in the first segment. *

* This method sets the maximum packet length supported by the target device. - * By default, this is be set to MTU - 3, which means that no splitting will be done. + * By default, this is be set to MTU - 3, which means that each BLE packet will contain the full + * SMP packet (header + CBOR-encoded data). For devices supporting reading McuMgr parameters + * (nRF Connect SDK 2.0+) this value is automatically obtained after connection using + * {@link DefaultManager#params()}. *

* Keep in mind, that before Android 5 requesting higher MTU was not supported. Setting the * maximum length to a greater value is required on those devices in order to upgrade * the firmware, send file or send any other SMP packet that is longer than 20 bytes. * + * @since 1.3 * @param maxLength the maximum packet length. */ - public void setDeviceSidePacketMergingSupported(int maxLength) { + public final void setMaxPacketLength(final int maxLength) { mMaxPacketLength = maxLength; } + /** + * Returns the maximum length of a SMP packet that can be transmitted over by the transport. + * @return the maximum + */ + public final int getMaxPacketLength() { + return mMaxPacketLength; + } + + /** + * Sets the maximum packet length for the transport. + * + * Starting from version 1.3 the library can automatically obtain the value from a device build + * on nRF Connect SDK 2.0+ using the new {@link DefaultManager#params()} command. If the feature + * is not supported on the device the maximum length defaults to MTU-3 bytes. + * + * @param maxLength the maximum packet length. + * @deprecated Use {@link #setMaxPacketLength(int)} instead. + */ + @Deprecated + public void setDeviceSidePacketMergingSupported(int maxLength) { + setMaxPacketLength(maxLength); + } + //******************************************************************************************* // Logging //******************************************************************************************* From d0f6e0b6bf994de69b2099932d791c514ff2d968 Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Fri, 13 May 2022 14:35:30 +0200 Subject: [PATCH 2/2] Displaying buffer data in Device Status section --- .../fragment/mcumgr/DeviceStatusFragment.java | 8 +++ .../ObservableMcuMgrBleTransport.java | 4 +- .../mcumgr/DeviceStatusViewModel.java | 68 ++++++++++++++++++- .../layout/fragment_card_device_status.xml | 38 ++++++++--- .../main/res/values/strings_device_status.xml | 4 ++ 5 files changed, 110 insertions(+), 12 deletions(-) diff --git a/sample/src/main/java/io/runtime/mcumgr/sample/fragment/mcumgr/DeviceStatusFragment.java b/sample/src/main/java/io/runtime/mcumgr/sample/fragment/mcumgr/DeviceStatusFragment.java index 3e1fb72b..886cad9e 100644 --- a/sample/src/main/java/io/runtime/mcumgr/sample/fragment/mcumgr/DeviceStatusFragment.java +++ b/sample/src/main/java/io/runtime/mcumgr/sample/fragment/mcumgr/DeviceStatusFragment.java @@ -91,6 +91,14 @@ public void onViewCreated(@NonNull final View view, @Nullable final Bundle saved break; } }); + viewModel.getBufferParams().observe(getViewLifecycleOwner(), params -> { + if (params != null) { + final String text = getString(R.string.status_mcumgr_buffer_size, params.count, params.size); + binding.mcumgrBufferSize.setText(text); + } else { + binding.mcumgrBufferSize.setText(R.string.status_unknown); + } + }); viewModel.getBusyState().observe(getViewLifecycleOwner(), busy -> binding.workIndicator.setVisibility(busy ? View.VISIBLE : View.GONE)); } diff --git a/sample/src/main/java/io/runtime/mcumgr/sample/observable/ObservableMcuMgrBleTransport.java b/sample/src/main/java/io/runtime/mcumgr/sample/observable/ObservableMcuMgrBleTransport.java index ecd496d5..449303e0 100644 --- a/sample/src/main/java/io/runtime/mcumgr/sample/observable/ObservableMcuMgrBleTransport.java +++ b/sample/src/main/java/io/runtime/mcumgr/sample/observable/ObservableMcuMgrBleTransport.java @@ -102,12 +102,12 @@ public void onBondingFailed(@NonNull final BluetoothDevice device) { setLoggingEnabled(true); } - @Nullable + @NonNull public LiveData getState() { return connectionState; } - @Nullable + @NonNull public LiveData getBondingState() { return bondingState; } diff --git a/sample/src/main/java/io/runtime/mcumgr/sample/viewmodel/mcumgr/DeviceStatusViewModel.java b/sample/src/main/java/io/runtime/mcumgr/sample/viewmodel/mcumgr/DeviceStatusViewModel.java index 0d00d632..75957775 100644 --- a/sample/src/main/java/io/runtime/mcumgr/sample/viewmodel/mcumgr/DeviceStatusViewModel.java +++ b/sample/src/main/java/io/runtime/mcumgr/sample/viewmodel/mcumgr/DeviceStatusViewModel.java @@ -6,13 +6,22 @@ package io.runtime.mcumgr.sample.viewmodel.mcumgr; +import org.jetbrains.annotations.NotNull; + +import androidx.annotation.NonNull; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import javax.inject.Inject; import javax.inject.Named; +import androidx.lifecycle.Observer; +import io.runtime.mcumgr.McuMgrCallback; import io.runtime.mcumgr.McuMgrTransport; +import io.runtime.mcumgr.ble.McuMgrBleTransport; +import io.runtime.mcumgr.exception.McuMgrException; +import io.runtime.mcumgr.managers.DefaultManager; +import io.runtime.mcumgr.response.dflt.McuMgrParamsResponse; import io.runtime.mcumgr.sample.observable.BondingState; import io.runtime.mcumgr.sample.observable.ConnectionState; import io.runtime.mcumgr.sample.observable.ObservableMcuMgrBleTransport; @@ -21,11 +30,45 @@ public class DeviceStatusViewModel extends McuMgrViewModel { private final LiveData connectionStateLiveData; private final LiveData bondStateLiveData; + private final MutableLiveData bufferLiveData = new MutableLiveData<>(); + private final Observer connectionStateObserver = new Observer() { + @Override + public void onChanged(final ConnectionState connectionState) { + if (connectionState == ConnectionState.READY) { + defaultManager.params(new McuMgrCallback() { + @Override + public void onResponse(@NotNull final McuMgrParamsResponse response) { + bufferLiveData.postValue(new McuMgrBufferParams(response)); + } + + @Override + public void onError(@NotNull final McuMgrException error) { + final McuMgrTransport transport = defaultManager.getTransporter(); + if (transport instanceof McuMgrBleTransport) { + final McuMgrBleTransport bleTransport = (McuMgrBleTransport) transport; + final int maxPacketLength = bleTransport.getMaxPacketLength(); + final McuMgrBufferParams mcuParams = new McuMgrBufferParams(maxPacketLength); + bufferLiveData.postValue(mcuParams); + } else { + bufferLiveData.postValue(null); + } + } + }); + } else { + bufferLiveData.postValue(null); + } + } + }; + + private final DefaultManager defaultManager; + @Inject - DeviceStatusViewModel(final McuMgrTransport transport, + DeviceStatusViewModel(final DefaultManager manager, @Named("busy") final MutableLiveData state) { super(state); + defaultManager = manager; + final McuMgrTransport transport = manager.getTransporter(); if (transport instanceof ObservableMcuMgrBleTransport) { connectionStateLiveData = ((ObservableMcuMgrBleTransport) transport).getState(); bondStateLiveData = ((ObservableMcuMgrBleTransport) transport).getBondingState(); @@ -45,6 +88,13 @@ public void onDisconnected() { connectionStateLiveData = liveData; bondStateLiveData = new MutableLiveData<>(BondingState.NOT_BONDED); } + connectionStateLiveData.observeForever(connectionStateObserver); + } + + @Override + protected void onCleared() { + connectionStateLiveData.removeObserver(connectionStateObserver); + super.onCleared(); } public LiveData getConnectionState() { @@ -55,4 +105,20 @@ public LiveData getBondState() { return bondStateLiveData; } + public LiveData getBufferParams() { return bufferLiveData; } + + public static class McuMgrBufferParams { + public final int size; + public final int count; + + private McuMgrBufferParams(@NonNull final McuMgrParamsResponse response) { + size = response.bufSize; + count = response.bufCount; + } + + private McuMgrBufferParams(final int maxPacketLength) { + size = maxPacketLength; + count = 1; + } + } } diff --git a/sample/src/main/res/layout/fragment_card_device_status.xml b/sample/src/main/res/layout/fragment_card_device_status.xml index 04f0266a..753e263a 100644 --- a/sample/src/main/res/layout/fragment_card_device_status.xml +++ b/sample/src/main/res/layout/fragment_card_device_status.xml @@ -46,6 +46,17 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/toolbar"/> + + + app:layout_constraintTop_toBottomOf="@+id/connection_status_label"/> + + + app:layout_constraintTop_toBottomOf="@+id/bonding_status_label"/> \ No newline at end of file diff --git a/sample/src/main/res/values/strings_device_status.xml b/sample/src/main/res/values/strings_device_status.xml index 5285b64c..cc04c965 100644 --- a/sample/src/main/res/values/strings_device_status.xml +++ b/sample/src/main/res/values/strings_device_status.xml @@ -9,6 +9,7 @@ Device Status Connection status: Bonding status: + Buffer details: Not connected Connecting… @@ -23,4 +24,7 @@ Not bonded Bonding… Bonded + + UNKNOWN + %d x %d bytes \ No newline at end of file