From cfa1fc42d70f8f8e92582c391875fd3adddd4f3d Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 14 Feb 2021 15:50:21 +0100 Subject: [PATCH] DetermineBasalAdapterSMBJS -> kt --- .../DetermineBasalAdapterSMBJS.java | 373 ------------------ .../openAPSSMB/DetermineBasalAdapterSMBJS.kt | 290 ++++++++++++++ .../aps/openAPSSMB/OpenAPSSMBPlugin.java | 21 +- 3 files changed, 298 insertions(+), 386 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java deleted file mode 100644 index 96649420c3..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java +++ /dev/null @@ -1,373 +0,0 @@ -package info.nightscout.androidaps.plugins.aps.openAPSSMB; - -import androidx.annotation.Nullable; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.javascript.Context; -import org.mozilla.javascript.Function; -import org.mozilla.javascript.NativeJSON; -import org.mozilla.javascript.NativeObject; -import org.mozilla.javascript.RhinoException; -import org.mozilla.javascript.Scriptable; -import org.mozilla.javascript.ScriptableObject; -import org.mozilla.javascript.Undefined; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.nio.charset.StandardCharsets; - -import javax.inject.Inject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.data.IobTotal; -import info.nightscout.androidaps.data.MealData; -import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.db.TemporaryBasal; -import info.nightscout.androidaps.interfaces.ActivePluginProvider; -import info.nightscout.androidaps.interfaces.ProfileFunction; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback; -import info.nightscout.androidaps.plugins.aps.loop.ScriptReader; -import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; -import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.utils.SafeParse; -import info.nightscout.androidaps.utils.resources.ResourceHelper; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - - -public class DetermineBasalAdapterSMBJS { - private final HasAndroidInjector injector; - @Inject AAPSLogger aapsLogger; - @Inject ConstraintChecker constraintChecker; - @Inject SP sp; - @Inject ResourceHelper resourceHelper; - @Inject ProfileFunction profileFunction; - @Inject TreatmentsPlugin treatmentsPlugin; - @Inject ActivePluginProvider activePluginProvider; - @Inject OpenHumansUploader openHumansUploader; - - - private final ScriptReader mScriptReader; - private JSONObject mProfile; - private JSONObject mGlucoseStatus; - private JSONArray mIobData; - private JSONObject mMealData; - private JSONObject mCurrentTemp; - private JSONObject mAutosensData = null; - private boolean mMicrobolusAllowed; - private boolean mSMBAlwaysAllowed; - private long mCurrentTime; - private boolean mIsSaveCgmSource; - - private String storedCurrentTemp = null; - private String storedIobData = null; - - private String storedGlucoseStatus = null; - private String storedProfile = null; - private String storedMeal_data = null; - - private String scriptDebug = ""; - - /** - * Main code - */ - - DetermineBasalAdapterSMBJS(ScriptReader scriptReader, HasAndroidInjector injector) { - mScriptReader = scriptReader; - this.injector = injector; - injector.androidInjector().inject(this); - } - - - @Nullable - public DetermineBasalResultSMB invoke() { - - - aapsLogger.debug(LTag.APS, ">>> Invoking detemine_basal <<<"); - aapsLogger.debug(LTag.APS, "Glucose status: " + (storedGlucoseStatus = mGlucoseStatus.toString())); - aapsLogger.debug(LTag.APS, "IOB data: " + (storedIobData = mIobData.toString())); - aapsLogger.debug(LTag.APS, "Current temp: " + (storedCurrentTemp = mCurrentTemp.toString())); - aapsLogger.debug(LTag.APS, "Profile: " + (storedProfile = mProfile.toString())); - aapsLogger.debug(LTag.APS, "Meal data: " + (storedMeal_data = mMealData.toString())); - if (mAutosensData != null) - aapsLogger.debug(LTag.APS, "Autosens data: " + mAutosensData.toString()); - else - aapsLogger.debug(LTag.APS, "Autosens data: " + "undefined"); - aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined"); - aapsLogger.debug(LTag.APS, "MicroBolusAllowed: " + mMicrobolusAllowed); - aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: " + mSMBAlwaysAllowed); - aapsLogger.debug(LTag.APS, "CurrentTime: " + mCurrentTime); - aapsLogger.debug(LTag.APS, "isSaveCgmSource: " + mIsSaveCgmSource); - - - DetermineBasalResultSMB determineBasalResultSMB = null; - - Context rhino = Context.enter(); - Scriptable scope = rhino.initStandardObjects(); - // Turn off optimization to make Rhino Android compatible - rhino.setOptimizationLevel(-1); - - try { - - //register logger callback for console.log and console.error - ScriptableObject.defineClass(scope, LoggerCallback.class); - Scriptable myLogger = rhino.newObject(scope, "LoggerCallback", null); - scope.put("console2", scope, myLogger); - rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null); - - //set module parent - rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null); - rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null); - rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null); - - //generate functions "determine_basal" and "setTempBasal" - rhino.evaluateString(scope, readFile("OpenAPSSMB/determine-basal.js"), "JavaScript", 0, null); - rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null); - Object determineBasalObj = scope.get("determine_basal", scope); - Object setTempBasalFunctionsObj = scope.get("tempBasalFunctions", scope); - - //call determine-basal - if (determineBasalObj instanceof Function && setTempBasalFunctionsObj instanceof NativeObject) { - Function determineBasalJS = (Function) determineBasalObj; - - //prepare parameters - Object[] params = new Object[]{ - makeParam(mGlucoseStatus, rhino, scope), - makeParam(mCurrentTemp, rhino, scope), - makeParamArray(mIobData, rhino, scope), - makeParam(mProfile, rhino, scope), - makeParam(mAutosensData, rhino, scope), - makeParam(mMealData, rhino, scope), - setTempBasalFunctionsObj, - Boolean.valueOf(mMicrobolusAllowed), - makeParam(null, rhino, scope), // reservoir data as undefined - Long.valueOf(mCurrentTime), - Boolean.valueOf(mIsSaveCgmSource) - }; - - - NativeObject jsResult = (NativeObject) determineBasalJS.call(rhino, scope, scope, params); - scriptDebug = LoggerCallback.Companion.getScriptDebug(); - - // Parse the jsResult object to a JSON-String - String result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString(); - aapsLogger.debug(LTag.APS, "Result: " + result); - try { - JSONObject resultJson = new JSONObject(result); - openHumansUploader.enqueueSMBData(mProfile, mGlucoseStatus, mIobData, mMealData, mCurrentTemp, mAutosensData, mMicrobolusAllowed, mSMBAlwaysAllowed, resultJson); - determineBasalResultSMB = new DetermineBasalResultSMB(injector, resultJson); - } catch (JSONException e) { - aapsLogger.error(LTag.APS, "Unhandled exception", e); - } - } else { - aapsLogger.error(LTag.APS, "Problem loading JS Functions"); - } - } catch (IOException e) { - aapsLogger.error(LTag.APS, "IOException"); - } catch (RhinoException e) { - aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString()); - } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { - aapsLogger.error(LTag.APS, e.toString()); - } finally { - Context.exit(); - } - - storedGlucoseStatus = mGlucoseStatus.toString(); - storedIobData = mIobData.toString(); - storedCurrentTemp = mCurrentTemp.toString(); - storedProfile = mProfile.toString(); - storedMeal_data = mMealData.toString(); - - return determineBasalResultSMB; - - } - - String getGlucoseStatusParam() { - return storedGlucoseStatus; - } - - String getCurrentTempParam() { - return storedCurrentTemp; - } - - String getIobDataParam() { - return storedIobData; - } - - String getProfileParam() { - return storedProfile; - } - - String getMealDataParam() { - return storedMeal_data; - } - - String getScriptDebug() { - return scriptDebug; - } - - public void setData(Profile profile, - double maxIob, - double maxBasal, - double minBg, - double maxBg, - double targetBg, - double basalrate, - IobTotal[] iobArray, - GlucoseStatus glucoseStatus, - MealData mealData, - double autosensDataRatio, - boolean tempTargetSet, - boolean microBolusAllowed, - boolean uamAllowed, - boolean advancedFiltering, - boolean isSaveCgmSource - ) throws JSONException { - - PumpInterface pump = activePluginProvider.getActivePump(); - Double pumpbolusstep = pump.getPumpDescription().bolusStep; - mProfile = new JSONObject(); - - mProfile.put("max_iob", maxIob); - //mProfile.put("dia", profile.getDia()); - mProfile.put("type", "current"); - mProfile.put("max_daily_basal", profile.getMaxDailyBasal()); - mProfile.put("max_basal", maxBasal); - mProfile.put("min_bg", minBg); - mProfile.put("max_bg", maxBg); - mProfile.put("target_bg", targetBg); - mProfile.put("carb_ratio", profile.getIc()); - mProfile.put("sens", profile.getIsfMgdl()); - mProfile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3)); - mProfile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4d)); - - //mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)); - mProfile.put("high_temptarget_raises_sensitivity", false); - //mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity)); - mProfile.put("low_temptarget_lowers_sensitivity", false); - - - mProfile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target)); - mProfile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target)); - mProfile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments); - mProfile.put("exercise_mode", SMBDefaults.exercise_mode); - mProfile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target); - mProfile.put("maxCOB", SMBDefaults.maxCOB); - mProfile.put("skip_neutral_temps", pump.setNeutralTempAtFullHour()); - // min_5m_carbimpact is not used within SMB determinebasal - //if (mealData.usedMinCarbsImpact > 0) { - // mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact); - //} else { - // mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact)); - //} - mProfile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap); - mProfile.put("enableUAM", uamAllowed); - mProfile.put("A52_risk_enable", SMBDefaults.A52_risk_enable); - - boolean smbEnabled = sp.getBoolean(R.string.key_use_smb, false); - mProfile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval)); - mProfile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false)); - mProfile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false)); - mProfile.put("allowSMB_with_high_temptarget", smbEnabled && sp.getBoolean(R.string.key_allowSMB_with_high_temptarget, false)); - mProfile.put("enableSMB_always", smbEnabled && sp.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering); - mProfile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering); - mProfile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes)); - mProfile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes)); - //set the min SMB amount to be the amount set by the pump. - mProfile.put("bolus_increment", pumpbolusstep); - mProfile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold)); - - mProfile.put("current_basal", basalrate); - mProfile.put("temptargetSet", tempTargetSet); - mProfile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2"))); - - if (profileFunction.getUnits().equals(Constants.MMOL)) { - mProfile.put("out_units", "mmol/L"); - } - - - long now = System.currentTimeMillis(); - TemporaryBasal tb = treatmentsPlugin.getTempBasalFromHistory(now); - - mCurrentTemp = new JSONObject(); - mCurrentTemp.put("temp", "absolute"); - mCurrentTemp.put("duration", tb != null ? tb.getPlannedRemainingMinutes() : 0); - mCurrentTemp.put("rate", tb != null ? tb.tempBasalConvertedToAbsolute(now, profile) : 0d); - - // as we have non default temps longer than 30 mintues - TemporaryBasal tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()); - if (tempBasal != null) { - mCurrentTemp.put("minutesrunning", tempBasal.getRealDuration()); - } - - mIobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray); - - mGlucoseStatus = new JSONObject(); - mGlucoseStatus.put("glucose", glucoseStatus.glucose); - mGlucoseStatus.put("noise", glucoseStatus.noise); - - if (sp.getBoolean(R.string.key_always_use_shortavg, false)) { - mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta); - } else { - mGlucoseStatus.put("delta", glucoseStatus.delta); - } - mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta); - mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta); - mGlucoseStatus.put("date", glucoseStatus.date); - - mMealData = new JSONObject(); - mMealData.put("carbs", mealData.carbs); - mMealData.put("boluses", mealData.boluses); - mMealData.put("mealCOB", mealData.mealCOB); - mMealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation); - mMealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation); - mMealData.put("lastBolusTime", mealData.lastBolusTime); - mMealData.put("lastCarbTime", mealData.lastCarbTime); - - - if (constraintChecker.isAutosensModeEnabled().value()) { - mAutosensData = new JSONObject(); - mAutosensData.put("ratio", autosensDataRatio); - } else { - mAutosensData = new JSONObject(); - mAutosensData.put("ratio", 1.0); - } - mMicrobolusAllowed = microBolusAllowed; - mSMBAlwaysAllowed = advancedFiltering; - - mCurrentTime = now; - - mIsSaveCgmSource = isSaveCgmSource; - } - - private Object makeParam(JSONObject jsonObject, Context rhino, Scriptable scope) { - - if (jsonObject == null) return Undefined.instance; - - return NativeJSON.parse(rhino, scope, jsonObject.toString(), (context, scriptable, scriptable1, objects) -> objects[1]); - } - - private Object makeParamArray(JSONArray jsonArray, Context rhino, Scriptable scope) { - //Object param = NativeJSON.parse(rhino, scope, "{myarray: " + jsonArray.toString() + " }", new Callable() { - return NativeJSON.parse(rhino, scope, jsonArray.toString(), (context, scriptable, scriptable1, objects) -> objects[1]); - } - - private String readFile(String filename) throws IOException { - byte[] bytes = mScriptReader.readFile(filename); - String string = new String(bytes, StandardCharsets.UTF_8); - if (string.startsWith("#!/usr/bin/env node")) { - string = string.substring(20); - } - return string; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt new file mode 100644 index 0000000000..13a11fa774 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.kt @@ -0,0 +1,290 @@ +package info.nightscout.androidaps.plugins.aps.openAPSSMB + +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.R +import info.nightscout.androidaps.data.IobTotal +import info.nightscout.androidaps.data.MealData +import info.nightscout.androidaps.data.Profile +import info.nightscout.androidaps.interfaces.ActivePluginProvider +import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.aps.logger.LoggerCallback +import info.nightscout.androidaps.plugins.aps.loop.ScriptReader +import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.utils.SafeParse +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import org.mozilla.javascript.* +import org.mozilla.javascript.Function +import java.io.IOException +import java.lang.reflect.InvocationTargetException +import java.nio.charset.StandardCharsets +import javax.inject.Inject + +class DetermineBasalAdapterSMBJS internal constructor(private val scriptReader: ScriptReader, private val injector: HasAndroidInjector) { + + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var constraintChecker: ConstraintChecker + @Inject lateinit var sp: SP + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var profileFunction: ProfileFunction + @Inject lateinit var treatmentsPlugin: TreatmentsPlugin + @Inject lateinit var activePluginProvider: ActivePluginProvider + @Inject lateinit var openHumansUploader: OpenHumansUploader + + private var profile = JSONObject() + private var mGlucoseStatus = JSONObject() + private var iobData: JSONArray? = null + private var mealData = JSONObject() + private var currentTemp = JSONObject() + private var autosensData = JSONObject() + private var microBolusAllowed = false + private var smbAlwaysAllowed = false + private var currentTime: Long = 0 + private var saveCgmSource = false + var currentTempParam: String? = null + private set + var iobDataParam: String? = null + private set + var glucoseStatusParam: String? = null + private set + var profileParam: String? = null + private set + var mealDataParam: String? = null + private set + var scriptDebug = "" + private set + + @Suppress("SpellCheckingInspection") + operator fun invoke(): DetermineBasalResultSMB? { + aapsLogger.debug(LTag.APS, ">>> Invoking determine_basal <<<") + aapsLogger.debug(LTag.APS, "Glucose status: " + mGlucoseStatus.toString().also { glucoseStatusParam = it }) + aapsLogger.debug(LTag.APS, "IOB data: " + iobData.toString().also { iobDataParam = it }) + aapsLogger.debug(LTag.APS, "Current temp: " + currentTemp.toString().also { currentTempParam = it }) + aapsLogger.debug(LTag.APS, "Profile: " + profile.toString().also { profileParam = it }) + aapsLogger.debug(LTag.APS, "Meal data: " + mealData.toString().also { mealDataParam = it }) + aapsLogger.debug(LTag.APS, "Autosens data: $autosensData") + aapsLogger.debug(LTag.APS, "Reservoir data: " + "undefined") + aapsLogger.debug(LTag.APS, "MicroBolusAllowed: $microBolusAllowed") + aapsLogger.debug(LTag.APS, "SMBAlwaysAllowed: $smbAlwaysAllowed") + aapsLogger.debug(LTag.APS, "CurrentTime: $currentTime") + aapsLogger.debug(LTag.APS, "isSaveCgmSource: $saveCgmSource") + var determineBasalResultSMB: DetermineBasalResultSMB? = null + val rhino = Context.enter() + val scope: Scriptable = rhino.initStandardObjects() + // Turn off optimization to make Rhino Android compatible + rhino.optimizationLevel = -1 + try { + + //register logger callback for console.log and console.error + ScriptableObject.defineClass(scope, LoggerCallback::class.java) + val myLogger = rhino.newObject(scope, "LoggerCallback", null) + scope.put("console2", scope, myLogger) + rhino.evaluateString(scope, readFile("OpenAPSAMA/loggerhelper.js"), "JavaScript", 0, null) + + //set module parent + rhino.evaluateString(scope, "var module = {\"parent\":Boolean(1)};", "JavaScript", 0, null) + rhino.evaluateString(scope, "var round_basal = function round_basal(basal, profile) { return basal; };", "JavaScript", 0, null) + rhino.evaluateString(scope, "require = function() {return round_basal;};", "JavaScript", 0, null) + + //generate functions "determine_basal" and "setTempBasal" + rhino.evaluateString(scope, readFile("OpenAPSSMB/determine-basal.js"), "JavaScript", 0, null) + rhino.evaluateString(scope, readFile("OpenAPSSMB/basal-set-temp.js"), "setTempBasal.js", 0, null) + val determineBasalObj = scope["determine_basal", scope] + val setTempBasalFunctionsObj = scope["tempBasalFunctions", scope] + + //call determine-basal + if (determineBasalObj is Function && setTempBasalFunctionsObj is NativeObject) { + + //prepare parameters + val params = arrayOf( + makeParam(mGlucoseStatus, rhino, scope), + makeParam(currentTemp, rhino, scope), + makeParamArray(iobData, rhino, scope), + makeParam(profile, rhino, scope), + makeParam(autosensData, rhino, scope), + makeParam(mealData, rhino, scope), + setTempBasalFunctionsObj, + java.lang.Boolean.valueOf(microBolusAllowed), + makeParam(null, rhino, scope), // reservoir data as undefined + java.lang.Long.valueOf(currentTime), + java.lang.Boolean.valueOf(saveCgmSource) + ) + val jsResult = determineBasalObj.call(rhino, scope, scope, params) as NativeObject + scriptDebug = LoggerCallback.scriptDebug + + // Parse the jsResult object to a JSON-String + val result = NativeJSON.stringify(rhino, scope, jsResult, null, null).toString() + aapsLogger.debug(LTag.APS, "Result: $result") + try { + val resultJson = JSONObject(result) + openHumansUploader.enqueueSMBData(profile, mGlucoseStatus, iobData, mealData, currentTemp, autosensData, microBolusAllowed, smbAlwaysAllowed, resultJson) + determineBasalResultSMB = DetermineBasalResultSMB(injector, resultJson) + } catch (e: JSONException) { + aapsLogger.error(LTag.APS, "Unhandled exception", e) + } + } else { + aapsLogger.error(LTag.APS, "Problem loading JS Functions") + } + } catch (e: IOException) { + aapsLogger.error(LTag.APS, "IOException") + } catch (e: RhinoException) { + aapsLogger.error(LTag.APS, "RhinoException: (" + e.lineNumber() + "," + e.columnNumber() + ") " + e.toString()) + } catch (e: IllegalAccessException) { + aapsLogger.error(LTag.APS, e.toString()) + } catch (e: InstantiationException) { + aapsLogger.error(LTag.APS, e.toString()) + } catch (e: InvocationTargetException) { + aapsLogger.error(LTag.APS, e.toString()) + } finally { + Context.exit() + } + glucoseStatusParam = mGlucoseStatus.toString() + iobDataParam = iobData.toString() + currentTempParam = currentTemp.toString() + profileParam = profile.toString() + mealDataParam = mealData.toString() + return determineBasalResultSMB + } + + @Suppress("SpellCheckingInspection") fun setData(profile: Profile, + maxIob: Double, + maxBasal: Double, + minBg: Double, + maxBg: Double, + targetBg: Double, + basalRate: Double, + iobArray: Array, + glucoseStatus: GlucoseStatus, + mealData: MealData, + autosensDataRatio: Double, + tempTargetSet: Boolean, + microBolusAllowed: Boolean, + uamAllowed: Boolean, + advancedFiltering: Boolean, + isSaveCgmSource: Boolean + ) { + val pump = activePluginProvider.activePump + val pumpBolusStep = pump.pumpDescription.bolusStep + this.profile.put("max_iob", maxIob) + //mProfile.put("dia", profile.getDia()); + this.profile.put("type", "current") + this.profile.put("max_daily_basal", profile.maxDailyBasal) + this.profile.put("max_basal", maxBasal) + this.profile.put("min_bg", minBg) + this.profile.put("max_bg", maxBg) + this.profile.put("target_bg", targetBg) + this.profile.put("carb_ratio", profile.ic) + this.profile.put("sens", profile.isfMgdl) + this.profile.put("max_daily_safety_multiplier", sp.getInt(R.string.key_openapsama_max_daily_safety_multiplier, 3)) + this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0)) + + //mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity)); + this.profile.put("high_temptarget_raises_sensitivity", false) + //mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity)); + this.profile.put("low_temptarget_lowers_sensitivity", false) + this.profile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target)) + this.profile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target)) + this.profile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments) + this.profile.put("exercise_mode", SMBDefaults.exercise_mode) + this.profile.put("half_basal_exercise_target", SMBDefaults.half_basal_exercise_target) + this.profile.put("maxCOB", SMBDefaults.maxCOB) + this.profile.put("skip_neutral_temps", pump.setNeutralTempAtFullHour()) + // min_5m_carbimpact is not used within SMB determinebasal + //if (mealData.usedMinCarbsImpact > 0) { + // mProfile.put("min_5m_carbimpact", mealData.usedMinCarbsImpact); + //} else { + // mProfile.put("min_5m_carbimpact", SP.getDouble(R.string.key_openapsama_min_5m_carbimpact, SMBDefaults.min_5m_carbimpact)); + //} + this.profile.put("remainingCarbsCap", SMBDefaults.remainingCarbsCap) + this.profile.put("enableUAM", uamAllowed) + this.profile.put("A52_risk_enable", SMBDefaults.A52_risk_enable) + val smbEnabled = sp.getBoolean(R.string.key_use_smb, false) + this.profile.put("SMBInterval", sp.getInt(R.string.key_smbinterval, SMBDefaults.SMBInterval)) + this.profile.put("enableSMB_with_COB", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_COB, false)) + this.profile.put("enableSMB_with_temptarget", smbEnabled && sp.getBoolean(R.string.key_enableSMB_with_temptarget, false)) + this.profile.put("allowSMB_with_high_temptarget", smbEnabled && sp.getBoolean(R.string.key_allowSMB_with_high_temptarget, false)) + this.profile.put("enableSMB_always", smbEnabled && sp.getBoolean(R.string.key_enableSMB_always, false) && advancedFiltering) + this.profile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering) + this.profile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes)) + this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes)) + //set the min SMB amount to be the amount set by the pump. + this.profile.put("bolus_increment", pumpBolusStep) + this.profile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold)) + this.profile.put("current_basal", basalRate) + this.profile.put("temptargetSet", tempTargetSet) + this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2"))) + if (profileFunction.getUnits() == Constants.MMOL) { + this.profile.put("out_units", "mmol/L") + } + val now = System.currentTimeMillis() + val tb = treatmentsPlugin.getTempBasalFromHistory(now) + currentTemp.put("temp", "absolute") + currentTemp.put("duration", tb?.plannedRemainingMinutes ?: 0) + currentTemp.put("rate", tb?.tempBasalConvertedToAbsolute(now, profile) ?: 0.0) + + // as we have non default temps longer than 30 mintues + val tempBasal = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) + if (tempBasal != null) { + currentTemp.put("minutesrunning", tempBasal.realDuration) + } + iobData = IobCobCalculatorPlugin.convertToJSONArray(iobArray) + mGlucoseStatus.put("glucose", glucoseStatus.glucose) + mGlucoseStatus.put("noise", glucoseStatus.noise) + if (sp.getBoolean(R.string.key_always_use_shortavg, false)) { + mGlucoseStatus.put("delta", glucoseStatus.short_avgdelta) + } else { + mGlucoseStatus.put("delta", glucoseStatus.delta) + } + mGlucoseStatus.put("short_avgdelta", glucoseStatus.short_avgdelta) + mGlucoseStatus.put("long_avgdelta", glucoseStatus.long_avgdelta) + mGlucoseStatus.put("date", glucoseStatus.date) + this.mealData.put("carbs", mealData.carbs) + this.mealData.put("boluses", mealData.boluses) + this.mealData.put("mealCOB", mealData.mealCOB) + this.mealData.put("slopeFromMaxDeviation", mealData.slopeFromMaxDeviation) + this.mealData.put("slopeFromMinDeviation", mealData.slopeFromMinDeviation) + this.mealData.put("lastBolusTime", mealData.lastBolusTime) + this.mealData.put("lastCarbTime", mealData.lastCarbTime) + if (constraintChecker.isAutosensModeEnabled().value()) { + autosensData.put("ratio", autosensDataRatio) + } else { + autosensData.put("ratio", 1.0) + } + this.microBolusAllowed = microBolusAllowed + smbAlwaysAllowed = advancedFiltering + currentTime = now + saveCgmSource = isSaveCgmSource + } + + private fun makeParam(jsonObject: JSONObject?, rhino: Context, scope: Scriptable): Any { + return if (jsonObject == null) Undefined.instance + else NativeJSON.parse(rhino, scope, jsonObject.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array -> objects[1] } + } + + private fun makeParamArray(jsonArray: JSONArray?, rhino: Context, scope: Scriptable): Any { + return NativeJSON.parse(rhino, scope, jsonArray.toString()) { _: Context?, _: Scriptable?, _: Scriptable?, objects: Array -> objects[1] } + } + + @Throws(IOException::class) private fun readFile(filename: String): String { + val bytes = scriptReader.readFile(filename) + var string = String(bytes, StandardCharsets.UTF_8) + if (string.startsWith("#!/usr/bin/env node")) { + string = string.substring(20) + } + return string + } + + init { + injector.androidInjector().inject(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java index 4ddbcdca76..c3a19cb1f6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java @@ -265,19 +265,14 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr profiler.log(LTag.APS, "SMB data gathering", start); start = System.currentTimeMillis(); - try { - determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, activePlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData, - lastAutosensResult.ratio, //autosensDataRatio - isTempTarget, - smbAllowed.value(), - uam.value(), - advancedFiltering.value(), - activePlugin.getActiveBgSource().getClass().getSimpleName().equals("DexcomPlugin") - ); - } catch (JSONException e) { - fabricPrivacy.logException(e); - return; - } + determineBasalAdapterSMBJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, activePlugin.getActivePump().getBaseBasalRate(), iobArray, glucoseStatus, mealData, + lastAutosensResult.ratio, //autosensDataRatio + isTempTarget, + smbAllowed.value(), + uam.value(), + advancedFiltering.value(), + activePlugin.getActiveBgSource().getClass().getSimpleName().equals("DexcomPlugin") + ); long now = System.currentTimeMillis();