Fix Open Humans Uploader
This commit is contained in:
parent
5533f87bbc
commit
fa8e784733
5 changed files with 65 additions and 35 deletions
|
@ -106,7 +106,7 @@ public class DetermineBasalAdapterMAJS {
|
||||||
log.debug("Result: " + result);
|
log.debug("Result: " + result);
|
||||||
try {
|
try {
|
||||||
JSONObject resultJson = new JSONObject(result);
|
JSONObject resultJson = new JSONObject(result);
|
||||||
OpenHumansUploader.INSTANCE.enqueueAMAData(mProfile, mGlucoseStatus, mIobData, mMealData, mCurrentTemp, resultJson);
|
OpenHumansUploader.INSTANCE.enqueueMAData(mProfile, mGlucoseStatus, mIobData, mMealData, mCurrentTemp, resultJson);
|
||||||
determineBasalResultMA = new DetermineBasalResultMA(jsResult, resultJson);
|
determineBasalResultMA = new DetermineBasalResultMA(jsResult, resultJson);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
log.error("Unhandled exception", e);
|
log.error("Unhandled exception", e);
|
||||||
|
|
|
@ -13,8 +13,10 @@ class OHUploadWorker(
|
||||||
) : RxWorker(context, workerParameters) {
|
) : RxWorker(context, workerParameters) {
|
||||||
|
|
||||||
override fun createWork() = Single.defer {
|
override fun createWork() = Single.defer {
|
||||||
val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as? WifiManager
|
||||||
if (SP.getBoolean("key_oh_wifi_only", true) && wifiManager.isWifiEnabled && wifiManager.connectionInfo.networkId != -1) {
|
val wifiOnly = SP.getBoolean("key_oh_wifi_only", true)
|
||||||
|
val isConnectedToWifi = wifiManager?.isWifiEnabled ?: false && wifiManager?.connectionInfo?.networkId != -1
|
||||||
|
if (!wifiOnly || (wifiOnly && isConnectedToWifi)) {
|
||||||
OpenHumansUploader.uploadData()
|
OpenHumansUploader.uploadData()
|
||||||
.andThen(Single.just(Result.success()))
|
.andThen(Single.just(Result.success()))
|
||||||
.onErrorResumeNext { Single.just(Result.retry()) }
|
.onErrorResumeNext { Single.just(Result.retry()) }
|
||||||
|
|
|
@ -6,12 +6,12 @@ import io.reactivex.Completable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.disposables.Disposables
|
import io.reactivex.disposables.Disposables
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
|
import okio.BufferedSink
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import okio.BufferedSink
|
|
||||||
|
|
||||||
class OpenHumansAPI(
|
class OpenHumansAPI(
|
||||||
private val baseUrl: String,
|
private val baseUrl: String,
|
||||||
|
@ -32,7 +32,7 @@ class OpenHumansAPI(
|
||||||
fun refreshAccessToken(refreshToken: String): Single<OAuthTokens> = sendTokenRequest(FormBody.Builder()
|
fun refreshAccessToken(refreshToken: String): Single<OAuthTokens> = sendTokenRequest(FormBody.Builder()
|
||||||
.add("grant_type", "refresh_token")
|
.add("grant_type", "refresh_token")
|
||||||
.add("redirect_uri", redirectUri)
|
.add("redirect_uri", redirectUri)
|
||||||
.add("code", refreshToken)
|
.add("refresh_token", refreshToken)
|
||||||
.build())
|
.build())
|
||||||
|
|
||||||
private fun sendTokenRequest(body: FormBody) = Request.Builder()
|
private fun sendTokenRequest(body: FormBody) = Request.Builder()
|
||||||
|
@ -49,8 +49,10 @@ class OpenHumansAPI(
|
||||||
if (jsonObject == null) throw OHHttpException(response.code, response.message, "No body")
|
if (jsonObject == null) throw OHHttpException(response.code, response.message, "No body")
|
||||||
if (!jsonObject.has("expires_in")) throw OHMissingFieldException("expires_in")
|
if (!jsonObject.has("expires_in")) throw OHMissingFieldException("expires_in")
|
||||||
OAuthTokens(
|
OAuthTokens(
|
||||||
accessToken = jsonObject.getString("access_token") ?: throw OHMissingFieldException("access_token"),
|
accessToken = jsonObject.getString("access_token")
|
||||||
refreshToken = jsonObject.getString("refresh_token") ?: throw OHMissingFieldException("refresh_token"),
|
?: throw OHMissingFieldException("access_token"),
|
||||||
|
refreshToken = jsonObject.getString("refresh_token")
|
||||||
|
?: throw OHMissingFieldException("refresh_token"),
|
||||||
expiresAt = response.sentRequestAtMillis + jsonObject.getInt("expires_in") * 1000L
|
expiresAt = response.sentRequestAtMillis + jsonObject.getInt("expires_in") * 1000L
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -61,7 +63,10 @@ class OpenHumansAPI(
|
||||||
.get()
|
.get()
|
||||||
.build()
|
.build()
|
||||||
.toSingle()
|
.toSingle()
|
||||||
.map { it.jsonBody.getString("project_member_id") ?: throw OHMissingFieldException("project_member_id") }
|
.map {
|
||||||
|
it.jsonBody.getString("project_member_id")
|
||||||
|
?: throw OHMissingFieldException("project_member_id")
|
||||||
|
}
|
||||||
|
|
||||||
fun prepareFileUpload(accessToken: String, fileName: String, metadata: FileMetadata): Single<PreparedUpload> = Request.Builder()
|
fun prepareFileUpload(accessToken: String, fileName: String, metadata: FileMetadata): Single<PreparedUpload> = Request.Builder()
|
||||||
.url("$baseUrl/api/direct-sharing/project/files/upload/direct/?access_token=$accessToken")
|
.url("$baseUrl/api/direct-sharing/project/files/upload/direct/?access_token=$accessToken")
|
||||||
|
@ -109,7 +114,6 @@ class OpenHumansAPI(
|
||||||
.doOnSuccess { it.jsonBody }
|
.doOnSuccess { it.jsonBody }
|
||||||
.ignoreElement()
|
.ignoreElement()
|
||||||
|
|
||||||
|
|
||||||
private fun Request.toSingle() = Single.create<Response> {
|
private fun Request.toSingle() = Single.create<Response> {
|
||||||
val call = client.newCall(this)
|
val call = client.newCall(this)
|
||||||
call.enqueue(object : Callback {
|
call.enqueue(object : Callback {
|
||||||
|
@ -124,11 +128,13 @@ class OpenHumansAPI(
|
||||||
it.setDisposable(Disposables.fromRunnable { call.cancel() })
|
it.setDisposable(Disposables.fromRunnable { call.cancel() })
|
||||||
}
|
}
|
||||||
|
|
||||||
private val Response.jsonBody get() = use { _ ->
|
private val Response.jsonBody
|
||||||
val jsonObject = body?.let { JSONObject(it.string()) } ?: throw OHHttpException(code, message, null)
|
get() = use { _ ->
|
||||||
if (!isSuccessful) throw OHHttpException(code, message, jsonObject.getString("detail"))
|
val jsonObject = body?.let { JSONObject(it.string()) }
|
||||||
jsonObject
|
?: throw OHHttpException(code, message, null)
|
||||||
}
|
if (!isSuccessful) throw OHHttpException(code, message, jsonObject.getString("detail"))
|
||||||
|
jsonObject
|
||||||
|
}
|
||||||
|
|
||||||
data class OAuthTokens(
|
data class OAuthTokens(
|
||||||
val accessToken: String,
|
val accessToken: String,
|
||||||
|
@ -144,6 +150,7 @@ class OpenHumansAPI(
|
||||||
val startDate: Long? = null,
|
val startDate: Long? = null,
|
||||||
val endDate: Long? = null
|
val endDate: Long? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun toJSON(): JSONObject {
|
fun toJSON(): JSONObject {
|
||||||
val jsonObject = JSONObject()
|
val jsonObject = JSONObject()
|
||||||
jsonObject.put("tags", JSONArray().apply { tags.forEach { put(it) } })
|
jsonObject.put("tags", JSONArray().apply { tags.forEach { put(it) } })
|
||||||
|
@ -166,12 +173,14 @@ class OpenHumansAPI(
|
||||||
val meaning: String,
|
val meaning: String,
|
||||||
val detail: String?
|
val detail: String?
|
||||||
) : RuntimeException() {
|
) : RuntimeException() {
|
||||||
|
|
||||||
override val message: String get() = toString()
|
override val message: String get() = toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class OHMissingFieldException(
|
data class OHMissingFieldException(
|
||||||
val name: String
|
val name: String
|
||||||
) : RuntimeException() {
|
) : RuntimeException() {
|
||||||
|
|
||||||
override val message: String get() = toString()
|
override val message: String get() = toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,16 +52,16 @@ object OpenHumansUploader : PluginBase(
|
||||||
|
|
||||||
private val log = LoggerFactory.getLogger(L.OPENHUMANS)
|
private val log = LoggerFactory.getLogger(L.OPENHUMANS)
|
||||||
|
|
||||||
const val OPEN_HUMANS_URL = "https://www.openhumans.org"
|
private const val OPEN_HUMANS_URL = "https://www.openhumans.org"
|
||||||
const val CLIENT_ID = "oie6DvnaEOagTxSoD6BukkLPwDhVr6cMlN74Ihz1"
|
private const val CLIENT_ID = "oie6DvnaEOagTxSoD6BukkLPwDhVr6cMlN74Ihz1"
|
||||||
const val CLIENT_SECRET = "jR0N8pkH1jOwtozHc7CsB1UPcJzFN95ldHcK4VGYIApecr8zGJox0v06xLwPLMASScngT12aIaIHXAVCJeKquEXAWG1XekZdbubSpccgNiQBmuVmIF8nc1xSKSNJltCf"
|
private const val CLIENT_SECRET = "jR0N8pkH1jOwtozHc7CsB1UPcJzFN95ldHcK4VGYIApecr8zGJox0v06xLwPLMASScngT12aIaIHXAVCJeKquEXAWG1XekZdbubSpccgNiQBmuVmIF8nc1xSKSNJltCf"
|
||||||
const val REDIRECT_URL = "androidaps://setup-openhumans"
|
private const val REDIRECT_URL = "androidaps://setup-openhumans"
|
||||||
const val AUTH_URL = "https://www.openhumans.org/direct-sharing/projects/oauth2/authorize/?client_id=$CLIENT_ID&response_type=code"
|
const val AUTH_URL = "https://www.openhumans.org/direct-sharing/projects/oauth2/authorize/?client_id=$CLIENT_ID&response_type=code"
|
||||||
const val WORK_NAME = "Open Humans"
|
const val WORK_NAME = "Open Humans"
|
||||||
const val COPY_NOTIFICATION_ID = 3122
|
private const val COPY_NOTIFICATION_ID = 3122
|
||||||
const val FAILURE_NOTIFICATION_ID = 3123
|
private const val FAILURE_NOTIFICATION_ID = 3123
|
||||||
const val SUCCESS_NOTIFICATION_ID = 3124
|
private const val SUCCESS_NOTIFICATION_ID = 3124
|
||||||
const val SIGNED_OUT_NOTIFICATION_ID = 3125
|
private const val SIGNED_OUT_NOTIFICATION_ID = 3125
|
||||||
|
|
||||||
private val openHumansAPI = OpenHumansAPI(OPEN_HUMANS_URL, CLIENT_ID, CLIENT_SECRET, REDIRECT_URL)
|
private val openHumansAPI = OpenHumansAPI(OPEN_HUMANS_URL, CLIENT_ID, CLIENT_SECRET, REDIRECT_URL)
|
||||||
private val FILE_NAME_DATE_FORMAT = SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.US).apply { timeZone = TimeZone.getTimeZone("UTC") }
|
private val FILE_NAME_DATE_FORMAT = SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.US).apply { timeZone = TimeZone.getTimeZone("UTC") }
|
||||||
|
@ -123,13 +123,13 @@ object OpenHumansUploader : PluginBase(
|
||||||
super.onStart()
|
super.onStart()
|
||||||
setupNotificationChannel()
|
setupNotificationChannel()
|
||||||
if (isSetup) scheduleWorker(false)
|
if (isSetup) scheduleWorker(false)
|
||||||
SP.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
SP.registerListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
copyDisposable?.dispose()
|
copyDisposable?.dispose()
|
||||||
cancelWorker()
|
cancelWorker()
|
||||||
SP.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
|
SP.unregisterListener(this)
|
||||||
super.onStop()
|
super.onStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ object OpenHumansUploader : PluginBase(
|
||||||
put("result", result)
|
put("result", result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enqueueAMAData(profile: JSONObject, glucoseStatus: JSONObject, iobData: JSONObject, mealData: JSONObject, currentTemp: JSONObject, result: JSONObject) = insertQueueItem("APSData") {
|
fun enqueueMAData(profile: JSONObject, glucoseStatus: JSONObject, iobData: JSONObject, mealData: JSONObject, currentTemp: JSONObject, result: JSONObject) = insertQueueItem("APSData") {
|
||||||
put("algorithm", "MA")
|
put("algorithm", "MA")
|
||||||
put("profile", profile)
|
put("profile", profile)
|
||||||
put("glucoseStatus", glucoseStatus)
|
put("glucoseStatus", glucoseStatus)
|
||||||
|
@ -290,6 +290,9 @@ object OpenHumansUploader : PluginBase(
|
||||||
copyExistingDataToQueue()
|
copyExistingDataToQueue()
|
||||||
RxBus.send(OpenHumansFragment.UpdateViewEvent)
|
RxBus.send(OpenHumansFragment.UpdateViewEvent)
|
||||||
}
|
}
|
||||||
|
.doOnError {
|
||||||
|
log.error("Failed to login to Open Humans", it)
|
||||||
|
}
|
||||||
.ignoreElement()
|
.ignoreElement()
|
||||||
|
|
||||||
fun logout() {
|
fun logout() {
|
||||||
|
@ -318,22 +321,22 @@ object OpenHumansUploader : PluginBase(
|
||||||
.map { enqueueBGReading(it); increaseCounter() }
|
.map { enqueueBGReading(it); increaseCounter() }
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allCareportalEvents) })
|
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allCareportalEvents) })
|
||||||
.map { enqueueCareportalEvent(it); increaseCounter() }
|
.map { enqueueCareportalEvent(it); increaseCounter() }
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allExtendedBoluses) })
|
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allExtendedBoluses) })
|
||||||
.map { enqueueExtendedBolus(it); increaseCounter() }
|
.map { enqueueExtendedBolus(it); increaseCounter() }
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allProfileSwitches) })
|
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allProfileSwitches) })
|
||||||
.map { enqueueProfileSwitch(it); increaseCounter() }
|
.map { enqueueProfileSwitch(it); increaseCounter() }
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTDDs) })
|
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTDDs) })
|
||||||
.map { enqueueTotalDailyDose(it); increaseCounter() }
|
.map { enqueueTotalDailyDose(it); increaseCounter() }
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTemporaryBasals) })
|
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTemporaryBasals) })
|
||||||
.map { enqueueTemporaryBasal(it); increaseCounter() }
|
.map { enqueueTemporaryBasal(it); increaseCounter() }
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTempTargets) })
|
.andThen(Observable.defer { Observable.fromIterable(MainApp.getDbHelper().allTempTargets) })
|
||||||
.map { enqueueTempTarget(it); increaseCounter() }
|
.map { enqueueTempTarget(it); increaseCounter() }
|
||||||
.ignoreElements()
|
.ignoreElements()
|
||||||
.doOnSubscribe {
|
.doOnSubscribe {
|
||||||
wakeLock.acquire(TimeUnit.MINUTES.toMillis(20))
|
wakeLock.acquire(TimeUnit.MINUTES.toMillis(20))
|
||||||
|
@ -362,7 +365,8 @@ object OpenHumansUploader : PluginBase(
|
||||||
.setContentTitle(MainApp.gs(R.string.finishing_open_humans_setup))
|
.setContentTitle(MainApp.gs(R.string.finishing_open_humans_setup))
|
||||||
.setContentText(MainApp.gs(R.string.this_may_take_a_while))
|
.setContentText(MainApp.gs(R.string.this_may_take_a_while))
|
||||||
.setStyle(NotificationCompat.BigTextStyle())
|
.setStyle(NotificationCompat.BigTextStyle())
|
||||||
.setProgress(maxProgress?.toInt() ?: 0, currentProgress?.toInt() ?: 0, maxProgress == null || currentProgress == null)
|
.setProgress(maxProgress?.toInt() ?: 0, currentProgress?.toInt()
|
||||||
|
?: 0, maxProgress == null || currentProgress == null)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setAutoCancel(false)
|
.setAutoCancel(false)
|
||||||
.setSmallIcon(R.drawable.notif_icon)
|
.setSmallIcon(R.drawable.notif_icon)
|
||||||
|
@ -406,8 +410,15 @@ object OpenHumansUploader : PluginBase(
|
||||||
if (it is OpenHumansAPI.OHHttpException && it.code == 401 && it.detail == "Invalid token.") {
|
if (it is OpenHumansAPI.OHHttpException && it.code == 401 && it.detail == "Invalid token.") {
|
||||||
handleSignOut()
|
handleSignOut()
|
||||||
}
|
}
|
||||||
|
log.error("Error while uploading to Open Humans", it)
|
||||||
|
}
|
||||||
|
.doOnComplete {
|
||||||
|
log.info("Upload successful")
|
||||||
|
RxBus.send(OpenHumansFragment.UpdateQueueEvent)
|
||||||
|
}
|
||||||
|
.doOnSubscribe {
|
||||||
|
log.info("Starting upload")
|
||||||
}
|
}
|
||||||
.doOnComplete { RxBus.send(OpenHumansFragment.UpdateQueueEvent) }
|
|
||||||
|
|
||||||
private fun uploadFile(accessToken: String, uploadData: UploadData) = Completable.defer {
|
private fun uploadFile(accessToken: String, uploadData: UploadData) = Completable.defer {
|
||||||
openHumansAPI.prepareFileUpload(accessToken, uploadData.fileName, uploadData.metadata)
|
openHumansAPI.prepareFileUpload(accessToken, uploadData.fileName, uploadData.metadata)
|
||||||
|
@ -450,7 +461,7 @@ object OpenHumansUploader : PluginBase(
|
||||||
zos.writeFile("ApplicationInfo.json", applicationInfo.toString().toByteArray())
|
zos.writeFile("ApplicationInfo.json", applicationInfo.toString().toByteArray())
|
||||||
tags.add("ApplicationInfo")
|
tags.add("ApplicationInfo")
|
||||||
|
|
||||||
val preferences = JSONObject(SP.sharedPreferences.all.filterKeys { it.isAllowedKey() })
|
val preferences = JSONObject(SP.getAll().filterKeys { it.isAllowedKey() })
|
||||||
zos.writeFile("Preferences.json", preferences.toString().toByteArray())
|
zos.writeFile("Preferences.json", preferences.toString().toByteArray())
|
||||||
tags.add("Preferences")
|
tags.add("Preferences")
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import info.nightscout.androidaps.MainApp;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class SP {
|
public class SP {
|
||||||
public static SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
private static final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
||||||
|
|
||||||
static public Map<String, ?> getAll() {
|
static public Map<String, ?> getAll() {
|
||||||
return sharedPreferences.getAll();
|
return sharedPreferences.getAll();
|
||||||
|
@ -26,6 +26,14 @@ public class SP {
|
||||||
return sharedPreferences.contains(key);
|
return sharedPreferences.contains(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public void registerListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
|
||||||
|
sharedPreferences.registerOnSharedPreferenceChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void unregisterListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
|
||||||
|
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
static public boolean contains(int resourceId) {
|
static public boolean contains(int resourceId) {
|
||||||
return sharedPreferences.contains(MainApp.gs(resourceId));
|
return sharedPreferences.contains(MainApp.gs(resourceId));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue