diff --git a/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfile.kt b/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfile.kt index 2596ef9583..fa8b2774be 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfile.kt +++ b/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfile.kt @@ -1,7 +1,5 @@ package info.nightscout.androidaps.data.defaultProfile -import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.data.ProfileImplOld import info.nightscout.androidaps.data.PureProfile import info.nightscout.androidaps.extensions.pureProfileFromJson import info.nightscout.androidaps.interfaces.GlucoseUnit diff --git a/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfileDPV.kt b/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfileDPV.kt index a0a555cc30..78ed97b335 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfileDPV.kt +++ b/app/src/main/java/info/nightscout/androidaps/data/defaultProfile/DefaultProfileDPV.kt @@ -1,7 +1,6 @@ package info.nightscout.androidaps.data.defaultProfile import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.data.ProfileImplOld import info.nightscout.androidaps.data.PureProfile import info.nightscout.androidaps.extensions.pureProfileFromJson import info.nightscout.androidaps.interfaces.GlucoseUnit diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index 1520dd0bbd..4496928738 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -4,8 +4,6 @@ import android.content.Context; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; -import androidx.annotation.Nullable; - import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; import com.j256.ormlite.dao.CloseableIterator; import com.j256.ormlite.dao.Dao; @@ -20,9 +18,6 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; import javax.inject.Inject; @@ -32,7 +27,6 @@ import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.openhumans.OpenHumansUploader; import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; import info.nightscout.androidaps.utils.DateUtil; @@ -51,12 +45,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { @Inject VirtualPumpPlugin virtualPumpPlugin; @Inject OpenHumansUploader openHumansUploader; @Inject ActivePlugin activePlugin; - @Inject NSUpload nsUpload; @Inject DateUtil dateUtil; public static final String DATABASE_NAME = "AndroidAPSDb"; - public static final String DATABASE_DANARHISTORY = "DanaRHistory"; - public static final String DATABASE_DBREQUESTS = "DBRequests"; private static final int DATABASE_VERSION = 13; @@ -76,10 +67,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { try { aapsLogger.info(LTag.DATABASE, "onCreate"); - TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); - TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); - TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); - TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class); TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class); @@ -103,10 +90,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { if (oldVersion < 7) { aapsLogger.info(LTag.DATABASE, "onUpgrade"); - TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); - TableUtils.dropTable(connectionSource, DbRequest.class, true); - TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); - TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); onCreate(database, connectionSource); } else if (oldVersion < 10) { TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class); @@ -149,15 +132,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { public void resetDatabases() { try { - TableUtils.dropTable(connectionSource, DanaRHistoryRecord.class, true); - TableUtils.dropTable(connectionSource, DbRequest.class, true); - TableUtils.dropTable(connectionSource, TemporaryBasal.class, true); - TableUtils.dropTable(connectionSource, ExtendedBolus.class, true); TableUtils.dropTable(connectionSource, OmnipodHistoryRecord.class, true); - TableUtils.createTableIfNotExists(connectionSource, DanaRHistoryRecord.class); - TableUtils.createTableIfNotExists(connectionSource, DbRequest.class); - TableUtils.createTableIfNotExists(connectionSource, TemporaryBasal.class); - TableUtils.createTableIfNotExists(connectionSource, ExtendedBolus.class); TableUtils.createTableIfNotExists(connectionSource, OmnipodHistoryRecord.class); updateEarliestDataChange(0); } catch (SQLException e) { @@ -177,22 +152,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { // ------------------ getDao ------------------------------------------- - private Dao getDaoDanaRHistory() throws SQLException { - return getDao(DanaRHistoryRecord.class); - } - - private Dao getDaoDbRequest() throws SQLException { - return getDao(DbRequest.class); - } - - private Dao getDaoTemporaryBasal() throws SQLException { - return getDao(TemporaryBasal.class); - } - - private Dao getDaoExtendedBolus() throws SQLException { - return getDao(ExtendedBolus.class); - } - private Dao getDaoInsightPumpID() throws SQLException { return getDao(InsightPumpID.class); } @@ -213,76 +172,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return getDao(OHQueueItem.class); } - public long roundDateToSec(long date) { - long rounded = date - date % 1000; - if (rounded != date) - aapsLogger.debug(LTag.DATABASE, "Rounding " + date + " to " + rounded); - return rounded; - } - - // ------------- DbRequests handling ------------------- - - public void create(DbRequest dbr) throws SQLException { - getDaoDbRequest().create(dbr); - } - - public int delete(DbRequest dbr) { - try { - return getDaoDbRequest().delete(dbr); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return 0; - } - - public int deleteDbRequest(String nsClientId) { - try { - return getDaoDbRequest().deleteById(nsClientId); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return 0; - } - - public void deleteDbRequestbyMongoId(String action, String id) { - try { - QueryBuilder queryBuilder = getDaoDbRequest().queryBuilder(); - // By nsID - Where where = queryBuilder.where(); - where.eq("_id", id).and().eq("action", action); - queryBuilder.limit(10L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List dbList = getDaoDbRequest().query(preparedQuery); - for (DbRequest r : dbList) delete(r); - // By nsClientID - where = queryBuilder.where(); - where.eq("nsClientID", id).and().eq("action", action); - queryBuilder.limit(10L); - preparedQuery = queryBuilder.prepare(); - dbList = getDaoDbRequest().query(preparedQuery); - for (DbRequest r : dbList) delete(r); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void deleteAllDbRequests() { - try { - TableUtils.clearTable(connectionSource, DbRequest.class); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public CloseableIterator getDbRequestIterator() { - try { - return getDaoDbRequest().closeableIterator(); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - return null; - } - } - public static void updateEarliestDataChange(long newDate) { if (earliestDataChange == null) { earliestDataChange = newDate; @@ -293,433 +182,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } } - // ----------------- DanaRHistory handling -------------------- - - public void createOrUpdate(DanaRHistoryRecord record) { - try { - getDaoDanaRHistory().createOrUpdate(record); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public List getDanaRHistoryRecordsByType(byte type) { - List historyList; - try { - QueryBuilder queryBuilder = getDaoDanaRHistory().queryBuilder(); - queryBuilder.orderBy("recordDate", false); - Where where = queryBuilder.where(); - where.eq("recordCode", type); - queryBuilder.limit(200L); - PreparedQuery preparedQuery = queryBuilder.prepare(); - historyList = getDaoDanaRHistory().query(preparedQuery); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - historyList = new ArrayList<>(); - } - return historyList; - } - - // ------------ TemporaryBasal handling --------------- - - //return true if new record was created - public boolean createOrUpdate(TemporaryBasal tempBasal) { - try { - TemporaryBasal old; - tempBasal.date = roundDateToSec(tempBasal.date); - - if (tempBasal.source == Source.PUMP) { - // check for changed from pump change in NS - QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("pumpId", tempBasal.pumpId); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = getDaoTemporaryBasal().query(preparedQuery); - if (trList.size() > 0) { - // do nothing, pump history record cannot be changed - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Already exists from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); - return false; - } - - // search by date (in case its standard record that has become pump record) - QueryBuilder queryBuilder2 = getDaoTemporaryBasal().queryBuilder(); - Where where2 = queryBuilder2.where(); - where2.eq("date", tempBasal.date); - PreparedQuery preparedQuery2 = queryBuilder2.prepare(); - List trList2 = getDaoTemporaryBasal().query(preparedQuery2); - - if (trList2.size() > 0) { - old = trList2.get(0); - - old.copyFromPump(tempBasal); - old.source = Source.PUMP; - - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updated record with Pump Data : " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); - - getDaoTemporaryBasal().update(old); - openHumansUploader.enqueueTemporaryBasal(old); - - updateEarliestDataChange(tempBasal.date); -// scheduleTemporaryBasalChange(); - - return false; - } - - getDaoTemporaryBasal().create(tempBasal); - openHumansUploader.enqueueTemporaryBasal(tempBasal); - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); - updateEarliestDataChange(tempBasal.date); -// scheduleTemporaryBasalChange(); - return true; - } - if (tempBasal.source == Source.NIGHTSCOUT) { - old = getDaoTemporaryBasal().queryForId(tempBasal.date); - if (old != null) { - if (!old.isAbsolute && tempBasal.isAbsolute) { // converted to absolute by "ns_sync_use_absolute" - // so far ignore, do not convert back because it may not be accurate - return false; - } - if (!old.isEqual(tempBasal)) { - long oldDate = old.date; - getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too - old.copyFrom(tempBasal); - getDaoTemporaryBasal().create(old); - openHumansUploader.enqueueTemporaryBasal(old); - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by date from: " + Source.getString(tempBasal.source) + " " + old.toString()); - updateEarliestDataChange(oldDate); - updateEarliestDataChange(old.date); -// scheduleTemporaryBasalChange(); - return true; - } - return false; - } - // find by NS _id - if (tempBasal._id != null) { - QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", tempBasal._id); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = getDaoTemporaryBasal().query(preparedQuery); - if (trList.size() > 0) { - old = trList.get(0); - if (!old.isEqual(tempBasal)) { - long oldDate = old.date; - getDaoTemporaryBasal().delete(old); // need to delete/create because date may change too - old.copyFrom(tempBasal); - getDaoTemporaryBasal().create(old); - openHumansUploader.enqueueTemporaryBasal(old); - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: Updating record by _id from: " + Source.getString(tempBasal.source) + " " + old.toString()); - updateEarliestDataChange(oldDate); - updateEarliestDataChange(old.date); -// scheduleTemporaryBasalChange(); - return true; - } - } - } - getDaoTemporaryBasal().create(tempBasal); - openHumansUploader.enqueueTemporaryBasal(tempBasal); - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); - updateEarliestDataChange(tempBasal.date); -// scheduleTemporaryBasalChange(); - return true; - } - if (tempBasal.source == Source.USER) { - getDaoTemporaryBasal().create(tempBasal); - openHumansUploader.enqueueTemporaryBasal(tempBasal); - aapsLogger.debug(LTag.DATABASE, "TEMPBASAL: New record from: " + Source.getString(tempBasal.source) + " " + tempBasal.toString()); - updateEarliestDataChange(tempBasal.date); -// scheduleTemporaryBasalChange(); - return true; - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return false; - } - - public void delete(TemporaryBasal tempBasal) { - try { - getDaoTemporaryBasal().delete(tempBasal); - openHumansUploader.enqueueTemporaryBasal(tempBasal, true); - updateEarliestDataChange(tempBasal.date); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } -// scheduleTemporaryBasalChange(); - } - - public List getTemporaryBasalsDataFromTime(long mills, boolean ascending) { - try { - List tempbasals; - QueryBuilder queryBuilder = getDaoTemporaryBasal().queryBuilder(); - queryBuilder.orderBy("date", ascending); - Where where = queryBuilder.where(); - where.ge("date", mills); - PreparedQuery preparedQuery = queryBuilder.prepare(); - tempbasals = getDaoTemporaryBasal().query(preparedQuery); - return tempbasals; - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return new ArrayList(); - } - - /* - { - "_id": "59232e1ddd032d04218dab00", - "eventType": "Temp Basal", - "duration": 60, - "percent": -50, - "created_at": "2017-05-22T18:29:57Z", - "enteredBy": "AndroidAPS", - "notes": "Basal Temp Start 50% 60.0 min", - "NSCLIENT_ID": 1495477797863, - "mills": 1495477797000, - "mgdl": 194.5, - "endmills": 1495481397000 - } - */ - - public TemporaryBasal findTempBasalByPumpId(Long pumpId) { - try { - QueryBuilder queryBuilder = null; - queryBuilder = getDaoTemporaryBasal().queryBuilder(); - queryBuilder.orderBy("date", false); - Where where = queryBuilder.where(); - where.eq("pumpId", pumpId); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = getDaoTemporaryBasal().query(preparedQuery); - - if (list.size() > 0) - return list.get(0); - else - return null; - - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return null; - } - - - // ------------ ExtendedBolus handling --------------- - - public ExtendedBolus getExtendedBolusByPumpId(long pumpId) { - try { - return getDaoExtendedBolus().queryBuilder() - .where().eq("pumpId", pumpId) - .queryForFirst(); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return null; - } - - public void delete(ExtendedBolus extendedBolus) { - try { - getDaoExtendedBolus().delete(extendedBolus); - openHumansUploader.enqueueExtendedBolus(extendedBolus, true); - updateEarliestDataChange(extendedBolus.date); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } -// scheduleExtendedBolusChange(); - } - - /* -{ - "_id": "5924898d577eb0880e355337", - "eventType": "Combo Bolus", - "duration": 120, - "splitNow": 0, - "splitExt": 100, - "enteredinsulin": 1, - "relative": 1, - "created_at": "2017-05-23T19:12:14Z", - "enteredBy": "AndroidAPS", - "NSCLIENT_ID": 1495566734628, - "mills": 1495566734000, - "mgdl": 106 -} - */ - - // ---------------- ProfileSwitch handling --------------- - -/* - public boolean createOrUpdate(ProfileSwitch profileSwitch) { - try { - ProfileSwitch old; - profileSwitch.date = roundDateToSec(profileSwitch.date); - - if (profileSwitch.source == Source.NIGHTSCOUT) { - old = getDaoProfileSwitch().queryForId(profileSwitch.date); - if (old != null) { - if (!old.isEqual(profileSwitch)) { - profileSwitch.source = old.source; - profileSwitch.profileName = old.profileName; // preserver profileName to prevent multiple CPP extension - getDaoProfileSwitch().delete(old); // need to delete/create because date may change too - getDaoProfileSwitch().create(profileSwitch); - aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: Updating record by date from: " + Source.getString(profileSwitch.source) + " " + old.toString()); - openHumansUploader.enqueueProfileSwitch(profileSwitch); - scheduleProfileSwitchChange(); - return true; - } - return false; - } - // find by NS _id - if (profileSwitch._id != null) { - QueryBuilder queryBuilder = getDaoProfileSwitch().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", profileSwitch._id); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List trList = getDaoProfileSwitch().query(preparedQuery); - if (trList.size() > 0) { - old = trList.get(0); - if (!old.isEqual(profileSwitch)) { - getDaoProfileSwitch().delete(old); // need to delete/create because date may change too - old.copyFrom(profileSwitch); - getDaoProfileSwitch().create(old); - aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: Updating record by _id from: " + Source.getString(profileSwitch.source) + " " + old.toString()); - openHumansUploader.enqueueProfileSwitch(old); - scheduleProfileSwitchChange(); - return true; - } - } - } - // look for already added percentage from NS - profileSwitch.profileName = PercentageSplitter.INSTANCE.pureName(profileSwitch.profileName); - getDaoProfileSwitch().create(profileSwitch); - aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString()); - openHumansUploader.enqueueProfileSwitch(profileSwitch); - scheduleProfileSwitchChange(); - return true; - } - if (profileSwitch.source == Source.USER) { - getDaoProfileSwitch().create(profileSwitch); - aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: New record from: " + Source.getString(profileSwitch.source) + " " + profileSwitch.toString()); - openHumansUploader.enqueueProfileSwitch(profileSwitch); - scheduleProfileSwitchChange(); - return true; - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return false; - } - - public void delete(ProfileSwitch profileSwitch) { - try { - getDaoProfileSwitch().delete(profileSwitch); - openHumansUploader.enqueueProfileSwitch(profileSwitch, true); - scheduleProfileSwitchChange(); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - private void scheduleProfileSwitchChange() { - class PostRunnable implements Runnable { - public void run() { - aapsLogger.debug(LTag.DATABASE, "Firing EventProfileNeedsUpdate"); - rxBus.send(new EventReloadProfileSwitchData()); - rxBus.send(new EventProfileNeedsUpdate()); - scheduledProfileSwitchEventPost = null; - } - } - // prepare task for execution in 1 sec - // cancel waiting task to prevent sending multiple posts - if (scheduledProfileSwitchEventPost != null) - scheduledProfileSwitchEventPost.cancel(false); - Runnable task = new PostRunnable(); - final int sec = 1; - scheduledProfileSwitchEventPost = profileSwitchEventWorker.schedule(task, sec, TimeUnit.SECONDS); - - } -*/ - /* -{ - "_id":"592fa43ed97496a80da913d2", - "created_at":"2017-06-01T05:20:06Z", - "eventType":"Profile Switch", - "profile":"2016 +30%", - "units":"mmol", - "enteredBy":"sony", - "NSCLIENT_ID":1496294454309, -} - */ -/* - - public void createProfileSwitchFromJsonIfNotExists(JSONObject trJson) { - try { - ProfileSwitch profileSwitch = new ProfileSwitch(StaticInjector.Companion.getInstance()); - profileSwitch.date = trJson.getLong("mills"); - if (trJson.has("duration")) - profileSwitch.durationInMinutes = trJson.getInt("duration"); - profileSwitch._id = trJson.getString("_id"); - profileSwitch.profileName = trJson.getString("profile"); - profileSwitch.isCPP = trJson.has("CircadianPercentageProfile"); - profileSwitch.source = Source.NIGHTSCOUT; - if (trJson.has("timeshift")) - profileSwitch.timeshift = trJson.getInt("timeshift"); - if (trJson.has("percentage")) - profileSwitch.percentage = trJson.getInt("percentage"); - if (trJson.has("profileJson")) - profileSwitch.profileJson = trJson.getString("profileJson"); - else { - ProfileSource profileSource = activePlugin.getActiveProfileSource(); - ProfileStore store = profileSource.getProfile(); - if (store != null) { - PureProfile profile = store.getSpecificProfile(profileSwitch.profileName); - if (profile != null) { - profileSwitch.profileJson = profile.getJsonObject().toString(); - aapsLogger.debug(LTag.DATABASE, "Profile switch prefilled with JSON from local store"); - // Update data in NS - nsUpload.updateProfileSwitch(profileSwitch, dateUtil); - } else { - aapsLogger.debug(LTag.DATABASE, "JSON for profile switch doesn't exist. Ignoring: " + trJson.toString()); - return; - } - } else { - aapsLogger.debug(LTag.DATABASE, "Store for profile switch doesn't exist. Ignoring: " + trJson.toString()); - return; - } - } - if (trJson.has("profilePlugin")) - profileSwitch.profilePlugin = trJson.getString("profilePlugin"); - createOrUpdate(profileSwitch); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception: " + trJson.toString(), e); - } - } - - public void deleteProfileSwitchById(String _id) { - ProfileSwitch stored = findProfileSwitchById(_id); - if (stored != null) { - aapsLogger.debug(LTag.DATABASE, "PROFILESWITCH: Removing ProfileSwitch record from database: " + stored.toString()); - delete(stored); - scheduleProfileSwitchChange(); - } - } - - public ProfileSwitch findProfileSwitchById(String _id) { - try { - QueryBuilder queryBuilder = getDaoProfileSwitch().queryBuilder(); - Where where = queryBuilder.where(); - where.eq("_id", _id); - PreparedQuery preparedQuery = queryBuilder.prepare(); - List list = getDaoProfileSwitch().query(preparedQuery); - - if (list.size() == 1) { - return list.get(0); - } else { - return null; - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return null; - } -*/ // ---------------- Insight history handling --------------- public void createOrUpdate(InsightHistoryOffset offset) { @@ -924,14 +386,4 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { } return 0L; } - - public long getCountOfAllRows() { - try { - return getDaoExtendedBolus().countOf() - + getDaoTemporaryBasal().countOf(); - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return 0L; - } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java index 4c3816c934..89d892fe97 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelperProvider.java @@ -5,8 +5,6 @@ import androidx.annotation.Nullable; import com.j256.ormlite.dao.CloseableIterator; -import org.json.JSONObject; - import java.sql.SQLException; import java.util.List; @@ -23,61 +21,24 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { @Inject DatabaseHelperProvider() { } - @Override public void createOrUpdate(@NonNull DanaRHistoryRecord record) { - MainApp.Companion.getDbHelper().createOrUpdate(record); - } - @Override public void createOrUpdate(@NonNull OmnipodHistoryRecord record) { MainApp.Companion.getDbHelper().createOrUpdate(record); } - @NonNull @Override public List getDanaRHistoryRecordsByType(byte type) { - return MainApp.Companion.getDbHelper().getDanaRHistoryRecordsByType(type); - } - - @Override public long size(@NonNull String table) { - return MainApp.Companion.getDbHelper().size(table); - } - - @Override public void create(@NonNull DbRequest record) { - try { - MainApp.Companion.getDbHelper().create(record); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - @Override public void deleteAllDbRequests() { - MainApp.Companion.getDbHelper().deleteAllDbRequests(); - } - - @Override public int deleteDbRequest(@NonNull String id) { - return MainApp.Companion.getDbHelper().deleteDbRequest(id); - } - - @Override public void deleteDbRequestbyMongoId(@NonNull String action, @NonNull String _id) { - MainApp.Companion.getDbHelper().deleteDbRequestbyMongoId(action, _id); - } - - @NonNull @Override public CloseableIterator getDbRequestIterator() { - return MainApp.Companion.getDbHelper().getDbRequestIterator(); - } - - @Override public long roundDateToSec(long date) { - return MainApp.Companion.getDbHelper().roundDateToSec(date); - } - @Override public boolean createOrUpdate(@NonNull TemporaryBasal tempBasal) { - return MainApp.Companion.getDbHelper().createOrUpdate(tempBasal); +// return MainApp.Companion.getDbHelper().createOrUpdate(tempBasal); + return false; } @Nullable @Override public TemporaryBasal findTempBasalByPumpId(long id) { - return MainApp.Companion.getDbHelper().findTempBasalByPumpId(id); +// return MainApp.Companion.getDbHelper().findTempBasalByPumpId(id); + return null; } @Deprecated @NonNull @Override public List getTemporaryBasalsDataFromTime(long mills, boolean ascending) { - return MainApp.Companion.getDbHelper().getTemporaryBasalsDataFromTime(mills, ascending); +// return MainApp.Companion.getDbHelper().getTemporaryBasalsDataFromTime(mills, ascending); + return null; } @NonNull @Override public List getAllOmnipodHistoryRecordsFromTimestamp(long timestamp, boolean ascending) { @@ -101,11 +62,12 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { } @Override public void delete(@NonNull ExtendedBolus extendedBolus) { - MainApp.Companion.getDbHelper().delete(extendedBolus); +// MainApp.Companion.getDbHelper().delete(extendedBolus); } @Nullable @Override public ExtendedBolus getExtendedBolusByPumpId(long pumpId) { - return MainApp.Companion.getDbHelper().getExtendedBolusByPumpId(pumpId); +// return MainApp.Companion.getDbHelper().getExtendedBolusByPumpId(pumpId); + return null; } @Nullable @Override public InsightBolusID getInsightBolusID(@NonNull String pumpSerial, int bolusID, long timestamp) { @@ -140,10 +102,6 @@ public class DatabaseHelperProvider implements DatabaseHelperInterface { MainApp.Companion.getDbHelper().clearOpenHumansQueue(); } - @Override public long getCountOfAllRows() { - return MainApp.Companion.getDbHelper().getCountOfAllRows(); - } - @Override public void removeAllOHQueueItemsWithIdSmallerThan(long id) { MainApp.Companion.getDbHelper().removeAllOHQueueItemsWithIdSmallerThan(id); } diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt index b7881ca7f4..05b5974bb5 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppComponent.kt @@ -7,6 +7,7 @@ import dagger.android.AndroidInjector import info.nightscout.androidaps.MainApp import info.nightscout.androidaps.automation.di.AutomationModule import info.nightscout.androidaps.combo.di.ComboModule +import info.nightscout.androidaps.dana.di.DanaHistoryModule import info.nightscout.androidaps.di.CoreModule import info.nightscout.androidaps.dana.di.DanaModule import info.nightscout.androidaps.danar.di.DanaRModule @@ -45,6 +46,7 @@ import javax.inject.Singleton UIModule::class, CoreModule::class, DanaModule::class, + DanaHistoryModule::class, DanaRModule::class, DanaRSModule::class, ComboModule::class, diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt index 46af1a1228..1266f526fe 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/AppModule.kt @@ -6,33 +6,35 @@ import dagger.Lazy import dagger.Module import dagger.Provides import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.db.DatabaseHelperProvider import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin -import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin import info.nightscout.androidaps.plugins.configBuilder.PluginStore +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefsImpl import info.nightscout.androidaps.plugins.general.nsclient.DataSyncSelectorImplementation -import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.pump.PumpSyncImplementation import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.queue.CommandQueue +import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.androidNotification.NotificationHolderImpl import info.nightscout.androidaps.utils.buildHelper.ConfigImpl import info.nightscout.androidaps.utils.resources.IconsProviderImplementation +import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.rx.DefaultAapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.storage.FileStorage import info.nightscout.androidaps.utils.storage.Storage import javax.inject.Singleton + @Suppress("unused") @Module(includes = [ AppModule.AppBindings::class @@ -65,13 +67,9 @@ open class AppModule { @Provides @Singleton - fun providesUploadQueue( - aapsLogger: AAPSLogger, - databaseHelper: DatabaseHelperInterface, - context: Context, - sp: SP, - rxBus: RxBusWrapper - ): UploadQueueAdminInterface = UploadQueue(aapsLogger, databaseHelper, context, sp, rxBus) + fun provideProfileFunction(aapsLogger: AAPSLogger, sp: SP, resourceHelper: ResourceHelper, activePlugin: ActivePlugin, repository: AppRepository, dateUtil: DateUtil): ProfileFunction { + return ProfileFunctionImplementation(aapsLogger, sp, resourceHelper, activePlugin, repository, dateUtil) + } @Provides @Singleton @@ -99,7 +97,6 @@ open class AppModule { @Binds fun bindLoopInterface(loopPlugin: LoopPlugin): LoopInterface @Binds fun bindIobCobCalculatorInterface(iobCobCalculatorPlugin: IobCobCalculatorPlugin): IobCobCalculator @Binds fun bindSmsCommunicatorInterface(smsCommunicatorPlugin: SmsCommunicatorPlugin): SmsCommunicator - @Binds fun bindUploadQueueAdminInterfaceToUploadQueue(uploadQueueAdminInterface: UploadQueueAdminInterface) : UploadQueueInterface @Binds fun bindDataSyncSelector(dataSyncSelectorImplementation: DataSyncSelectorImplementation): DataSyncSelector @Binds fun bindPumpSync(pumpSyncImplementation: PumpSyncImplementation): PumpSync diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt index 15298fb768..60eb3ace15 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/FragmentsModule.kt @@ -29,7 +29,6 @@ import info.nightscout.androidaps.plugins.general.tidepool.TidepoolFragment import info.nightscout.androidaps.plugins.general.wear.WearFragment import info.nightscout.androidaps.plugins.insulin.InsulinFragment import info.nightscout.androidaps.plugins.profile.local.LocalProfileFragment -import info.nightscout.androidaps.plugins.profile.ns.NSProfileFragment import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpFragment import info.nightscout.androidaps.plugins.source.BGSourceFragment import info.nightscout.androidaps.plugins.treatments.TreatmentsFragment @@ -46,8 +45,7 @@ abstract class FragmentsModule { @ContributesAndroidInjector abstract fun contributesAutomationFragment(): AutomationFragment @ContributesAndroidInjector abstract fun contributesBGSourceFragment(): BGSourceFragment - @ContributesAndroidInjector - abstract fun contributesConfigBuilderFragment(): ConfigBuilderFragment + @ContributesAndroidInjector abstract fun contributesConfigBuilderFragment(): ConfigBuilderFragment @ContributesAndroidInjector abstract fun contributesFoodFragment(): FoodFragment @ContributesAndroidInjector abstract fun contributesInsulinFragment(): InsulinFragment @@ -58,10 +56,8 @@ abstract class FragmentsModule { @ContributesAndroidInjector abstract fun contributesOverviewFragment(): OverviewFragment @ContributesAndroidInjector abstract fun contributesLoopFragment(): LoopFragment @ContributesAndroidInjector abstract fun contributesMaintenanceFragment(): MaintenanceFragment - @ContributesAndroidInjector abstract fun contributesNSProfileFragment(): NSProfileFragment @ContributesAndroidInjector abstract fun contributesNSClientFragment(): NSClientFragment - @ContributesAndroidInjector - abstract fun contributesSmsCommunicatorFragment(): SmsCommunicatorFragment + @ContributesAndroidInjector abstract fun contributesSmsCommunicatorFragment(): SmsCommunicatorFragment @ContributesAndroidInjector abstract fun contributesWearFragment(): WearFragment @ContributesAndroidInjector abstract fun contributesTidepoolFragment(): TidepoolFragment @@ -85,8 +81,7 @@ abstract class FragmentsModule { @ContributesAndroidInjector abstract fun contributesEditEventDialog(): EditEventDialog @ContributesAndroidInjector abstract fun contributesEditTriggerDialog(): EditTriggerDialog - @ContributesAndroidInjector - abstract fun contributesEditQuickWizardDialog(): EditQuickWizardDialog + @ContributesAndroidInjector abstract fun contributesEditQuickWizardDialog(): EditQuickWizardDialog @ContributesAndroidInjector abstract fun contributesExtendedBolusDialog(): ExtendedBolusDialog @ContributesAndroidInjector abstract fun contributesFillDialog(): FillDialog @@ -102,8 +97,7 @@ abstract class FragmentsModule { @ContributesAndroidInjector abstract fun contributesWizardDialog(): WizardDialog @ContributesAndroidInjector abstract fun contributesWizardInfoDialog(): WizardInfoDialog - @ContributesAndroidInjector - abstract fun contributesExchangeAuthTokenDialot(): OpenHumansLoginActivity.ExchangeAuthTokenDialog + @ContributesAndroidInjector abstract fun contributesExchangeAuthTokenDialog(): OpenHumansLoginActivity.ExchangeAuthTokenDialog @ContributesAndroidInjector abstract fun contributesPasswordCheck(): PasswordCheck } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt index 02506911ec..5cb174b533 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt @@ -37,7 +37,6 @@ import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin import info.nightscout.androidaps.plugins.insulin.InsulinOrefUltraRapidActingPlugin import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin -import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin @@ -192,12 +191,6 @@ abstract class PluginsModule { @IntKey(220) abstract fun bindOpenAPSSMBPlugin(plugin: OpenAPSSMBPlugin): PluginBase - @Binds - @AllConfigs - @IntoMap - @IntKey(230) - abstract fun bindNSProfilePlugin(plugin: NSProfilePlugin): PluginBase - @Binds @NotNSClient @IntoMap diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt index 0c67611761..2e7bb25b43 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/WorkersModule.kt @@ -9,7 +9,7 @@ import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker import info.nightscout.androidaps.plugins.general.nsclient.NSClientUpdateRemoveAckWorker import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin -import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin +import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin import info.nightscout.androidaps.plugins.source.* @Module @@ -24,7 +24,7 @@ abstract class WorkersModule { @ContributesAndroidInjector abstract fun contributesTomatoWorker(): TomatoPlugin.TomatoWorker @ContributesAndroidInjector abstract fun contributesEversenseWorker(): EversensePlugin.EversenseWorker @ContributesAndroidInjector abstract fun contributesNSClientSourceWorker(): NSClientSourcePlugin.NSClientSourceWorker - @ContributesAndroidInjector abstract fun contributesNSProfileWorker(): NSProfilePlugin.NSProfileWorker + @ContributesAndroidInjector abstract fun contributesNSProfileWorker(): LocalProfilePlugin.NSProfileWorker @ContributesAndroidInjector abstract fun contributesSmsCommunicatorWorker(): SmsCommunicatorPlugin.SmsCommunicatorWorker @ContributesAndroidInjector abstract fun contributesNSClientWorker(): NSClientAddUpdateWorker @ContributesAndroidInjector abstract fun contributesNSClientAddAckWorker(): NSClientAddAckWorker diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt index 0dcb282da6..eab790dc48 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.kt @@ -403,7 +403,7 @@ open class LoopPlugin @Inject constructor( val waiting = PumpEnactResult(injector) waiting.queued = true if (resultAfterConstraints.tempBasalRequested) lastRun.tbrSetByPump = waiting - if (resultAfterConstraints.bolusRequested) lastRun.smbSetByPump = waiting + if (resultAfterConstraints.bolusRequested()) lastRun.smbSetByPump = waiting rxBus.send(EventLoopUpdateGui()) fabricPrivacy.logCustom("APSRequest") applyTBRRequest(resultAfterConstraints, profile, object : Callback() { @@ -600,7 +600,7 @@ open class LoopPlugin @Inject constructor( } private fun applySMBRequest(request: APSResult, callback: Callback?) { - if (!request.bolusRequested) { + if (!request.bolusRequested()) { return } val pump = activePlugin.activePump diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt index 6f66dd235f..5411bd2fa3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalResultAMA.kt @@ -40,7 +40,6 @@ class DetermineBasalResultAMA private constructor(injector: HasAndroidInjector) tempBasalRequested = false } } - bolusRequested = false } override fun newAndClone(injector: HasAndroidInjector): DetermineBasalResultAMA { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt index 996621b8db..aa5dff4b38 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalResultSMB.kt @@ -35,7 +35,6 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector) duration = -1 } if (result.has("units")) { - bolusRequested = true smb = result.getDouble("units") } else { smb = 0.0 diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt similarity index 100% rename from core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt rename to app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctionImplementation.kt diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.kt index da4fb503a1..a40f4fb752 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.kt @@ -28,7 +28,7 @@ class Objective3 @Inject constructor(injector: HasAndroidInjector) : Objective(i } override fun specialActionEnabled(): Boolean = - NSClientService.isConnected && NSClientService.hasWriteAuth + nsClientPlugin.nsClientService?.isConnected == true && nsClientPlugin.nsClientService?.hasWriteAuth == true override fun specialAction(activity: FragmentActivity, input: String) { objectivesPlugin.completeObjectives(activity, input) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt index 4337808106..8ff8dac818 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/maintenance/MaintenanceFragment.kt @@ -7,13 +7,13 @@ import android.view.View import android.view.ViewGroup import dagger.android.support.DaggerFragment import info.nightscout.androidaps.R +import info.nightscout.androidaps.dana.database.DanaHistoryDatabase import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding import info.nightscout.androidaps.events.EventNewBG import info.nightscout.androidaps.interfaces.DataSyncSelector -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface import info.nightscout.androidaps.interfaces.ImportExportPrefs import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger @@ -38,7 +38,7 @@ class MaintenanceFragment : DaggerFragment() { @Inject lateinit var importExportPrefs: ImportExportPrefs @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var repository: AppRepository - @Inject lateinit var databaseHelper: DatabaseHelperInterface + @Inject lateinit var danaHistoryDatabase: DanaHistoryDatabase @Inject lateinit var uel: UserEntryLogger @Inject lateinit var dataSyncSelector: DataSyncSelector @Inject lateinit var pumpSync: PumpSync @@ -68,8 +68,8 @@ class MaintenanceFragment : DaggerFragment() { OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.maintenance), resourceHelper.gs(R.string.reset_db_confirm), Runnable { compositeDisposable.add( fromAction { - databaseHelper.resetDatabases() repository.clearDatabases() + danaHistoryDatabase.clearAllTables() dataSyncSelector.resetToNextFullSync() pumpSync.connectNewPump() } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt index 99b9febf03..7e3dd1bb8f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/DataSyncSelectorImplementation.kt @@ -2,14 +2,14 @@ package info.nightscout.androidaps.plugins.general.nsclient import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository -import info.nightscout.androidaps.database.entities.DeviceStatus import info.nightscout.androidaps.database.entities.* +import info.nightscout.androidaps.extensions.toJson import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.DataSyncSelector import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.extensions.toJson +import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject @@ -21,9 +21,27 @@ class DataSyncSelectorImplementation @Inject constructor( private val profileFunction: ProfileFunction, private val nsClientPlugin: NSClientPlugin, private val activePlugin: ActivePlugin, - private val appRepository: AppRepository + private val appRepository: AppRepository, + private val localProfilePlugin: LocalProfilePlugin ) : DataSyncSelector { + override fun doUpload() { + if (sp.getBoolean(R.string.key_ns_upload, true)) { + processChangedBolusesCompat() + processChangedCarbsCompat() + processChangedBolusCalculatorResultsCompat() + processChangedTemporaryBasalsCompat() + processChangedExtendedBolusesCompat() + processChangedProfileSwitchesCompat() + processChangedGlucoseValuesCompat() + processChangedTempTargetsCompat() + processChangedFoodsCompat() + processChangedTherapyEventsCompat() + processChangedDeviceStatusesCompat() + processChangedProfileStore() + } + } + override fun resetToNextFullSync() { sp.remove(R.string.key_ns_temporary_target_last_synced_id) sp.remove(R.string.key_ns_glucose_value_last_synced_id) @@ -36,6 +54,7 @@ class DataSyncSelectorImplementation @Inject constructor( sp.remove(R.string.key_ns_extended_bolus_last_synced_id) sp.remove(R.string.key_ns_therapy_event_last_synced_id) sp.remove(R.string.key_ns_profile_switch_last_synced_id) + sp.remove(R.string.key_ns_profile_store_last_synced_timestamp) } override fun confirmLastBolusIdIfGreater(lastSynced: Long) { @@ -445,4 +464,18 @@ class DataSyncSelectorImplementation @Inject constructor( } return false } + + override fun confirmLastProfileStore(lastSynced: Long) { + sp.putLong(R.string.key_ns_profile_store_last_synced_timestamp, lastSynced) + } + + override fun processChangedProfileStore() { + val lastSync = sp.getLong(R.string.key_ns_profile_store_last_synced_timestamp, 0) + val lastChange = sp.getLong(R.string.key_local_profile_last_change, 0) + if (lastChange == 0L) return + localProfilePlugin.createProfileStore() + val profileJson = localProfilePlugin.profile?.data ?: return + if (lastChange > lastSync) + nsClientPlugin.nsClientService?.dbAdd("profile", profileJson, DataSyncSelector.PairProfileStore(profileJson, dateUtil.now())) + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt index 39c20b00e3..3404d2008f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddAckWorker.kt @@ -147,7 +147,7 @@ class NSClientAddAckWorker( dataSyncSelector.confirmLastCarbsIdIfGreater(pair.updateRecordId) } .blockingGet() - rxBus.send(EventNSClientNewLog("DBADD", "Acked Carbs" + pair.value.interfaceIDs.nightscoutId)) + rxBus.send(EventNSClientNewLog("DBADD", "Acked Carbs " + pair.value.interfaceIDs.nightscoutId)) // Send new if waiting dataSyncSelector.processChangedCarbsCompat() } @@ -166,7 +166,7 @@ class NSClientAddAckWorker( dataSyncSelector.confirmLastBolusCalculatorResultsIdIfGreater(pair.updateRecordId) } .blockingGet() - rxBus.send(EventNSClientNewLog("DBADD", "Acked BolusCalculatorResult" + pair.value.interfaceIDs.nightscoutId)) + rxBus.send(EventNSClientNewLog("DBADD", "Acked BolusCalculatorResult " + pair.value.interfaceIDs.nightscoutId)) // Send new if waiting dataSyncSelector.processChangedBolusCalculatorResultsCompat() } @@ -185,7 +185,7 @@ class NSClientAddAckWorker( dataSyncSelector.confirmLastTemporaryBasalIdIfGreater(pair.updateRecordId) } .blockingGet() - rxBus.send(EventNSClientNewLog("DBADD", "Acked TemporaryBasal" + pair.value.interfaceIDs.nightscoutId)) + rxBus.send(EventNSClientNewLog("DBADD", "Acked TemporaryBasal " + pair.value.interfaceIDs.nightscoutId)) // Send new if waiting dataSyncSelector.processChangedTemporaryBasalsCompat() } @@ -204,7 +204,7 @@ class NSClientAddAckWorker( dataSyncSelector.confirmLastExtendedBolusIdIfGreater(pair.updateRecordId) } .blockingGet() - rxBus.send(EventNSClientNewLog("DBADD", "Acked ExtendedBolus" + pair.value.interfaceIDs.nightscoutId)) + rxBus.send(EventNSClientNewLog("DBADD", "Acked ExtendedBolus " + pair.value.interfaceIDs.nightscoutId)) // Send new if waiting dataSyncSelector.processChangedTemporaryBasalsCompat() } @@ -223,7 +223,7 @@ class NSClientAddAckWorker( dataSyncSelector.confirmLastProfileSwitchIdIfGreater(pair.updateRecordId) } .blockingGet() - rxBus.send(EventNSClientNewLog("DBADD", "Acked ProfileSwitch" + pair.value.interfaceIDs.nightscoutId)) + rxBus.send(EventNSClientNewLog("DBADD", "Acked ProfileSwitch " + pair.value.interfaceIDs.nightscoutId)) // Send new if waiting dataSyncSelector.processChangedTemporaryBasalsCompat() } @@ -242,10 +242,15 @@ class NSClientAddAckWorker( dataSyncSelector.confirmLastDeviceStatusIdIfGreater(deviceStatus.id) } .blockingGet() - rxBus.send(EventNSClientNewLog("DBADD", "Acked DeviceStatus" + deviceStatus.interfaceIDs.nightscoutId)) + rxBus.send(EventNSClientNewLog("DBADD", "Acked DeviceStatus " + deviceStatus.interfaceIDs.nightscoutId)) // Send new if waiting dataSyncSelector.processChangedDeviceStatusesCompat() } + + is PairProfileStore -> { + dataSyncSelector.confirmLastProfileStore(ack.originalObject.timestampSync) + rxBus.send(EventNSClientNewLog("DBADD", "Acked ProfileStore " + ack.id)) + } } return ret } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt index 83b19b2a16..7520cc1326 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientAddUpdateWorker.kt @@ -14,6 +14,7 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.database.entities.ValueWithUnit import info.nightscout.androidaps.database.transactions.* import info.nightscout.androidaps.extensions.* +import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -43,13 +44,11 @@ class NSClientAddUpdateWorker( @Inject lateinit var dateUtil: DateUtil @Inject lateinit var config: Config @Inject lateinit var repository: AppRepository + @Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var rxBus: RxBusWrapper @Inject lateinit var uel: UserEntryLogger override fun doWork(): Result { - val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT - if (!acceptNSData) return Result.success() - val treatments = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1)) ?: return Result.failure(workDataOf("Error" to "missing input data")) @@ -73,62 +72,66 @@ class NSClientAddUpdateWorker( if (mills > latestDateInReceivedData) latestDateInReceivedData = mills if (insulin > 0) { - bolusFromJson(json)?.let { bolus -> - repository.runTransactionForResult(SyncNsBolusTransaction(bolus, invalidateByNsOnly = false)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) - ret = Result.failure(workDataOf("Error" to it.toString())) - } - .blockingGet() - .also { result -> - result.inserted.forEach { - uel.log(Action.BOLUS, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.Insulin(it.amount) - ) - aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") + if (sp.getBoolean(R.string.key_ns_receive_insulin, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) { + bolusFromJson(json)?.let { bolus -> + repository.runTransactionForResult(SyncNsBolusTransaction(bolus, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) + ret = Result.failure(workDataOf("Error" to it.toString())) } - result.invalidated.forEach { - uel.log(Action.BOLUS_REMOVED, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.Insulin(it.amount) - ) - aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(Action.BOLUS, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.Insulin(it.amount) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") + } + result.invalidated.forEach { + uel.log(Action.BOLUS_REMOVED, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.Insulin(it.amount) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId bolus $it") + } } - result.updatedNsId.forEach { - aapsLogger.debug(LTag.DATABASE, "Updated nsId bolus $it") - } - } - } ?: aapsLogger.error("Error parsing bolus json $json") + } ?: aapsLogger.error("Error parsing bolus json $json") + } } if (carbs > 0) { - carbsFromJson(json)?.let { carb -> - repository.runTransactionForResult(SyncNsCarbsTransaction(carb, invalidateByNsOnly = false)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) - ret = Result.failure(workDataOf("Error" to it.toString())) - } - .blockingGet() - .also { result -> - result.inserted.forEach { - uel.log(Action.CARBS, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.Gram(it.amount.toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") + if (sp.getBoolean(R.string.key_ns_receive_carbs, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) { + carbsFromJson(json)?.let { carb -> + repository.runTransactionForResult(SyncNsCarbsTransaction(carb, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving carbs", it) + ret = Result.failure(workDataOf("Error" to it.toString())) } - result.invalidated.forEach { - uel.log(Action.CARBS_REMOVED, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.Gram(it.amount.toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(Action.CARBS, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.Gram(it.amount.toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") + } + result.invalidated.forEach { + uel.log(Action.CARBS_REMOVED, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.Gram(it.amount.toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId carbs $it") + } } - result.updatedNsId.forEach { - aapsLogger.debug(LTag.DATABASE, "Updated nsId carbs $it") - } - } - } ?: aapsLogger.error("Error parsing bolus json $json") + } ?: aapsLogger.error("Error parsing bolus json $json") + } } // Convert back emulated TBR -> EB if (eventType == TherapyEvent.Type.TEMPORARY_BASAL.text && json.has("extendedEmulated")) { @@ -140,46 +143,48 @@ class NSClientAddUpdateWorker( when { insulin > 0 || carbs > 0 -> Any() eventType == TherapyEvent.Type.TEMPORARY_TARGET.text -> - temporaryTargetFromJson(json)?.let { temporaryTarget -> - repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTarget, invalidateByNsOnly = false)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) - ret = Result.failure(workDataOf("Error" to it.toString())) - } - .blockingGet() - .also { result -> - result.inserted.forEach { tt -> - uel.log(Action.TT, Sources.NSClient, - ValueWithUnit.TherapyEventTTReason(tt.reason), - ValueWithUnit.fromGlucoseUnit(tt.lowTarget, Constants.MGDL), - ValueWithUnit.fromGlucoseUnit(tt.highTarget, Constants.MGDL).takeIf { tt.lowTarget != tt.highTarget }, - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryTarget $tt") + if (sp.getBoolean(R.string.key_ns_receive_temp_target, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) { + temporaryTargetFromJson(json)?.let { temporaryTarget -> + repository.runTransactionForResult(SyncNsTemporaryTargetTransaction(temporaryTarget, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it) + ret = Result.failure(workDataOf("Error" to it.toString())) } - result.invalidated.forEach { tt -> - uel.log(Action.TT_REMOVED, Sources.NSClient, - ValueWithUnit.TherapyEventTTReason(tt.reason), - ValueWithUnit.Mgdl(tt.lowTarget), - ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget }, - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryTarget $tt") + .blockingGet() + .also { result -> + result.inserted.forEach { tt -> + uel.log(Action.TT, Sources.NSClient, + ValueWithUnit.TherapyEventTTReason(tt.reason), + ValueWithUnit.fromGlucoseUnit(tt.lowTarget, Constants.MGDL), + ValueWithUnit.fromGlucoseUnit(tt.highTarget, Constants.MGDL).takeIf { tt.lowTarget != tt.highTarget }, + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryTarget $tt") + } + result.invalidated.forEach { tt -> + uel.log(Action.TT_REMOVED, Sources.NSClient, + ValueWithUnit.TherapyEventTTReason(tt.reason), + ValueWithUnit.Mgdl(tt.lowTarget), + ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget }, + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryTarget $tt") + } + result.ended.forEach { tt -> + uel.log(Action.CANCEL_TT, Sources.NSClient, + ValueWithUnit.TherapyEventTTReason(tt.reason), + ValueWithUnit.Mgdl(tt.lowTarget), + ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget }, + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Updated TemporaryTarget $tt") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryTarget $it") + } } - result.ended.forEach { tt -> - uel.log(Action.CANCEL_TT, Sources.NSClient, - ValueWithUnit.TherapyEventTTReason(tt.reason), - ValueWithUnit.Mgdl(tt.lowTarget), - ValueWithUnit.Mgdl(tt.highTarget).takeIf { tt.lowTarget != tt.highTarget }, - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tt.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Updated TemporaryTarget $tt") - } - result.updatedNsId.forEach { - aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryTarget $it") - } - } - } ?: aapsLogger.error("Error parsing TT json $json") + } ?: aapsLogger.error("Error parsing TT json $json") + } eventType == TherapyEvent.Type.CANNULA_CHANGE.text || eventType == TherapyEvent.Type.INSULIN_CHANGE.text || eventType == TherapyEvent.Type.SENSOR_CHANGE.text || @@ -190,158 +195,167 @@ class NSClientAddUpdateWorker( eventType == TherapyEvent.Type.EXERCISE.text || eventType == TherapyEvent.Type.APS_OFFLINE.text || eventType == TherapyEvent.Type.PUMP_BATTERY_CHANGE.text -> - therapyEventFromJson(json)?.let { therapyEvent -> - repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEvent, invalidateByNsOnly = false)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) - ret = Result.failure(workDataOf("Error" to it.toString())) - } - .blockingGet() - .also { result -> - val action = when (eventType) { - TherapyEvent.Type.CANNULA_CHANGE.text -> Action.SITE_CHANGE - TherapyEvent.Type.INSULIN_CHANGE.text -> Action.RESERVOIR_CHANGE - else -> Action.CAREPORTAL + if (sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || config.NSCLIENT) { + therapyEventFromJson(json)?.let { therapyEvent -> + repository.runTransactionForResult(SyncNsTherapyEventTransaction(therapyEvent, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) + ret = Result.failure(workDataOf("Error" to it.toString())) } - result.inserted.forEach { - uel.log(action, Sources.NSClient, - it.note ?: "", - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.TherapyEventType(it.type) - ) - aapsLogger.debug(LTag.DATABASE, "Inserted TherapyEvent $it") + .blockingGet() + .also { result -> + val action = when (eventType) { + TherapyEvent.Type.CANNULA_CHANGE.text -> Action.SITE_CHANGE + TherapyEvent.Type.INSULIN_CHANGE.text -> Action.RESERVOIR_CHANGE + else -> Action.CAREPORTAL + } + result.inserted.forEach { + uel.log(action, Sources.NSClient, + it.note ?: "", + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.TherapyEventType(it.type) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted TherapyEvent $it") + } + result.invalidated.forEach { + uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient, + it.note ?: "", + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.TherapyEventType(it.type) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated TherapyEvent $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId TherapyEvent $it") + } } - result.invalidated.forEach { - uel.log(Action.CAREPORTAL_REMOVED, Sources.NSClient, - it.note ?: "", - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.TherapyEventType(it.type) - ) - aapsLogger.debug(LTag.DATABASE, "Invalidated TherapyEvent $it") - } - result.updatedNsId.forEach { - aapsLogger.debug(LTag.DATABASE, "Updated nsId TherapyEvent $it") - } - } - } ?: aapsLogger.error("Error parsing TherapyEvent json $json") + } ?: aapsLogger.error("Error parsing TherapyEvent json $json") + } eventType == TherapyEvent.Type.COMBO_BOLUS.text -> - extendedBolusFromJson(json)?.let { extendedBolus -> - repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus, invalidateByNsOnly = false)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving extended bolus", it) - ret = Result.failure(workDataOf("Error" to it.toString())) - } - .blockingGet() - .also { result -> - result.inserted.forEach { - uel.log(Action.EXTENDED_BOLUS, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.Insulin(it.amount), - ValueWithUnit.UnitPerHour(it.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Inserted ExtendedBolus $it") + if (config.NSCLIENT) { + extendedBolusFromJson(json)?.let { extendedBolus -> + repository.runTransactionForResult(SyncNsExtendedBolusTransaction(extendedBolus, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving extended bolus", it) + ret = Result.failure(workDataOf("Error" to it.toString())) } - result.invalidated.forEach { - uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.Insulin(it.amount), - ValueWithUnit.UnitPerHour(it.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Invalidated ExtendedBolus $it") + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(Action.EXTENDED_BOLUS, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.Insulin(it.amount), + ValueWithUnit.UnitPerHour(it.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted ExtendedBolus $it") + } + result.invalidated.forEach { + uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.Insulin(it.amount), + ValueWithUnit.UnitPerHour(it.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated ExtendedBolus $it") + } + result.ended.forEach { + uel.log(Action.CANCEL_EXTENDED_BOLUS, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.Insulin(it.amount), + ValueWithUnit.UnitPerHour(it.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Updated ExtendedBolus $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId ExtendedBolus $it") + } } - result.ended.forEach { - uel.log(Action.CANCEL_EXTENDED_BOLUS, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.Insulin(it.amount), - ValueWithUnit.UnitPerHour(it.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Updated ExtendedBolus $it") - } - result.updatedNsId.forEach { - aapsLogger.debug(LTag.DATABASE, "Updated nsId ExtendedBolus $it") - } - } - } ?: aapsLogger.error("Error parsing ExtendedBolus json $json") + } ?: aapsLogger.error("Error parsing ExtendedBolus json $json") + } eventType == TherapyEvent.Type.TEMPORARY_BASAL.text -> - temporaryBasalFromJson(json)?.let { temporaryBasal -> - repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal, invalidateByNsOnly = false)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it) - ret = Result.failure(workDataOf("Error" to it.toString())) - } - .blockingGet() - .also { result -> - result.inserted.forEach { - uel.log(Action.TEMP_BASAL, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.UnitPerHour(it.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it") + if (config.NSCLIENT) { + temporaryBasalFromJson(json)?.let { temporaryBasal -> + repository.runTransactionForResult(SyncNsTemporaryBasalTransaction(temporaryBasal, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it) + ret = Result.failure(workDataOf("Error" to it.toString())) } - result.invalidated.forEach { - uel.log(Action.TEMP_BASAL_REMOVED, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.UnitPerHour(it.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryBasal $it") + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(Action.TEMP_BASAL, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.UnitPerHour(it.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it") + } + result.invalidated.forEach { + uel.log(Action.TEMP_BASAL_REMOVED, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.UnitPerHour(it.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryBasal $it") + } + result.ended.forEach { + uel.log(Action.CANCEL_TEMP_BASAL, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp), + ValueWithUnit.UnitPerHour(it.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) + ) + aapsLogger.debug(LTag.DATABASE, "Ended TemporaryBasal $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryBasal $it") + } } - result.ended.forEach { - uel.log(Action.CANCEL_TEMP_BASAL, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp), - ValueWithUnit.UnitPerHour(it.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(it.duration).toInt()) - ) - aapsLogger.debug(LTag.DATABASE, "Ended TemporaryBasal $it") - } - result.updatedNsId.forEach { - aapsLogger.debug(LTag.DATABASE, "Updated nsId TemporaryBasal $it") - } - } - } ?: aapsLogger.error("Error parsing TemporaryBasal json $json") + } ?: aapsLogger.error("Error parsing TemporaryBasal json $json") + } eventType == TherapyEvent.Type.PROFILE_SWITCH.text -> - profileSwitchFromJson(json, dateUtil)?.let { profileSwitch -> - repository.runTransactionForResult(SyncNsProfileSwitchTransaction(profileSwitch, invalidateByNsOnly = false)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving ProfileSwitch", it) - ret = Result.failure(workDataOf("Error" to it.toString())) - } - .blockingGet() - .also { result -> - result.inserted.forEach { - uel.log(Action.PROFILE_SWITCH, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp)) - aapsLogger.debug(LTag.DATABASE, "Inserted ProfileSwitch $it") + if (sp.getBoolean(R.string.key_ns_receive_profile_switch, false) && buildHelper.isEngineeringMode() || config.NSCLIENT) { + profileSwitchFromJson(json, dateUtil, activePlugin)?.let { profileSwitch -> + repository.runTransactionForResult(SyncNsProfileSwitchTransaction(profileSwitch, invalidateByNsOnly = false)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving ProfileSwitch", it) + ret = Result.failure(workDataOf("Error" to it.toString())) } - result.invalidated.forEach { - uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.NSClient, - ValueWithUnit.Timestamp(it.timestamp)) - aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") + .blockingGet() + .also { result -> + result.inserted.forEach { + uel.log(Action.PROFILE_SWITCH, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp)) + aapsLogger.debug(LTag.DATABASE, "Inserted ProfileSwitch $it") + } + result.invalidated.forEach { + uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.NSClient, + ValueWithUnit.Timestamp(it.timestamp)) + aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") + } + result.updatedNsId.forEach { + aapsLogger.debug(LTag.DATABASE, "Updated nsId ProfileSwitch $it") + } } - result.updatedNsId.forEach { - aapsLogger.debug(LTag.DATABASE, "Updated nsId ProfileSwitch $it") - } - } - } ?: aapsLogger.error("Error parsing TemporaryBasal json $json") + } ?: aapsLogger.error("Error parsing ProfileSwitch json $json") + } } - if (eventType == TherapyEvent.Type.ANNOUNCEMENT.text) { - val date = safeGetLong(json, "mills") - val now = System.currentTimeMillis() - val enteredBy = JsonHelper.safeGetString(json, "enteredBy", "") - val notes = JsonHelper.safeGetString(json, "notes", "") - if (date > now - 15 * 60 * 1000L && notes.isNotEmpty() - && enteredBy != sp.getString("careportal_enteredby", "AndroidAPS")) { - val defaultVal = config.NSCLIENT - if (sp.getBoolean(R.string.key_ns_announcements, defaultVal)) { - val announcement = Notification(Notification.NS_ANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60) - rxBus.send(EventNewNotification(announcement)) + if (sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || config.NSCLIENT) + if (eventType == TherapyEvent.Type.ANNOUNCEMENT.text) { + val date = safeGetLong(json, "mills") + val now = System.currentTimeMillis() + val enteredBy = JsonHelper.safeGetString(json, "enteredBy", "") + val notes = JsonHelper.safeGetString(json, "notes", "") + if (date > now - 15 * 60 * 1000L && notes.isNotEmpty() + && enteredBy != sp.getString("careportal_enteredby", "AndroidAPS")) { + val defaultVal = config.NSCLIENT + if (sp.getBoolean(R.string.key_ns_announcements, defaultVal)) { + val announcement = Notification(Notification.NS_ANNOUNCEMENT, notes, Notification.ANNOUNCEMENT, 60) + rxBus.send(EventNewNotification(announcement)) + } } } - } } nsClientPlugin.updateLatestDateReceivedIfNewer(latestDateInReceivedData) return ret diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.kt index d2e77a4f95..80b508766d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientFragment.kt @@ -12,14 +12,11 @@ import info.nightscout.androidaps.database.entities.UserEntry.Action import info.nightscout.androidaps.database.entities.UserEntry.Sources import info.nightscout.androidaps.databinding.NsClientFragmentBinding import info.nightscout.androidaps.interfaces.DataSyncSelector -import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI import info.nightscout.androidaps.utils.FabricPrivacy -import info.nightscout.androidaps.utils.HtmlHelper.fromHtml import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers @@ -33,7 +30,6 @@ class NSClientFragment : DaggerFragment() { @Inject lateinit var sp: SP @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var rxBus: RxBusWrapper - @Inject lateinit var uploadQueue: UploadQueueAdminInterface @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var dataSyncSelector: DataSyncSelector @@ -72,18 +68,6 @@ class NSClientFragment : DaggerFragment() { binding.restart.paintFlags = binding.restart.paintFlags or Paint.UNDERLINE_TEXT_FLAG binding.deliverNow.setOnClickListener { nsClientPlugin.resend("GUI") } binding.deliverNow.paintFlags = binding.deliverNow.paintFlags or Paint.UNDERLINE_TEXT_FLAG - binding.clearQueue.setOnClickListener { - context?.let { context -> - OKDialog.showConfirmation(context, resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.clearqueueconfirm), Runnable { - uel.log(Action.NS_QUEUE_CLEARED, Sources.NSClient) - uploadQueue.clearQueue() - updateGui() - }) - } - } - binding.clearQueue.paintFlags = binding.clearQueue.paintFlags or Paint.UNDERLINE_TEXT_FLAG - binding.showQueue.setOnClickListener { rxBus.send(EventNSClientNewLog("QUEUE", uploadQueue.textList())) } - binding.showQueue.paintFlags = binding.showQueue.paintFlags or Paint.UNDERLINE_TEXT_FLAG binding.fullSync.setOnClickListener { context?.let { context -> OKDialog.showConfirmation(context, resourceHelper.gs(R.string.nsclientinternal), resourceHelper.gs(R.string.full_sync), Runnable { @@ -116,7 +100,6 @@ class NSClientFragment : DaggerFragment() { binding.log.text = nsClientPlugin.textLog if (nsClientPlugin.autoscroll) binding.logScrollview.fullScroll(ScrollView.FOCUS_DOWN) binding.url.text = nsClientPlugin.url() - binding.queue.text = fromHtml(resourceHelper.gs(R.string.queue) + " " + uploadQueue.size() + "") binding.status.text = nsClientPlugin.status } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt index a769f2ec38..8c73fd908f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientMbgWorker.kt @@ -8,13 +8,13 @@ import dagger.android.HasAndroidInjector import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.transactions.SyncNsTherapyEventTransaction +import info.nightscout.androidaps.extensions.therapyEventFromNsMbg import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.general.nsclient.data.NSMbg import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.buildHelper.BuildHelper -import info.nightscout.androidaps.extensions.therapyEventFromNsMbg import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject @@ -33,7 +33,7 @@ class NSClientMbgWorker( override fun doWork(): Result { var ret = Result.success() - val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT + val acceptNSData = sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || config.NSCLIENT if (!acceptNSData) return ret val mbgArray = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java deleted file mode 100644 index ae28f50b36..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.java +++ /dev/null @@ -1,320 +0,0 @@ -package info.nightscout.androidaps.plugins.general.nsclient; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.text.Spanned; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.SwitchPreference; - -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.interfaces.Config; -import info.nightscout.androidaps.Constants; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventAppExit; -import info.nightscout.androidaps.events.EventChargingState; -import info.nightscout.androidaps.events.EventNetworkChange; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck; -import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientResend; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI; -import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService; -import info.nightscout.androidaps.utils.FabricPrivacy; -import info.nightscout.androidaps.utils.HtmlHelper; -import info.nightscout.androidaps.utils.ToastUtils; -import info.nightscout.androidaps.utils.buildHelper.BuildHelper; -import info.nightscout.androidaps.utils.resources.ResourceHelper; -import info.nightscout.androidaps.utils.rx.AapsSchedulers; -import info.nightscout.androidaps.utils.sharedPreferences.SP; -import io.reactivex.disposables.CompositeDisposable; - -@Singleton -public class NSClientPlugin extends PluginBase { - private final CompositeDisposable disposable = new CompositeDisposable(); - - private final AAPSLogger aapsLogger; - private final RxBusWrapper rxBus; - private final ResourceHelper resourceHelper; - private final Context context; - private final AapsSchedulers aapsSchedulers; - private final FabricPrivacy fabricPrivacy; - private final SP sp; - private final NsClientReceiverDelegate nsClientReceiverDelegate; - private final Config config; - private final BuildHelper buildHelper; - - public Handler handler; - - private final List listLog = new ArrayList<>(); - Spanned textLog = HtmlHelper.INSTANCE.fromHtml(""); - - public boolean paused; - boolean autoscroll; - - public String status = ""; - - public @Nullable NSClientService nsClientService = null; - - - @Inject - public NSClientPlugin( - HasAndroidInjector injector, - AAPSLogger aapsLogger, - AapsSchedulers aapsSchedulers, - RxBusWrapper rxBus, - ResourceHelper resourceHelper, - Context context, - FabricPrivacy fabricPrivacy, - SP sp, - NsClientReceiverDelegate nsClientReceiverDelegate, - Config config, - BuildHelper buildHelper - ) { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(NSClientFragment.class.getName()) - .pluginIcon(R.drawable.ic_nightscout_syncs) - .pluginName(R.string.nsclientinternal) - .shortName(R.string.nsclientinternal_shortname) - .preferencesId(R.xml.pref_nsclientinternal) - .description(R.string.description_ns_client), - aapsLogger, resourceHelper, injector - ); - - this.aapsLogger = aapsLogger; - this.aapsSchedulers = aapsSchedulers; - this.rxBus = rxBus; - this.resourceHelper = resourceHelper; - this.context = context; - this.fabricPrivacy = fabricPrivacy; - this.sp = sp; - this.nsClientReceiverDelegate = nsClientReceiverDelegate; - this.config = config; - this.buildHelper = buildHelper; - - if (config.getNSCLIENT()) { - getPluginDescription().alwaysEnabled(true).visibleByDefault(true); - } - if (handler == null) { - HandlerThread handlerThread = new HandlerThread(NSClientPlugin.class.getSimpleName() + "Handler"); - handlerThread.start(); - handler = new Handler(handlerThread.getLooper()); - } - - } - - public boolean isAllowed() { - return nsClientReceiverDelegate.allowed; - } - - - @Override - protected void onStart() { - paused = sp.getBoolean(R.string.key_nsclientinternal_paused, false); - autoscroll = sp.getBoolean(R.string.key_nsclientinternal_autoscroll, true); - - Intent intent = new Intent(context, NSClientService.class); - context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - super.onStart(); - - nsClientReceiverDelegate.grabReceiversState(); - disposable.add(rxBus - .toObservable(EventNSClientStatus.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - status = event.getStatus(resourceHelper); - rxBus.send(new EventNSClientUpdateGUI()); - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventNetworkChange.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventPreferenceChange.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventAppExit.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - if (nsClientService != null) { - context.unbindService(mConnection); - } - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventNSClientNewLog.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - addToLog(event); - aapsLogger.debug(LTag.NSCLIENT, event.getAction() + " " + event.getLogText()); - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventChargingState.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(nsClientReceiverDelegate::onStatusEvent, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventNSClientResend.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> resend(event.getReason()), fabricPrivacy::logException) - ); - } - - @Override - protected void onStop() { - context.getApplicationContext().unbindService(mConnection); - disposable.clear(); - super.onStop(); - } - - @Override - public void preprocessPreferences(@NonNull PreferenceFragmentCompat preferenceFragment) { - super.preprocessPreferences(preferenceFragment); - - if (config.getNSCLIENT()) { - SwitchPreference key_ns_uploadlocalprofile = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_uploadlocalprofile)); - if (key_ns_uploadlocalprofile != null) key_ns_uploadlocalprofile.setVisible(false); - SwitchPreference key_ns_autobackfill = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_autobackfill)); - if (key_ns_autobackfill != null) key_ns_autobackfill.setVisible(false); - SwitchPreference key_ns_create_announcements_from_errors = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_create_announcements_from_errors)); - if (key_ns_create_announcements_from_errors != null) - key_ns_create_announcements_from_errors.setVisible(false); - SwitchPreference key_ns_create_announcements_from_carbs_req = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_create_announcements_from_carbs_req)); - if (key_ns_create_announcements_from_carbs_req != null) - key_ns_create_announcements_from_carbs_req.setVisible(false); - SwitchPreference key_ns_upload_only = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_upload_only)); - if (key_ns_upload_only != null) { - key_ns_upload_only.setVisible(false); - key_ns_upload_only.setEnabled(false); - } - SwitchPreference key_ns_sync_use_absolute = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_sync_use_absolute)); - if (key_ns_sync_use_absolute != null) key_ns_sync_use_absolute.setVisible(false); - } else { - // APS or pumpControl mode - SwitchPreference key_ns_upload_only = preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_upload_only)); - if (key_ns_upload_only != null) - key_ns_upload_only.setVisible(buildHelper.isEngineeringMode()); - } - } - - private final ServiceConnection mConnection = new ServiceConnection() { - - public void onServiceDisconnected(ComponentName name) { - aapsLogger.debug(LTag.NSCLIENT, "Service is disconnected"); - nsClientService = null; - } - - public void onServiceConnected(ComponentName name, IBinder service) { - aapsLogger.debug(LTag.NSCLIENT, "Service is connected"); - NSClientService.LocalBinder mLocalBinder = (NSClientService.LocalBinder) service; - if (mLocalBinder != null) // is null when running in roboelectric - nsClientService = mLocalBinder.getServiceInstance(); - } - }; - - synchronized void clearLog() { - handler.post(() -> { - synchronized (listLog) { - listLog.clear(); - } - rxBus.send(new EventNSClientUpdateGUI()); - }); - } - - private synchronized void addToLog(final EventNSClientNewLog ev) { - handler.post(() -> { - synchronized (listLog) { - listLog.add(ev); - // remove the first line if log is too large - if (listLog.size() >= Constants.MAX_LOG_LINES) { - listLog.remove(0); - } - } - rxBus.send(new EventNSClientUpdateGUI()); - }); - } - - synchronized void updateLog() { - try { - StringBuilder newTextLog = new StringBuilder(); - synchronized (listLog) { - for (EventNSClientNewLog log : listLog) { - newTextLog.append(log.toPreparedHtml()); - } - } - textLog = HtmlHelper.INSTANCE.fromHtml(newTextLog.toString()); - } catch (OutOfMemoryError e) { - ToastUtils.showToastInUiThread(context, rxBus, "Out of memory!\nStop using this phone !!!", R.raw.error); - } - } - - void resend(String reason) { - if (nsClientService != null) - nsClientService.resend(reason); - } - - public void pause(boolean newState) { - sp.putBoolean(R.string.key_nsclientinternal_paused, newState); - paused = newState; - rxBus.send(new EventPreferenceChange(resourceHelper, R.string.key_nsclientinternal_paused)); - } - - public String url() { - return NSClientService.nsURL; - } - - public boolean hasWritePermission() { - return NSClientService.hasWriteAuth; - } - - public void handleClearAlarm(NSAlarm originalAlarm, long silenceTimeInMsec) { - - if (!isEnabled(PluginType.GENERAL)) { - return; - } - if (sp.getBoolean(R.string.key_ns_noupload, false)) { - aapsLogger.debug(LTag.NSCLIENT, "Upload disabled. Message dropped"); - return; - } - - AlarmAck ack = new AlarmAck(); - ack.level = originalAlarm.level(); - ack.group = originalAlarm.group(); - ack.silenceTime = silenceTimeInMsec; - - if (nsClientService != null) - nsClientService.sendAlarmAck(ack); - } - - public void updateLatestDateReceivedIfNewer(long latestReceived) { - if (nsClientService != null && latestReceived > nsClientService.latestDateInReceivedData) - nsClientService.latestDateInReceivedData = latestReceived; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.kt new file mode 100644 index 0000000000..54bc13f0bd --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientPlugin.kt @@ -0,0 +1,243 @@ +package info.nightscout.androidaps.plugins.general.nsclient + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.ServiceConnection +import android.os.Handler +import android.os.HandlerThread +import android.os.IBinder +import androidx.preference.PreferenceFragmentCompat +import androidx.preference.PreferenceScreen +import androidx.preference.SwitchPreference +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants +import info.nightscout.androidaps.R +import info.nightscout.androidaps.events.EventAppExit +import info.nightscout.androidaps.events.EventChargingState +import info.nightscout.androidaps.events.EventNetworkChange +import info.nightscout.androidaps.events.EventPreferenceChange +import info.nightscout.androidaps.interfaces.Config +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginDescription +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck +import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientResend +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI +import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.HtmlHelper.fromHtml +import info.nightscout.androidaps.utils.ToastUtils +import info.nightscout.androidaps.utils.buildHelper.BuildHelper +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class NSClientPlugin @Inject constructor( + injector: HasAndroidInjector, + aapsLogger: AAPSLogger, + private val aapsSchedulers: AapsSchedulers, + private val rxBus: RxBusWrapper, + resourceHelper: ResourceHelper, + private val context: Context, + private val fabricPrivacy: FabricPrivacy, + private val sp: SP, + private val nsClientReceiverDelegate: NsClientReceiverDelegate, + private val config: Config, + private val buildHelper: BuildHelper +) : PluginBase(PluginDescription() + .mainType(PluginType.GENERAL) + .fragmentClass(NSClientFragment::class.java.name) + .pluginIcon(R.drawable.ic_nightscout_syncs) + .pluginName(R.string.nsclientinternal) + .shortName(R.string.nsclientinternal_shortname) + .preferencesId(R.xml.pref_nsclientinternal) + .description(R.string.description_ns_client), + aapsLogger, resourceHelper, injector +) { + + private val disposable = CompositeDisposable() + var handler: Handler? = null + private val listLog: MutableList = ArrayList() + var textLog = fromHtml("") + var paused = false + var autoscroll = false + var status = "" + var nsClientService: NSClientService? = null + val isAllowed: Boolean + get() = nsClientReceiverDelegate.allowed + + init { + if (config.NSCLIENT) { + pluginDescription.alwaysEnabled(true).visibleByDefault(true) + } + if (handler == null) { + val handlerThread = HandlerThread(NSClientPlugin::class.java.simpleName + "Handler") + handlerThread.start() + handler = Handler(handlerThread.looper) + } + } + + override fun onStart() { + paused = sp.getBoolean(R.string.key_nsclientinternal_paused, false) + autoscroll = sp.getBoolean(R.string.key_nsclientinternal_autoscroll, true) + val intent = Intent(context, NSClientService::class.java) + context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE) + super.onStart() + nsClientReceiverDelegate.grabReceiversState() + disposable.add(rxBus + .toObservable(EventNSClientStatus::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ event: EventNSClientStatus -> + status = event.getStatus(resourceHelper) + rxBus.send(EventNSClientUpdateGUI()) + }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventNetworkChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventPreferenceChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventAppExit::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ if (nsClientService != null) context.unbindService(mConnection) }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventNSClientNewLog::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ event: EventNSClientNewLog -> + addToLog(event) + aapsLogger.debug(LTag.NSCLIENT, event.action + " " + event.logText) + }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventChargingState::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ ev -> nsClientReceiverDelegate.onStatusEvent(ev) }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventNSClientResend::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ event -> resend(event.reason) }, fabricPrivacy::logException) + ) + } + + override fun onStop() { + context.applicationContext.unbindService(mConnection) + disposable.clear() + super.onStop() + } + + override fun preprocessPreferences(preferenceFragment: PreferenceFragmentCompat) { + super.preprocessPreferences(preferenceFragment) + if (config.NSCLIENT) { + preferenceFragment.findPreference(resourceHelper.gs(R.string.ns_sync_options))?.isVisible = false + + preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_create_announcements_from_errors))?.isVisible = false + preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_create_announcements_from_carbs_req))?.isVisible = false + preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_sync_use_absolute))?.isVisible = false + } else { + // APS or pumpControl mode + preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_receive_profile_switch))?.isVisible = buildHelper.isEngineeringMode() + preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_receive_insulin))?.isVisible = buildHelper.isEngineeringMode() + preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_receive_carbs))?.isVisible = buildHelper.isEngineeringMode() + preferenceFragment.findPreference(resourceHelper.gs(R.string.key_ns_receive_temp_target))?.isVisible = buildHelper.isEngineeringMode() + } + } + + private val mConnection: ServiceConnection = object : ServiceConnection { + override fun onServiceDisconnected(name: ComponentName) { + aapsLogger.debug(LTag.NSCLIENT, "Service is disconnected") + nsClientService = null + } + + override fun onServiceConnected(name: ComponentName, service: IBinder) { + aapsLogger.debug(LTag.NSCLIENT, "Service is connected") + val mLocalBinder = service as NSClientService.LocalBinder + @Suppress("UNNECESSARY_SAFE_CALL") + nsClientService = mLocalBinder?.serviceInstance // is null when running in roboelectric + } + } + + @Synchronized fun clearLog() { + handler?.post { + synchronized(listLog) { listLog.clear() } + rxBus.send(EventNSClientUpdateGUI()) + } + } + + @Synchronized private fun addToLog(ev: EventNSClientNewLog) { + handler?.post { + synchronized(listLog) { + listLog.add(ev) + // remove the first line if log is too large + if (listLog.size >= Constants.MAX_LOG_LINES) { + listLog.removeAt(0) + } + } + rxBus.send(EventNSClientUpdateGUI()) + } + } + + @Synchronized fun updateLog() { + try { + val newTextLog = StringBuilder() + synchronized(listLog) { + for (log in listLog) { + newTextLog.append(log.toPreparedHtml()) + } + } + textLog = fromHtml(newTextLog.toString()) + } catch (e: OutOfMemoryError) { + ToastUtils.showToastInUiThread(context, rxBus, "Out of memory!\nStop using this phone !!!", R.raw.error) + } + } + + fun resend(reason: String) { + nsClientService?.resend(reason) + } + + fun pause(newState: Boolean) { + sp.putBoolean(R.string.key_nsclientinternal_paused, newState) + paused = newState + rxBus.send(EventPreferenceChange(resourceHelper, R.string.key_nsclientinternal_paused)) + } + + fun url(): String = nsClientService?.nsURL ?: "" + fun hasWritePermission(): Boolean = nsClientService?.hasWriteAuth ?: false + + fun handleClearAlarm(originalAlarm: NSAlarm, silenceTimeInMilliseconds: Long) { + if (!isEnabled(PluginType.GENERAL)) return + if (!sp.getBoolean(R.string.key_ns_upload, false)) { + aapsLogger.debug(LTag.NSCLIENT, "Upload disabled. Message dropped") + return + } + nsClientService?.sendAlarmAck( + AlarmAck().also { ack -> + ack.level = originalAlarm.level() + ack.group = originalAlarm.group() + ack.silenceTime = silenceTimeInMilliseconds + }) + } + + fun updateLatestDateReceivedIfNewer(latestReceived: Long) { + nsClientService?.let { if (latestReceived > it.latestDateInReceivedData) it.latestDateInReceivedData = latestReceived } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt index a2423de9ce..ee8dac6c47 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NSClientRemoveWorker.kt @@ -42,8 +42,9 @@ class NSClientRemoveWorker( @Inject lateinit var uel: UserEntryLogger override fun doWork(): Result { - val acceptNSData = !sp.getBoolean(R.string.key_ns_upload_only, true) && buildHelper.isEngineeringMode() || config.NSCLIENT - if (!acceptNSData) return Result.success() + // Do not accept removed data over WS. Only invalidated trough NSClient + @Suppress("ConstantConditionIf") + if (true) return Result.success() var ret = Result.success() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java deleted file mode 100644 index d54f48d511..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.java +++ /dev/null @@ -1,117 +0,0 @@ -package info.nightscout.androidaps.plugins.general.nsclient; - -import java.util.Arrays; - -import javax.inject.Inject; -import javax.inject.Singleton; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventChargingState; -import info.nightscout.androidaps.events.EventNetworkChange; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.receivers.ReceiverStatusStore; -import info.nightscout.androidaps.utils.resources.ResourceHelper; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - -@Singleton -class NsClientReceiverDelegate { - - private boolean allowedChargingState = true; - private boolean allowedNetworkState = true; - boolean allowed = true; - - private RxBusWrapper rxBus; - private ResourceHelper resourceHelper; - private SP sp; - private ReceiverStatusStore receiverStatusStore; - - @Inject - public NsClientReceiverDelegate( - RxBusWrapper rxBus, - ResourceHelper resourceHelper, - SP sp, - ReceiverStatusStore receiverStatusStore - ) { - this.rxBus = rxBus; - this.resourceHelper = resourceHelper; - this.sp = sp; - this.receiverStatusStore = receiverStatusStore; - } - - void grabReceiversState() { - - receiverStatusStore.updateNetworkStatus(); - } - - void onStatusEvent(EventPreferenceChange ev) { - if (ev.isChanged(resourceHelper, R.string.key_ns_wifionly) || - ev.isChanged(resourceHelper, R.string.key_ns_wifi_ssids) || - ev.isChanged(resourceHelper, R.string.key_ns_allowroaming) - ) { - receiverStatusStore.updateNetworkStatus(); - onStatusEvent(receiverStatusStore.getLastNetworkEvent()); - } else if (ev.isChanged(resourceHelper, R.string.key_ns_chargingonly)) { - receiverStatusStore.broadcastChargingState(); - } - } - - void onStatusEvent(final EventChargingState ev) { - boolean newChargingState = calculateStatus(ev); - - if (newChargingState != allowedChargingState) { - allowedChargingState = newChargingState; - processStateChange(); - } - } - - void onStatusEvent(final EventNetworkChange ev) { - boolean newNetworkState = calculateStatus(ev); - - if (newNetworkState != allowedNetworkState) { - allowedNetworkState = newNetworkState; - processStateChange(); - } - } - - private void processStateChange() { - boolean newAllowedState = allowedChargingState && allowedNetworkState; - if (newAllowedState != allowed) { - allowed = newAllowedState; - rxBus.send(new EventPreferenceChange(resourceHelper.gs(R.string.key_nsclientinternal_paused))); - } - } - - boolean calculateStatus(final EventChargingState ev) { - boolean chargingOnly = sp.getBoolean(R.string.key_ns_chargingonly, false); - boolean newAllowedState = true; - - if (!ev.isCharging() && chargingOnly) { - newAllowedState = false; - } - - return newAllowedState; - } - - boolean calculateStatus(final EventNetworkChange ev) { - boolean wifiOnly = sp.getBoolean(R.string.key_ns_wifionly, false); - String allowedSSIDstring = sp.getString(R.string.key_ns_wifi_ssids, ""); - String[] allowedSSIDs = allowedSSIDstring.split(";"); - if (allowedSSIDstring.isEmpty()) allowedSSIDs = new String[0]; - boolean allowRoaming = sp.getBoolean(R.string.key_ns_allowroaming, true); - - boolean newAllowedState = true; - - if (ev.getWifiConnected()) { - if (allowedSSIDs.length != 0 && !Arrays.asList(allowedSSIDs).contains(ev.getSsid())) { - newAllowedState = false; - } - } else { - if ((!allowRoaming && ev.getRoaming()) || wifiOnly) { - newAllowedState = false; - } - } - - return newAllowedState; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.kt new file mode 100644 index 0000000000..fa67b25cda --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/NsClientReceiverDelegate.kt @@ -0,0 +1,91 @@ +package info.nightscout.androidaps.plugins.general.nsclient + +import info.nightscout.androidaps.R +import info.nightscout.androidaps.events.EventChargingState +import info.nightscout.androidaps.events.EventNetworkChange +import info.nightscout.androidaps.events.EventPreferenceChange +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.receivers.ReceiverStatusStore +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class NsClientReceiverDelegate @Inject constructor( + private val rxBus: RxBusWrapper, + private val resourceHelper: ResourceHelper, + private val sp: SP, + private val receiverStatusStore: ReceiverStatusStore +) { + + private var allowedChargingState = true + private var allowedNetworkState = true + var allowed = true + + fun grabReceiversState() { + receiverStatusStore.updateNetworkStatus() + } + + fun onStatusEvent(ev: EventPreferenceChange) { + if (ev.isChanged(resourceHelper, R.string.key_ns_wifionly) || + ev.isChanged(resourceHelper, R.string.key_ns_wifi_ssids) || + ev.isChanged(resourceHelper, R.string.key_ns_allowroaming)) { + receiverStatusStore.updateNetworkStatus() + onStatusEvent(receiverStatusStore.lastNetworkEvent) + } else if (ev.isChanged(resourceHelper, R.string.key_ns_chargingonly)) { + receiverStatusStore.broadcastChargingState() + } + } + + fun onStatusEvent(ev: EventChargingState) { + val newChargingState = calculateStatus(ev) + if (newChargingState != allowedChargingState) { + allowedChargingState = newChargingState + processStateChange() + } + } + + fun onStatusEvent(ev: EventNetworkChange?) { + val newNetworkState = calculateStatus(ev) + if (newNetworkState != allowedNetworkState) { + allowedNetworkState = newNetworkState + processStateChange() + } + } + + private fun processStateChange() { + val newAllowedState = allowedChargingState && allowedNetworkState + if (newAllowedState != allowed) { + allowed = newAllowedState + rxBus.send(EventPreferenceChange(resourceHelper.gs(R.string.key_nsclientinternal_paused))) + } + } + + fun calculateStatus(ev: EventChargingState): Boolean { + val chargingOnly = sp.getBoolean(R.string.key_ns_chargingonly, false) + var newAllowedState = true + if (!ev.isCharging && chargingOnly) { + newAllowedState = false + } + return newAllowedState + } + + fun calculateStatus(ev: EventNetworkChange?): Boolean { + val wifiOnly = sp.getBoolean(R.string.key_ns_wifionly, false) + val allowedSsidString = sp.getString(R.string.key_ns_wifi_ssids, "") + val allowedSSIDs: List = if (allowedSsidString.isEmpty()) List(0) { "" } else allowedSsidString.split(";") + val allowRoaming = sp.getBoolean(R.string.key_ns_allowroaming, true) + var newAllowedState = true + if (ev?.wifiConnected == true) { + if (allowedSSIDs.isNotEmpty() && !allowedSSIDs.contains(ev.ssid)) { + newAllowedState = false + } + } else { + if (!allowRoaming && ev?.roaming == true || wifiOnly) { + newAllowedState = false + } + } + return newAllowedState + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/UploadQueue.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/UploadQueue.java deleted file mode 100644 index f7669b182d..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/UploadQueue.java +++ /dev/null @@ -1,124 +0,0 @@ -package info.nightscout.androidaps.plugins.general.nsclient; - -import android.content.Context; -import android.content.Intent; -import android.os.SystemClock; - -import com.j256.ormlite.dao.CloseableIterator; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.sql.SQLException; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.DbRequest; -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; -import info.nightscout.androidaps.interfaces.UploadQueueAdminInterface; -import info.nightscout.androidaps.interfaces.UploadQueueInterface; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientResend; -import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - -/** - * Created by mike on 21.02.2016. - */ -public class UploadQueue implements UploadQueueAdminInterface { - private final AAPSLogger aapsLogger; - private final DatabaseHelperInterface databaseHelper; - private final Context context; - private final SP sp; - private final RxBusWrapper rxBus; - - public UploadQueue( - AAPSLogger aapsLogger, - DatabaseHelperInterface databaseHelper, - Context context, - SP sp, - RxBusWrapper rxBus - ) { - this.aapsLogger = aapsLogger; - this.databaseHelper = databaseHelper; - this.context = context; - this.sp = sp; - this.rxBus = rxBus; - } - - public String status() { - return "QUEUE: " + databaseHelper.size(DatabaseHelper.DATABASE_DBREQUESTS); - } - - @Override - public long size() { - return databaseHelper.size(DatabaseHelper.DATABASE_DBREQUESTS); - } - - private void startService() { - if (NSClientService.handler == null) { - context.startService(new Intent(context, NSClientService.class)); - SystemClock.sleep(2000); - } - } - - public void add(final DbRequest dbr) { - if (sp.getBoolean(R.string.key_ns_noupload, false)) return; - aapsLogger.debug(LTag.NSCLIENT, "Adding to queue: " + dbr.log()); - try { - databaseHelper.create(dbr); - } catch (Exception e) { - aapsLogger.error("Unhandled exception", e); - } - rxBus.send(new EventNSClientResend("newdata")); - } - - @Override public void clearQueue() { - startService(); - if (NSClientService.handler != null) { - NSClientService.handler.post(() -> { - aapsLogger.debug(LTag.NSCLIENT, "ClearQueue"); - databaseHelper.deleteAllDbRequests(); - aapsLogger.debug(LTag.NSCLIENT, status()); - }); - } - } - - @Override - public void removeByMongoId(final String action, final String _id) { - if (_id == null || _id.equals("")) - return; - startService(); - if (NSClientService.handler != null) { - NSClientService.handler.post(() -> { - databaseHelper.deleteDbRequestbyMongoId(action, _id); - aapsLogger.debug(LTag.NSCLIENT, "Removing " + _id + " from UploadQueue. " + status()); - }); - } - } - - @Override public String textList() { - String result = ""; - CloseableIterator iterator; - try { - iterator = databaseHelper.getDbRequestIterator(); - try { - while (iterator.hasNext()) { - DbRequest dbr = iterator.next(); - result += "
"; - result += dbr.action.toUpperCase() + " "; - result += dbr.collection + ": "; - result += dbr.data; - } - } finally { - iterator.close(); - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - return result; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java deleted file mode 100644 index 078d56943e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.java +++ /dev/null @@ -1,913 +0,0 @@ -package info.nightscout.androidaps.plugins.general.nsclient.services; - -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.Bundle; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.PowerManager; -import android.os.SystemClock; - -import androidx.work.OneTimeWorkRequest; - -import com.google.common.base.Charsets; -import com.google.common.hash.Hashing; -import com.j256.ormlite.dao.CloseableIterator; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import dagger.android.DaggerService; -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.interfaces.Config; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.database.AppRepository; -import info.nightscout.androidaps.db.DbRequest; -import info.nightscout.androidaps.events.EventAppExit; -import info.nightscout.androidaps.events.EventConfigBuilderChange; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.interfaces.DataSyncSelector; -import info.nightscout.androidaps.interfaces.DatabaseHelperInterface; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.UploadQueueInterface; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.general.food.FoodPlugin; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddAckWorker; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientAddUpdateWorker; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientMbgWorker; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientRemoveWorker; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientUpdateRemoveAckWorker; -import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck; -import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck; -import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck; -import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck; -import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm; -import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; -import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus; -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI; -import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; -import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; -import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction; -import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin; -import info.nightscout.androidaps.plugins.source.NSClientSourcePlugin; -import info.nightscout.androidaps.receivers.DataWorker; -import info.nightscout.androidaps.services.Intents; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.FabricPrivacy; -import info.nightscout.androidaps.utils.JsonHelper; -import info.nightscout.androidaps.utils.T; -import info.nightscout.androidaps.utils.buildHelper.BuildHelper; -import info.nightscout.androidaps.utils.resources.ResourceHelper; -import info.nightscout.androidaps.utils.rx.AapsSchedulers; -import info.nightscout.androidaps.utils.sharedPreferences.SP; -import io.reactivex.disposables.CompositeDisposable; -import io.socket.client.IO; -import io.socket.client.Socket; -import io.socket.emitter.Emitter; - -public class NSClientService extends DaggerService { - @Inject HasAndroidInjector injector; - @Inject AAPSLogger aapsLogger; - @Inject AapsSchedulers aapsSchedulers; - @Inject NSSettingsStatus nsSettingsStatus; - @Inject NSDeviceStatus nsDeviceStatus; - @Inject DatabaseHelperInterface databaseHelper; - @Inject RxBusWrapper rxBus; - @Inject ResourceHelper resourceHelper; - @Inject SP sp; - @Inject FabricPrivacy fabricPrivacy; - @Inject NSClientPlugin nsClientPlugin; - @Inject BuildHelper buildHelper; - @Inject Config config; - @Inject DateUtil dateUtil; - @Inject UploadQueueInterface uploadQueue; - @Inject DataWorker dataWorker; - @Inject DataSyncSelector dataSyncSelector; - @Inject AppRepository repository; - - private final CompositeDisposable disposable = new CompositeDisposable(); - - static public PowerManager.WakeLock mWakeLock; - private final IBinder mBinder = new NSClientService.LocalBinder(); - - static public Handler handler; - - public static Socket mSocket; - public static boolean isConnected = false; - public static boolean hasWriteAuth = false; - private static Integer dataCounter = 0; - private static Integer connectCounter = 0; - - - private boolean nsEnabled = false; - static public String nsURL = ""; - private String nsAPISecret = ""; - private String nsDevice = ""; - private final Integer nsHours = 48; - - public long lastResendTime = 0; - public long lastAckTime = 0; - - public long latestDateInReceivedData = 0; - - private String nsAPIhashCode = ""; - - private final ArrayList reconnections = new ArrayList<>(); - private final int WATCHDOG_INTERVAL_MINUTES = 2; - private final int WATCHDOG_RECONNECT_IN = 15; - private final int WATCHDOG_MAX_CONNECTIONS = 5; - - public NSClientService() { - super(); - if (handler == null) { - HandlerThread handlerThread = new HandlerThread(NSClientService.class.getSimpleName() + "Handler"); - handlerThread.start(); - handler = new Handler(handlerThread.getLooper()); - } - } - - @Override - public void onCreate() { - super.onCreate(); - PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); - mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:NSClientService"); - mWakeLock.acquire(); - - initialize(); - - disposable.add(rxBus - .toObservable(EventConfigBuilderChange.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - if (nsEnabled != nsClientPlugin.isEnabled(PluginType.GENERAL)) { - latestDateInReceivedData = 0; - destroy(); - initialize(); - } - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventPreferenceChange.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - if (event.isChanged(resourceHelper, R.string.key_nsclientinternal_url) || - event.isChanged(resourceHelper, R.string.key_nsclientinternal_api_secret) || - event.isChanged(resourceHelper, R.string.key_nsclientinternal_paused) - ) { - latestDateInReceivedData = 0; - destroy(); - initialize(); - } - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventAppExit.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - aapsLogger.debug(LTag.NSCLIENT, "EventAppExit received"); - destroy(); - stopSelf(); - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(EventNSClientRestart.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(event -> { - latestDateInReceivedData = 0; - restart(); - }, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(NSAuthAck.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(this::processAuthAck, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(NSUpdateAck.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(this::processUpdateAck, fabricPrivacy::logException) - ); - disposable.add(rxBus - .toObservable(NSAddAck.class) - .observeOn(aapsSchedulers.getIo()) - .subscribe(this::processAddAck, fabricPrivacy::logException) - ); - } - - @Override - public void onDestroy() { - super.onDestroy(); - disposable.clear(); - if (mWakeLock.isHeld()) mWakeLock.release(); - } - - public void processAddAck(NSAddAck ack) { - lastAckTime = dateUtil.now(); - dataWorker.enqueue( - new OneTimeWorkRequest.Builder(NSClientAddAckWorker.class) - .setInputData(dataWorker.storeInputData(ack, null)) - .build()); - } - - public void processUpdateAck(NSUpdateAck ack) { - lastAckTime = dateUtil.now(); - dataWorker.enqueue( - new OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker.class) - .setInputData(dataWorker.storeInputData(ack, null)) - .build()); - } - - public void processAuthAck(NSAuthAck ack) { - String connectionStatus = "Authenticated ("; - if (ack.read) connectionStatus += "R"; - if (ack.write) connectionStatus += "W"; - if (ack.write_treatment) connectionStatus += "T"; - connectionStatus += ')'; - isConnected = true; - hasWriteAuth = ack.write && ack.write_treatment; - rxBus.send(new EventNSClientStatus(connectionStatus)); - rxBus.send(new EventNSClientNewLog("AUTH", connectionStatus)); - if (!ack.write) { - rxBus.send(new EventNSClientNewLog("ERROR", "Write permission not granted !!!!")); - } - if (!ack.write_treatment) { - rxBus.send(new EventNSClientNewLog("ERROR", "Write treatment permission not granted !!!!")); - } - if (!hasWriteAuth) { - Notification noperm = new Notification(Notification.NSCLIENT_NO_WRITE_PERMISSION, resourceHelper.gs(R.string.nowritepermission), Notification.URGENT); - rxBus.send(new EventNewNotification(noperm)); - } else { - rxBus.send(new EventDismissNotification(Notification.NSCLIENT_NO_WRITE_PERMISSION)); - } - } - - public class LocalBinder extends Binder { - public NSClientService getServiceInstance() { - return NSClientService.this; - } - - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - - return START_STICKY; - } - - @SuppressWarnings("deprecation") - public void initialize() { - dataCounter = 0; - - readPreferences(); - - if (!nsAPISecret.equals("")) - nsAPIhashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString(); - - rxBus.send(new EventNSClientStatus("Initializing")); - if (!nsClientPlugin.isAllowed()) { - rxBus.send(new EventNSClientNewLog("NSCLIENT", "not allowed")); - rxBus.send(new EventNSClientStatus("Not allowed")); - } else if (nsClientPlugin.paused) { - rxBus.send(new EventNSClientNewLog("NSCLIENT", "paused")); - rxBus.send(new EventNSClientStatus("Paused")); - } else if (!nsEnabled) { - rxBus.send(new EventNSClientNewLog("NSCLIENT", "disabled")); - rxBus.send(new EventNSClientStatus("Disabled")); - } else if (!nsURL.equals("") && (buildHelper.isEngineeringMode() || nsURL.toLowerCase().startsWith("https://"))) { - try { - rxBus.send(new EventNSClientStatus("Connecting ...")); - IO.Options opt = new IO.Options(); - opt.forceNew = true; - opt.reconnection = true; - mSocket = IO.socket(nsURL, opt); - mSocket.on(Socket.EVENT_CONNECT, onConnect); - mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect); - mSocket.on(Socket.EVENT_ERROR, onError); - mSocket.on(Socket.EVENT_CONNECT_ERROR, onError); - mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onError); - mSocket.on(Socket.EVENT_PING, onPing); - rxBus.send(new EventNSClientNewLog("NSCLIENT", "do connect")); - mSocket.connect(); - mSocket.on("dataUpdate", onDataUpdate); - mSocket.on("announcement", onAnnouncement); - mSocket.on("alarm", onAlarm); - mSocket.on("urgent_alarm", onUrgentAlarm); - mSocket.on("clear_alarm", onClearAlarm); - } catch (URISyntaxException | RuntimeException e) { - rxBus.send(new EventNSClientNewLog("NSCLIENT", "Wrong URL syntax")); - rxBus.send(new EventNSClientStatus("Wrong URL syntax")); - } - } else if (nsURL.toLowerCase().startsWith("http://")) { - rxBus.send(new EventNSClientNewLog("NSCLIENT", "NS URL not encrypted")); - rxBus.send(new EventNSClientStatus("Not encrypted")); - } else { - rxBus.send(new EventNSClientNewLog("NSCLIENT", "No NS URL specified")); - rxBus.send(new EventNSClientStatus("Not configured")); - } - } - - private final Emitter.Listener onConnect = new Emitter.Listener() { - @Override - public void call(Object... args) { - connectCounter++; - String socketId = mSocket != null ? mSocket.id() : "NULL"; - rxBus.send(new EventNSClientNewLog("NSCLIENT", "connect #" + connectCounter + " event. ID: " + socketId)); - if (mSocket != null) - sendAuthMessage(new NSAuthAck(rxBus)); - watchdog(); - } - }; - - void watchdog() { - synchronized (reconnections) { - long now = dateUtil.now(); - reconnections.add(now); - for (int i = 0; i < reconnections.size(); i++) { - Long r = reconnections.get(i); - if (r < now - T.mins(WATCHDOG_INTERVAL_MINUTES).msecs()) { - reconnections.remove(r); - } - } - rxBus.send(new EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " mins: " + reconnections.size() + "/" + WATCHDOG_MAX_CONNECTIONS)); - if (reconnections.size() >= WATCHDOG_MAX_CONNECTIONS) { - Notification n = new Notification(Notification.NS_MALFUNCTION, resourceHelper.gs(R.string.nsmalfunction), Notification.URGENT); - rxBus.send(new EventNewNotification(n)); - rxBus.send(new EventNSClientNewLog("WATCHDOG", "pausing for " + WATCHDOG_RECONNECT_IN + " mins")); - nsClientPlugin.pause(true); - rxBus.send(new EventNSClientUpdateGUI()); - new Thread(() -> { - SystemClock.sleep(T.mins(WATCHDOG_RECONNECT_IN).msecs()); - rxBus.send(new EventNSClientNewLog("WATCHDOG", "reenabling NSClient")); - nsClientPlugin.pause(false); - }).start(); - } - } - } - - private final Emitter.Listener onDisconnect = new Emitter.Listener() { - @Override - public void call(Object... args) { - aapsLogger.debug(LTag.NSCLIENT, "disconnect reason: {}", args); - rxBus.send(new EventNSClientNewLog("NSCLIENT", "disconnect event")); - } - }; - - public synchronized void destroy() { - if (mSocket != null) { - mSocket.off(Socket.EVENT_CONNECT); - mSocket.off(Socket.EVENT_DISCONNECT); - mSocket.off(Socket.EVENT_PING); - mSocket.off("dataUpdate"); - mSocket.off("announcement"); - mSocket.off("alarm"); - mSocket.off("urgent_alarm"); - mSocket.off("clear_alarm"); - - rxBus.send(new EventNSClientNewLog("NSCLIENT", "destroy")); - isConnected = false; - hasWriteAuth = false; - mSocket.disconnect(); - mSocket = null; - } - } - - - public void sendAuthMessage(NSAuthAck ack) { - JSONObject authMessage = new JSONObject(); - try { - authMessage.put("client", "Android_" + nsDevice); - authMessage.put("history", nsHours); - authMessage.put("status", true); // receive status - authMessage.put("from", latestDateInReceivedData); // send data newer than - authMessage.put("secret", nsAPIhashCode); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - return; - } - rxBus.send(new EventNSClientNewLog("AUTH", "requesting auth")); - if (mSocket != null) - mSocket.emit("authorize", authMessage, ack); - } - - public void readPreferences() { - nsEnabled = nsClientPlugin.isEnabled(PluginType.GENERAL); - nsURL = sp.getString(R.string.key_nsclientinternal_url, ""); - nsAPISecret = sp.getString(R.string.key_nsclientinternal_api_secret, ""); - nsDevice = sp.getString("careportal_enteredby", ""); - } - - private final Emitter.Listener onError = new Emitter.Listener() { - @Override - public void call(final Object... args) { - String msg = "Unknown Error"; - if (args.length > 0 && args[0] != null) { - msg = args[0].toString(); - } - rxBus.send(new EventNSClientNewLog("ERROR", msg)); - } - }; - - private final Emitter.Listener onPing = new Emitter.Listener() { - @Override - public void call(final Object... args) { - rxBus.send(new EventNSClientNewLog("PING", "received")); - // send data if there is something waiting - resend("Ping received"); - } - }; - - private final Emitter.Listener onAnnouncement = new Emitter.Listener() { - /* - { - "level":0, - "title":"Announcement", - "message":"test", - "plugin":{"name":"treatmentnotify","label":"Treatment Notifications","pluginType":"notification","enabled":true}, - "group":"Announcement", - "isAnnouncement":true, - "key":"9ac46ad9a1dcda79dd87dae418fce0e7955c68da" - } - */ - @Override - public void call(final Object... args) { - JSONObject data; - try { - data = (JSONObject) args[0]; - handleAnnouncement(data); - } catch (Exception e) { - aapsLogger.error("Unhandled exception", e); - } - } - }; - - private final Emitter.Listener onAlarm = new Emitter.Listener() { - /* - { - "level":1, - "title":"Warning HIGH", - "message":"BG Now: 5 -0.2 → mmol\/L\nRaw BG: 4.8 mmol\/L Čistý\nBG 15m: 4.8 mmol\/L\nIOB: -0.02U\nCOB: 0g", - "eventName":"high", - "plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, - "pushoverSound":"climb", - "debug":{"lastSGV":5,"thresholds":{"bgHigh":180,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, - "group":"default", - "key":"simplealarms_1" - } - */ - @Override - public void call(final Object... args) { - JSONObject data; - try { - data = (JSONObject) args[0]; - handleAlarm(data); - } catch (Exception e) { - aapsLogger.error("Unhandled exception", e); - } - } - }; - - private final Emitter.Listener onUrgentAlarm = args -> { - JSONObject data; - try { - data = (JSONObject) args[0]; - handleUrgentAlarm(data); - } catch (Exception e) { - aapsLogger.error("Unhandled exception", e); - } - }; - - private final Emitter.Listener onClearAlarm = new Emitter.Listener() { - /* - { - "clear":true, - "title":"All Clear", - "message":"default - Urgent was ack'd", - "group":"default" - } - */ - @Override - public void call(final Object... args) { - JSONObject data; - try { - data = (JSONObject) args[0]; - rxBus.send(new EventNSClientNewLog("CLEARALARM", "received")); - rxBus.send(new EventDismissNotification(Notification.NS_ALARM)); - rxBus.send(new EventDismissNotification(Notification.NS_URGENT_ALARM)); - aapsLogger.debug(LTag.NSCLIENT, data.toString()); - } catch (Exception e) { - aapsLogger.error("Unhandled exception", e); - } - } - }; - - private final Emitter.Listener onDataUpdate = new Emitter.Listener() { - @Override - public void call(final Object... args) { - NSClientService.handler.post(() -> { - PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - "AndroidAPS:NSClientService_onDataUpdate"); - wakeLock.acquire(); - try { - - JSONObject data = (JSONObject) args[0]; - boolean broadcastProfile = false; - try { - // delta means only increment/changes are comming - boolean isDelta = data.has("delta"); - boolean isFull = !isDelta; - rxBus.send(new EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + (isDelta ? " delta" : " full"))); - - if (data.has("status")) { - JSONObject status = data.getJSONObject("status"); - nsSettingsStatus.handleNewData(status); - } else if (!isDelta) { - rxBus.send(new EventNSClientNewLog("ERROR", "Unsupported Nightscout version !!!!")); - } - - if (data.has("profiles")) { - JSONArray profiles = data.getJSONArray("profiles"); - if (profiles.length() > 0) { - // take the newest - JSONObject profileStoreJson = (JSONObject) profiles.get(profiles.length() - 1); - rxBus.send(new EventNSClientNewLog("PROFILE", "profile received")); - dataWorker.enqueue( - new OneTimeWorkRequest.Builder(NSProfilePlugin.NSProfileWorker.class) - .setInputData(dataWorker.storeInputData(profileStoreJson, null)) - .build()); - - if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { - Bundle bundle = new Bundle(); - bundle.putString("profile", profileStoreJson.toString()); - bundle.putBoolean("delta", isDelta); - Intent intent = new Intent(Intents.ACTION_NEW_PROFILE); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - sendBroadcast(intent); - } - } - } - - if (data.has("treatments")) { - JSONArray treatments = data.getJSONArray("treatments"); - JSONArray removedTreatments = new JSONArray(); - JSONArray addedOrUpdatedTreatments = new JSONArray(); - if (treatments.length() > 0) - rxBus.send(new EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments")); - for (Integer index = 0; index < treatments.length(); index++) { - JSONObject jsonTreatment = treatments.getJSONObject(index); - String action = JsonHelper.safeGetStringAllowNull(jsonTreatment, "action", null); - long mills = JsonHelper.safeGetLong(jsonTreatment, "mills"); - - if (action == null) addedOrUpdatedTreatments.put(jsonTreatment); - else if (action.equals("update")) - addedOrUpdatedTreatments.put(jsonTreatment); - else if (action.equals("remove") && mills > dateUtil.now() - T.days(1).msecs()) // handle 1 day old deletions only - removedTreatments.put(jsonTreatment); - } - if (removedTreatments.length() > 0) { - dataWorker.enqueue( - new OneTimeWorkRequest.Builder(NSClientRemoveWorker.class) - .setInputData(dataWorker.storeInputData(removedTreatments, null)) - .build()); - - if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { - Bundle bundle = new Bundle(); - bundle.putString("treatments", removedTreatments.toString()); - bundle.putBoolean("delta", isDelta); - Intent intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - sendBroadcast(intent); - } - } - if (addedOrUpdatedTreatments.length() > 0) { - dataWorker.enqueue( - new OneTimeWorkRequest.Builder(NSClientAddUpdateWorker.class) - .setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments, null)) - .build()); - - if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { - List splitted = splitArray(addedOrUpdatedTreatments); - for (JSONArray part : splitted) { - Bundle bundle = new Bundle(); - bundle.putString("treatments", part.toString()); - bundle.putBoolean("delta", isDelta); - Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - sendBroadcast(intent); - } - } - } - } - if (data.has("devicestatus")) { - JSONArray devicestatuses = data.getJSONArray("devicestatus"); - if (devicestatuses.length() > 0) { - rxBus.send(new EventNSClientNewLog("DATA", "received " + devicestatuses.length() + " device statuses")); - nsDeviceStatus.handleNewData(devicestatuses); - } - } - if (data.has("food")) { - JSONArray foods = data.getJSONArray("food"); - if (foods.length() > 0) - rxBus.send(new EventNSClientNewLog("DATA", "received " + foods.length() + " foods")); - dataWorker.enqueue( - new OneTimeWorkRequest.Builder(FoodPlugin.FoodWorker.class) - .setInputData(dataWorker.storeInputData(foods, null)) - .build()); - } - //noinspection SpellCheckingInspection - if (data.has("mbgs")) { - JSONArray mbgArray = data.getJSONArray("mbgs"); - if (mbgArray.length() > 0) - rxBus.send(new EventNSClientNewLog("DATA", "received " + mbgArray.length() + " mbgs")); - dataWorker.enqueue( - new OneTimeWorkRequest.Builder(NSClientMbgWorker.class) - .setInputData(dataWorker.storeInputData(mbgArray, null)) - .build()); - } - if (data.has("cals")) { - JSONArray cals = data.getJSONArray("cals"); - if (cals.length() > 0) - rxBus.send(new EventNSClientNewLog("DATA", "received " + cals.length() + " cals")); - // Calibrations ignored - } - if (data.has("sgvs")) { - JSONArray sgvs = data.getJSONArray("sgvs"); - if (sgvs.length() > 0) - rxBus.send(new EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs")); - - dataWorker.enqueue(new OneTimeWorkRequest.Builder(NSClientSourcePlugin.NSClientSourceWorker.class) - .setInputData(dataWorker.storeInputData(sgvs, null)) - .build()); - - List splitted = splitArray(sgvs); - if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { - for (JSONArray part : splitted) { - Bundle bundle = new Bundle(); - bundle.putString("sgvs", part.toString()); - bundle.putBoolean("delta", isDelta); - Intent intent = new Intent(Intents.ACTION_NEW_SGV); - intent.putExtras(bundle); - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - sendBroadcast(intent); - } - } - } - rxBus.send(new EventNSClientNewLog("LAST", dateUtil.dateAndTimeString(latestDateInReceivedData))); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - //rxBus.send(new EventNSClientNewLog("NSCLIENT", "onDataUpdate end"); - } finally { - if (wakeLock.isHeld()) wakeLock.release(); - } - }); - } - }; - - public void dbUpdate(DbRequest dbr, NSUpdateAck ack) { - try { - if (!isConnected || !hasWriteAuth) return; - JSONObject message = new JSONObject(); - message.put("collection", dbr.collection); - message.put("_id", dbr._id); - message.put("data", new JSONObject(dbr.data)); - mSocket.emit("dbUpdate", message, ack); - rxBus.send(new EventNSClientNewLog("DBUPDATE " + dbr.collection, "Sent " + dbr._id)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void dbUpdate(String collection, String _id, JSONObject data, Object originalObject) { - try { - if (!isConnected || !hasWriteAuth) return; - JSONObject message = new JSONObject(); - message.put("collection", collection); - message.put("_id", _id); - message.put("data", data); - mSocket.emit("dbUpdate", message, new NSUpdateAck("dbUpdate", _id, aapsLogger, rxBus, originalObject)); - rxBus.send(new EventNSClientNewLog("DBUPDATE " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + _id)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void dbRemove(DbRequest dbr, NSUpdateAck ack) { - try { - if (!isConnected || !hasWriteAuth) return; - JSONObject message = new JSONObject(); - message.put("collection", dbr.collection); - message.put("_id", dbr._id); - mSocket.emit("dbRemove", message, ack); - rxBus.send(new EventNSClientNewLog("DBREMOVE " + dbr.collection, "Sent " + dbr._id)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void dbRemove(String collection, String _id, Object originalObject) { - try { - if (!isConnected || !hasWriteAuth) return; - JSONObject message = new JSONObject(); - message.put("collection", collection); - message.put("_id", _id); - mSocket.emit("dbRemove", message, new NSUpdateAck("dbRemove", _id, aapsLogger, rxBus, originalObject)); - rxBus.send(new EventNSClientNewLog("DBREMOVE " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + _id)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void dbAdd(DbRequest dbr, NSAddAck ack) { - try { - if (!isConnected || !hasWriteAuth) return; - JSONObject message = new JSONObject(); - message.put("collection", dbr.collection); - message.put("data", new JSONObject(dbr.data)); - mSocket.emit("dbAdd", message, ack); - rxBus.send(new EventNSClientNewLog("DBADD " + dbr.collection, "Sent " + dbr.nsClientID)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void dbAdd(String collection, JSONObject data, Object originalObject) { - try { - if (!isConnected || !hasWriteAuth) return; - JSONObject message = new JSONObject(); - message.put("collection", collection); - message.put("data", data); - mSocket.emit("dbAdd", message, new NSAddAck(aapsLogger, rxBus, originalObject)); - rxBus.send(new EventNSClientNewLog("DBADD " + collection, "Sent " + originalObject.getClass().getSimpleName() + " " + data)); - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - } - } - - public void sendAlarmAck(AlarmAck alarmAck) { - if (!isConnected || !hasWriteAuth) return; - mSocket.emit("ack", alarmAck.level, alarmAck.group, alarmAck.silenceTime); - rxBus.send(new EventNSClientNewLog("ALARMACK ", alarmAck.level + " " + alarmAck.group + " " + alarmAck.silenceTime)); - } - - public void resend(final String reason) { - if (!isConnected || !hasWriteAuth) return; - - handler.post(() -> { - if (mSocket == null || !mSocket.connected()) return; - - rxBus.send(new EventNSClientNewLog("QUEUE", "Resend started: " + reason)); - - if (lastAckTime > System.currentTimeMillis() - 10 * 1000L) { - aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastAckTime: " + ((System.currentTimeMillis() - lastAckTime) / 1000L) + " sec"); - return; - } - - dataSyncSelector.processChangedBolusesCompat(); - dataSyncSelector.processChangedCarbsCompat(); - dataSyncSelector.processChangedBolusCalculatorResultsCompat(); - dataSyncSelector.processChangedTemporaryBasalsCompat(); - dataSyncSelector.processChangedExtendedBolusesCompat(); - dataSyncSelector.processChangedProfileSwitchesCompat(); - dataSyncSelector.processChangedGlucoseValuesCompat(); - dataSyncSelector.processChangedTempTargetsCompat(); - dataSyncSelector.processChangedFoodsCompat(); - dataSyncSelector.processChangedTherapyEventsCompat(); - dataSyncSelector.processChangedDeviceStatusesCompat(); - - if (uploadQueue.size() == 0) - return; - - if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) { - aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec"); - return; - } - lastResendTime = System.currentTimeMillis(); - - CloseableIterator iterator; - int maxcount = 30; - try { - iterator = databaseHelper.getDbRequestIterator(); - try { - while (iterator.hasNext() && maxcount > 0) { - DbRequest dbr = iterator.next(); - if (dbr.action.equals("dbAdd")) { - NSAddAck addAck = new NSAddAck(aapsLogger, rxBus, null); - dbAdd(dbr, addAck); - } else if (dbr.action.equals("dbRemove")) { - NSUpdateAck removeAck = new NSUpdateAck("dbRemove", dbr._id, aapsLogger, rxBus, null); - dbRemove(dbr, removeAck); - } else if (dbr.action.equals("dbUpdate")) { - NSUpdateAck updateAck = new NSUpdateAck("dbUpdate", dbr._id, aapsLogger, rxBus, null); - dbUpdate(dbr, updateAck); - } - maxcount--; - } - } finally { - iterator.close(); - } - } catch (SQLException e) { - aapsLogger.error("Unhandled exception", e); - } - - rxBus.send(new EventNSClientNewLog("QUEUE", "Resend ended: " + reason)); - }); - } - - public void restart() { - destroy(); - initialize(); - } - - private void handleAnnouncement(JSONObject announcement) { - boolean defaultVal = config.getNSCLIENT(); - if (sp.getBoolean(R.string.key_ns_announcements, defaultVal)) { - NSAlarm nsAlarm = new NSAlarm(announcement); - Notification notification = new NotificationWithAction(injector, nsAlarm); - rxBus.send(new EventNewNotification(notification)); - rxBus.send(new EventNSClientNewLog("ANNOUNCEMENT", JsonHelper.safeGetString(announcement, "message", "received"))); - aapsLogger.debug(LTag.NSCLIENT, announcement.toString()); - } - } - - private void handleAlarm(JSONObject alarm) { - boolean defaultVal = config.getNSCLIENT(); - if (sp.getBoolean(R.string.key_ns_alarms, defaultVal)) { - long snoozedTo = sp.getLong(R.string.key_snoozedTo, 0L); - if (snoozedTo == 0L || System.currentTimeMillis() > snoozedTo) { - NSAlarm nsAlarm = new NSAlarm(alarm); - Notification notification = new NotificationWithAction(injector, nsAlarm); - rxBus.send(new EventNewNotification(notification)); - } - rxBus.send(new EventNSClientNewLog("ALARM", JsonHelper.safeGetString(alarm, "message", "received"))); - aapsLogger.debug(LTag.NSCLIENT, alarm.toString()); - } - } - - private void handleUrgentAlarm(JSONObject alarm) { - boolean defaultVal = config.getNSCLIENT(); - if (sp.getBoolean(R.string.key_ns_alarms, defaultVal)) { - long snoozedTo = sp.getLong(R.string.key_snoozedTo, 0L); - if (snoozedTo == 0L || System.currentTimeMillis() > snoozedTo) { - NSAlarm nsAlarm = new NSAlarm(alarm); - Notification notification = new NotificationWithAction(injector, nsAlarm); - rxBus.send(new EventNewNotification(notification)); - } - rxBus.send(new EventNSClientNewLog("URGENTALARM", JsonHelper.safeGetString(alarm, "message", "received"))); - aapsLogger.debug(LTag.NSCLIENT, alarm.toString()); - } - } - - public List splitArray(JSONArray array) { - List ret = new ArrayList<>(); - try { - int size = array.length(); - int count = 0; - JSONArray newarr = null; - for (int i = 0; i < size; i++) { - if (count == 0) { - if (newarr != null) { - ret.add(newarr); - } - newarr = new JSONArray(); - count = 20; - } - newarr.put(array.get(i)); - --count; - } - if (newarr != null && newarr.length() > 0) { - ret.add(newarr); - } - } catch (JSONException e) { - aapsLogger.error("Unhandled exception", e); - ret = new ArrayList<>(); - ret.add(array); - } - return ret; - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.kt new file mode 100644 index 0000000000..ad73e4160b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.kt @@ -0,0 +1,738 @@ +package info.nightscout.androidaps.plugins.general.nsclient.services + +import android.content.Intent +import android.os.* +import androidx.work.OneTimeWorkRequest +import com.google.common.base.Charsets +import com.google.common.hash.Hashing +import dagger.android.DaggerService +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.events.EventAppExit +import info.nightscout.androidaps.events.EventConfigBuilderChange +import info.nightscout.androidaps.events.EventPreferenceChange +import info.nightscout.androidaps.interfaces.Config +import info.nightscout.androidaps.interfaces.DataSyncSelector +import info.nightscout.androidaps.interfaces.DatabaseHelperInterface +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.general.food.FoodPlugin.FoodWorker +import info.nightscout.androidaps.plugins.general.nsclient.* +import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAddAck +import info.nightscout.androidaps.plugins.general.nsclient.acks.NSAuthAck +import info.nightscout.androidaps.plugins.general.nsclient.acks.NSUpdateAck +import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck +import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm +import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus +import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus +import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification +import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification +import info.nightscout.androidaps.plugins.general.overview.notifications.Notification +import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction +import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin +import info.nightscout.androidaps.plugins.source.NSClientSourcePlugin.NSClientSourceWorker +import info.nightscout.androidaps.receivers.DataWorker +import info.nightscout.androidaps.services.Intents +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.JsonHelper.safeGetLong +import info.nightscout.androidaps.utils.JsonHelper.safeGetString +import info.nightscout.androidaps.utils.JsonHelper.safeGetStringAllowNull +import info.nightscout.androidaps.utils.T.Companion.days +import info.nightscout.androidaps.utils.T.Companion.mins +import info.nightscout.androidaps.utils.buildHelper.BuildHelper +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.socket.client.IO +import io.socket.client.Socket +import io.socket.emitter.Emitter +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.net.URISyntaxException +import java.util.* +import javax.inject.Inject + +class NSClientService : DaggerService() { + + @Inject lateinit var injector: HasAndroidInjector + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var aapsSchedulers: AapsSchedulers + @Inject lateinit var nsSettingsStatus: NSSettingsStatus + @Inject lateinit var nsDeviceStatus: NSDeviceStatus + @Inject lateinit var databaseHelper: DatabaseHelperInterface + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var resourceHelper: ResourceHelper + @Inject lateinit var sp: SP + @Inject lateinit var fabricPrivacy: FabricPrivacy + @Inject lateinit var nsClientPlugin: NSClientPlugin + @Inject lateinit var buildHelper: BuildHelper + @Inject lateinit var config: Config + @Inject lateinit var dateUtil: DateUtil + @Inject lateinit var dataWorker: DataWorker + @Inject lateinit var dataSyncSelector: DataSyncSelector + @Inject lateinit var repository: AppRepository + + companion object { + private const val WATCHDOG_INTERVAL_MINUTES = 2 + private const val WATCHDOG_RECONNECT_IN = 15 + private const val WATCHDOG_MAX_CONNECTIONS = 5 + } + + private val disposable = CompositeDisposable() + + // public PowerManager.WakeLock mWakeLock; + private val binder: IBinder = LocalBinder() + private var handler: Handler? = null + private var socket: Socket? = null + private var dataCounter = 0 + private var connectCounter = 0 + private var nsEnabled = false + private var nsAPISecret = "" + private var nsDevice = "" + private val nsHours = 48 + private var lastAckTime: Long = 0 + private var nsApiHashCode = "" + private val reconnections = ArrayList() + + var isConnected = false + var hasWriteAuth = false + var nsURL = "" + var latestDateInReceivedData: Long = 0 + override fun onCreate() { + super.onCreate() + // PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); +// mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:NSClientService"); +// mWakeLock.acquire(); + initialize() + disposable.add(rxBus + .toObservable(EventConfigBuilderChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ + if (nsEnabled != nsClientPlugin.isEnabled(PluginType.GENERAL)) { + latestDateInReceivedData = 0 + destroy() + initialize() + } + }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventPreferenceChange::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ event: EventPreferenceChange -> + if (event.isChanged(resourceHelper, R.string.key_nsclientinternal_url) || + event.isChanged(resourceHelper, R.string.key_nsclientinternal_api_secret) || + event.isChanged(resourceHelper, R.string.key_nsclientinternal_paused)) { + latestDateInReceivedData = 0 + destroy() + initialize() + } + }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventAppExit::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ + aapsLogger.debug(LTag.NSCLIENT, "EventAppExit received") + destroy() + stopSelf() + }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(EventNSClientRestart::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ + latestDateInReceivedData = 0 + restart() + }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(NSAuthAck::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ ack -> processAuthAck(ack) }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(NSUpdateAck::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ ack -> processUpdateAck(ack) }, fabricPrivacy::logException) + ) + disposable.add(rxBus + .toObservable(NSAddAck::class.java) + .observeOn(aapsSchedulers.io) + .subscribe({ ack -> processAddAck(ack) }, fabricPrivacy::logException) + ) + } + + override fun onDestroy() { + super.onDestroy() + disposable.clear() + // if (mWakeLock.isHeld()) mWakeLock.release(); + } + + private fun processAddAck(ack: NSAddAck) { + lastAckTime = dateUtil.now() + dataWorker.enqueue( + OneTimeWorkRequest.Builder(NSClientAddAckWorker::class.java) + .setInputData(dataWorker.storeInputData(ack, null)) + .build()) + } + + private fun processUpdateAck(ack: NSUpdateAck) { + lastAckTime = dateUtil.now() + dataWorker.enqueue( + OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker::class.java) + .setInputData(dataWorker.storeInputData(ack, null)) + .build()) + } + + fun processAuthAck(ack: NSAuthAck) { + var connectionStatus = "Authenticated (" + if (ack.read) connectionStatus += "R" + if (ack.write) connectionStatus += "W" + if (ack.write_treatment) connectionStatus += "T" + connectionStatus += ')' + isConnected = true + hasWriteAuth = ack.write && ack.write_treatment + rxBus.send(EventNSClientStatus(connectionStatus)) + rxBus.send(EventNSClientNewLog("AUTH", connectionStatus)) + if (!ack.write) { + rxBus.send(EventNSClientNewLog("ERROR", "Write permission not granted ")) + } + if (!ack.write_treatment) { + rxBus.send(EventNSClientNewLog("ERROR", "Write treatment permission not granted ")) + } + if (!hasWriteAuth) { + val noWritePerm = Notification(Notification.NSCLIENT_NO_WRITE_PERMISSION, resourceHelper.gs(R.string.nowritepermission), Notification.URGENT) + rxBus.send(EventNewNotification(noWritePerm)) + } else { + rxBus.send(EventDismissNotification(Notification.NSCLIENT_NO_WRITE_PERMISSION)) + } + } + + inner class LocalBinder : Binder() { + + val serviceInstance: NSClientService + get() = this@NSClientService + } + + override fun onBind(intent: Intent): IBinder { + return binder + } + + override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + return START_STICKY + } + + fun initialize() { + dataCounter = 0 + readPreferences() + @Suppress("UnstableApiUsage", "DEPRECATION") + if (nsAPISecret != "") nsApiHashCode = Hashing.sha1().hashString(nsAPISecret, Charsets.UTF_8).toString() + rxBus.send(EventNSClientStatus("Initializing")) + if (!nsClientPlugin.isAllowed) { + rxBus.send(EventNSClientNewLog("NSCLIENT", "not allowed")) + rxBus.send(EventNSClientStatus("Not allowed")) + } else if (nsClientPlugin.paused) { + rxBus.send(EventNSClientNewLog("NSCLIENT", "paused")) + rxBus.send(EventNSClientStatus("Paused")) + } else if (!nsEnabled) { + rxBus.send(EventNSClientNewLog("NSCLIENT", "disabled")) + rxBus.send(EventNSClientStatus("Disabled")) + } else if (nsURL != "" && (buildHelper.isEngineeringMode() || nsURL.toLowerCase(Locale.getDefault()).startsWith("https://"))) { + try { + rxBus.send(EventNSClientStatus("Connecting ...")) + val opt = IO.Options() + opt.forceNew = true + opt.reconnection = true + socket = IO.socket(nsURL, opt).also { socket -> + socket.on(Socket.EVENT_CONNECT, onConnect) + socket.on(Socket.EVENT_DISCONNECT, onDisconnect) + socket.on(Socket.EVENT_ERROR, onError) + socket.on(Socket.EVENT_CONNECT_ERROR, onError) + socket.on(Socket.EVENT_CONNECT_TIMEOUT, onError) + socket.on(Socket.EVENT_PING, onPing) + rxBus.send(EventNSClientNewLog("NSCLIENT", "do connect")) + socket.connect() + socket.on("dataUpdate", onDataUpdate) + socket.on("announcement", onAnnouncement) + socket.on("alarm", onAlarm) + socket.on("urgent_alarm", onUrgentAlarm) + socket.on("clear_alarm", onClearAlarm) + } + } catch (e: URISyntaxException) { + rxBus.send(EventNSClientNewLog("NSCLIENT", "Wrong URL syntax")) + rxBus.send(EventNSClientStatus("Wrong URL syntax")) + } catch (e: RuntimeException) { + rxBus.send(EventNSClientNewLog("NSCLIENT", "Wrong URL syntax")) + rxBus.send(EventNSClientStatus("Wrong URL syntax")) + } + } else if (nsURL.toLowerCase(Locale.getDefault()).startsWith("http://")) { + rxBus.send(EventNSClientNewLog("NSCLIENT", "NS URL not encrypted")) + rxBus.send(EventNSClientStatus("Not encrypted")) + } else { + rxBus.send(EventNSClientNewLog("NSCLIENT", "No NS URL specified")) + rxBus.send(EventNSClientStatus("Not configured")) + } + } + + private val onConnect = Emitter.Listener { + connectCounter++ + val socketId = socket?.id() ?: "NULL" + rxBus.send(EventNSClientNewLog("NSCLIENT", "connect #$connectCounter event. ID: $socketId")) + if (socket != null) sendAuthMessage(NSAuthAck(rxBus)) + watchdog() + } + + private fun watchdog() { + synchronized(reconnections) { + val now = dateUtil.now() + reconnections.add(now) + for (r in reconnections.reversed()) { + if (r < now - mins(WATCHDOG_INTERVAL_MINUTES.toLong()).msecs()) { + reconnections.remove(r) + } + } + rxBus.send(EventNSClientNewLog("WATCHDOG", "connections in last " + WATCHDOG_INTERVAL_MINUTES + " minutes: " + reconnections.size + "/" + WATCHDOG_MAX_CONNECTIONS)) + if (reconnections.size >= WATCHDOG_MAX_CONNECTIONS) { + val n = Notification(Notification.NS_MALFUNCTION, resourceHelper.gs(R.string.nsmalfunction), Notification.URGENT) + rxBus.send(EventNewNotification(n)) + rxBus.send(EventNSClientNewLog("WATCHDOG", "pausing for $WATCHDOG_RECONNECT_IN minutes")) + nsClientPlugin.pause(true) + rxBus.send(EventNSClientUpdateGUI()) + Thread { + SystemClock.sleep(mins(WATCHDOG_RECONNECT_IN.toLong()).msecs()) + rxBus.send(EventNSClientNewLog("WATCHDOG", "re-enabling NSClient")) + nsClientPlugin.pause(false) + }.start() + } + } + } + + private val onDisconnect = Emitter.Listener { args -> + aapsLogger.debug(LTag.NSCLIENT, "disconnect reason: {}", *args) + rxBus.send(EventNSClientNewLog("NSCLIENT", "disconnect event")) + } + + @Synchronized fun destroy() { + socket?.off(Socket.EVENT_CONNECT) + socket?.off(Socket.EVENT_DISCONNECT) + socket?.off(Socket.EVENT_PING) + socket?.off("dataUpdate") + socket?.off("announcement") + socket?.off("alarm") + socket?.off("urgent_alarm") + socket?.off("clear_alarm") + rxBus.send(EventNSClientNewLog("NSCLIENT", "destroy")) + isConnected = false + hasWriteAuth = false + socket?.disconnect() + socket = null + } + + private fun sendAuthMessage(ack: NSAuthAck?) { + val authMessage = JSONObject() + try { + authMessage.put("client", "Android_$nsDevice") + authMessage.put("history", nsHours) + authMessage.put("status", true) // receive status + authMessage.put("from", latestDateInReceivedData) // send data newer than + authMessage.put("secret", nsApiHashCode) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + return + } + rxBus.send(EventNSClientNewLog("AUTH", "requesting auth")) + socket?.emit("authorize", authMessage, ack) + } + + fun readPreferences() { + nsEnabled = nsClientPlugin.isEnabled(PluginType.GENERAL) + nsURL = sp.getString(R.string.key_nsclientinternal_url, "") + nsAPISecret = sp.getString(R.string.key_nsclientinternal_api_secret, "") + nsDevice = sp.getString("careportal_enteredby", "") + } + + private val onError = Emitter.Listener { args -> + var msg = "Unknown Error" + if (args.isNotEmpty() && args[0] != null) { + msg = args[0].toString() + } + rxBus.send(EventNSClientNewLog("ERROR", msg)) + } + private val onPing = Emitter.Listener { + rxBus.send(EventNSClientNewLog("PING", "received")) + // send data if there is something waiting + resend("Ping received") + } + private val onAnnouncement = Emitter.Listener { args -> + + /* + { + "level":0, + "title":"Announcement", + "message":"test", + "plugin":{"name":"treatmentnotify","label":"Treatment Notifications","pluginType":"notification","enabled":true}, + "group":"Announcement", + "isAnnouncement":true, + "key":"9ac46ad9a1dcda79dd87dae418fce0e7955c68da" + } + */ + val data: JSONObject + try { + data = args[0] as JSONObject + handleAnnouncement(data) + } catch (e: Exception) { + aapsLogger.error("Unhandled exception", e) + } + } + private val onAlarm = Emitter.Listener { args -> + + /* + { + "level":1, + "title":"Warning HIGH", + "message":"BG Now: 5 -0.2 → mmol\/L\nRaw BG: 4.8 mmol\/L Čistý\nBG 15m: 4.8 mmol\/L\nIOB: -0.02U\nCOB: 0g", + "eventName":"high", + "plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, + "pushoverSound":"climb", + "debug":{"lastSGV":5,"thresholds":{"bgHigh":180,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, + "group":"default", + "key":"simplealarms_1" + } + */ + val data: JSONObject + try { + data = args[0] as JSONObject + handleAlarm(data) + } catch (e: Exception) { + aapsLogger.error("Unhandled exception", e) + } + } + private val onUrgentAlarm = Emitter.Listener { args: Array -> + val data: JSONObject + try { + data = args[0] as JSONObject + handleUrgentAlarm(data) + } catch (e: Exception) { + aapsLogger.error("Unhandled exception", e) + } + } + private val onClearAlarm = Emitter.Listener { args -> + + /* + { + "clear":true, + "title":"All Clear", + "message":"default - Urgent was ack'd", + "group":"default" + } + */ + val data: JSONObject + try { + data = args[0] as JSONObject + rxBus.send(EventNSClientNewLog("CLEARALARM", "received")) + rxBus.send(EventDismissNotification(Notification.NS_ALARM)) + rxBus.send(EventDismissNotification(Notification.NS_URGENT_ALARM)) + aapsLogger.debug(LTag.NSCLIENT, data.toString()) + } catch (e: Exception) { + aapsLogger.error("Unhandled exception", e) + } + } + private val onDataUpdate = Emitter.Listener { args -> + handler?.post { + val powerManager = getSystemService(POWER_SERVICE) as PowerManager + val wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "AndroidAPS:NSClientService_onDataUpdate") + wakeLock.acquire(3000) + try { + val data = args[0] as JSONObject + try { + // delta means only increment/changes are coming + val isDelta = data.has("delta") + rxBus.send(EventNSClientNewLog("DATA", "Data packet #" + dataCounter++ + if (isDelta) " delta" else " full")) + if (data.has("status")) { + val status = data.getJSONObject("status") + nsSettingsStatus.handleNewData(status) + } else if (!isDelta) { + rxBus.send(EventNSClientNewLog("ERROR", "Unsupported Nightscout version ")) + } + if (data.has("profiles")) { + val profiles = data.getJSONArray("profiles") + if (profiles.length() > 0) { + // take the newest + val profileStoreJson = profiles[profiles.length() - 1] as JSONObject + rxBus.send(EventNSClientNewLog("PROFILE", "profile received")) + dataWorker.enqueue( + OneTimeWorkRequest.Builder(LocalProfilePlugin.NSProfileWorker::class.java) + .setInputData(dataWorker.storeInputData(profileStoreJson, null)) + .build()) + if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { + val bundle = Bundle() + bundle.putString("profile", profileStoreJson.toString()) + bundle.putBoolean("delta", isDelta) + val intent = Intent(Intents.ACTION_NEW_PROFILE) + intent.putExtras(bundle) + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + sendBroadcast(intent) + } + } + } + if (data.has("treatments")) { + val treatments = data.getJSONArray("treatments") + val removedTreatments = JSONArray() + val addedOrUpdatedTreatments = JSONArray() + if (treatments.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + treatments.length() + " treatments")) + for (index in 0 until treatments.length()) { + val jsonTreatment = treatments.getJSONObject(index) + val action = safeGetStringAllowNull(jsonTreatment, "action", null) + val mills = safeGetLong(jsonTreatment, "mills") + if (action == null) addedOrUpdatedTreatments.put(jsonTreatment) else if (action == "update") addedOrUpdatedTreatments.put(jsonTreatment) else if (action == "remove" && mills > dateUtil.now() - days(1).msecs()) // handle 1 day old deletions only + removedTreatments.put(jsonTreatment) + } + if (removedTreatments.length() > 0) { + dataWorker.enqueue( + OneTimeWorkRequest.Builder(NSClientRemoveWorker::class.java) + .setInputData(dataWorker.storeInputData(removedTreatments, null)) + .build()) + if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { + val bundle = Bundle() + bundle.putString("treatments", removedTreatments.toString()) + bundle.putBoolean("delta", isDelta) + val intent = Intent(Intents.ACTION_REMOVED_TREATMENT) + intent.putExtras(bundle) + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + sendBroadcast(intent) + } + } + if (addedOrUpdatedTreatments.length() > 0) { + dataWorker.enqueue( + OneTimeWorkRequest.Builder(NSClientAddUpdateWorker::class.java) + .setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments, null)) + .build()) + if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { + val splitted = splitArray(addedOrUpdatedTreatments) + for (part in splitted) { + val bundle = Bundle() + bundle.putString("treatments", part.toString()) + bundle.putBoolean("delta", isDelta) + val intent = Intent(Intents.ACTION_CHANGED_TREATMENT) + intent.putExtras(bundle) + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + sendBroadcast(intent) + } + } + } + } + if (data.has("devicestatus")) { + val devicestatuses = data.getJSONArray("devicestatus") + if (devicestatuses.length() > 0) { + rxBus.send(EventNSClientNewLog("DATA", "received " + devicestatuses.length() + " device statuses")) + nsDeviceStatus.handleNewData(devicestatuses) + } + } + if (data.has("food")) { + val foods = data.getJSONArray("food") + if (foods.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + foods.length() + " foods")) + dataWorker.enqueue( + OneTimeWorkRequest.Builder(FoodWorker::class.java) + .setInputData(dataWorker.storeInputData(foods, null)) + .build()) + } + if (data.has("mbgs")) { + val mbgArray = data.getJSONArray("mbgs") + if (mbgArray.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + mbgArray.length() + " mbgs")) + dataWorker.enqueue( + OneTimeWorkRequest.Builder(NSClientMbgWorker::class.java) + .setInputData(dataWorker.storeInputData(mbgArray, null)) + .build()) + } + if (data.has("cals")) { + val cals = data.getJSONArray("cals") + if (cals.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + cals.length() + " cals")) + // Calibrations ignored + } + if (data.has("sgvs")) { + val sgvs = data.getJSONArray("sgvs") + if (sgvs.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + sgvs.length() + " sgvs")) + dataWorker.enqueue(OneTimeWorkRequest.Builder(NSClientSourceWorker::class.java) + .setInputData(dataWorker.storeInputData(sgvs, null)) + .build()) + val splitted = splitArray(sgvs) + if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { + for (part in splitted) { + val bundle = Bundle() + bundle.putString("sgvs", part.toString()) + bundle.putBoolean("delta", isDelta) + val intent = Intent(Intents.ACTION_NEW_SGV) + intent.putExtras(bundle) + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + sendBroadcast(intent) + } + } + } + rxBus.send(EventNSClientNewLog("LAST", dateUtil.dateAndTimeString(latestDateInReceivedData))) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + //rxBus.send(new EventNSClientNewLog("NSCLIENT", "onDataUpdate end"); + } finally { + if (wakeLock.isHeld) wakeLock.release() + } + } + } + + fun dbUpdate(collection: String, _id: String?, data: JSONObject?, originalObject: Any) { + try { + if (_id == null) return + if (!isConnected || !hasWriteAuth) return + val message = JSONObject() + message.put("collection", collection) + message.put("_id", _id) + message.put("data", data) + socket?.emit("dbUpdate", message, NSUpdateAck("dbUpdate", _id, aapsLogger, rxBus, originalObject)) + rxBus.send(EventNSClientNewLog("DBUPDATE $collection", "Sent " + originalObject.javaClass.simpleName + " " + _id)) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + } + + fun dbRemove(collection: String, _id: String?, originalObject: Any) { + try { + if (_id == null) return + if (!isConnected || !hasWriteAuth) return + val message = JSONObject() + message.put("collection", collection) + message.put("_id", _id) + socket?.emit("dbRemove", message, NSUpdateAck("dbRemove", _id, aapsLogger, rxBus, originalObject)) + rxBus.send(EventNSClientNewLog("DBREMOVE $collection", "Sent " + originalObject.javaClass.simpleName + " " + _id)) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + } + + fun dbAdd(collection: String, data: JSONObject, originalObject: Any) { + try { + if (!isConnected || !hasWriteAuth) return + val message = JSONObject() + message.put("collection", collection) + message.put("data", data) + socket?.emit("dbAdd", message, NSAddAck(aapsLogger, rxBus, originalObject)) + rxBus.send(EventNSClientNewLog("DBADD $collection", "Sent " + originalObject.javaClass.simpleName + " " + data)) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + } + } + + fun sendAlarmAck(alarmAck: AlarmAck) { + if (!isConnected || !hasWriteAuth) return + socket?.emit("ack", alarmAck.level, alarmAck.group, alarmAck.silenceTime) + rxBus.send(EventNSClientNewLog("ALARMACK ", alarmAck.level.toString() + " " + alarmAck.group + " " + alarmAck.silenceTime)) + } + + fun resend(reason: String) { + if (!isConnected || !hasWriteAuth) return + handler?.post { + if (socket?.connected() != true) return@post + if (lastAckTime > System.currentTimeMillis() - 10 * 1000L) { + aapsLogger.debug(LTag.NSCLIENT, "Skipping resend by lastAckTime: " + (System.currentTimeMillis() - lastAckTime) / 1000L + " sec") + return@post + } + val powerManager = getSystemService(POWER_SERVICE) as PowerManager + val wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "AndroidAPS:NSClientService_onDataUpdate") + wakeLock.acquire(mins(10).msecs()) + try { + rxBus.send(EventNSClientNewLog("QUEUE", "Resend started: $reason")) + dataSyncSelector.doUpload() + rxBus.send(EventNSClientNewLog("QUEUE", "Resend ended: $reason")) + } finally { + if (wakeLock.isHeld) wakeLock.release() + } + } + } + + fun restart() { + destroy() + initialize() + } + + private fun handleAnnouncement(announcement: JSONObject) { + val defaultVal = config.NSCLIENT + if (sp.getBoolean(R.string.key_ns_announcements, defaultVal)) { + val nsAlarm = NSAlarm(announcement) + val notification: Notification = NotificationWithAction(injector, nsAlarm) + rxBus.send(EventNewNotification(notification)) + rxBus.send(EventNSClientNewLog("ANNOUNCEMENT", safeGetString(announcement, "message", "received"))) + aapsLogger.debug(LTag.NSCLIENT, announcement.toString()) + } + } + + private fun handleAlarm(alarm: JSONObject) { + val defaultVal = config.NSCLIENT + if (sp.getBoolean(R.string.key_ns_alarms, defaultVal)) { + val snoozedTo = sp.getLong(R.string.key_snoozedTo, 0L) + if (snoozedTo == 0L || System.currentTimeMillis() > snoozedTo) { + val nsAlarm = NSAlarm(alarm) + val notification: Notification = NotificationWithAction(injector, nsAlarm) + rxBus.send(EventNewNotification(notification)) + } + rxBus.send(EventNSClientNewLog("ALARM", safeGetString(alarm, "message", "received"))) + aapsLogger.debug(LTag.NSCLIENT, alarm.toString()) + } + } + + private fun handleUrgentAlarm(alarm: JSONObject) { + val defaultVal = config.NSCLIENT + if (sp.getBoolean(R.string.key_ns_alarms, defaultVal)) { + val snoozedTo = sp.getLong(R.string.key_snoozedTo, 0L) + if (snoozedTo == 0L || System.currentTimeMillis() > snoozedTo) { + val nsAlarm = NSAlarm(alarm) + val notification: Notification = NotificationWithAction(injector, nsAlarm) + rxBus.send(EventNewNotification(notification)) + } + rxBus.send(EventNSClientNewLog("URGENTALARM", safeGetString(alarm, "message", "received"))) + aapsLogger.debug(LTag.NSCLIENT, alarm.toString()) + } + } + + private fun splitArray(array: JSONArray): List { + var ret: MutableList = ArrayList() + try { + val size = array.length() + var count = 0 + var newarr: JSONArray? = null + for (i in 0 until size) { + if (count == 0) { + if (newarr != null) ret.add(newarr) + newarr = JSONArray() + count = 20 + } + newarr?.put(array[i]) + --count + } + if (newarr != null && newarr.length() > 0) ret.add(newarr) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + ret = ArrayList() + ret.add(array) + } + return ret + } + + init { + if (handler == null) { + val handlerThread = HandlerThread(NSClientService::class.java.simpleName + "Handler") + handlerThread.start() + handler = Handler(handlerThread.looper) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt index cf4f0c62fa..a331fcd88d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/openhumans/OpenHumansUploader.kt @@ -178,24 +178,24 @@ class OpenHumansUploader @Inject constructor( } } - @JvmOverloads - fun enqueueTreatment(treatment: Treatment?, deleted: Boolean = false) = treatment?.let { - insertQueueItem("Treatments") { - put("date", treatment.date) - put("isValid", treatment.isValid) - put("source", treatment.source) - put("nsId", treatment._id) - put("boluscalc", treatment.boluscalc) - put("carbs", treatment.carbs) - put("dia", treatment.dia) - put("insulin", treatment.insulin) - put("insulinInterfaceID", treatment.insulinInterfaceID) - put("isSMB", treatment.isSMB) - put("mealBolus", treatment.mealBolus) - put("bolusCalcJson", treatment.getBoluscalc()) - put("isDeletion", deleted) - } - } + // @JvmOverloads + // fun enqueueTreatment(treatment: Treatment?, deleted: Boolean = false) = treatment?.let { + // insertQueueItem("Treatments") { + // put("date", treatment.date) + // put("isValid", treatment.isValid) + // put("source", treatment.source) + // put("nsId", treatment._id) + // put("boluscalc", treatment.boluscalc) + // put("carbs", treatment.carbs) + // put("dia", treatment.dia) + // put("insulin", treatment.insulin) + // put("insulinInterfaceID", treatment.insulinInterfaceID) + // put("isSMB", treatment.isSMB) + // put("mealBolus", treatment.mealBolus) + // put("bolusCalcJson", treatment.getBoluscalc()) + // put("isDeletion", deleted) + // } + // } @JvmOverloads fun enqueueTherapyEvent(therapyEvent: TherapyEvent, deleted: Boolean = false) = insertQueueItem("TherapyEvents") { @@ -210,17 +210,17 @@ class OpenHumansUploader @Inject constructor( put("isDeletion", deleted) } - @JvmOverloads - fun enqueueExtendedBolus(extendedBolus: ExtendedBolus, deleted: Boolean = false) = insertQueueItem("ExtendedBoluses") { - put("date", extendedBolus.date) - put("isValid", extendedBolus.isValid) - put("source", extendedBolus.source) - put("nsId", extendedBolus._id) - put("pumpId", extendedBolus.pumpId) - put("insulin", extendedBolus.insulin) - put("durationInMinutes", extendedBolus.durationInMinutes) - put("isDeletion", deleted) - } + // @JvmOverloads + // fun enqueueExtendedBolus(extendedBolus: ExtendedBolus, deleted: Boolean = false) = insertQueueItem("ExtendedBoluses") { + // put("date", extendedBolus.date) + // put("isValid", extendedBolus.isValid) + // put("source", extendedBolus.source) + // put("nsId", extendedBolus._id) + // put("pumpId", extendedBolus.pumpId) + // put("insulin", extendedBolus.insulin) + // put("durationInMinutes", extendedBolus.durationInMinutes) + // put("isDeletion", deleted) + // } // @JvmOverloads // fun enqueueProfileSwitch(profileSwitch: ProfileSwitch, deleted: Boolean = false) = insertQueueItem("ProfileSwitches") { @@ -244,22 +244,22 @@ class OpenHumansUploader @Inject constructor( // put("double", tdd.total) // } - @JvmOverloads - fun enqueueTemporaryBasal(temporaryBasal: TemporaryBasal?, deleted: Boolean = false) = temporaryBasal?.let { - insertQueueItem("TemporaryBasals") { - put("date", temporaryBasal.date) - put("isValid", temporaryBasal.isValid) - put("source", temporaryBasal.source) - put("nsId", temporaryBasal._id) - put("pumpId", temporaryBasal.pumpId) - put("durationInMinutes", temporaryBasal.durationInMinutes) - put("durationInMinutes", temporaryBasal.durationInMinutes) - put("isAbsolute", temporaryBasal.isAbsolute) - put("percentRate", temporaryBasal.percentRate) - put("absoluteRate", temporaryBasal.absoluteRate) - put("isDeletion", deleted) - } - } + // @JvmOverloads + // fun enqueueTemporaryBasal(temporaryBasal: TemporaryBasal?, deleted: Boolean = false) = temporaryBasal?.let { + // insertQueueItem("TemporaryBasals") { + // put("date", temporaryBasal.date) + // put("isValid", temporaryBasal.isValid) + // put("source", temporaryBasal.source) + // put("nsId", temporaryBasal._id) + // put("pumpId", temporaryBasal.pumpId) + // put("durationInMinutes", temporaryBasal.durationInMinutes) + // put("durationInMinutes", temporaryBasal.durationInMinutes) + // put("isAbsolute", temporaryBasal.isAbsolute) + // put("percentRate", temporaryBasal.percentRate) + // put("absoluteRate", temporaryBasal.absoluteRate) + // put("isDeletion", deleted) + // } + // } @JvmOverloads fun enqueueTempTarget(tempTarget: TemporaryTarget?, deleted: Boolean = false) = tempTarget?.let { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt index 8810a7613f..9f34c84065 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.kt @@ -10,6 +10,7 @@ import android.graphics.Paint import android.graphics.drawable.AnimationDrawable import android.os.Bundle import android.os.Handler +import android.os.HandlerThread import android.util.DisplayMetrics import android.view.LayoutInflater import android.view.View @@ -24,10 +25,8 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.jjoe64.graphview.GraphView import dagger.android.HasAndroidInjector import dagger.android.support.DaggerFragment -import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R -import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.entities.TemporaryTarget @@ -124,7 +123,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList private lateinit var dm: DisplayMetrics private var axisWidth: Int = 0 private var rangeToDisplay = 6 // for graph - private var loopHandler = Handler() + private lateinit var loopHandler: Handler private var refreshLoop: Runnable? = null private val secondaryGraphs = ArrayList() @@ -150,6 +149,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + loopHandler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper) // pre-process landscape mode val screenWidth = dm.widthPixels @@ -297,14 +297,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList if (childFragmentManager.isStateSaved) return activity?.let { activity -> when (v.id) { - R.id.treatment_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TreatmentDialog().show(childFragmentManager, "Overview") }) - R.id.wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) WizardDialog().show(childFragmentManager, "Overview") }) - R.id.insulin_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) InsulinDialog().show(childFragmentManager, "Overview") }) + R.id.treatment_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TreatmentDialog().show(childFragmentManager, "Overview") }) + R.id.wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) WizardDialog().show(childFragmentManager, "Overview") }) + R.id.insulin_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) InsulinDialog().show(childFragmentManager, "Overview") }) R.id.quick_wizard_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) onClickQuickWizard() }) - R.id.carbs_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) CarbsDialog().show(childFragmentManager, "Overview") }) - R.id.temp_target -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TempTargetDialog().show(childFragmentManager, "Overview") }) + R.id.carbs_button -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) CarbsDialog().show(childFragmentManager, "Overview") }) + R.id.temp_target -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) TempTargetDialog().show(childFragmentManager, "Overview") }) - R.id.active_profile -> { + R.id.active_profile -> { ProfileViewerDialog().also { pvd -> pvd.arguments = Bundle().also { it.putLong("time", dateUtil.now()) @@ -313,7 +313,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList }.show(childFragmentManager, "ProfileViewDialog") } - R.id.cgm_button -> { + R.id.cgm_button -> { if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) openCgmApp("com.eveningoutpost.dexdrip") else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) { @@ -324,7 +324,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } } - R.id.calibration_button -> { + R.id.calibration_button -> { if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) { CalibrationDialog().show(childFragmentManager, "CalibrationDialog") } else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) { @@ -339,27 +339,29 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } } - R.id.accept_temp_button -> { + R.id.accept_temp_button -> { profileFunction.getProfile() ?: return if (loopPlugin.isEnabled(PluginType.LOOP)) { - val lastRun = loopPlugin.lastRun - loopPlugin.invoke("Accept temp button", false) - if (lastRun?.lastAPSRun != null && lastRun.constraintsProcessed?.isChangeRequested == true) { - protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { - OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned() - ?: "".toSpanned(), { - uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview) - binding.buttonsLayout.acceptTempButton.visibility = View.GONE - (context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID) - rxBus.send(EventWearInitiateAction("cancelChangeRequest")) - loopPlugin.acceptChangeRequest() + loopHandler.post { + val lastRun = loopPlugin.lastRun + loopPlugin.invoke("Accept temp button", false) + if (lastRun?.lastAPSRun != null && lastRun.constraintsProcessed?.isChangeRequested == true) { + protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { + OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned() + ?: "".toSpanned(), { + uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview) + binding.buttonsLayout.acceptTempButton.visibility = View.GONE + (context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).cancel(Constants.notificationID) + rxBus.send(EventWearInitiateAction("cancelChangeRequest")) + Thread { loopPlugin.acceptChangeRequest() }.run() + }) }) - }) + } } } } - R.id.aps_mode -> { + R.id.aps_mode -> { protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { if (isAdded) LoopDialog().also { dialog -> dialog.arguments = Bundle().also { it.putInt("showOkCancel", 1) } @@ -391,7 +393,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList return true } - R.id.aps_mode -> { + R.id.aps_mode -> { activity?.let { activity -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { LoopDialog().also { dialog -> @@ -401,8 +403,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList } } - R.id.temp_target -> v.performClick() - R.id.active_profile -> activity?.let { activity -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "Overview") }) } + R.id.temp_target -> v.performClick() + R.id.active_profile -> activity?.let { activity -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "Overview") }) } } return false @@ -775,7 +777,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList if (config.APS && lastRun?.constraintsProcessed != null) { if (lastRun.constraintsProcessed!!.carbsReq > 0) { //only display carbsreq when carbs have not been entered recently - val lastCarb = repository.getLastCarbsRecordWrapped().blockingGet() + val lastCarb = repository.getLastCarbsRecordWrapped().blockingGet() val lastCarbsTime = if (lastCarb is ValueWrapper.Existing) lastCarb.value.timestamp else 0L if (lastCarbsTime < lastRun.lastAPSRun) { cobText = cobText + " | " + lastRun.constraintsProcessed!!.carbsReq + " " + resourceHelper.gs(R.string.required) @@ -860,7 +862,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList // **** BG **** if (predictionsAvailable && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) - graphData.addBgReadings(fromTime, toTime, highLine, apsResult?.predictions?.map { bg-> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper) }?.toMutableList()) + graphData.addBgReadings(fromTime, toTime, highLine, apsResult?.predictions?.map { bg -> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, resourceHelper) }?.toMutableList()) else graphData.addBgReadings(fromTime, toTime, highLine, null) if (buildHelper.isDev()) graphData.addBucketedData(fromTime, toTime) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt index a4da17f159..4d17a119be 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/graphData/GraphData.kt @@ -400,9 +400,8 @@ class GraphData( time += 5 * 60 * 1000L continue } - var iob = 0.0 var absIob = 0.0 - iob = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile).iob + val iob: Double = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile).iob if (absScale) absIob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob if (abs(lastIob - iob) > 0.02) { if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale)) @@ -461,8 +460,7 @@ class GraphData( time += 5 * 60 * 1000L continue } - var iob = 0.0 - iob = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob + val iob: Double = iobCobCalculator.calculateAbsInsulinFromTreatmentsAndTemps(time).iob if (abs(lastIob - iob) > 0.02) { if (abs(lastIob - iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale)) iobArray.add(ScaledDataPoint(time, iob, iobScale)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt index 2487892414..31f01df6c1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt @@ -54,6 +54,9 @@ class LocalProfileFragment : DaggerFragment() { private val save = Runnable { doEdit() basalView?.updateLabel(resourceHelper.gs(R.string.basal_label) + ": " + sumLabel()) + localProfilePlugin.profile?.getSpecificProfile(spinner?.selectedItem.toString())?.let { + binding.basalGraph.show(ProfileSealed.Pure(it)) + } } private val textWatch = object : TextWatcher { @@ -124,7 +127,7 @@ class LocalProfileFragment : DaggerFragment() { binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, binding.save, textWatch) binding.dia.tag = "LP_DIA" TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic, "IC", resourceHelper.gs(R.string.ic_label), currentProfile.ic, null, hardLimits.minIC(), hardLimits.maxIC(), 0.1, DecimalFormat("0.0"), save) - basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal, "BASAL", resourceHelper.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, 10.0, 0.01, DecimalFormat("0.00"), save) + basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", resourceHelper.gs(R.string.basal_label) + ": " + sumLabel(), currentProfile.basal, null, pumpDescription.basalMinimumRate, 10.0, 0.01, DecimalFormat("0.00"), save) if (units == Constants.MGDL) { TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf, "ISF", resourceHelper.gs(R.string.isf_label), currentProfile.isf, null, HardLimits.MIN_ISF, HardLimits.MAX_ISF, 1.0, DecimalFormat("0"), save) TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target, "TARGET", resourceHelper.gs(R.string.target_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_TARGET_BG[0].toDouble(), HardLimits.VERY_HARD_LIMIT_TARGET_BG[1].toDouble(), 1.0, DecimalFormat("0"), save) @@ -162,6 +165,9 @@ class LocalProfileFragment : DaggerFragment() { } } }) + localProfilePlugin.profile?.getSpecificProfile(spinner?.selectedItem.toString())?.let { + binding.basalGraph.show(ProfileSealed.Pure(it)) + } binding.profileAdd.setOnClickListener { if (localProfilePlugin.isEdited) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt index 12d657fe79..86b56591ff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfilePlugin.kt @@ -1,6 +1,10 @@ package info.nightscout.androidaps.plugins.profile.local +import android.content.Context import androidx.fragment.app.FragmentActivity +import androidx.work.Worker +import androidx.work.WorkerParameters +import androidx.work.workDataOf import dagger.android.HasAndroidInjector import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R @@ -12,7 +16,8 @@ import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload +import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged +import info.nightscout.androidaps.receivers.DataWorker import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DecimalFormatter import info.nightscout.androidaps.utils.HardLimits @@ -35,7 +40,6 @@ class LocalProfilePlugin @Inject constructor( resourceHelper: ResourceHelper, private val sp: SP, private val profileFunction: ProfileFunction, - private val nsUpload: NSUpload, private val activePlugin: ActivePlugin, private val hardLimits: HardLimits, private val dateUtil: DateUtil @@ -144,7 +148,7 @@ class LocalProfilePlugin @Inject constructor( if (name.contains(".")) namesOK = false } if (namesOK) - rawProfile?.let { nsUpload.uploadProfileStore(it.data) } + sp.putLong(R.string.key_local_profile_last_change, dateUtil.now()) else activity?.let { OKDialog.show(it, "", resourceHelper.gs(R.string.profilenamecontainsdot)) @@ -167,61 +171,64 @@ class LocalProfilePlugin @Inject constructor( p.dia = sp.getDouble(localProfileNumbered + "dia", Constants.defaultDIA) try { p.ic = JSONArray(sp.getString(localProfileNumbered + "ic", defaultArray)) - } catch (e1: JSONException) { - try { - p.ic = JSONArray(defaultArray) - } catch (ignored: JSONException) { - } - aapsLogger.error("Exception", e1) - } - - try { p.isf = JSONArray(sp.getString(localProfileNumbered + "isf", defaultArray)) - } catch (e1: JSONException) { - try { - p.isf = JSONArray(defaultArray) - } catch (ignored: JSONException) { - } - aapsLogger.error("Exception", e1) - } - - try { p.basal = JSONArray(sp.getString(localProfileNumbered + "basal", defaultArray)) - } catch (e1: JSONException) { - try { - p.basal = JSONArray(defaultArray) - } catch (ignored: JSONException) { - } - aapsLogger.error("Exception", e1) - } - - try { p.targetLow = JSONArray(sp.getString(localProfileNumbered + "targetlow", defaultArray)) - } catch (e1: JSONException) { - try { - p.targetLow = JSONArray(defaultArray) - } catch (ignored: JSONException) { - } - aapsLogger.error("Exception", e1) - } - - try { p.targetHigh = JSONArray(sp.getString(localProfileNumbered + "targethigh", defaultArray)) - } catch (e1: JSONException) { - try { - p.targetHigh = JSONArray(defaultArray) - } catch (ignored: JSONException) { - } - aapsLogger.error("Exception", e1) + profiles.add(p) + } catch (e: JSONException) { + aapsLogger.error("Exception", e) } - - profiles.add(p) } + // create at least one profile if doesn't exist + if (profiles.size < 1) profiles.add(defaultProfile()) isEdited = false numOfProfiles = profiles.size createAndStoreConvertedProfile() } + @Synchronized + fun loadFromStore(store: ProfileStore) { + try { + val newProfiles: ArrayList = ArrayList() + for (p in store.getProfileList()) { + store.getSpecificProfile(p.toString())?.let { + val sp = copyFrom(it, p.toString()) + sp.name = p.toString() + newProfiles.add(sp) + } + } + if (newProfiles.size > 0) { + profiles = newProfiles + numOfProfiles = profiles.size + currentProfileIndex = 0 + isEdited = false + createAndStoreConvertedProfile() + aapsLogger.debug(LTag.PROFILE, "Accepted ${profiles.size} profiles") + rxBus.send(EventLocalProfileChanged()) + } else + aapsLogger.debug(LTag.PROFILE, "ProfileStore not accepted") + } catch (e: Exception) { + aapsLogger.error("Error loading ProfileStore", e) + } + } + + private fun defaultProfile(): SingleProfile = + SingleProfile().also { p -> + p.name = Constants.LOCAL_PROFILE + p.mgdl = profileFunction.getUnits() == GlucoseUnit.MGDL + p.dia = Constants.defaultDIA + try { + p.ic = JSONArray(defaultArray) + p.isf = JSONArray(defaultArray) + p.basal = JSONArray(defaultArray) + p.targetLow = JSONArray(defaultArray) + p.targetHigh = JSONArray(defaultArray) + } catch (e: JSONException) { + aapsLogger.error("Exception", e) + } + } + fun copyFrom(pureProfile: PureProfile, newName: String): SingleProfile { var verifiedName = newName if (rawProfile?.getSpecificProfile(newName) != null) { @@ -380,4 +387,36 @@ class LocalProfilePlugin @Inject constructor( get() = rawProfile?.getDefaultProfile()?.let { DecimalFormatter.to2Decimal(ProfileSealed.Pure(it).percentageBasalSum()) + "U " } ?: "INVALID" + + // cannot be inner class because of needed injection + class NSProfileWorker( + context: Context, + params: WorkerParameters + ) : Worker(context, params) { + + @Inject lateinit var injector: HasAndroidInjector + @Inject lateinit var aapsLogger: AAPSLogger + @Inject lateinit var rxBus: RxBusWrapper + @Inject lateinit var dateUtil: DateUtil + @Inject lateinit var dataWorker: DataWorker + @Inject lateinit var sp: SP + @Inject lateinit var config: Config + @Inject lateinit var localProfilePlugin: LocalProfilePlugin + + init { + (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) + } + + override fun doWork(): Result { + val profileJson = dataWorker.pickupJSONObject(inputData.getLong(DataWorker.STORE_KEY, -1)) + ?: return Result.failure(workDataOf("Error" to "missing input data")) + if (sp.getBoolean(R.string.key_ns_receive_profile_store, false) || config.NSCLIENT) { + localProfilePlugin.loadFromStore(ProfileStore(injector, profileJson, dateUtil)) + aapsLogger.debug(LTag.PROFILE, "Received profileStore: $profileJson") + return Result.success(workDataOf("Data" to profileJson.toString())) + } + return Result.success() + } + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfileFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfileFragment.kt deleted file mode 100644 index ea46599693..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfileFragment.kt +++ /dev/null @@ -1,170 +0,0 @@ -package info.nightscout.androidaps.plugins.profile.ns - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.ArrayAdapter -import dagger.android.support.DaggerFragment -import info.nightscout.androidaps.R -import info.nightscout.androidaps.data.ProfileSealed -import info.nightscout.androidaps.database.entities.UserEntry.Action -import info.nightscout.androidaps.database.entities.UserEntry.Sources -import info.nightscout.androidaps.database.entities.ValueWithUnit -import info.nightscout.androidaps.databinding.NsprofileFragmentBinding -import info.nightscout.androidaps.interfaces.ActivePlugin -import info.nightscout.androidaps.interfaces.Config -import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.logging.UserEntryLogger -import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.DecimalFormatter -import info.nightscout.androidaps.utils.FabricPrivacy -import info.nightscout.androidaps.utils.alertDialogs.OKDialog -import info.nightscout.androidaps.utils.resources.ResourceHelper -import info.nightscout.androidaps.utils.rx.AapsSchedulers -import io.reactivex.disposables.CompositeDisposable -import io.reactivex.rxkotlin.plusAssign -import javax.inject.Inject - -class NSProfileFragment : DaggerFragment() { - - @Inject lateinit var rxBus: RxBusWrapper - @Inject lateinit var resourceHelper: ResourceHelper - @Inject lateinit var fabricPrivacy: FabricPrivacy - @Inject lateinit var profileFunction: ProfileFunction - @Inject lateinit var nsProfilePlugin: NSProfilePlugin - @Inject lateinit var aapsSchedulers: AapsSchedulers - @Inject lateinit var dateUtil: DateUtil - @Inject lateinit var uel: UserEntryLogger - @Inject lateinit var activePlugin: ActivePlugin - @Inject lateinit var config: Config - - private var disposable: CompositeDisposable = CompositeDisposable() - - private var _binding: NsprofileFragmentBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. - private val binding get() = _binding!! - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View { - _binding = NsprofileFragmentBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - binding.profileviewer.closeLayout.close.visibility = View.GONE // not needed for fragment - - binding.profileswitch.setOnClickListener { - val name = binding.spinner.selectedItem?.toString() ?: "" - nsProfilePlugin.profile?.let { store -> - store.getSpecificProfile(name)?.let { - activity?.let { activity -> - OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.nsprofile), - resourceHelper.gs(R.string.activate_profile) + ": " + name + " ?", Runnable { - uel.log(Action.PROFILE_SWITCH, Sources.NSProfile, - ValueWithUnit.SimpleString(name), - ValueWithUnit.Percent(100)) - profileFunction.createProfileSwitch(store, name, 0, 100, 0, dateUtil.now()) - }) - } - } - } - } - - binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { - override fun onNothingSelected(parent: AdapterView<*>?) { - if (_binding == null) return - binding.profileviewer.invalidprofile.visibility = View.VISIBLE - binding.profileviewer.noprofile.visibility = View.VISIBLE - binding.profileviewer.units.text = "" - binding.profileviewer.dia.text = "" - binding.profileviewer.activeprofile.text = "" - binding.profileviewer.ic.text = "" - binding.profileviewer.isf.text = "" - binding.profileviewer.basal.text = "" - binding.profileviewer.basaltotal.text = "" - binding.profileviewer.target.text = "" - binding.profileswitch.visibility = View.GONE - } - - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - if (_binding == null) return - val name = binding.spinner.getItemAtPosition(position).toString() - - binding.profileswitch.visibility = View.GONE - - nsProfilePlugin.profile?.let { store -> - store.getSpecificProfile(name)?.let { profile -> - if (_binding == null) return - val pss = ProfileSealed.Pure(profile) - binding.profileviewer.units.text = pss.units.asText - binding.profileviewer.dia.text = resourceHelper.gs(R.string.format_hours, pss.dia) - binding.profileviewer.activeprofile.text = name - binding.profileviewer.ic.text = pss.getIcList(resourceHelper, dateUtil) - binding.profileviewer.isf.text = pss.getIsfList(resourceHelper, dateUtil) - binding.profileviewer.basal.text = pss.getBasalList(resourceHelper, dateUtil) - binding.profileviewer.basaltotal.text = String.format(resourceHelper.gs(R.string.profile_total), DecimalFormatter.to2Decimal(pss.baseBasalSum())) - binding.profileviewer.target.text = pss.getTargetList(resourceHelper, dateUtil) - binding.profileviewer.basalGraph.show(pss) - if (pss.isValid("NSProfileFragment", activePlugin.activePump, config, resourceHelper, rxBus)) { - binding.profileviewer.invalidprofile.visibility = View.GONE - binding.profileswitch.visibility = View.VISIBLE - } else { - binding.profileviewer.invalidprofile.visibility = View.VISIBLE - binding.profileswitch.visibility = View.GONE - } - } - } - } - } - } - - @Synchronized - override fun onResume() { - super.onResume() - disposable += rxBus - .toObservable(EventNSProfileUpdateGUI::class.java) - .observeOn(aapsSchedulers.main) - .subscribe({ updateGUI() }, fabricPrivacy::logException) - updateGUI() - } - - @Synchronized - override fun onPause() { - super.onPause() - disposable.clear() - } - - @Synchronized - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - @Synchronized - fun updateGUI() { - if (_binding == null) return - binding.profileviewer.noprofile.visibility = View.VISIBLE - - nsProfilePlugin.profile?.let { profileStore -> - context?.let { context -> - val profileList = profileStore.getProfileList() - val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) - binding.spinner.adapter = adapter - // set selected to actual profile - for (p in profileList.indices) { - if (profileList[p] == profileFunction.getProfileName()) - binding.spinner.setSelection(p) - } - binding.profileviewer.noprofile.visibility = View.GONE - } - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.kt deleted file mode 100644 index e2cf6875a7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/NSProfilePlugin.kt +++ /dev/null @@ -1,110 +0,0 @@ -package info.nightscout.androidaps.plugins.profile.ns - -import android.content.Context -import androidx.work.Worker -import androidx.work.WorkerParameters -import androidx.work.workDataOf -import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.interfaces.Config -import info.nightscout.androidaps.R -import info.nightscout.androidaps.events.EventProfileStoreChanged -import info.nightscout.androidaps.interfaces.PluginBase -import info.nightscout.androidaps.interfaces.PluginDescription -import info.nightscout.androidaps.interfaces.PluginType -import info.nightscout.androidaps.interfaces.ProfileSource -import info.nightscout.androidaps.interfaces.ProfileStore -import info.nightscout.androidaps.logging.AAPSLogger -import info.nightscout.androidaps.logging.LTag -import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart -import info.nightscout.androidaps.plugins.profile.ns.events.EventNSProfileUpdateGUI -import info.nightscout.androidaps.receivers.DataWorker -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.resources.ResourceHelper -import info.nightscout.androidaps.utils.sharedPreferences.SP -import org.json.JSONObject -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NSProfilePlugin @Inject constructor( - injector: HasAndroidInjector, - aapsLogger: AAPSLogger, - private val rxBus: RxBusWrapper, - resourceHelper: ResourceHelper, - private val sp: SP, - private val dateUtil: DateUtil, - config: Config -) : PluginBase(PluginDescription() - .mainType(PluginType.PROFILE) - .fragmentClass(NSProfileFragment::class.java.name) - .pluginIcon(R.drawable.ic_nightscout_profile) - .pluginName(R.string.nsprofile) - .shortName(R.string.profileviewer_shortname) - .alwaysEnabled(config.NSCLIENT) - .alwaysVisible(config.NSCLIENT) - .showInList(!config.NSCLIENT) - .description(R.string.description_profile_nightscout), - aapsLogger, resourceHelper, injector -), ProfileSource { - - override var profile: ProfileStore? = null - - override val profileName: String? - get() = profile?.getDefaultProfileName() - - override fun onStart() { - super.onStart() - loadNSProfile() - } - - private fun storeNSProfile() { - sp.putString("profile", profile!!.data.toString()) - aapsLogger.debug(LTag.PROFILE, "Storing profile") - } - - private fun loadNSProfile() { - aapsLogger.debug(LTag.PROFILE, "Loading stored profile") - val profileString = sp.getStringOrNull("profile", null) - if (profileString != null) { - aapsLogger.debug(LTag.PROFILE, "Loaded profile: $profileString") - profile = ProfileStore(injector, JSONObject(profileString), dateUtil) - } else { - aapsLogger.debug(LTag.PROFILE, "Stored profile not found") - // force restart of nsclient to fetch profile - rxBus.send(EventNSClientRestart()) - } - } - - - // cannot be inner class because of needed injection - class NSProfileWorker( - context: Context, - params: WorkerParameters - ) : Worker(context, params) { - - @Inject lateinit var injector: HasAndroidInjector - @Inject lateinit var nsProfilePlugin: NSProfilePlugin - @Inject lateinit var aapsLogger: AAPSLogger - @Inject lateinit var rxBus: RxBusWrapper - @Inject lateinit var dateUtil: DateUtil - @Inject lateinit var dataWorker: DataWorker - - init { - (context.applicationContext as HasAndroidInjector).androidInjector().inject(this) - } - - override fun doWork(): Result { - val profileString = dataWorker.pickupJSONObject(inputData.getLong(DataWorker.STORE_KEY, -1)) - ?: return Result.failure(workDataOf("Error" to "missing input data")) - nsProfilePlugin.profile = ProfileStore(injector, profileString, dateUtil) - nsProfilePlugin.storeNSProfile() - if (nsProfilePlugin.isEnabled()) { - rxBus.send(EventProfileStoreChanged()) - rxBus.send(EventNSProfileUpdateGUI()) - } - aapsLogger.debug(LTag.PROFILE, "Received profileStore: ${nsProfilePlugin.profile}") - return Result.success() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/events/EventNSProfileUpdateGUI.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/events/EventNSProfileUpdateGUI.kt deleted file mode 100644 index 0d7c320876..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/ns/events/EventNSProfileUpdateGUI.kt +++ /dev/null @@ -1,5 +0,0 @@ -package info.nightscout.androidaps.plugins.profile.ns.events - -import info.nightscout.androidaps.events.EventUpdateGui - -class EventNSProfileUpdateGUI : EventUpdateGui() diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.kt index b8761d0f3a..3612901830 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/mdi/MDIPlugin.kt @@ -61,7 +61,7 @@ class MDIPlugin @Inject constructor( override fun waitForDisconnectionInSeconds(): Int = 0 override fun stopConnecting() {} override fun getPumpStatus(reason: String) {} - override fun setNewBasalProfile(profile: Profile): PumpEnactResult = PumpEnactResult(injector).success(true) + override fun setNewBasalProfile(profile: Profile): PumpEnactResult = PumpEnactResult(injector).success(true).enacted(true) override fun isThisProfileSet(profile: Profile): Boolean = false override fun lastDataTime(): Long = System.currentTimeMillis() override val baseBasalRate: Double = 0.0 diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt index 984b137af2..76da448516 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/virtual/VirtualPumpPlugin.kt @@ -4,12 +4,12 @@ import android.os.SystemClock import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreference import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.R import info.nightscout.androidaps.data.DetailedBolusInfo -import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.events.EventPreferenceChange +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag @@ -25,8 +25,6 @@ import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.InstanceId.instanceId import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.TimeChangeType -import info.nightscout.androidaps.extensions.convertedToAbsolute -import info.nightscout.androidaps.extensions.plannedRemainingMinutes import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.sharedPreferences.SP @@ -139,7 +137,6 @@ open class VirtualPumpPlugin @Inject constructor( override fun isHandshakeInProgress(): Boolean = false override fun connect(reason: String) { - //if (!Config.NSCLIENT) NSUpload.uploadDeviceStatus() lastDataTime = System.currentTimeMillis() } @@ -152,12 +149,9 @@ open class VirtualPumpPlugin @Inject constructor( override fun setNewBasalProfile(profile: Profile): PumpEnactResult { lastDataTime = System.currentTimeMillis() + rxBus.send(EventNewNotification(Notification(Notification.PROFILE_SET_OK, resourceHelper.gs(R.string.profile_set_ok), Notification.INFO, 60))) // Do nothing here. we are using database profile - val result = PumpEnactResult(injector) - result.success = true - val notification = Notification(Notification.PROFILE_SET_OK, resourceHelper.gs(R.string.profile_set_ok), Notification.INFO, 60) - rxBus.send(EventNewNotification(notification)) - return result + return PumpEnactResult(injector).success(true).enacted(true) } override fun isThisProfileSet(profile: Profile): Boolean { @@ -400,7 +394,7 @@ open class VirtualPumpPlugin @Inject constructor( aapsLogger.debug(LTag.PUMP, "Pump in configuration: $pumpType, PumpType object: $pumpTypeNew") if (this.pumpType == pumpTypeNew) return aapsLogger.debug(LTag.PUMP, "New pump configuration found ($pumpTypeNew), changing from previous (${this.pumpType})") - pumpDescription.setPumpDescription(pumpTypeNew) + pumpDescription.fillFor(pumpTypeNew) this.pumpType = pumpTypeNew } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt index d9c2f221e5..52874bb335 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/NSClientSourcePlugin.kt @@ -5,12 +5,12 @@ import androidx.work.Worker import androidx.work.WorkerParameters import androidx.work.workDataOf import dagger.android.HasAndroidInjector -import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.interfaces.BgSource +import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.PluginBase import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType @@ -115,7 +115,7 @@ class NSClientSourcePlugin @Inject constructor( override fun doWork(): Result { var ret = Result.success() - if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_autobackfill, true) && !dexcomPlugin.isEnabled()) return Result.success() + if (!nsClientSourcePlugin.isEnabled() && !sp.getBoolean(R.string.key_ns_receive_cgm, true) && !dexcomPlugin.isEnabled()) return Result.success() val sgvs = dataWorker.pickupJSONArray(inputData.getLong(DataWorker.STORE_KEY, -1)) ?: return Result.failure(workDataOf("Error" to "missing input data")) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentService.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentService.java index 3619e209f6..a8293002f8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentService.java @@ -105,25 +105,10 @@ public class TreatmentService extends OrmLiteBaseService impleme return wrapped.queryForAll(); } - public void delete(Treatment data) throws SQLException { - wrapped.delete(data); - openHumansUploader.enqueueTreatment(data, true); - } - - public void create(Treatment data) throws SQLException { - wrapped.create(data); - openHumansUploader.enqueueTreatment(data); - } - public Treatment queryForId(long id) throws SQLException { return wrapped.queryForId(id); } - public void update(Treatment data) throws SQLException { - wrapped.update(data); - openHumansUploader.enqueueTreatment(data); - } - public QueryBuilder queryBuilder() { return wrapped.queryBuilder(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java index b57e49323d..d994c0475f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/TreatmentsPlugin.java @@ -1,9 +1,6 @@ package info.nightscout.androidaps.plugins.treatments; import android.content.Context; -import android.os.Bundle; - -import com.google.firebase.analytics.FirebaseAnalytics; import java.util.List; import java.util.stream.Collectors; @@ -14,11 +11,9 @@ import javax.inject.Singleton; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.activities.ErrorHelperActivity; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.database.AppRepository; import info.nightscout.androidaps.db.ExtendedBolus; -import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.interfaces.ActivePlugin; @@ -29,14 +24,8 @@ import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.interfaces.TreatmentServiceInterface; import info.nightscout.androidaps.interfaces.TreatmentsInterface; -import info.nightscout.androidaps.interfaces.UpdateReturn; import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; -import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin; -import info.nightscout.androidaps.plugins.pump.medtronic.data.MedtronicHistoryData; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -47,14 +36,10 @@ import io.reactivex.disposables.CompositeDisposable; @Singleton public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface { - private final Context context; - private final AapsSchedulers aapsSchedulers; private final SP sp; private final RxBusWrapper rxBus; - private final ResourceHelper resourceHelper; private final ProfileFunction profileFunction; private final ActivePlugin activePlugin; - private final NSUpload nsUpload; private final FabricPrivacy fabricPrivacy; private final DateUtil dateUtil; private final DatabaseHelperInterface databaseHelper; @@ -63,8 +48,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface private final CompositeDisposable disposable = new CompositeDisposable(); protected TreatmentServiceInterface service; - private final boolean useNewPumpSync = false; - @Inject public TreatmentsPlugin( @@ -77,7 +60,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface SP sp, ProfileFunction profileFunction, ActivePlugin activePlugin, - NSUpload nsUpload, FabricPrivacy fabricPrivacy, DateUtil dateUtil, DatabaseHelperInterface databaseHelper, @@ -94,16 +76,12 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface .setDefault(), aapsLogger, resourceHelper, injector ); - this.resourceHelper = resourceHelper; - this.context = context; this.rxBus = rxBus; - this.aapsSchedulers = aapsSchedulers; this.sp = sp; this.profileFunction = profileFunction; this.activePlugin = activePlugin; this.fabricPrivacy = fabricPrivacy; this.dateUtil = dateUtil; - this.nsUpload = nsUpload; this.databaseHelper = databaseHelper; this.repository = repository; } @@ -232,48 +210,38 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface @Deprecated @Override public boolean addToHistoryTempBasal(TemporaryBasal tempBasal) { - if (useNewPumpSync) { - throw new IllegalStateException("Migrate to new DB"); - } else { - getAapsLogger().error("!!! addToHistoryTempBasal: Need to migrate to new DB"); - } - + throw new IllegalStateException("Migrate to new DB"); +/* //log.debug("Adding new TemporaryBasal record" + tempBasal.toString()); boolean newRecordCreated = databaseHelper.createOrUpdate(tempBasal); if (newRecordCreated) { -// if (tempBasal.durationInMinutes == 0) -// nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); -// else if (tempBasal.isAbsolute) -// nsUpload.uploadTempBasalStartAbsolute(tempBasal, null); -// else -// nsUpload.uploadTempBasalStartPercent(tempBasal, profileFunction.getProfile(tempBasal.date)); + if (tempBasal.durationInMinutes == 0) + nsUpload.uploadTempBasalEnd(tempBasal.date, false, tempBasal.pumpId); + else if (tempBasal.isAbsolute) + nsUpload.uploadTempBasalStartAbsolute(tempBasal, null); + else + nsUpload.uploadTempBasalStartPercent(tempBasal, profileFunction.getProfile(tempBasal.date)); } return newRecordCreated; + */ } @Deprecated public TreatmentUpdateReturn createOrUpdateMedtronic(Treatment treatment, boolean fromNightScout) { - if (useNewPumpSync) { - throw new IllegalStateException("Migrate to new DB"); - } else { - getAapsLogger().error("!!! createOrUpdateMedtronic: Need to migrate to new DB"); - } - + throw new IllegalStateException("Migrate to new DB"); +/* UpdateReturn resultRecord = getService().createOrUpdateMedtronic(treatment, fromNightScout); return new TreatmentUpdateReturn(resultRecord.getSuccess(), resultRecord.getNewRecord()); + */ } // return true if new record is created @Deprecated @Override public boolean addToHistoryTreatment(DetailedBolusInfo detailedBolusInfo, boolean allowUpdate) { - if (useNewPumpSync) { - throw new IllegalStateException("Migrate to new DB"); - } else { - getAapsLogger().error("!!! addToHistoryTreatment: Need to migrate to new DB"); - } - + throw new IllegalStateException("Migrate to new DB"); +/* boolean medtronicPump = activePlugin.getActivePump() instanceof MedtronicPumpPlugin; getAapsLogger().debug(MedtronicHistoryData.doubleBolusDebug, LTag.DATATREATMENTS, "DoubleBolusDebug: addToHistoryTreatment::isMedtronicPump={} " + medtronicPump); @@ -317,10 +285,8 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface getService().createOrUpdateMedtronic(carbsTreatment, false); //log.debug("Adding new Treatment record" + carbsTreatment); } - - getAapsLogger().error("nsUpload.uploadTreatmentRecord(detailedBolusInfo) not possible."); -// if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING) -// nsUpload.uploadTreatmentRecord(detailedBolusInfo); + if (newRecordCreated && detailedBolusInfo.getBolusType() != DetailedBolusInfo.BolusType.PRIMING) + nsUpload.uploadTreatmentRecord(detailedBolusInfo); if (!allowUpdate && !creatOrUpdateResult.getSuccess()) { getAapsLogger().error("Treatment could not be added to DB", new Exception()); @@ -336,6 +302,6 @@ public class TreatmentsPlugin extends PluginBase implements TreatmentsInterface } return newRecordCreated; - + */ } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt index 9b846f613f..2ba8978ea8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsBolusCarbsFragment.kt @@ -156,7 +156,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { }) } } - val nsUploadOnly = sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode() + val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_insulin, false) || !sp.getBoolean(R.string.key_ns_receive_carbs, false) || !buildHelper.isEngineeringMode() if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE binding.showInvalidated.setOnCheckedChangeListener { _, _ -> rxBus.send(EventTreatmentUpdateGui()) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt index 4c90c80e08..ce75d4dc3c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsCareportalFragment.kt @@ -102,7 +102,7 @@ class TreatmentsCareportalFragment : DaggerFragment() { } } - val nsUploadOnly = sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode() + val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || !buildHelper.isEngineeringMode() if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE binding.showInvalidated.setOnCheckedChangeListener { _, _ -> rxBus.send(EventTreatmentUpdateGui()) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt index 1ca2b2d2ac..796c811f0f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsProfileSwitchFragment.kt @@ -21,12 +21,10 @@ import info.nightscout.androidaps.dialogs.ProfileViewerDialog import info.nightscout.androidaps.events.EventProfileSwitchChanged import info.nightscout.androidaps.extensions.getCustomizedName import info.nightscout.androidaps.extensions.toVisibility -import info.nightscout.androidaps.interfaces.UploadQueueInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper -import info.nightscout.androidaps.plugins.general.nsclient.NSUpload import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin @@ -55,8 +53,6 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { @Inject lateinit var localProfilePlugin: LocalProfilePlugin @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var fabricPrivacy: FabricPrivacy - @Inject lateinit var nsUpload: NSUpload - @Inject lateinit var uploadQueue: UploadQueueInterface @Inject lateinit var dateUtil: DateUtil @Inject lateinit var buildHelper: BuildHelper @Inject lateinit var aapsSchedulers: AapsSchedulers @@ -103,7 +99,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { } } } - if (sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode()) binding.refreshFromNightscout.visibility = View.GONE + if (!sp.getBoolean(R.string.key_ns_receive_profile_switch, false) || !buildHelper.isEngineeringMode()) binding.refreshFromNightscout.visibility = View.GONE binding.showInvalidated.setOnCheckedChangeListener { _, _ -> rxBus.send(EventTreatmentUpdateGui()) } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt index 78ead608b6..d603263fc1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/treatments/fragments/TreatmentsTempTargetFragment.kt @@ -23,7 +23,6 @@ import info.nightscout.androidaps.databinding.TreatmentsTemptargetFragmentBindin import info.nightscout.androidaps.databinding.TreatmentsTemptargetItemBinding import info.nightscout.androidaps.events.EventTempTargetChange import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.androidaps.interfaces.UploadQueueInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger @@ -58,7 +57,6 @@ class TreatmentsTempTargetFragment : DaggerFragment() { @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var profileFunction: ProfileFunction @Inject lateinit var resourceHelper: ResourceHelper - @Inject lateinit var uploadQueue: UploadQueueInterface @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var translator: Translator @Inject lateinit var dateUtil: DateUtil @@ -99,7 +97,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() { }) } } - val nsUploadOnly = sp.getBoolean(R.string.key_ns_upload_only, true) || !buildHelper.isEngineeringMode() + val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_temp_target, false) || !buildHelper.isEngineeringMode() if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.INVISIBLE binding.showInvalidated.setOnCheckedChangeListener { _, _ -> rxBus.send(EventTreatmentUpdateGui()) @@ -151,7 +149,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() { _binding = null } - private inner class RecyclerViewAdapter internal constructor(private var tempTargetList: List) : RecyclerView.Adapter() { + private inner class RecyclerViewAdapter(private var tempTargetList: List) : RecyclerView.Adapter() { private val dbRecord = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() private val currentlyActiveTarget = if (dbRecord is ValueWrapper.Existing) dbRecord.value else null diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.kt b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.kt index c795c988fb..7759448f6f 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandSetProfile.kt @@ -6,6 +6,7 @@ import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.CommandQueueProvider +import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.logging.LTag @@ -25,9 +26,10 @@ class CommandSetProfile constructor( @Inject lateinit var activePlugin: ActivePlugin @Inject lateinit var dateUtil: DateUtil @Inject lateinit var commandQueue: CommandQueueProvider + @Inject lateinit var config: Config override fun execute() { - if (commandQueue.isThisProfileSet(profile)) { + if (commandQueue.isThisProfileSet(profile) && repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing) { aapsLogger.debug(LTag.PUMPQUEUE, "Correct profile already set. profile: $profile") callback?.result(PumpEnactResult(injector).success(true).enacted(false))?.run() return @@ -37,7 +39,7 @@ class CommandSetProfile constructor( callback?.result(r)?.run() // Send SMS notification if ProfileSwitch is coming from NS val profileSwitch = repository.getEffectiveProfileSwitchActiveAt(dateUtil.now()).blockingGet() - if (profileSwitch is ValueWrapper.Existing && r.enacted && hasNsId) { + if (profileSwitch is ValueWrapper.Existing && r.enacted && hasNsId && !config.NSCLIENT) { if (smsCommunicatorPlugin.isEnabled(PluginType.GENERAL)) smsCommunicatorPlugin.sendNotificationToAllNumbers(resourceHelper.gs(R.string.profile_set_ok)) } diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt index afc160dd53..1b78360966 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt +++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.kt @@ -129,7 +129,8 @@ class KeepAliveReceiver : DaggerBroadcastReceiver() { if (lastReadStatus != 0L && lastReadStatus > System.currentTimeMillis() - T.mins(5).msecs()) { localAlertUtils.checkPumpUnreachableAlarm(lastConnection, isStatusOutdated, loopPlugin.isDisconnected) } - if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE)) { + if (!pump.isThisProfileSet(profile) && !commandQueue.isRunning(Command.CommandType.BASAL_PROFILE) + || profileFunction.getProfile() == null) { rxBus.send(EventProfileSwitchChanged()) } else if (isStatusOutdated && !pump.isBusy()) { lastReadStatus = System.currentTimeMillis() diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt index 469b30269d..b65a284149 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt @@ -19,11 +19,8 @@ import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesFragm import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus -import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService import info.nightscout.androidaps.plugins.profile.local.LocalProfileFragment import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin -import info.nightscout.androidaps.plugins.profile.ns.NSProfileFragment -import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange import info.nightscout.androidaps.plugins.pump.omnipod.dash.OmnipodDashPumpPlugin import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin @@ -53,7 +50,6 @@ class SWDefinition @Inject constructor( private val configBuilder: ConfigBuilder, private val loopPlugin: LoopPlugin, private val nsClientPlugin: NSClientPlugin, - private val nsProfilePlugin: NSProfilePlugin, private val importExportPrefs: ImportExportPrefs, private val androidPermission: AndroidPermission, private val cryptoUtil: CryptoUtil, @@ -189,8 +185,8 @@ class SWDefinition @Inject constructor( .label(R.string.status) .initialStatus(nsClientPlugin.status) ) - .validator { nsClientPlugin.nsClientService != null && NSClientService.isConnected && NSClientService.hasWriteAuth } - .visibility { !(nsClientPlugin.nsClientService != null && NSClientService.isConnected && NSClientService.hasWriteAuth) } + .validator { nsClientPlugin.nsClientService?.isConnected == true && nsClientPlugin.nsClientService?.hasWriteAuth == true } + .visibility { !(nsClientPlugin.nsClientService?.isConnected == true && nsClientPlugin.nsClientService?.hasWriteAuth == true) } private val screenPatientName = SWScreen(injector, R.string.patient_name) .skippable(true) .add(SWInfoText(injector) @@ -254,27 +250,14 @@ class SWDefinition @Inject constructor( .option(PluginType.BGSOURCE, R.string.configbuilder_bgsource_description) .label(R.string.configbuilder_bgsource)) .add(SWBreak(injector)) - private val screenProfile = SWScreen(injector, R.string.configbuilder_profile) - .skippable(false) - .add(SWInfoText(injector) - .label(R.string.setupwizard_profile_description)) - .add(SWBreak(injector)) - .add(SWPlugin(injector, this) - .option(PluginType.PROFILE, R.string.configbuilder_profile_description) - .label(R.string.configbuilder_profile)) - private val screenNsProfile = SWScreen(injector, R.string.nsprofile) - .skippable(false) - .add(SWInfoText(injector) - .label(R.string.adjustprofileinns)) - .add(SWFragment(injector, this) - .add(NSProfileFragment())) - .validator { nsProfilePlugin.profile?.getDefaultProfile()?.let { ProfileSealed.Pure(it).isValid("StartupWizard", activePlugin.activePump, config, resourceHelper, rxBus) } ?: false } - .visibility { nsProfilePlugin.isEnabled() } private val screenLocalProfile = SWScreen(injector, R.string.localprofile) .skippable(false) .add(SWFragment(injector, this) .add(LocalProfileFragment())) - .validator { localProfilePlugin.profile?.getDefaultProfile()?.let { ProfileSealed.Pure(it).isValid("StartupWizard", activePlugin.activePump, config, resourceHelper, rxBus) } ?: false } + .validator { + localProfilePlugin.profile?.getDefaultProfile()?.let { ProfileSealed.Pure(it).isValid("StartupWizard", activePlugin.activePump, config, resourceHelper, rxBus) } + ?: false + } .visibility { localProfilePlugin.isEnabled() } private val screenProfileSwitch = SWScreen(injector, R.string.careportal_profileswitch) .skippable(false) @@ -399,8 +382,6 @@ class SWDefinition @Inject constructor( .add(screenAge) .add(screenInsulin) .add(screenBgSource) - .add(screenProfile) - .add(screenNsProfile) .add(screenLocalProfile) .add(screenProfileSwitch) .add(screenPump) @@ -428,8 +409,6 @@ class SWDefinition @Inject constructor( .add(screenAge) .add(screenInsulin) .add(screenBgSource) - .add(screenProfile) - .add(screenNsProfile) .add(screenLocalProfile) .add(screenProfileSwitch) .add(screenPump) diff --git a/app/src/main/res/layout/localprofile_fragment.xml b/app/src/main/res/layout/localprofile_fragment.xml index 5893faa7b6..920d10f4ee 100644 --- a/app/src/main/res/layout/localprofile_fragment.xml +++ b/app/src/main/res/layout/localprofile_fragment.xml @@ -92,8 +92,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" - android:weightSum="5" - android:paddingBottom="10dp"> + android:paddingBottom="10dp" + android:weightSum="5"> + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical"> + + + + + + + android:text="@string/activate_profile" /> - - - - - - - - - - -