Support for new Dexcom app

This commit is contained in:
Tebbe Ubben 2019-06-19 01:38:55 +02:00
parent 013e10aef0
commit 5af80ceb02
12 changed files with 175 additions and 466 deletions

View file

@ -21,7 +21,7 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="sugar.free.sightremote.HISTORY_BROADCASTS" />
<uses-permission android:name="com.dexcom.cgm.EXTERNAL_PERMISSION" />
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
@ -88,10 +88,8 @@
<action android:name="com.eveningoutpost.dexdrip.NS_EMULATOR"/>
<!-- Receiver from glimp -->
<action android:name="it.ct.glicemia.ACTION_GLUCOSE_MEASURED"/>
<!-- Receiver from DexcomG5 -->
<action android:name="com.dexcom.cgm.DATA"/>
<action android:name="com.dexcom.cgm.AndroidAPSEVGCallback.BROADCAST"/>
<action android:name="com.dexcom.cgm.g5.AndroidAPSEVGCallback.BROADCAST"/>
<!-- Receiver from Dexcom -->
<action android:name="com.dexcom.cgm.EXTERNAL_BROADCAST"/>
<!-- Receiver from Poctech -->
<action android:name="com.china.poctech.data"/>
<!-- Receiver from Tomato -->
@ -284,6 +282,7 @@
android:name=".plugins.pump.insight.activities.InsightPairingInformationActivity"
android:label="@string/pairing_information"
android:theme="@style/AppTheme" />
<activity android:name=".activities.RequestDexcomPermissionActivity" />
<uses-library android:name="org.apache.http.legacy" android:required="false"/>

View file

@ -72,8 +72,7 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin;
@ -192,8 +191,7 @@ public class MainApp extends Application {
pluginsList.add(SourceNSClientPlugin.getPlugin());
pluginsList.add(SourceMM640gPlugin.getPlugin());
pluginsList.add(SourceGlimpPlugin.getPlugin());
pluginsList.add(SourceDexcomG5Plugin.getPlugin());
pluginsList.add(SourceDexcomG6Plugin.getPlugin());
pluginsList.add(SourceDexcomPlugin.INSTANCE);
pluginsList.add(SourcePoctechPlugin.getPlugin());
pluginsList.add(SourceTomatoPlugin.getPlugin());
pluginsList.add(SourceEversensePlugin.getPlugin());

View file

@ -39,9 +39,9 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.general.wear.WearPlugin;
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatuslinePlugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
@ -144,7 +144,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
addPreferencesFromResource(R.xml.pref_overview);
addPreferencesFromResourceIfEnabled(SourceDexcomG5Plugin.getPlugin(), PluginType.BGSOURCE);
addPreferencesFromResourceIfEnabled(SourceDexcomPlugin.INSTANCE, PluginType.BGSOURCE);
addPreferencesFromResourceIfEnabled(CareportalPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(SafetyPlugin.getPlugin(), PluginType.CONSTRAINTS);
if (Config.APS) {

View file

@ -0,0 +1,25 @@
package info.nightscout.androidaps.activities
import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin
class RequestDexcomPermissionActivity : AppCompatActivity() {
private val requestCode = "AndroidAPS <3".map { it.toInt() }.sum()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(arrayOf(SourceDexcomPlugin.PERMISSION), requestCode)
} else {
finish()
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
finish()
}
}

View file

@ -108,8 +108,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress;
import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.treatments.fragments.ProfileViewerDialog;
@ -661,8 +660,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
@Override
public void onClick(View v) {
boolean xdrip = SourceXdripPlugin.getPlugin().isEnabled(PluginType.BGSOURCE);
boolean g5 = SourceDexcomG5Plugin.getPlugin().isEnabled(PluginType.BGSOURCE);
boolean g6 = SourceDexcomG6Plugin.getPlugin().isEnabled(PluginType.BGSOURCE);
boolean dexcom = SourceDexcomPlugin.INSTANCE.isEnabled(PluginType.BGSOURCE);
String units = ProfileFunctions.getInstance().getProfileUnits();
FragmentManager manager = getFragmentManager();
@ -685,10 +683,16 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (xdrip) {
CalibrationDialog calibrationDialog = new CalibrationDialog();
calibrationDialog.show(manager, "CalibrationDialog");
} else if (g5 || g6) {
} else if (dexcom) {
try {
Intent i = new Intent("com.dexcom.cgm.activities.MeterEntryActivity");
startActivity(i);
String packageName = SourceDexcomPlugin.INSTANCE.findDexcomPackageName();
if (packageName != null) {
Intent i = new Intent("com.dexcom.cgm.activities.MeterEntryActivity");
i.setPackage(packageName);
startActivity(i);
} else {
ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.dexcom_app_not_installed));
}
} catch (ActivityNotFoundException e) {
ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.g5appnotdetected));
}
@ -697,14 +701,14 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
case R.id.overview_cgmbutton:
if (xdrip)
openCgmApp("com.eveningoutpost.dexdrip");
else if (g5 && units.equals(Constants.MGDL))
openCgmApp("com.dexcom.cgm.region5.mgdl");
else if (g5 && units.equals(Constants.MMOL))
openCgmApp("com.dexcom.cgm.region5.mmol");
else if (g6 && units.equals(Constants.MGDL))
openCgmApp("com.dexcom.g6.region3.mgdl");
else if (g6 && units.equals(Constants.MMOL))
openCgmApp("com.dexcom.g6.region3.mmol");
else if (dexcom) {
String packageName = SourceDexcomPlugin.INSTANCE.findDexcomPackageName();
if (packageName != null) {
openCgmApp(packageName);
} else {
ToastUtils.showToastInUiThread(getActivity(), MainApp.gs(R.string.dexcom_app_not_installed));
}
}
break;
case R.id.overview_treatmentbutton:
NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog();
@ -1188,10 +1192,10 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// **** Calibration & CGM buttons ****
boolean xDripIsBgSource = MainApp.getSpecificPlugin(SourceXdripPlugin.class) != null && MainApp.getSpecificPlugin(SourceXdripPlugin.class).isEnabled(PluginType.BGSOURCE);
boolean g5IsBgSource = MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class) != null && MainApp.getSpecificPlugin(SourceDexcomG5Plugin.class).isEnabled(PluginType.BGSOURCE);
boolean dexcomIsSource = SourceDexcomPlugin.INSTANCE.isEnabled(PluginType.BGSOURCE);
boolean bgAvailable = DatabaseHelper.actualBg() != null;
if (calibrationButton != null) {
if ((xDripIsBgSource || g5IsBgSource) && bgAvailable && SP.getBoolean(R.string.key_show_calibration_button, true)) {
if ((xDripIsBgSource || dexcomIsSource) && bgAvailable && SP.getBoolean(R.string.key_show_calibration_button, true)) {
calibrationButton.setVisibility(View.VISIBLE);
} else {
calibrationButton.setVisibility(View.GONE);
@ -1200,7 +1204,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (cgmButton != null) {
if (xDripIsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
cgmButton.setVisibility(View.VISIBLE);
} else if (g5IsBgSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
} else if (dexcomIsSource && SP.getBoolean(R.string.key_show_cgm_button, false)) {
cgmButton.setVisibility(View.VISIBLE);
} else {
cgmButton.setVisibility(View.GONE);

View file

@ -1,232 +0,0 @@
package info.nightscout.androidaps.plugins.source;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 28.11.2017.
*/
public class SourceDexcomG5Plugin extends PluginBase implements BgSourceInterface {
private static Logger log = LoggerFactory.getLogger(L.BGSOURCE);
private static SourceDexcomG5Plugin plugin = null;
public static SourceDexcomG5Plugin getPlugin() {
if (plugin == null)
plugin = new SourceDexcomG5Plugin();
return plugin;
}
private SourceDexcomG5Plugin() {
super(new PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment.class.getName())
.pluginName(R.string.DexcomG5)
.shortName(R.string.dexcomG5_shortname)
.preferencesId(R.xml.pref_bgsource)
.description(R.string.description_source_dexcom_g5)
);
}
@Override
public boolean advancedFilteringSupported() {
return true;
}
@Override
public void handleNewData(Intent intent) {
// onHandleIntent Bundle{ data => [{"m_time":1511939180,"m_trend":"NotComputable","m_value":335}]; android.support.content.wakelockid => 95; }Bundle
if (!isEnabled(PluginType.BGSOURCE)) return;
if (intent.getAction().equals(Intents.DEXCOMG5_BG))
handleNewDataOld(intent);
if (intent.getAction().equals(Intents.DEXCOMG5_BG_NEW))
handleNewDataNew(intent);
}
public void handleNewDataOld(Intent intent) {
// onHandleIntent Bundle{ data => [{"m_time":1511939180,"m_trend":"NotComputable","m_value":335}]; android.support.content.wakelockid => 95; }Bundle
Bundle bundle = intent.getExtras();
if (bundle == null) return;
BgReading bgReading = new BgReading();
String data = bundle.getString("data");
if (L.isEnabled(L.BGSOURCE))
log.debug("Received Dexcom Data", data);
if (data == null) return;
try {
JSONArray jsonArray = new JSONArray(data);
if (L.isEnabled(L.BGSOURCE))
log.debug("Received Dexcom Data size:" + jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = jsonArray.getJSONObject(i);
bgReading.value = json.getInt("m_value");
bgReading.direction = json.getString("m_trend");
bgReading.date = json.getLong("m_time") * 1000L;
bgReading.raw = 0;
boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "DexcomG5");
if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
NSUpload.uploadBg(bgReading, "AndroidAPS-DexcomG5");
}
if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) {
NSUpload.sendToXdrip(bgReading);
}
}
} catch (JSONException e) {
log.error("Exception: ", e);
}
}
public void handleNewDataNew(Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle == null) return;
if (L.isEnabled(L.BGSOURCE)) {
if (bundle.containsKey("transmitterSystemTime"))
log.debug("transmitterSystemTime: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterSystemTime")));
if (bundle.containsKey("transmitterRemainingTime"))
log.debug("transmitterRemainingTime: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterRemainingTime")));
log.debug("transmitterId: " + bundle.getString("transmitterId"));
if (bundle.containsKey("transmitterActivatedOn"))
log.debug("transmitterActivatedOn: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterActivatedOn")));
log.debug("transmitterVersion: " + bundle.getString("transmitterVersion"));
log.debug("transmitterSoftwareNumber: " + bundle.getString("transmitterSoftwareNumber"));
log.debug("transmitterStorageTimeDays: " + bundle.getInt("transmitterStorageTimeDays"));
log.debug("transmitterApiVersion: " + bundle.getInt("transmitterApiVersion"));
log.debug("transmitterMaxRuntimeDays: " + bundle.getInt("transmitterMaxRuntimeDays"));
log.debug("transmitterMaxStorageTimeDays: " + bundle.getInt("transmitterMaxStorageTimeDays"));
log.debug("transmitterCGMProcessorFirmwareVersion: " + bundle.getString("transmitterCGMProcessorFirmwareVersion"));
log.debug("transmitterBleRadioFirmwareVersion: " + bundle.getString("transmitterBleRadioFirmwareVersion"));
log.debug("transmitterHardwareVersion: " + bundle.getInt("transmitterHardwareVersion"));
log.debug("transmitterBleSoftDeviceVersion: " + bundle.getString("transmitterBleSoftDeviceVersion"));
log.debug("transmitterNordicAsicHwID: " + bundle.getInt("transmitterNordicAsicHwID"));
log.debug("transmitterSessionTimeDays: " + bundle.getInt("transmitterSessionTimeDays"));
log.debug("transmitterFeatureFlags: " + bundle.getInt("transmitterFeatureFlags"));
}
if (bundle.containsKey("sensorInsertionTime")) {
long sensorInsertionTime = bundle.getLong("sensorInsertionTime");
if (L.isEnabled(L.BGSOURCE))
log.debug("sensorInsertionTime: " + DateUtil.dateAndTimeFullString(sensorInsertionTime));
if (SP.getBoolean(R.string.key_dexcom_lognssensorchange, false)) {
try {
if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) {
JSONObject data = new JSONObject();
data.put("enteredBy", "AndroidAPS-DexcomG5");
data.put("created_at", DateUtil.toISOString(sensorInsertionTime));
data.put("eventType", CareportalEvent.SENSORCHANGE);
NSUpload.uploadCareportalEntryToNS(data);
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
}
if (bundle.containsKey("glucoseValues")) {
int[] glucoseValues = bundle.getIntArray("glucoseValues");
int[] glucoseRecordIDs = bundle.getIntArray("glucoseRecordIDs");
long[] glucoseRecordedTimestamps = bundle.getLongArray("glucoseRecordedTimestamps");
long[] glucoseSessionStartTimes = bundle.getLongArray("glucoseSessionStartTimes");
long[] glucoseSystemTimestamps = bundle.getLongArray("glucoseSystemTimestamps");
String[] glucoseTransmitterIDS = bundle.getStringArray("glucoseTransmitterIDS");
long[] glucoseTransmitterTimestamps = bundle.getLongArray("glucoseTransmitterTimestamps");
String[] glucoseTrendsArrows = bundle.getStringArray("glucoseTrendsArrows");
boolean[] glucoseWasBackfilled = bundle.getBooleanArray("glucoseWasBackfilled");
if (L.isEnabled(L.BGSOURCE)) {
log.debug("glucoseValues", Arrays.toString(glucoseValues));
log.debug("glucoseRecordIDs", Arrays.toString(glucoseRecordIDs));
log.debug("glucoseRecordedTimestamps", Arrays.toString(glucoseRecordedTimestamps));
log.debug("glucoseSessionStartTimes", Arrays.toString(glucoseSessionStartTimes));
log.debug("glucoseSystemTimestamps", Arrays.toString(glucoseSystemTimestamps));
log.debug("glucoseTransmitterIDS", Arrays.toString(glucoseTransmitterIDS));
log.debug("glucoseTransmitterTimestamps", Arrays.toString(glucoseTransmitterTimestamps));
log.debug("glucoseTrendsArrows", Arrays.toString(glucoseTrendsArrows));
log.debug("glucoseWasBackfilled", Arrays.toString(glucoseWasBackfilled));
}
for (int i = 0; i < glucoseValues.length; i++) {
BgReading bgReading = new BgReading();
bgReading.value = glucoseValues[i];
bgReading.direction = glucoseTrendsArrows[i];
bgReading.date = glucoseTransmitterTimestamps[i];
bgReading.raw = 0;
boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "DexcomG5");
if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
NSUpload.uploadBg(bgReading, "AndroidAPS-DexcomG5");
}
if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) {
NSUpload.sendToXdrip(bgReading);
}
}
}
if (bundle.containsKey("meterValues")) {
String[] meterEntryTypes = bundle.getStringArray("meterEntryTypes");
long[] meterTimestamps = bundle.getLongArray("meterTimestamps");
int[] meterValues = bundle.getIntArray("meterValues");
long[] meterRecordedTimestamps = bundle.getLongArray("meterRecordedTimestamps");
int[] meterTransmitterIDs = bundle.getIntArray("meterTransmitterIDs");
long[] meterTransmitterTimestamps = bundle.getLongArray("meterTransmitterTimestamps");
if (L.isEnabled(L.BGSOURCE)) {
log.debug("meterValues", Arrays.toString(meterValues));
log.debug("meterEntryTypes", Arrays.toString(meterEntryTypes));
log.debug("meterTimestamps", Arrays.toString(meterTimestamps));
log.debug("meterTransmitterTimestamps", Arrays.toString(meterTransmitterTimestamps));
log.debug("meterRecordedTimestamps", Arrays.toString(meterRecordedTimestamps));
log.debug("meterTransmitterIDs", Arrays.toString(meterTransmitterIDs));
}
for (int i = 0; i < meterValues.length; i++) {
try {
if (MainApp.getDbHelper().getCareportalEventFromTimestamp(meterTimestamps[i]) == null) {
JSONObject data = new JSONObject();
data.put("enteredBy", "AndroidAPS-DexcomG5");
data.put("created_at", DateUtil.toISOString(meterTimestamps[i]));
data.put("eventType", CareportalEvent.BGCHECK);
data.put("glucoseType", "Finger");
data.put("glucose", meterValues[i]);
data.put("units", Constants.MGDL);
NSUpload.uploadCareportalEntryToNS(data);
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
}
}
}

View file

@ -1,174 +0,0 @@
package info.nightscout.androidaps.plugins.source;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.BgSourceInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 30.11.2018.
*/
public class SourceDexcomG6Plugin extends PluginBase implements BgSourceInterface {
private static Logger log = LoggerFactory.getLogger(L.BGSOURCE);
private static SourceDexcomG6Plugin plugin = null;
public static SourceDexcomG6Plugin getPlugin() {
if (plugin == null)
plugin = new SourceDexcomG6Plugin();
return plugin;
}
private SourceDexcomG6Plugin() {
super(new PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment.class.getName())
.pluginName(R.string.DexcomG6)
.shortName(R.string.dexcomG6_shortname)
.preferencesId(R.xml.pref_bgsource)
.description(R.string.description_source_dexcom_g6)
);
}
@Override
public boolean advancedFilteringSupported() {
return true;
}
@Override
public void handleNewData(Intent intent) {
if (!isEnabled(PluginType.BGSOURCE)) return;
Bundle bundle = intent.getExtras();
if (bundle == null) return;
if (L.isEnabled(L.BGSOURCE)) {
if (bundle.containsKey("transmitterSystemTime"))
log.debug("transmitterSystemTime: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterSystemTime")));
log.debug("transmitterId: " + bundle.getString("transmitterId"));
if (bundle.containsKey("transmitterActivatedOn"))
log.debug("transmitterActivatedOn: " + DateUtil.dateAndTimeFullString(bundle.getLong("transmitterActivatedOn")));
log.debug("transmitterVersion: " + bundle.getString("transmitterVersion"));
log.debug("transmitterSoftwareNumber: " + bundle.getString("transmitterSoftwareNumber"));
log.debug("transmitterStorageTimeDays: " + bundle.getInt("transmitterStorageTimeDays"));
log.debug("transmitterApiVersion: " + bundle.getInt("transmitterApiVersion"));
log.debug("transmitterMaxRuntimeDays: " + bundle.getInt("transmitterMaxRuntimeDays"));
log.debug("transmitterMaxStorageTimeDays: " + bundle.getInt("transmitterMaxStorageTimeDays"));
log.debug("transmitterCGMProcessorFirmwareVersion: " + bundle.getString("transmitterCGMProcessorFirmwareVersion"));
log.debug("transmitterBleRadioFirmwareVersion: " + bundle.getString("transmitterBleRadioFirmwareVersion"));
log.debug("transmitterHardwareVersion: " + bundle.getInt("transmitterHardwareVersion"));
log.debug("transmitterBleSoftDeviceVersion: " + bundle.getString("transmitterBleSoftDeviceVersion"));
log.debug("transmitterNordicAsicHwID: " + bundle.getInt("transmitterNordicAsicHwID"));
log.debug("transmitterSessionTimeDays: " + bundle.getInt("transmitterSessionTimeDays"));
log.debug("transmitterFeatureFlags: " + bundle.getInt("transmitterFeatureFlags"));
if (bundle.containsKey("sensorCode"))
log.debug("sensorCode: " + bundle.getString("sensorCode"));
}
if (bundle.containsKey("sensorInsertionTime")) {
long sensorInsertionTime = bundle.getLong("sensorInsertionTime");
if (L.isEnabled(L.BGSOURCE))
log.debug("sensorInsertionTime: " + DateUtil.dateAndTimeFullString(sensorInsertionTime));
if (SP.getBoolean(R.string.key_dexcom_lognssensorchange, false)) {
try {
if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) {
JSONObject data = new JSONObject();
data.put("enteredBy", "AndroidAPS-DexcomG6");
data.put("created_at", DateUtil.toISOString(sensorInsertionTime));
data.put("eventType", CareportalEvent.SENSORCHANGE);
NSUpload.uploadCareportalEntryToNS(data);
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
}
if (bundle.containsKey("evgTimestamps")) {
long[] timestamps = bundle.getLongArray("evgTimestamps");
long[] transmitterTimes = bundle.getLongArray("transmitterTimes");
int[] evgs = bundle.getIntArray("evgs");
int[] predictiveEVGs = bundle.getIntArray("predictiveEVGs");
String[] trendArrows = bundle.getStringArray("trendArrows");
if (L.isEnabled(L.BGSOURCE)) {
log.debug("timestamps", Arrays.toString(timestamps));
log.debug("transmitterTimes", Arrays.toString(transmitterTimes));
log.debug("evgs", Arrays.toString(evgs));
log.debug("predictiveEVGs", Arrays.toString(predictiveEVGs));
log.debug("trendArrows", Arrays.toString(trendArrows));
}
for (int i = 0; i < transmitterTimes.length; i++) {
BgReading bgReading = new BgReading();
bgReading.value = evgs[i];
bgReading.direction = trendArrows[i];
bgReading.date = timestamps[i];
bgReading.raw = 0;
boolean isNew = MainApp.getDbHelper().createIfNotExists(bgReading, "DexcomG6");
if (isNew && SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
NSUpload.uploadBg(bgReading, "AndroidAPS-DexcomG6");
}
if (isNew && SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) {
NSUpload.sendToXdrip(bgReading);
}
}
}
if (bundle.containsKey("meterValues")) {
int[] meterValues = bundle.getIntArray("meterValues");
String[] meterEntryTypes = bundle.getStringArray("meterEntryTypes");
long[] meterTimestamps = bundle.getLongArray("meterTimestamps");
long[] meterTransmitterTimestamps = bundle.getLongArray("meterTransmitterTimestamps");
long[] meterRecordedTimestamps = bundle.getLongArray("meterRecordedTimestamps");
int[] meterRecordIDs = bundle.getIntArray("meterRecordIDs");
if (L.isEnabled(L.BGSOURCE)) {
log.debug("meterValues", Arrays.toString(meterValues));
log.debug("meterEntryTypes", Arrays.toString(meterEntryTypes));
log.debug("meterTimestamps", Arrays.toString(meterTimestamps));
log.debug("meterTransmitterTimestamps", Arrays.toString(meterTransmitterTimestamps));
log.debug("meterRecordedTimestamps", Arrays.toString(meterRecordedTimestamps));
log.debug("meterRecordIDs", Arrays.toString(meterRecordIDs));
}
for (int i = 0; i < meterValues.length; i++) {
try {
if (MainApp.getDbHelper().getCareportalEventFromTimestamp(meterTimestamps[i]) == null) {
JSONObject data = new JSONObject();
data.put("enteredBy", "AndroidAPS-DexcomG6");
data.put("created_at", DateUtil.toISOString(meterTimestamps[i]));
data.put("eventType", CareportalEvent.BGCHECK);
data.put("glucoseType", "Finger");
data.put("glucose", meterValues[i]);
data.put("units", Constants.MGDL);
NSUpload.uploadCareportalEntryToNS(data);
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
}
}
}

View file

@ -0,0 +1,111 @@
package info.nightscout.androidaps.plugins.source
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.content.ContextCompat
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.RequestDexcomPermissionActivity
import info.nightscout.androidaps.db.BgReading
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.interfaces.BgSourceInterface
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.SP
import org.json.JSONObject
import org.slf4j.LoggerFactory
object SourceDexcomPlugin : PluginBase(PluginDescription()
.mainType(PluginType.BGSOURCE)
.fragmentClass(BGSourceFragment::class.java.name)
.pluginName(R.string.dexcom_app_patched)
.shortName(R.string.dexcom_short)
.preferencesId(R.xml.pref_bgsource)
.description(R.string.description_source_dexcom)), BgSourceInterface {
private val log = LoggerFactory.getLogger(L.BGSOURCE)
private val PACKAGE_NAMES = arrayOf("com.dexcom.cgm.region1.mgdl", "com.dexcom.cgm.region1.mmol",
"com.dexcom.cgm.region2.mgdl", "com.dexcom.cgm.region2.mmol",
"com.dexcom.g6.region1.mmol", "com.dexcom.g6.region2.mgdl",
"com.dexcom.g6.region3.mgdl", "com.dexcom.g6.region3.mmol")
const val PERMISSION = "com.dexcom.cgm.EXTERNAL_PERMISSION"
override fun advancedFilteringSupported(): Boolean {
return true
}
override fun onStart() {
super.onStart()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(MainApp.instance(), PERMISSION) != PackageManager.PERMISSION_GRANTED) {
val intent = Intent(MainApp.instance(), RequestDexcomPermissionActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(intent)
}
}
fun findDexcomPackageName(): String? {
val packageManager = MainApp.instance().packageManager;
for (packageInfo in packageManager.getInstalledPackages(0)) {
if (PACKAGE_NAMES.contains(packageInfo.packageName)) return packageInfo.packageName
}
return null
}
override fun handleNewData(intent: Intent) {
if (!isEnabled(PluginType.BGSOURCE)) return
try {
val glucoseValues = intent.getBundleExtra("glucoseValues")
for (i in 0 until glucoseValues.size()) {
val glucoseValue = glucoseValues.getBundle(i.toString())
val bgReading = BgReading()
bgReading.value = glucoseValue!!.getInt("glucoseValue").toDouble()
bgReading.direction = glucoseValue.getString("trendArrow")
bgReading.date = glucoseValue.getLong("timestamp") * 1000
bgReading.raw = 0.0
if (MainApp.getDbHelper().createIfNotExists(bgReading, "Dexcom")) {
if (SP.getBoolean(R.string.key_dexcomg5_nsupload, false)) {
NSUpload.uploadBg(bgReading, "AndroidAPS-DexcomG6")
}
if (SP.getBoolean(R.string.key_dexcomg5_xdripupload, false)) {
NSUpload.sendToXdrip(bgReading)
}
}
}
val meters = intent.getBundleExtra("meters")
for (i in 0 until meters.size()) {
val meter = meters.getBundle(i.toString())
val timestamp = meter.getLong("timestamp") * 1000
if (MainApp.getDbHelper().getCareportalEventFromTimestamp(timestamp) != null) continue
val jsonObject = JSONObject()
jsonObject.put("enteredBy", "AndroidAPS-Dexcom")
jsonObject.put("created_at", DateUtil.toISOString(timestamp))
jsonObject.put("eventType", CareportalEvent.BGCHECK)
jsonObject.put("glucoseType", "Finger")
jsonObject.put("glucose", meter.getInt("meterValue"))
jsonObject.put("units", Constants.MGDL)
NSUpload.uploadCareportalEntryToNS(jsonObject)
}
if (SP.getBoolean(R.string.key_dexcom_lognssensorchange, false) && intent.hasExtra("sensorInsertionTime")) {
val sensorInsertionTime = intent.extras.getLong("sensorInsertionTime") * 1000
if (MainApp.getDbHelper().getCareportalEventFromTimestamp(sensorInsertionTime) == null) {
val jsonObject = JSONObject()
jsonObject.put("enteredBy", "AndroidAPS-Dexcom")
jsonObject.put("created_at", DateUtil.toISOString(sensorInsertionTime))
jsonObject.put("eventType", CareportalEvent.SENSORCHANGE)
NSUpload.uploadCareportalEntryToNS(jsonObject)
}
}
} catch (e : Exception) {
log.error("Error while processing intent from Dexcom App", e)
}
}
}

View file

@ -25,8 +25,7 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.pump.danaR.activities.DanaRNSHistorySync;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomG5Plugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomG6Plugin;
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceEversensePlugin;
import info.nightscout.androidaps.plugins.source.SourceGlimpPlugin;
import info.nightscout.androidaps.plugins.source.SourceMM640gPlugin;
@ -69,12 +68,8 @@ public class DataService extends IntentService {
SourceMM640gPlugin.getPlugin().handleNewData(intent);
} else if (Intents.GLIMP_BG.equals(action)) {
SourceGlimpPlugin.getPlugin().handleNewData(intent);
} else if (Intents.DEXCOMG5_BG.equals(action)) {
SourceDexcomG5Plugin.getPlugin().handleNewData(intent);
} else if (Intents.DEXCOMG5_BG_NEW.equals(action)) {
SourceDexcomG5Plugin.getPlugin().handleNewData(intent);
} else if (Intents.DEXCOMG6_BG.equals(action)) {
SourceDexcomG6Plugin.getPlugin().handleNewData(intent);
} else if (Intents.DEXCOM_BG.equals(action)) {
SourceDexcomPlugin.INSTANCE.handleNewData(intent);
} else if (Intents.POCTECH_BG.equals(action)) {
SourcePoctechPlugin.getPlugin().handleNewData(intent);
} else if (Intents.TOMATO_BG.equals(action)) {

View file

@ -48,9 +48,7 @@ public interface Intents {
String GLIMP_BG = "it.ct.glicemia.ACTION_GLUCOSE_MEASURED";
String DEXCOMG5_BG = "com.dexcom.cgm.DATA";
String DEXCOMG5_BG_NEW = "com.dexcom.cgm.g5.AndroidAPSEVGCallback.BROADCAST";
String DEXCOMG6_BG = "com.dexcom.cgm.AndroidAPSEVGCallback.BROADCAST";
String DEXCOM_BG = "com.dexcom.cgm.EXTERNAL_BROADCAST";
String EVERSENSE_BG = "com.senseonics.AndroidAPSEventSubscriber.BROADCAST";
String POCTECH_BG = "com.china.poctech.data";

View file

@ -991,6 +991,7 @@
<string name="fabric_upload">Fabric Upload</string>
<string name="allow_automated_crash_reporting">Allow automated crash reporting and feature usage data to be sent to the developers via the fabric.io service.</string>
<string name="g5appnotdetected">Please update your Dexcom app to supported version</string>
<string name="dexcom_app_not_installed">Dexcom app is not installed.</string>
<string name="start_activity_tt">Start Activity TT</string>
<string name="start_eating_soon_tt">Start Eating soon TT</string>
<string name="temptargetshort">TT</string>
@ -1335,6 +1336,10 @@
<string name="very_old_version">very old version</string>
<string name="new_version_warning">New version for at least %1$d days available! Fallback to LGS after 60 days, loop will be disabled after 90 days</string>
<string name="dexcom_app_patched">Dexcom App (patched)</string>
<string name="dexcom_short">DXCM</string>
<string name="description_source_dexcom">Receive BG values from the patched Dexcom app.</string>
<plurals name="objective_days">
<item quantity="one">%1$d day</item>
<item quantity="other">%1$d days</item>

View file

@ -1,20 +0,0 @@
package info.nightscout.androidaps.plugins.source;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
public class SourceDexcomG5PluginTest {
@Test
public void getPlugin() {
Assert.assertNotEquals(null, SourceDexcomG5Plugin.getPlugin());
}
@Test
public void advancedFilteringSupported() {
Assert.assertEquals(true, SourceDexcomG5Plugin.getPlugin().advancedFilteringSupported());
}
}