Android-nRF-Connect-Device-Manager
Android-nRF-Connect-Device-Manager copied to clipboard
Add offset on file upload/download
Hi,
Are you considering adding an offset to the FileUploader and file download?
We implemented this kind of feature with your library, in our project.
If you want to add this feature we can integrate it with you.
Best regards, Tal
The FileManager
already has an API to download or upload a packet from/to an offset:
https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager/blob/52d62ba60979e6c404f74fb45c2ed230643e2ec3/mcumgr-core/src/main/java/io/runtime/mcumgr/managers/FsManager.java#L169-L175
https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager/blob/52d62ba60979e6c404f74fb45c2ed230643e2ec3/mcumgr-core/src/main/java/io/runtime/mcumgr/managers/FsManager.java#L213-L217
The FileUplader
is more like a helper to upload a full file, not just parts.
How does your addition works and what are you using it for?
We are uploading/Downloading a ~30MB file to/from our remote device at a slow rate (due to hardware limitations), so we need to continue the transfer of the file from the last offset.
I see from the documentation that the upload/download commands are for a single packet and not for the rest of the file from a specific offset as we need:
https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager/blob/52d62ba60979e6c404f74fb45c2ed230643e2ec3/mcumgr-core/src/main/java/io/runtime/mcumgr/managers/FsManager.java#L158-L175
https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager/blob/52d62ba60979e6c404f74fb45c2ed230643e2ec3/mcumgr-core/src/main/java/io/runtime/mcumgr/managers/FsManager.java#L197-L217
We added it to the FileUploader
in a simple and clean implementation, and also to the fileUpload
and fileDownload
methods that are in the FsManager
combined with the call to the status
method before to get the current file offset.
OK, I get it.
However, I believe the current FileUploader
may "resume" uploading just like the image uploader (they share logic):
- send first packet with file name and offset 0
- receive a notification with offset X
- continue sending from offset X
Have a look here: https://github.com/NordicSemiconductor/Android-nRF-Connect-Device-Manager/blob/52d62ba60979e6c404f74fb45c2ed230643e2ec3/mcumgr-core/src/main/java/io/runtime/mcumgr/transfer/Uploader.kt#L104
The first chunk (offset 0) is sent as a single packet. It is only after a response is received when the uploader starts several parallel uploads of following chunks, but the next offset is known at that point.
You just need to make sure to reply with an offset equal to the length of "already received part" when you receive offset 0 of a file that you partially already have.
Our use is to continue the upload on different days and connections, so we can't start sending the first packet from offset 0 every time. The same thing to downloading.
If it is something that you are willing to add to the library I can attach our code for the FileUploader
, fileUpload
and fileDownload
methods.
Our use is to continue the upload on different days and connections, so we can't start sending the first packet from offset 0 every time. The same thing to downloading.
I understand, but that doesn't change anything. The packet with offset 0 is sent to get the actual offset to start sending from. For example, on day 0 the uploader sends 100 packets with offsets 0-9999. On the following day the uploader again starts by sending packet with offset 0, but the device replies with a notification with offset 99999, so the next packet sent from the uploader will have offset 10000 and upload will resume. It is the device that keeps track of what it received so far, not the mobile app.
From our experience with the fileUpload
method of the FsManager
it just overrides the file and starts uploading again from 0.
We first get the offset from the status method.
Our fix for the FileUploader
is to add an offset for the constructor:
open class FileUploader(
private val fsManager: FsManager,
private val name: String,
data: ByteArray,
offset: Int = 0,
windowCapacity: Int = 1,
memoryAlignment: Int = 1
) : Uploader(
data,
windowCapacity,
memoryAlignment,
fsManager.mtu,
fsManager.scheme,
offset
) {
Then set the uploader's current offset to the passed offset:
abstract class Uploader(
private val data: ByteArray,
private val windowCapacity: Int,
private val memoryAlignment: Int,
internal var mtu: Int,
private val protocol: McuMgrScheme,
private var currentOffset: Int
) {
And send the initial chunk with the current offset:
next.send(newChunk(currentOffset))
We implemented similar things in the fileUpload
and fileDownload
methods.
From our experience with the fileUpload method of the FsManager it just overrides the file and starts uploading again from 0.
It depends on what offset it returns after receiving the packet with offset 0 again. It should check that it already has the file with this name and return the size instead of removing it and returning the size of the received packet.
What about downloading @philips77 i see that there is a new helper class for Uploading called FileUploader.kt Without downloading and altering the source code for mcumgr-core is there a way to download from an offset previously saved locally ?
Hmm.. I don't think there is. This is a good point.