Skip to content

Commit

Permalink
[RFR-1057] Make attachment upload compatible with collector
Browse files Browse the repository at this point in the history
Upgrade dependencies as the upload paths changed in there
  • Loading branch information
hb0 authored Jul 16, 2024
2 parents a7d7aaf + eeb9518 commit 202caf5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 60 deletions.
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ ext {
// (!) Match versions `android-app`, `SDK` and `camera-service`.
// When `android-app` is checkout out, `rootProject.uploaderVersion` in the submodules will point
// to `android-app/build.gradle` instead of `submodule/build.gradle`.
cyfaceSerializationVersion = "3.2.0"
cyfaceUploaderVersion = "1.3.0"
cyfaceSerializationVersion = "3.4.0"
cyfaceUploaderVersion = "1.4.1"
// These versions just document the currently linked version of this dependency.
// To upgrade the dependencies you need to update the submodules to a newer commit.
cyfaceAndroidBackendVersion = "7.12.0"
cyfaceAndroidBackendVersion = "7.12.1"
cyfaceEnergySettingsVersion = "4.0.6"
cyfaceCameraServiceVersion = "4.5.7"
cyfaceCameraServiceVersion = "4.5.8"

// Android SDK versions
minSdkVersion = 21 // device support
Expand Down
2 changes: 1 addition & 1 deletion camera_service
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import com.thegrizzlylabs.sardineandroid.impl.OkHttpSardine
import de.cyface.app.digural.MainActivity.Companion.TAG
import de.cyface.model.Json
import de.cyface.model.Json.JsonObject
import de.cyface.model.RequestMetaData
import de.cyface.uploader.Result
import de.cyface.uploader.UploadProgressListener
import de.cyface.uploader.Uploader
Expand All @@ -44,6 +43,9 @@ import de.cyface.uploader.exception.UnauthorizedException
import de.cyface.uploader.exception.UnexpectedResponseCode
import de.cyface.uploader.exception.UploadFailed
import de.cyface.uploader.exception.UploadSessionExpired
import de.cyface.uploader.model.Attachment
import de.cyface.uploader.model.Measurement
import de.cyface.uploader.model.Uploadable
import java.io.File
import java.io.IOException
import java.io.InterruptedIOException
Expand All @@ -58,8 +60,6 @@ import javax.net.ssl.SSLException
* To use this interface just call [WebdavUploader.uploadMeasurement] or [WebdavUploader.uploadAttachment].
*
* @author Armin Schnabel
* @version 1.0.0
* @since 3.8.0
* @property apiEndpoint An API endpoint running a Webdav data collector service, like `https://some.url/api/v3`
*/
class WebdavUploader(
Expand All @@ -82,12 +82,18 @@ class WebdavUploader(
@Suppress("unused", "CyclomaticComplexMethod", "LongMethod") // Part of the API
override fun uploadMeasurement(
jwtToken: String,
metaData: RequestMetaData,
uploadable: Measurement,
file: File,
progressListener: UploadProgressListener
): Result {
val endpoint = URL(measurementDirectory(metaData.measurementIdentifier.toLong()))
val result = uploadFile(metaData, file, MEASUREMENT_FILE_FILENAME, endpoint, progressListener)
val endpoint = URL(measurementDirectory(uploadable.identifier.measurementIdentifier))
val result = uploadFile(
uploadable,
uploadable.identifier.measurementIdentifier,
file,
MEASUREMENT_FILE_FILENAME,
endpoint,
)
if (result != Result.UPLOAD_FAILED) {
progressListener.updatedProgress(1.0f) // the whole file is uploaded
}
Expand All @@ -96,14 +102,21 @@ class WebdavUploader(

override fun uploadAttachment(
jwtToken: String,
metaData: RequestMetaData,
measurementId: Long,
uploadable: Attachment,
file: File,
fileName: String,
progressListener: UploadProgressListener
): Result {
val endpoint = attachmentsEndpoint(measurementId)
val result = uploadFile(metaData, file, fileName, endpoint, progressListener)
val measurementId = uploadable.identifier.measurementIdentifier
val deviceId = uploadable.identifier.deviceIdentifier.toString()
val endpoint = attachmentsEndpoint(deviceId, measurementId)
val result = uploadFile(
uploadable,
uploadable.identifier.measurementIdentifier,
file,
fileName,
endpoint
)
if (result != Result.UPLOAD_FAILED) {
progressListener.updatedProgress(1.0f) // the whole file is uploaded
}
Expand All @@ -114,7 +127,10 @@ class WebdavUploader(
return URL(measurementsDirectory())
}

override fun attachmentsEndpoint(measurementId: Long): URL {
override fun attachmentsEndpoint(deviceId: String, measurementId: Long): URL {
// For Webdav we use another directory structure than in the Collector API, here we use:
// /files/<login>/devices/<deviceId>/measurements/<measurementId>/attachments
// But the API uses /measurements/<deviceId>/<measurementId>/attachments
return URL(attachmentsDirectory(measurementId))
}

Expand All @@ -141,11 +157,11 @@ class WebdavUploader(

@Throws(UploadFailed::class)
private fun uploadFile(
metaData: RequestMetaData,
uploadable: Uploadable,
measurementId: Long,
file: File,
fileName: String,
endpoint: URL,
progressListener: UploadProgressListener
endpoint: URL
): Result {
return try {
// TODO: the sardine library has PRs which support input streams but they are not merged
Expand All @@ -165,7 +181,6 @@ class WebdavUploader(
// `Authenticating for response: Response{protocol=http/1.1, code=401, message=Unauthorized,`

val isMeasurementUpload = fileName == MEASUREMENT_FILE_FILENAME
val measurementId = metaData.measurementIdentifier.toLong()
ensureDirectoriesExist(isMeasurementUpload, measurementId)

// File uploads
Expand All @@ -175,7 +190,7 @@ class WebdavUploader(
val metaDataUri = "$uploadDir/meta.json"
if (!sardine.exists(metaDataUri)) {
Log.d(TAG, "upload meta data")
val metaDataMap = preRequestBody(metaData)
val metaDataMap = uploadable.toMap()
val metaDataJson = JsonObject.Builder()
metaDataMap.keys.forEach {
metaDataJson.add(Json.jsonKeyValue(it, metaDataMap.getValue(it)))
Expand Down Expand Up @@ -363,43 +378,5 @@ class WebdavUploader(
"$url/"
}
}

/**
* Assembles a `Map` which contains the metadata.
*
* @param metaData The metadata to convert.
* @return The meta data as `Map`.
*/
fun preRequestBody(metaData: RequestMetaData): Map<String, String> {
val attributes: MutableMap<String, String> = HashMap()

// Location meta data
metaData.startLocation?.let { startLocation ->
attributes["startLocLat"] = startLocation.latitude.toString()
attributes["startLocLon"] = startLocation.longitude.toString()
attributes["startLocTS"] = startLocation.timestamp.toString()
}
metaData.endLocation?.let { endLocation ->
attributes["endLocLat"] = endLocation.latitude.toString()
attributes["endLocLon"] = endLocation.longitude.toString()
attributes["endLocTS"] = endLocation.timestamp.toString()
}
attributes["locationCount"] = metaData.locationCount.toString()

// Remaining meta data
attributes["deviceId"] = metaData.deviceIdentifier
attributes["measurementId"] = metaData.measurementIdentifier
attributes["deviceType"] = metaData.deviceType
attributes["osVersion"] = metaData.operatingSystemVersion
attributes["appVersion"] = metaData.applicationVersion
attributes["length"] = metaData.length.toString()
attributes["modality"] = metaData.modality
attributes["formatVersion"] = metaData.formatVersion.toString()
attributes["logCount"] = metaData.logCount.toString()
attributes["imageCount"] = metaData.imageCount.toString()
attributes["videoCount"] = metaData.videoCount.toString()
attributes["filesSize"] = metaData.filesSize.toString()
return attributes
}
}
}

0 comments on commit 202caf5

Please sign in to comment.