diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index fb7f4a8..b589d56 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
deleted file mode 100644
index 12557ce..0000000
--- a/.idea/deploymentTargetDropDown.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 93512f7..5b230c0 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -5,16 +5,15 @@
diff --git a/.idea/misc.xml b/.idea/misc.xml
index a936f67..205cd15 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-
@@ -12,7 +11,7 @@
-
+
@@ -26,12 +25,14 @@
+
+
-
+
@@ -44,11 +45,13 @@
+
+
-
+
diff --git a/README.md b/README.md
index 412540c..85fbe7d 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,34 @@
# Esel
+There are two different methods how to access the readings from Eversense:
+* Companion mode, which reads the data from the Eversense notifications (works with the standard Eversense App)
+* Patched mode, which requires a patched version of the Eversense App (works completely offline, including backfilling)
+First of all, you need to install ESEL:
+1. Get the ESEL apk e.g. from https://github.com/BernhardRo/Esel/tree/master/apk
+2. Install the apk on your phone
+ * You need to enable installation of Apps from unknown sources
+3. Configuration:
+ * Allow ESEL to run in the background (it will ask for it)
+ * Allow ESEL access to the Android Notifications (it will ask for it)
+ * Upload to Nightscout: Activate "Send to NightScout" in the preferences. It needs a configured AndroidAPS with internal NSClient or NSClient itself installed on the same phone
+ * Inter-App-Broadcasts: Activate "Send to AAPS and xDrip". In xDrip and/or AndroidAPS activate the input method "640g/Eversense".
+ * "Smooth Data" applies a smoothing algorithm to the raw values and provides these smoothed values instead of the raw readings. Smoothing is per default disabled.
+
+## Companion Mode
+1. Install/use the official Eversense App from the Google Play Store
+ * Optional, but required for backfilling: Login to your Eversense account with your login data
+ * In Sync, enable Auto synchronization
+3. Configuration of ESEL:
+ * Disable the setting "Get data from patched Eversense App"
+ * For backfilling: Enable "Fill missing data from eversensedms.com"
+ * Provide as Email address and password your Eversense login data
+
+## Patched Eversense App
1. Uninstall the Eversense App (Warning: your local historical data (older than 1 week) will be lost!)
-2. Install the patched Eversense app (mod_com.senseonics.gen12androidapp-release.apk) and use it as described by the vendor
+2. Install the patched Eversense app (e.g. get it from https://cr4ck3d3v3r53n53.club) and use it as described by the vendor
* You need to enable installation of Apps from unknown sources
* Start the Eversense App, login, connect to your transmitter and use it just like the normal app.
-3. Build https://github.com/BernhardRo/Esel and install it on your phone.
-4. Configuration:
- * Allow ESEL to run in the background (it will ask for it)
- * Upload to Nightscout: Activate "Send to NightScout" in the preferences. It needs a configured AndroidAPS with internal NSClient or NSClient itself installed on the same phone
- * Inter-App-Broadcasts: Activate "Send to AAPS and xDrip". In xDrip and/or AndroidAPS activate the input method "640g/Eversense".
- * "Smooth Data" applies a smoothing algorithm to the raw values and provides these smoothed values instead of the raw readings. Smoothing is per default disabled.
- * For feedback contact @BernhardRo
-4. For the modification of the Eversense App, see: https://github.com/BernhardRo/Esel/wiki/How-to-modify-the-Android-Eversense-App
+3. Configuration of ESEL:
+ * Enable the setting "Get data from patched Eversense App"
If you run esel with a fresh installation of Eversense for the first time, it can take up to 15min until your first values appear in xDrip!
\ No newline at end of file
diff --git a/apk/esel_241.apk b/apk/esel_241.apk
new file mode 100644
index 0000000..60322fd
Binary files /dev/null and b/apk/esel_241.apk differ
diff --git a/apk/esel_301.apk b/apk/esel_301.apk
new file mode 100644
index 0000000..2c9fcad
Binary files /dev/null and b/apk/esel_301.apk differ
diff --git a/app/build.gradle b/app/build.gradle
index 9873ab8..018260d 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,12 +1,11 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.2"
+ compileSdk 30
defaultConfig {
applicationId "esel.esel.esel"
- minSdkVersion 22
- targetSdkVersion 25
+ minSdk 26
+ targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -17,16 +16,23 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
+ namespace 'esel.esel.esel'
}
dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
- androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'com.squareup.retrofit2:adapter-guava:2.9.0'
+ implementation 'com.google.code.gson:gson:2.10.1'
+ implementation 'com.squareup.retrofit2:retrofit-converters:2.8.1'
+ implementation 'com.squareup.retrofit2:adapter-guava:2.9.0'
+ implementation 'com.squareup.retrofit2:adapter-guava:2.9.0'
+ androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
- compile 'com.android.support:appcompat-v7:25.3.1'
- compile 'com.android.support:support-v4:25.3.1'
- compile 'com.android.support:design:25.3.1'
- compile 'com.android.support.constraint:constraint-layout:1.0.2'
- testCompile 'junit:junit:4.12'
+ implementation 'com.android.support:appcompat-v7:28.0.0'
+ implementation 'com.android.support:support-v4:28.0.0'
+ implementation 'com.android.support:design:28.0.0'
+ implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
+ testImplementation 'junit:junit:4.13.2'
}
diff --git a/app/debug/app-debug.apk b/app/debug/app-debug.apk
index af0b715..2c9fcad 100644
Binary files a/app/debug/app-debug.apk and b/app/debug/app-debug.apk differ
diff --git a/app/debug/esel.apk b/app/debug/esel.apk
deleted file mode 100644
index 97b7f46..0000000
Binary files a/app/debug/esel.apk and /dev/null differ
diff --git a/app/debug/output-metadata.json b/app/debug/output-metadata.json
new file mode 100644
index 0000000..aa6326a
--- /dev/null
+++ b/app/debug/output-metadata.json
@@ -0,0 +1,20 @@
+{
+ "version": 3,
+ "artifactType": {
+ "type": "APK",
+ "kind": "Directory"
+ },
+ "applicationId": "esel.esel.esel",
+ "variantName": "debug",
+ "elements": [
+ {
+ "type": "SINGLE",
+ "filters": [],
+ "attributes": [],
+ "versionCode": 1,
+ "versionName": "1.0",
+ "outputFile": "app-debug.apk"
+ }
+ ],
+ "elementType": "File"
+}
\ No newline at end of file
diff --git a/app/debug/output.json b/app/debug/output.json
deleted file mode 100644
index f20a39f..0000000
--- a/app/debug/output.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-debug.apk","fullName":"debug","baseName":"debug"},"path":"app-debug.apk","properties":{}}]
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d2b9833..e538d8b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,13 +1,14 @@
-
+
-
+
+
+
-
-
-
@@ -41,8 +40,21 @@
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
new file mode 100644
index 0000000..3ce16bb
Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ
diff --git a/app/src/main/java/esel/esel/esel/ErrorsActivity.java b/app/src/main/java/esel/esel/esel/ErrorsActivity.java
deleted file mode 100644
index 3569937..0000000
--- a/app/src/main/java/esel/esel/esel/ErrorsActivity.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package esel.esel.esel;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.support.v7.app.AlertDialog;
-import android.view.View;
-import android.support.design.widget.NavigationView;
-import android.support.v4.view.GravityCompat;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.widget.Button;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import java.io.IOException;
-
-import esel.esel.esel.datareader.Datareader;
-import esel.esel.esel.datareader.SGV;
-import esel.esel.esel.preferences.Preferences;
-import esel.esel.esel.preferences.PrefsFragment;
-import esel.esel.esel.util.LocalBroadcaster;
-import esel.esel.esel.util.ToastUtils;
-
-public class ErrorsActivity extends MenuActivity {
-
- private TextView textViewValue;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setupView(R.layout.activity_errors);
- textViewValue = (TextView) findViewById(R.id.textview_main);
- }
-
-}
diff --git a/app/src/main/java/esel/esel/esel/LogActivity.java b/app/src/main/java/esel/esel/esel/LogActivity.java
new file mode 100644
index 0000000..ad9dd34
--- /dev/null
+++ b/app/src/main/java/esel/esel/esel/LogActivity.java
@@ -0,0 +1,47 @@
+package esel.esel.esel;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.TextView;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+import esel.esel.esel.util.SP;
+
+public class LogActivity extends MenuActivity {
+
+ private static TextView textViewValue;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setupView(R.layout.activity_errors);
+ textViewValue = (TextView) findViewById(R.id.textview_main);
+ String msg = SP.getString("logging","");
+ textViewValue.setText(msg);
+ }
+ public static void addLog(String type,String tag, String value){
+ String msg = SP.getString("logging","");
+ int lines_limit = 500;
+ String[] lines = msg.split("\n");
+ if(lines.length>lines_limit){
+ int limit_to = (int)(lines_limit * 0.7);
+ StringBuilder strbuild = new StringBuilder();
+ for (int i = 0; i valueArray = Datareader.readDataFromContentProvider(getBaseContext(), 6, currentTime - syncTime);
+ boolean use_esdms = SP.getBoolean("use_esdms",false);
+ if(use_esdms){
+ class DataHandler implements EsNowDatareader.ProcessResultI{
+ @Override
+ public void ProcessResult(List data) {
+ if (data != null && data.size() > 0) {
+ textViewValue.setText("");
+ for (int i = 0; i < data.size(); i++) {
+ SGV sgv = data.get(i);
+ textViewValue.append(sgv.toString() +" " + sgv.direction + "\n");
+ //LocalBroadcaster.broadcast(sgv);
+ EselLog.LogI(TAG,String.valueOf(sgv.value) + " " + sgv.direction);
+ }
+ } else {
+ EselLog.LogE(TAG,"No access to eversensedms",true);
+ }
+ }
+ }
+
+ EsNowDatareader reader = new EsNowDatareader();
+ reader.queryCurrentValue(new DataHandler());
+
+
+
+ }else {
+ List valueArray = Datareader.readDataFromContentProvider(getBaseContext(), 6, currentTime - syncTime);
- if (valueArray != null && valueArray.size() > 0) {
- textViewValue.setText("");
- for (int i = 0; i < valueArray.size(); i++) {
- SGV sgv = valueArray.get(i);
- textViewValue.append(sgv.toString() + "\n");
- //LocalBroadcaster.broadcast(sgv);
+ if (valueArray != null && valueArray.size() > 0) {
+ textViewValue.setText("");
+ for (int i = 0; i < valueArray.size(); i++) {
+ SGV sgv = valueArray.get(i);
+ textViewValue.append(sgv.toString() +" " + sgv.direction+ "\n");
+ //LocalBroadcaster.broadcast(sgv);
+ EselLog.LogI(TAG,String.valueOf(sgv.value) + " " + sgv.direction);
+ }
+ } else {
+ EselLog.LogE(TAG,"DB not readable!",true);
}
- } else {
- ToastUtils.makeToast("DB not readable!");
}
- }catch (android.database.CursorIndexOutOfBoundsException eb) {
- eb.printStackTrace();
- ToastUtils.makeToast("DB is empty!\nIt can take up to 15min with running Eversense App until values are available!");
+ } catch (android.database.CursorIndexOutOfBoundsException eb) {
+ eb.printStackTrace();
+ EselLog.LogW(TAG,"DB is empty!\nIt can take up to 15min with running Eversense App until values are available!",true);
} catch (Exception e) {
e.printStackTrace();
}
@@ -107,13 +123,15 @@ public void onClick(View view) {
sync = SP.getInt("max-sync-hours", sync);
+
} catch (Exception e) {
e.printStackTrace();
}
+
ReadReceiver receiver = new ReadReceiver();
- int written = receiver.FullSync(getBaseContext(), sync);
- textViewValue.setText("Read " + written + " values from DB\n(last " + sync + " hours)");
+ receiver.FullSync(getBaseContext(), sync);
+ textViewValue.setText("Read values from DB\n(last " + sync + " hours)");
}
});
@@ -122,6 +140,7 @@ public void onClick(View view) {
@Override
public void onClick(View view) {
int sync = 8;
+
try {
sync = SP.getInt("max-sync-hours", sync);
@@ -130,34 +149,75 @@ public void onClick(View view) {
e.printStackTrace();
}
- ReadReceiver receiver = new ReadReceiver();
- String output = receiver.FullExport(getBaseContext(), sync);
- String filename = "esel_output_" + System.currentTimeMillis() + ".json";
- String path = Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator + Environment.DIRECTORY_DOWNLOADS;
- File file = new File(path,filename);
- if(!file.getParentFile().exists()){
- file.getParentFile().mkdir();
- }
- if(!file.getParentFile().canWrite()){
- ToastUtils.makeToast("Error: can not write data. Please enable the storage access permission for Esel.");
+ String filename = "esel_output_" + System.currentTimeMillis() + ".json";
+ String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + Environment.DIRECTORY_DOWNLOADS;
+ File file = new File(path, filename);
+
+ ReadReceiver receiver = new ReadReceiver();
+
+ receiver.FullExport(getBaseContext(),file, sync);
+
+ textViewValue.setText("Created file " + file.getAbsoluteFile() + " containing values from DB\n(last " + sync + " hours)");
+
+
}
- if(!file.exists()){
- try{
- file.createNewFile();
- FileWriter fileWriter = new FileWriter(file.getAbsoluteFile());
- BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
- bufferedWriter.write(output.toString());
- bufferedWriter.close();
- textViewValue.setText("Created file " + file.getAbsoluteFile() + " containing values from DB\n(last " + sync + " hours)");
- }catch(IOException err){
- ToastUtils.makeToast("Error creating file: " + err.toString() + " occured at: "+ err.getStackTrace().toString());
+ });
+
+ }
+
+ private void askForNotificationAccess() {
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
+ final String packageName = getPackageName();
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getBaseContext());
+
+ boolean nlenabled = NotificationManagerCompat.getEnabledListenerPackages(getBaseContext()).contains(packageName);
+
+ if (!nlenabled) {
+ final Runnable askNotificationAccessRunnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ final String msg = "Device does not appear to support notification access!";
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ ToastUtils.makeToast("Device does not appear to support notification access!");
+ }
+ });
+ }
}
+ };
+
+ try {
+ final Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
+ intent.setData(Uri.parse("package:" + packageName));
+ //startActivity(intent);
+
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("Please Allow Permission")
+ .setMessage("For data access in Companion Mode, ESEL needs access to the System Notifications.\n" +
+ "If the settings are not available due to restricted settings, see 'https://support.google.com/android/answer/12623953'.")
+ .setPositiveButton("OK", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ SystemClock.sleep(100);
+ MainActivity.this.runOnUiThread(askNotificationAccessRunnable);
+ dialog.dismiss();
+ }
+ }).show();
+ } catch (Exception e) {
+ ToastUtils.makeToast("Please whitelist ESEL in the phone settings.");
}
}
- });
+ }
- }
+}
private void askForBatteryOptimizationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
diff --git a/app/src/main/java/esel/esel/esel/MenuActivity.java b/app/src/main/java/esel/esel/esel/MenuActivity.java
index 4214c46..e8eb922 100644
--- a/app/src/main/java/esel/esel/esel/MenuActivity.java
+++ b/app/src/main/java/esel/esel/esel/MenuActivity.java
@@ -1,8 +1,6 @@
package esel.esel.esel;
import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
@@ -11,16 +9,8 @@
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import java.io.IOException;
-
-import esel.esel.esel.datareader.Datareader;
-import esel.esel.esel.datareader.SGV;
import esel.esel.esel.preferences.Preferences;
-import esel.esel.esel.util.ToastUtils;
/**
* Created by adrian on 07/08/17.
@@ -54,8 +44,8 @@ public boolean onNavigationItemSelected(MenuItem item) {
} else if (id == R.id.nav_home && !(this instanceof MainActivity)){
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
- } else if (id == R.id.nav_errors && !(this instanceof ErrorsActivity)){
- Intent intent = new Intent(this, ErrorsActivity.class);
+ } else if (id == R.id.nav_errors && !(this instanceof LogActivity)){
+ Intent intent = new Intent(this, LogActivity.class);
startActivity(intent);
}
diff --git a/app/src/main/java/esel/esel/esel/datareader/Datareader.java b/app/src/main/java/esel/esel/esel/datareader/Datareader.java
index 92508b1..7e75e2b 100644
--- a/app/src/main/java/esel/esel/esel/datareader/Datareader.java
+++ b/app/src/main/java/esel/esel/esel/datareader/Datareader.java
@@ -107,6 +107,7 @@ public static List readDataFromContentProvider(Context context, int number,
return valueArray;
}
+
public static SGV generateSGV(String dataString){
String[] tokens = dataString.split(",");
long timestamp = Long.parseLong(tokens[0]);
@@ -115,10 +116,6 @@ int record = Integer.parseInt(tokens[2]);
return new SGV(value, timestamp,record);
}
- public static SGV generateSGV(int value, long timestamp, int record){
- return new SGV(value, timestamp,record);
- }
-
}
diff --git a/app/src/main/java/esel/esel/esel/datareader/EsNotificationListener.java b/app/src/main/java/esel/esel/esel/datareader/EsNotificationListener.java
new file mode 100644
index 0000000..18af204
--- /dev/null
+++ b/app/src/main/java/esel/esel/esel/datareader/EsNotificationListener.java
@@ -0,0 +1,94 @@
+package esel.esel.esel.datareader;
+
+import android.app.Notification;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.widget.RemoteViews;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import esel.esel.esel.util.SP;
+
+/**
+ * Created by bernhard on 24-01-18.
+ */
+public class EsNotificationListener extends NotificationListenerService {
+
+ private static List lastReadings = new ArrayList();
+
+ @Override
+ public void onNotificationPosted(StatusBarNotification sbn) {
+
+ boolean use_patched_es = SP.getBoolean("use_patched_es", true);
+ if(use_patched_es){
+ return;
+ }
+
+ if (sbn.getPackageName().equals("com.senseonics.gen12androidapp") ||
+ sbn.getPackageName().equals("com.senseonics.androidapp")) {
+ Notification notification = sbn.getNotification();
+ if (notification != null && notification.tickerText != null) {
+ try {
+ SGV sgv = generateSGV(notification,lastReadings.size());
+ if(sgv != null) {
+ lastReadings.add(sgv);
+ }
+ } catch (NumberFormatException err) {
+ err.printStackTrace();
+ }
+ }
+ }
+
+ }
+
+ public static List getData(int number, long lastReadingTime){
+ List result = new ArrayList();
+ for (SGV reading:lastReadings) {
+ //if(reading.timestamp > lastReadingTime){
+ result.add(reading);
+ //}
+
+ }
+
+ while (result.size() > number){
+ result.remove(0);
+ }
+
+ if(result.size() == number){
+ SGV last = lastReadings.get(lastReadings.size()-1);
+ lastReadings.clear();
+ lastReadings.add(last);
+ }
+
+ return result;
+ }
+
+ public static SGV generateSGV(Notification notification ,int record){
+ long timestamp = notification.when;
+ String tickerText = (String) notification.tickerText;
+ int value;
+ if(tickerText.contains(".") || tickerText.contains(",")){ //is mmol/l
+ float valuef = Float.parseFloat(tickerText);
+ value = SGV.Convert(valuef);
+ }else{
+ value =Integer.parseInt(tickerText);
+ }
+
+ if(lastReadings.size()>0) {
+ long five_min = 300000l;
+ SGV oldSgv = lastReadings.get(lastReadings.size() - 1);
+ long lastreadingtime = oldSgv.timestamp; // SP.getLong("lastreadingtime_nl",timestamp);
+ int lastreadingvalue = oldSgv.raw; //SP.getInt("lastreadingvalue_nl",value);
+ if (value == lastreadingvalue && (lastreadingtime + (five_min * 1.05)) > timestamp ) { // no new value
+ return null;
+ }
+ }
+
+ // SP.putLong("lastreadingtime_nl",timestamp);
+ // SP.putInt("lastreadingvalue_nl",value);
+
+ return new SGV(value, timestamp,record);
+ }
+
+}
diff --git a/app/src/main/java/esel/esel/esel/datareader/EsNowDatareader.java b/app/src/main/java/esel/esel/esel/datareader/EsNowDatareader.java
new file mode 100644
index 0000000..c965203
--- /dev/null
+++ b/app/src/main/java/esel/esel/esel/datareader/EsNowDatareader.java
@@ -0,0 +1,329 @@
+package esel.esel.esel.datareader;
+
+import java.io.Reader;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import esel.esel.esel.util.CareService;
+import esel.esel.esel.util.EselLog;
+import esel.esel.esel.util.SP;
+import esel.esel.esel.util.ToastUtils;
+import esel.esel.esel.util.UserLoginService;
+import okhttp3.ResponseBody;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+public final class EsNowDatareader {
+
+ private static final String TAG = "EsNowDatareader";
+ private String username;
+ private String password;
+ static final String grant_type = "password";
+ static final String client_id = "eversenseMMAAndroid";
+ static final String client_secret = "6ksPx#]~wQ3U";
+ static final String BASE_AUTH_URL = "https://ousiamapialpha.eversensedms.com/connect/";
+ static final String BASE_URL = "https://ousalphaapiservices.eversensedms.com/";
+ private static DateTimeFormatter dateformat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
+ private static ZoneId zoneId = ZoneId.systemDefault();
+
+ private UserLoginService.SenseonicsTokenDto token;
+ private List user;
+ private List values;
+ private List events;
+ private LocalDateTime startDate;
+ private LocalDateTime endDate;
+ private ProcessResultI processor;
+
+
+ private int userId = 0;
+
+ private String bearer_token = "";
+ private long token_expires=0;
+
+ public EsNowDatareader() {
+
+ username = SP.getString("es_username","");
+ password =SP.getString("es_password","");
+
+ bearer_token = SP.getString("esnow_token", bearer_token);
+ token_expires = SP.getLong("es_now_token_expire", token_expires);
+ userId = SP.getInt("esnow_userId", userId);
+
+ }
+
+ static public void updateLogin(){
+ EsNowDatareader reader = new EsNowDatareader();
+
+ if(reader.bearer_token == "" || reader.tokenHasExpired() ) {
+ reader.login();
+ }
+ if(reader.userId == 0 ){
+ reader.currentUser();
+ }
+ }
+
+ private void login() {
+ LoginController login = new LoginController();
+ login.start();;
+ }
+
+ private boolean tokenHasExpired(){
+ long currentTime = System.currentTimeMillis();
+ return currentTime > token_expires;
+ }
+
+ private void currentUser() {
+ UserController data = new UserController();
+ data.start();
+ }
+ public void queryCurrentValue(ProcessResultI processor) {
+
+ this.processor = processor;
+ SgvController data = new SgvController();
+ data.start();
+
+
+ }
+
+ public void queryLastValues(ProcessResultI processor, int hours) {
+
+ LocalDateTime.now();
+ startDate = LocalDateTime.now().minusHours(hours);
+ endDate = LocalDateTime.now();
+ this.processor = processor;
+ SgvHistController data = new SgvHistController();
+ data.start();
+
+ }
+
+
+ private SGV generateSGV(CareService.UserEventDto data, int record){
+ ZonedDateTime date = ZonedDateTime.parse(data.eventDate,dateformat.withZone(ZoneId.of("UTC")));
+ long timestamp = (long)date.toEpochSecond() * 1000;
+ int sgv = data.value;
+
+ return new SGV(sgv,timestamp,record);
+ }
+
+ private SGV generateSGV(CareService.CurrentValuesDto data){
+ ZonedDateTime date = ZonedDateTime.parse(data.timeStamp,dateformat.withZone(ZoneId.of("UTC")));
+ long timestamp = (long)date.toEpochSecond() *1000;
+ int sgv = data.currentGlucose;
+
+ return new SGV(sgv,timestamp,1);
+ }
+
+
+ public class LoginController implements Callback {
+ public void start() {
+ Gson gson = new GsonBuilder()
+ .setLenient()
+ .create();
+
+ Retrofit retrofit = new Retrofit.Builder()
+ .baseUrl(BASE_AUTH_URL)
+ .addConverterFactory(GsonConverterFactory.create(gson))
+ .build();
+
+ UserLoginService login = retrofit.create(UserLoginService.class);
+
+ Call call = login.authenticate(grant_type,client_id,client_secret,username,password);
+ call.enqueue(this);
+
+ }
+
+ @Override
+ public void onResponse(Call call, Response response) {
+ if (response.isSuccessful()) {
+ token = response.body();
+ if(token != null) {
+ token.SetExpireDateTime();
+ bearer_token = token.GetBearerToken();
+ token_expires = token.expireDateTime;
+ SP.putString("esnow_token",bearer_token );
+ SP.putLong("es_now_token_expire", token_expires);
+ currentUser();
+ EselLog.LogI(TAG,"Eversensedms: Successfully logged in.");
+ }
+ } else {
+ try {
+ Reader reader = response.errorBody().charStream();
+ char[] charBuffer = new char[500];
+ int amountRead = reader.read(charBuffer);
+ charBuffer[amountRead] = '\0';
+ String msg = new String(charBuffer, 0, amountRead);
+ if(msg.contains("6008")){
+ EselLog.LogW(TAG,"Not authorized. Check username and password. Disabling Eversensedms...",true);
+ SP.putBoolean("use_esdms", false);
+ }else if(msg.contains("5005")) {
+ EselLog.LogW(TAG,"Not authorized. Check username and password. Account is locked. Try again in 30min. Disabling Eversensedms...",true);
+ SP.putBoolean("use_esdms", false);
+ }else{
+ EselLog.LogW(TAG,msg,true);
+ }
+
+
+ }catch(Exception err){
+ EselLog.LogE(TAG,err.getMessage(),true);
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ EselLog.LogE(TAG, t.getStackTrace().toString(), true);
+ }
+ }
+
+ public class UserController implements Callback> {
+ public void start() {
+ Gson gson = new GsonBuilder()
+ .setLenient()
+ .create();
+
+ Retrofit retrofit = new Retrofit.Builder()
+ .baseUrl(BASE_URL)
+ .addConverterFactory(GsonConverterFactory.create(gson))
+ .build();
+
+ CareService data = retrofit.create(CareService.class);
+
+ Call> call = data.getUserProfile(bearer_token);
+ call.enqueue(this);
+
+ }
+
+ @Override
+ public void onResponse(Call> call, Response> response) {
+ if (response.isSuccessful()) {
+ user = response.body();
+ if(user != null){
+ userId = user.get(0).userId;
+ SP.putInt("esnow_userId",userId );
+ EselLog.LogI(TAG,"UserId is " + userId);
+ }
+ } else {
+ try {
+ EselLog.LogE(TAG, response.errorBody().string(), true);
+ }catch(Exception err){
+ EselLog.LogE(TAG, err.getMessage(), true);
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call> call, Throwable t) {
+ EselLog.LogE(TAG, t.getStackTrace().toString(), true);
+ }
+ }
+
+
+ public class SgvController implements Callback> {
+
+
+ public void start() {
+ Gson gson = new GsonBuilder()
+ .setLenient()
+ .create();
+
+ Retrofit retrofit = new Retrofit.Builder()
+ .baseUrl(BASE_URL)
+ .addConverterFactory(GsonConverterFactory.create(gson))
+ .build();
+
+ CareService data = retrofit.create(CareService.class);
+
+ Call> call = data.getCurrentValues(bearer_token,userId);
+ call.enqueue(this);
+
+ }
+
+ @Override
+ public void onResponse(Call> call, Response> response) {
+ if (response.isSuccessful()) {
+ values = response.body();
+ List result = new ArrayList();
+ SGV value = generateSGV(values.get(0));
+ result.add(value);
+ if(processor != null) {
+ processor.ProcessResult(result);
+ }
+ } else {
+ try {
+ EselLog.LogE(TAG, response.errorBody().string(), true);
+ }catch(Exception err){
+ EselLog.LogE(TAG, err.getMessage(), true);
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call> call, Throwable t) {
+ EselLog.LogE(TAG, t.getStackTrace().toString(), true);
+ }
+ }
+
+ public class SgvHistController implements Callback> {
+
+ public void start() {
+ Gson gson = new GsonBuilder()
+ .setLenient()
+ .create();
+
+ Retrofit retrofit = new Retrofit.Builder()
+ .baseUrl(BASE_URL)
+ .addConverterFactory(GsonConverterFactory.create(gson))
+ .build();
+
+ CareService data = retrofit.create(CareService.class);
+
+ Call> call = data.getFollowingUserSensorGlucose(bearer_token,userId,startDate.format(dateformat),endDate.format(dateformat));
+ call.enqueue(this);
+
+ }
+
+ @Override
+ public void onResponse(Call> call, Response> response) {
+ if (response.isSuccessful()) {
+ events = response.body();
+ List result = new ArrayList();
+ for (int i = 0; i < events.size(); i++){
+ SGV value = generateSGV(events.get(i),i);
+ result.add(value);
+ }
+ if (processor != null){
+ processor.ProcessResult(result);
+ }
+
+ } else {
+ try {
+ EselLog.LogE(TAG, response.errorBody().string(), true);
+ }catch(Exception err){
+ EselLog.LogE(TAG, err.getMessage(), true);
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Call> call, Throwable t) {
+ EselLog.LogE(TAG, t.getStackTrace().toString(), true);
+ }
+ }
+
+ public interface ProcessResultI{
+
+ public void ProcessResult(List data);
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/esel/esel/esel/datareader/SGV.java b/app/src/main/java/esel/esel/esel/datareader/SGV.java
index fc5388e..db07dbe 100644
--- a/app/src/main/java/esel/esel/esel/datareader/SGV.java
+++ b/app/src/main/java/esel/esel/esel/datareader/SGV.java
@@ -16,9 +16,9 @@
*/
public class SGV {
- public int value;
+ public int value; //unit: md/dl (always used internally)
public int raw;
- public long timestamp;
+ public long timestamp; // UNIX time in ms
public int record;
public String direction;
@@ -34,6 +34,11 @@ public SGV(int value, long timestamp, int record){
else if (this.value > 400) { this.value = 400;}
}
+ static public int Convert(float mmoll){
+ float mgdl = mmoll * 18.0182f;
+ return Math.round(mgdl);
+ }
+
@Override
public String toString(){
DateFormat df = SimpleDateFormat.getDateTimeInstance();
@@ -42,28 +47,32 @@ public String toString(){
public void setDirection(double slope_by_minute) {
direction = "NONE";
- if (slope_by_minute <= (-3.5)) {
+ if (slope_by_minute <= (-3.5d)) {
direction = "DoubleDown";
- } else if (slope_by_minute <= (-2)) {
+ } else if (slope_by_minute <= (-2d)) {
direction = "SingleDown";
- } else if (slope_by_minute <= (-1)) {
+ } else if (slope_by_minute <= (-1d)) {
direction = "FortyFiveDown";
- } else if (slope_by_minute <= (1)) {
+ } else if (slope_by_minute <= (1d)) {
direction = "Flat";
- } else if (slope_by_minute <= (2)) {
+ } else if (slope_by_minute <= (2d)) {
direction = "FortyFiveUp";
- } else if (slope_by_minute <= (3.5)) {
+ } else if (slope_by_minute <= (3.5d)) {
direction = "SingleUp";
- } else if (slope_by_minute <= (40)) {
+ } else if (slope_by_minute <= (40d)) {
direction = "DoubleUp";
}
}
- public void smooth(int last,boolean onlyDummyRun){
- double value = this.value;
+ /**
+ * Created by bernhard on 2018-11-18.
+ */
+
+ public void smooth(int last,boolean enable_smooth){
+ double value = (double)this.value;
double lastSmooth = (double)last;
- if(onlyDummyRun){
+ if(!enable_smooth){
SP.putInt("lastReadingRaw", this.value);
SP.putFloat("readingSmooth",(float)this.value);
return;
@@ -77,7 +86,7 @@ public void smooth(int last,boolean onlyDummyRun){
double factor = SP.getDouble("smooth_factor",0.3,0.0,1.0);
double correction = SP.getDouble("correction_factor",0.5,0.0,1.0);
double descent_factor = SP.getDouble("descent_factor",0.0,0.0,1.0);
- int lastRaw = SP.getInt("lastReadingRaw", this.value);
+ float lastRaw = SP.getInt("lastReadingRaw", this.value);
SP.putInt("lastReadingRaw", this.value);
diff --git a/app/src/main/java/esel/esel/esel/receivers/ReadReceiver.java b/app/src/main/java/esel/esel/esel/receivers/ReadReceiver.java
index 45f2d8c..bf824bd 100644
--- a/app/src/main/java/esel/esel/esel/receivers/ReadReceiver.java
+++ b/app/src/main/java/esel/esel/esel/receivers/ReadReceiver.java
@@ -5,13 +5,9 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
import android.os.PowerManager;
-import android.util.Log;
import org.json.JSONArray;
-import org.json.JSONObject;
import java.io.BufferedWriter;
import java.io.File;
@@ -21,15 +17,16 @@
import java.util.List;
import esel.esel.esel.Esel;
-import esel.esel.esel.R;
+import esel.esel.esel.LogActivity;
import esel.esel.esel.datareader.Datareader;
+import esel.esel.esel.datareader.EsNotificationListener;
+import esel.esel.esel.datareader.EsNowDatareader;
import esel.esel.esel.datareader.SGV;
+import esel.esel.esel.util.EselLog;
import esel.esel.esel.util.LocalBroadcaster;
import esel.esel.esel.util.SP;
import esel.esel.esel.util.ToastUtils;
-import static android.content.ContentValues.TAG;
-
/**
* Created by adrian on 04/08/17.
*/
@@ -46,10 +43,10 @@ public class ReadReceiver extends BroadcastReceiver {
@Override
public synchronized void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Esel:ReadReceiver:Boradcast");
+ PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Esel:ReadReceiver:Broadcast");//Boradcast
wl.acquire();
- Log.d(TAG, "onReceive called");
+ EselLog.LogV(TAG,"onReceive called");
setAlarm(Esel.getsInstance());
@@ -67,7 +64,7 @@ public synchronized void onReceive(Context context, Intent intent) {
try {
SP.putLong("readReceiver-called", System.currentTimeMillis());
- //TODO: KeepAlive und ReadReceiver bei App-Beenden stoppen.
+
//String datastring = Datareader.readData();
@@ -82,7 +79,9 @@ public synchronized void onReceive(Context context, Intent intent) {
} catch (Exception e) {
- ToastUtils.makeToast("Exception: " + e.getMessage());
+ String msg = e.getMessage();
+ ToastUtils.makeToast("Exception: " + msg);
+ EselLog.LogE(TAG,msg);
}
@@ -98,38 +97,123 @@ public synchronized void onReceive(Context context, Intent intent) {
wl.release();
}
- public int FullSync(Context context, int syncHours){
+ public void FullSync(Context context, int syncHours){
long currentTime = System.currentTimeMillis();
long syncTime = syncHours * 60 * 60 * 1000L;
long lastTimestamp = currentTime - syncTime;
- //disable smoothing as historical data will be overwritten
- int written = broadcastData(context, lastTimestamp, false);
+
+ boolean use_esdms = SP.getBoolean("use_esdms", false);
+ if(use_esdms){
+
+ class DataHandler implements EsNowDatareader.ProcessResultI{
+
+ @Override
+ public void ProcessResult(List data) {
+ try {
+ int written = ProcesssValues( false, data);
+ String msg = "Full Sync done: Read " + written + " values from DB\n(last " + syncHours + " hours)";
+ //ToastUtils.makeToast(msg);
+ EselLog.LogI(TAG,msg,true);
+ }
+ catch(Exception e){
+ //ToastUtils.makeToast("No access to eversensedms");
+ EselLog.LogE(TAG,"No access to eversensedms",true);
+ }
+ }
+ }
+
+ EsNowDatareader reader = new EsNowDatareader();
+ reader.queryLastValues(new DataHandler(),syncHours);
+
+
+
+ }else {
+
+ //disable smoothing as historical data will be overwritten
+ int written = broadcastData(context, lastTimestamp, false);
+ String msg = "Full Sync done: Read " + written + " values from DB\n(last " + syncHours + " hours)";
+ //ToastUtils.makeToast(msg);
+ EselLog.LogI(TAG,msg,true);
+ }
SP.putLong("last_full_sync", currentTime);
- ToastUtils.makeToast("Full Sync done: Read " + written + " values from DB\n(last " + syncHours + " hours)");
- return written;
+
}
- public String FullExport(Context context, int syncHours){
+ public void FullExport(Context context,File file, int syncHours){
long currentTime = System.currentTimeMillis();
long syncTime = syncHours * 60 * 60 * 1000L;
long lastTimestamp = currentTime - syncTime;
+ int written = 0;
suppressBroadcast = true;
- int written = broadcastData(context, lastTimestamp, false);
- suppressBroadcast = false;
+ boolean use_esdms = SP.getBoolean("use_esdms", false);
+
+ if (use_esdms) {
+
+ class DataHandler implements EsNowDatareader.ProcessResultI {
+
+ @Override
+ public void ProcessResult(List data) {
+ int written = ProcesssValues( false,data);
+ String msg = "Full Sync done: Read " + written + " values from DB\n(last " + syncHours + " hours)";
+ //ToastUtils.makeToast(msg);
+ EselLog.LogI(TAG, msg,true);
+ WriteData(file,output.toString());
+ output = new JSONArray();
+ suppressBroadcast = false;
+
+ }
+ }
+
+ EsNowDatareader reader = new EsNowDatareader();
+ reader.queryLastValues(new DataHandler(), syncHours);
+
+ }else {
+
+ written = broadcastData(context, lastTimestamp, false);
+ suppressBroadcast = false;
+ WriteData(file,output.toString());
+ output = new JSONArray();
+ String msg = "Full Sync done: Read " + written + " values from DB\n(last " + syncHours + " hours)";
+ //ToastUtils.makeToast(msg);
+ EselLog.LogI(TAG, msg,true);
+
+ }
+
SP.putLong("last_full_sync", currentTime);
- ToastUtils.makeToast("Full Sync done: Read " + written + " values from DB\n(last " + syncHours + " hours)");
+ }
- String result = output.toString();
- output = new JSONArray();
+ private void WriteData(File file,String data){
+
+ if (!file.getParentFile().exists()) {
+ file.getParentFile().mkdir();
+ }
+ if (!file.getParentFile().canWrite()) {
+ String msg = "Error: can not write data. Please enable the storage access permission for Esel.";
+ //ToastUtils.makeToast(msg);
+ EselLog.LogE(TAG, msg,true);
+ }
+ if (!file.exists()) {
+ try {
+ file.createNewFile();
+ FileWriter fileWriter = new FileWriter(file.getAbsoluteFile());
+ BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
+ bufferedWriter.write(data.toString());
+ bufferedWriter.close();
+
+ } catch (IOException err) {
+ String msg = "Error creating file: " + err.toString() + " occured at: " + err.getStackTrace().toString();
+ //ToastUtils.makeToast(msg);
+ EselLog.LogE(TAG, msg,true);
+ }
+ }
- return result;
}
public int broadcastData(Context context, long lastReadingTime, boolean smoothEnabled) {
@@ -142,6 +226,9 @@ public int broadcastData(Context context, long lastReadingTime, boolean smoothEn
int size = 2;
long updatedReadingTime = lastReadingTime;
+ boolean use_patched_es = SP.getBoolean("use_patched_es", true);
+ boolean use_esdms = SP.getBoolean("use_esdms",false);
+
do {
lastReadingTime = updatedReadingTime;
@@ -158,89 +245,39 @@ public int broadcastData(Context context, long lastReadingTime, boolean smoothEn
//}
- }else{
+ }else if (use_patched_es){
valueArray = Datareader.readDataFromContentProvider(context, size, lastReadingTime);
- }
-
- if (valueArray.size() == 0) {
- ToastUtils.makeToast("DB not readable!");
- //wl.release();
- return result;
+ if (valueArray.size() == 0) {
+ //ToastUtils.makeToast("DB not readable!");
+ EselLog.LogE(TAG,"DB not readable!",true);
+ }
+ }else {
+ boolean read_from_nl = true;
+ if(use_esdms){
+ EsNowDatareader.updateLogin();
+ }
+ if(read_from_nl){
+ valueArray = EsNotificationListener.getData(size,lastReadingTime);
+ }
}
-
if (valueArray.size() != size) {
- //ToastUtils.makeToast("DB not readable!");
- //wl.release();
-
return result;
}
- for (int i = 0; i < valueArray.size(); i++) {
- SGV sgv = valueArray.get(i);
- long oldTime = SP.getLong("lastReadingTime", -1L);
-
- boolean newValue = oldTime != sgv.timestamp;
- boolean futureValue = false;
-
- if(sgv.timestamp - currentTime > (60 * 1000)){
- //sgv is from future
- long shiftValue = sgv.timestamp - currentTime;
- float sec = shiftValue/1000f;
- Log.d(TAG, "broadcastData called, value is in future by [sec] " + sec);
- futureValue = true;
- }
-
- if (newValue && !futureValue) {
- //if (!futureValue) {
- int oldValue = SP.getInt("lastReadingValue", -1);
- long sgvTime = sgv.timestamp;
- //check if old value is not older than 17min
- boolean hasTimeGap = (sgvTime - oldTime) > 12 * 60 *1000L;
-
- float slopeByMinute = 0f;
- if (oldTime != sgvTime) {
- slopeByMinute = (oldValue - sgv.value) * 60000.0f / ((oldTime - sgvTime) * 1.0f);
- }
- if(!hasTimeGap){
- sgv.setDirection(slopeByMinute);
- }
-
- if (sgv.value >= 39 /*&& oldValue >= 39*/) { //check for old value to ignore first 5 min
- //ToastUtils.makeToast(sgv.toString());
- if(SP.getBoolean("smooth_data",false) && smoothEnabled){
- sgv.smooth(oldValue,hasTimeGap);
- }
-
- if(!suppressBroadcast) {
- LocalBroadcaster.broadcast(sgv);
- }else{
- LocalBroadcaster.addSgvEntry(output,sgv);
- }
- result++;
- Log.d(TAG, "LocalBroadcaster.broadcast called, result = " + sgv.toString());
- } else {
- ToastUtils.makeToast("NOT A READING!");
- }
- SP.putLong("lastReadingTime", sgvTime);
- SP.putInt("lastReadingValue", sgv.value);
- //SP.putFloat("lastReadingDirection", slopeByMinute);
- }
- }
+ result += ProcesssValues(smoothEnabled,valueArray);
updatedReadingTime = SP.getLong("lastReadingTime", lastReadingTime);
} while (updatedReadingTime != lastReadingTime);
- //} catch (IOException e) {
- // ToastUtils.makeToast("IOException");
- //} catch (InterruptedException e) {
- // ToastUtils.makeToast("InterruptedException");
} catch (android.database.CursorIndexOutOfBoundsException eb) {
eb.printStackTrace();
- ToastUtils.makeToast("DB is empty!\nIt can take up to 15min with running Eversense App until values are available!");
+ //ToastUtils.makeToast("DB is empty!\nIt can take up to 15min with running Eversense App until values are available!");
+ EselLog.LogW(TAG,"DB is empty! It can take up to 15min with running Eversense App until values are available!",true);
} catch (Exception e) {
e.printStackTrace();
+ SP.putInt("lastReadingValue", 120);
}
//wl.release();
@@ -248,7 +285,80 @@ public int broadcastData(Context context, long lastReadingTime, boolean smoothEn
return result;
}
+ private int ProcesssValues( boolean smoothEnabled, List valueArray) {
+ int result = 0;
+
+ long currentTime = System.currentTimeMillis();
+
+ for (int i = 0; i < valueArray.size(); i++) {
+ SGV sgv = valueArray.get(i);
+ long oldTime = SP.getLong("lastReadingTime", -1L);
+
+ boolean newValue = oldTime != sgv.timestamp;
+ boolean futureValue = false;
+
+ if(sgv.timestamp - currentTime > (60 * 1000)){
+ //sgv is from future
+ long shiftValue = sgv.timestamp - currentTime;
+ float sec = shiftValue/1000f;
+ EselLog.LogW(TAG,"broadcastData called, value is in future by [sec] " + sec);
+ futureValue = true;
+ }
+ if (newValue && !futureValue) {
+ //if (!futureValue) {
+ int oldValue = sgv.value;
+
+ oldValue = SP.getInt("lastReadingValue", -1);
+
+ long sgvTime = sgv.timestamp;
+ //check if old value is not older than 12min
+ boolean hasTimeGap = (sgvTime - oldTime) > 12 * 60 *1000L;
+
+ if (sgv.value >= 39 /*&& oldValue >= 39*/) { //check for old value to ignore first 5 min
+ //ToastUtils.makeToast(sgv.toString());
+ if(smoothEnabled) {
+ boolean enable_smooth = SP.getBoolean("smooth_data", false) && !hasTimeGap;
+ sgv.smooth(oldValue, enable_smooth);
+ }
+
+// if(SP.getBoolean("smooth_data",false) && smoothEnabled){
+// sgv.smooth(oldValue,hasTimeGap);
+// }else {
+// sgv.smooth(oldValue,true); //
+// }
+
+ double slopeByMinute = 0d;
+ if (oldTime != sgvTime) {
+ slopeByMinute = (sgv.value - oldValue ) * 60000.0d / (( sgvTime - oldTime) * 1.0d);
+ }
+ if(!hasTimeGap){
+ sgv.setDirection(slopeByMinute);
+ }
+
+ try {
+ if (!suppressBroadcast) {
+ LocalBroadcaster.broadcast(sgv);
+ } else {
+ LocalBroadcaster.addSgvEntry(output, sgv);
+ }
+
+ result++;
+ }
+ catch(Exception e){
+ EselLog.LogE(TAG,"LocalBroadcaster.broadcast exception, result = " + e.getMessage());
+ }
+ } else {
+ ToastUtils.makeToast("NOT A READING!");
+ }
+ SP.putLong("lastReadingTime", sgvTime);
+ SP.putInt("lastReadingValue", sgv.value);
+ //SP.putFloat("lastReadingDirection", slopeByMinute);
+ }
+ }
+
+ return result;
+ }
public void setAlarm(Context context) {
diff --git a/app/src/main/java/esel/esel/esel/util/CareService.java b/app/src/main/java/esel/esel/esel/util/CareService.java
new file mode 100644
index 0000000..bc6e1a6
--- /dev/null
+++ b/app/src/main/java/esel/esel/esel/util/CareService.java
@@ -0,0 +1,142 @@
+package esel.esel.esel.util;
+
+
+import com.google.gson.annotations.SerializedName;
+import java.util.List;
+
+import esel.esel.esel.datareader.SGV;
+import retrofit2.http.Body;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.GET;
+import retrofit2.http.POST;
+import retrofit2.http.Query;
+import retrofit2.http.Header;
+import retrofit2.Call;
+
+public interface CareService {
+ //public static final Companion Companion = Companion.$$INSTANCE;
+
+ @GET("api/care/GetCurrentValues")
+ Call> getCurrentValues(@Header("Authorization") String token,@Query("FollowerUserID") int paramInt);
+
+ @GET("api/care/GetFollowingUserSensorGlucose")
+ Call> getFollowingUserSensorGlucose(@Header("Authorization") String token,@Query("UserID") int paramInt, @Query("startDate") String paramString1, @Query("endDate") String paramString2);
+
+
+ @GET("api/care/GetUserProfile")
+ Call> getUserProfile(@Header("Authorization") String token);
+
+ public static final class Companion {
+ static final Companion $$INSTANCE = new Companion();
+
+ private static final String CARE_BASE_PATH = "api/care/";
+ }
+
+
+ public final class CurrentValuesDto {
+ @SerializedName("CurrentGlucose")
+ public final int currentGlucose;
+
+ @SerializedName("GlucoseTrend")
+ public final int glucoseTrend;
+
+ @SerializedName("TimeStamp")
+ public final String timeStamp;
+
+ public CurrentValuesDto(int paramInt1, String paramString, int paramInt2) {
+ this.currentGlucose = paramInt1;
+ this.timeStamp = paramString;
+ this.glucoseTrend = paramInt2;
+ }
+ }
+
+ public final class UserEventDto {
+ @SerializedName("EventDate")
+ public final String eventDate;
+
+ @SerializedName("EventSubTypeID")
+ private final int eventSubTypeId;
+
+ @SerializedName("EventTypeID")
+ private final int eventTypeId;
+
+ @SerializedName("Value")
+ public final int value;
+
+ public UserEventDto(int paramInt1, int paramInt2, int paramInt3, String paramString) {
+ this.eventTypeId = paramInt1;
+ this.eventSubTypeId = paramInt2;
+ this.value = paramInt3;
+ this.eventDate = paramString;
+ }
+ }
+
+ public final class MemberDto {
+ @SerializedName("CurrentGlucose")
+ private final int currentGlucose;
+
+ @SerializedName("FirstName")
+ private final String firstName;
+
+ @SerializedName("GlucoseTrend")
+ private final int glucoseTrend;
+
+ @SerializedName("LastName")
+ private final String lastName;
+
+ @SerializedName("ProfileImage")
+ private final String profileImage;
+
+ @SerializedName("Status")
+ private final int status;
+
+ @SerializedName("CGTime")
+ private final String timestamp;
+
+ @SerializedName("UserName")
+ private final String userEmail;
+
+ @SerializedName("UserID")
+ private final int userId;
+
+ public MemberDto(int paramInt1, String paramString1, String paramString2, String paramString3, int paramInt2, int paramInt3, String paramString4, int paramInt4, String paramString5) {
+ this.userId = paramInt1;
+ this.userEmail = paramString1;
+ this.firstName = paramString2;
+ this.lastName = paramString3;
+ this.currentGlucose = paramInt2;
+ this.glucoseTrend = paramInt3;
+ this.profileImage = paramString4;
+ this.status = paramInt4;
+ this.timestamp = paramString5;
+ }
+ }
+
+ public final class UserProfileDto {
+ @SerializedName("FirstName")
+ private final String firstName;
+
+ @SerializedName("LastName")
+ private final String lastName;
+
+ @SerializedName("ProfileImage")
+ private final String profileImageBase64;
+
+ @SerializedName("UserID")
+ public final int userId;
+
+ @SerializedName("UserName")
+ private final String username;
+
+ public UserProfileDto(int paramInt, String paramString1, String paramString2, String paramString3, String paramString4) {
+ this.userId = paramInt;
+ this.username = paramString1;
+ this.firstName = paramString2;
+ this.lastName = paramString3;
+ this.profileImageBase64 = paramString4;
+ }
+ }
+
+
+}
diff --git a/app/src/main/java/esel/esel/esel/util/EselLog.java b/app/src/main/java/esel/esel/esel/util/EselLog.java
new file mode 100644
index 0000000..317b6b8
--- /dev/null
+++ b/app/src/main/java/esel/esel/esel/util/EselLog.java
@@ -0,0 +1,65 @@
+package esel.esel.esel.util;
+
+import android.util.Log;
+
+import esel.esel.esel.LogActivity;
+
+public class EselLog {
+
+
+ public static void LogI(String tag, String value, boolean toast) {
+ if(toast) {
+ ToastUtils.makeToast("Info: " + value);
+ }
+ LogI(tag,value);
+ }
+ public static void LogI(String tag, String value){
+ String type = "Info: ";
+ Log.v(tag,value);
+ LogActivity.addLog(type,tag,value);
+ }
+
+ public static void LogE(String tag, String value, boolean toast) {
+ if(toast) {
+ ToastUtils.makeToast("Error: " + value);
+ }
+
+ LogE(tag,value);
+ }
+
+ public static void LogE(String tag, String value){
+ String type = "Error: ";
+ Log.v(tag,value);
+ LogActivity.addLog(type,tag,value);
+ }
+
+ public static void LogW(String tag, String value, boolean toast) {
+ if(toast) {
+ ToastUtils.makeToast("Warning: " + value);
+ }
+
+ LogW(tag,value);
+ }
+
+ public static void LogW(String tag, String value){
+ String type = "Warning: ";
+ Log.v(tag,value);
+ LogActivity.addLog(type,tag,value);
+ }
+
+ public static void LogV(String tag, String value, boolean toast) {
+ if(toast) {
+ ToastUtils.makeToast("Message: " + value);
+ }
+
+ LogV(tag,value);
+ }
+
+ public static void LogV(String tag, String value){
+ String type = "Message: ";
+ Log.v(tag,value);
+ //LogActivity.addLog(type,tag,value);
+ }
+
+
+}
diff --git a/app/src/main/java/esel/esel/esel/util/LocalBroadcaster.java b/app/src/main/java/esel/esel/esel/util/LocalBroadcaster.java
index d75360f..a649fef 100644
--- a/app/src/main/java/esel/esel/esel/util/LocalBroadcaster.java
+++ b/app/src/main/java/esel/esel/esel/util/LocalBroadcaster.java
@@ -3,7 +3,6 @@
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
-import android.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -12,11 +11,10 @@
import java.util.List;
import java.util.Locale;
+import esel.esel.esel.LogActivity;
import esel.esel.esel.Esel;
import esel.esel.esel.datareader.SGV;
-import static android.content.ContentValues.TAG;
-
/**
* Created by adrian on 04/08/17.
*/
@@ -49,8 +47,11 @@ public static void broadcast(SGV sgv) {
sendBundle("dbAdd", "entries", generateSgvEntry(sgv), ACTION_DATABASE);
}
+ EselLog.LogI(TAG, String.valueOf(sgv.value) + " " + sgv.direction );
+
} catch (Exception e) {
- Log.e(TAG, "Unable to send bundle: " + e);
+ String msg = "Unable to send bundle: " + e;
+ EselLog.LogE(TAG,msg);
}
}
@@ -93,7 +94,7 @@ private static void sendBundle(String action, String collection, Object json, St
if (packageName != null) {
intent.setPackage(packageName);
Esel.getsInstance().sendBroadcast(intent);
- Log.d(TAG, "sent to: " + packageName);
+ EselLog.LogI(TAG,"send to: " + packageName);
}
}
}
diff --git a/app/src/main/java/esel/esel/esel/util/UserLoginService.java b/app/src/main/java/esel/esel/esel/util/UserLoginService.java
new file mode 100644
index 0000000..db77e99
--- /dev/null
+++ b/app/src/main/java/esel/esel/esel/util/UserLoginService.java
@@ -0,0 +1,69 @@
+package esel.esel.esel.util;
+
+import android.os.SystemClock;
+
+import com.google.gson.annotations.SerializedName;
+import retrofit2.Call;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
+import retrofit2.http.POST;
+import java.time.LocalDateTime;
+public interface UserLoginService {
+ @FormUrlEncoded
+ @POST("token")
+ Call authenticate(@Field("grant_type") String paramString1, @Field("client_id") String paramString2, @Field("client_secret") String paramString3, @Field("username") String paramString4, @Field("password") String paramString5);
+
+
+ public final class SenseonicsTokenDto {
+
+ @SerializedName("access_token")
+ private final String accessToken;
+
+ @SerializedName("as:client_id")
+ private final String clientId;
+
+ @SerializedName("expires")
+ private final String expired;
+
+ @SerializedName("expires_in")
+ private final Long expiresIn;
+
+ @SerializedName(".issued")
+ private final String issued;
+
+ @SerializedName("refresh_token")
+ private String refresh_token;
+
+ @SerializedName("token_type")
+ private final String tokenType;
+
+ @SerializedName("userName")
+ private final String userName;
+
+ public SenseonicsTokenDto(String paramString1, String paramString2, Long paramLong, String paramString3, String paramString4, String paramString5, String paramString6, String paramString7) {
+ this.accessToken = paramString1;
+ this.tokenType = paramString2;
+ this.expiresIn = paramLong;
+ this.refresh_token = paramString3;
+ this.clientId = paramString4;
+ this.userName = paramString5;
+ this.issued = paramString6;
+ this.expired = paramString7;
+
+ SetExpireDateTime();
+ }
+
+ public void SetExpireDateTime(){
+ long currentTime = System.currentTimeMillis();
+
+ this.expireDateTime = currentTime + (expiresIn * 1000);
+ }
+
+ public long expireDateTime;
+
+ public String GetBearerToken(){
+ return "Bearer "+ accessToken;
+ }
+
+ }
+}
diff --git a/app/src/main/res/drawable/esel_pic.png b/app/src/main/res/drawable/esel_pic.png
new file mode 100644
index 0000000..c1e7bb8
Binary files /dev/null and b/app/src/main/res/drawable/esel_pic.png differ
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..ca3826a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/app_bar_errors.xml b/app/src/main/res/layout/app_bar_errors.xml
index c8ba2b2..8b3b032 100644
--- a/app/src/main/res/layout/app_bar_errors.xml
+++ b/app/src/main/res/layout/app_bar_errors.xml
@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context="esel.esel.esel.ErrorsActivity">
+ tools:context="esel.esel.esel.LogActivity">
+ layout="@layout/content_errors"
+ />