Merge branch 'master' into insight-dev
# Conflicts: # app/src/main/java/info/nightscout/androidaps/plugins/Overview/notifications/Notification.java
This commit is contained in:
commit
d1f7086651
|
@ -63,7 +63,7 @@ android {
|
|||
targetSdkVersion 25
|
||||
multiDexEnabled true
|
||||
versionCode 1500
|
||||
version "2.0"
|
||||
version "2.0-insight"
|
||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
|
||||
|
@ -197,6 +197,7 @@ dependencies {
|
|||
implementation "com.google.android.gms:play-services-wearable:7.5.0"
|
||||
implementation(name: "android-edittext-validator-v1.3.4-mod", ext: "aar")
|
||||
implementation(name: "sightparser-release", ext: "aar")
|
||||
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
||||
|
||||
implementation("com.google.android:flexbox:0.3.0") {
|
||||
exclude group: "com.android.support"
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
android:name=".MainApp"
|
||||
android:allowBackup="true"
|
||||
android:icon="${appIcon}"
|
||||
android:roundIcon="${appIconRound}"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="${appIconRound}"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<meta-data
|
||||
|
@ -181,6 +181,8 @@
|
|||
android:exported="false" />
|
||||
|
||||
<service android:name=".plugins.Persistentnotification.DummyService" />
|
||||
<service android:name=".plugins.PumpInsightLocal.connection_service.InsightConnectionService" />
|
||||
<service android:name=".plugins.PumpInsightLocal.InsightAlertService" />
|
||||
|
||||
<meta-data
|
||||
android:name="io.fabric.ApiKey"
|
||||
|
@ -189,12 +191,25 @@
|
|||
<activity
|
||||
android:name=".setupwizard.SetupWizardActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:label="@string/title_activity_setup_wizard" />
|
||||
android:label="@string/title_activity_setup_wizard"
|
||||
android:theme="@style/AppTheme.NoActionBar" />
|
||||
|
||||
<activity android:name=".activities.SingleFragmentActivity"
|
||||
<activity
|
||||
android:name=".activities.SingleFragmentActivity"
|
||||
android:theme="@style/AppTheme" />
|
||||
<activity android:name=".plugins.Maintenance.activities.LogSettingActivity"></activity>
|
||||
<activity
|
||||
android:name=".plugins.PumpInsightLocal.activities.InsightPairingActivity"
|
||||
android:theme="@style/AppTheme"
|
||||
android:label="@string/insight_pairing" />
|
||||
<activity
|
||||
android:name=".plugins.PumpInsightLocal.activities.InsightAlertActivity"
|
||||
android:label="@string/pump_alert"
|
||||
android:theme="@style/InsightAlertDialog" />
|
||||
<activity
|
||||
android:name=".plugins.PumpInsightLocal.activities.InsightPairingInformationActivity"
|
||||
android:theme="@style/AppTheme"
|
||||
android:label="@string/pairing_information" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -59,6 +59,7 @@ import info.nightscout.androidaps.plugins.PumpDanaRKorean.DanaRKoreanPlugin;
|
|||
import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaRv2.DanaRv2Plugin;
|
||||
import info.nightscout.androidaps.plugins.PumpInsight.InsightPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.LocalInsightPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.androidaps.plugins.Sensitivity.SensitivityAAPSPlugin;
|
||||
|
@ -157,9 +158,10 @@ public class MainApp extends Application {
|
|||
if (Config.PUMPDRIVERS) pluginsList.add(DanaRKoreanPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(DanaRv2Plugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(DanaRSPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getInstance());
|
||||
pluginsList.add(CareportalPlugin.getPlugin());
|
||||
if (Config.PUMPDRIVERS && engineeringMode)
|
||||
pluginsList.add(InsightPlugin.getPlugin()); // <-- Enable Insight plugin here
|
||||
/*if (Config.PUMPDRIVERS && engineeringMode)
|
||||
pluginsList.add(InsightPlugin.getPlugin());*/
|
||||
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
|
||||
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
|
||||
pluginsList.add(VirtualPumpPlugin.getPlugin());
|
||||
|
|
|
@ -50,6 +50,9 @@ import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventNewHistor
|
|||
import info.nightscout.androidaps.plugins.NSClientInternal.NSUpload;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.activities.DanaRNSHistorySync;
|
||||
import info.nightscout.androidaps.plugins.PumpDanaR.comm.RecordTypes;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightBolusID;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightHistoryOffset;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.database.InsightPumpID;
|
||||
import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin;
|
||||
import info.nightscout.utils.JsonHelper;
|
||||
import info.nightscout.utils.PercentageSplitter;
|
||||
|
@ -76,8 +79,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
public static final String DATABASE_CAREPORTALEVENTS = "CareportalEvents";
|
||||
public static final String DATABASE_PROFILESWITCHES = "ProfileSwitches";
|
||||
public static final String DATABASE_TDDS = "TDDs";
|
||||
public static final String DATABASE_INSIGHT_HISTORY_OFFSETS = "InsightHistoryOffsets";
|
||||
public static final String DATABASE_INSIGHT_BOLUS_IDS = "InsightBolusIDs";
|
||||
public static final String DATABASE_INSIGHT_PUMP_IDS = "InsightPumpIDs";
|
||||
|
||||
private static final int DATABASE_VERSION = 9;
|
||||
private static final int DATABASE_VERSION = 10;
|
||||
|
||||
public static Long earliestDataChange = null;
|
||||
|
||||
|
@ -122,6 +128,9 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
TableUtils.createTableIfNotExists(connectionSource, CareportalEvent.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, ProfileSwitch.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, TDD.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
|
||||
} catch (SQLException e) {
|
||||
log.error("Can't create database", e);
|
||||
throw new RuntimeException(e);
|
||||
|
@ -138,6 +147,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
log.debug("Upgrading database from v7 to v8");
|
||||
} else if (oldVersion == 8 && newVersion == 9) {
|
||||
log.debug("Upgrading database from v8 to v9");
|
||||
} else if (oldVersion == 9 && newVersion == 10) {
|
||||
TableUtils.createTableIfNotExists(connectionSource, InsightHistoryOffset.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, InsightBolusID.class);
|
||||
TableUtils.createTableIfNotExists(connectionSource, InsightPumpID.class);
|
||||
} else {
|
||||
log.info(DatabaseHelper.class.getName(), "onUpgrade");
|
||||
TableUtils.dropTable(connectionSource, TempTarget.class, true);
|
||||
|
@ -327,6 +340,18 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return getDao(ProfileSwitch.class);
|
||||
}
|
||||
|
||||
private Dao<InsightPumpID, Long> getDaoInsightPumpID() throws SQLException {
|
||||
return getDao(InsightPumpID.class);
|
||||
}
|
||||
|
||||
private Dao<InsightBolusID, Long> getDaoInsightBolusID() throws SQLException {
|
||||
return getDao(InsightBolusID.class);
|
||||
}
|
||||
|
||||
private Dao<InsightHistoryOffset, String> getDaoInsightHistoryOffset() throws SQLException {
|
||||
return getDao(InsightHistoryOffset.class);
|
||||
}
|
||||
|
||||
public static long roundDateToSec(long date) {
|
||||
long rounded = date - date % 1000;
|
||||
if (rounded != date)
|
||||
|
@ -1149,6 +1174,17 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return false;
|
||||
}
|
||||
|
||||
public ExtendedBolus getExtendedBolusByPumpId(long pumpId) {
|
||||
try {
|
||||
return getDaoExtendedBolus().queryBuilder()
|
||||
.where().eq("pumpId", pumpId)
|
||||
.queryForFirst();
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void delete(ExtendedBolus extendedBolus) {
|
||||
try {
|
||||
getDaoExtendedBolus().delete(extendedBolus);
|
||||
|
@ -1656,5 +1692,67 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
|
|||
return null;
|
||||
}
|
||||
|
||||
// ---------------- Insight history handling ---------------
|
||||
|
||||
public void createOrUpdate(InsightHistoryOffset offset) {
|
||||
try {
|
||||
getDaoInsightHistoryOffset().createOrUpdate(offset);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public InsightHistoryOffset getInsightHistoryOffset(String pumpSerial) {
|
||||
try {
|
||||
return getDaoInsightHistoryOffset().queryForId(pumpSerial);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void createOrUpdate(InsightBolusID bolusID) {
|
||||
try {
|
||||
getDaoInsightBolusID().createOrUpdate(bolusID);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public InsightBolusID getInsightBolusID(String pumpSerial, int bolusID, long timestamp) {
|
||||
try {
|
||||
return getDaoInsightBolusID().queryBuilder()
|
||||
.where().eq("pumpSerial", pumpSerial)
|
||||
.and().eq("bolusID", bolusID)
|
||||
.and().between("timestamp", timestamp - 259200000, timestamp + 259200000)
|
||||
.queryForFirst();
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void createOrUpdate(InsightPumpID pumpID) {
|
||||
try {
|
||||
getDaoInsightPumpID().createOrUpdate(pumpID);
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public InsightPumpID getPumpStoppedEvent(String pumpSerial, long before) {
|
||||
try {
|
||||
return getDaoInsightPumpID().queryBuilder()
|
||||
.orderBy("timestamp", false)
|
||||
.where().eq("pumpSerial", pumpSerial)
|
||||
.and().eq("eventType", "PumpStopped")
|
||||
.and().lt("timestamp", before)
|
||||
.queryForFirst();
|
||||
} catch (SQLException e) {
|
||||
log.error("Unhandled exception", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------- Food handling ---------------
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ public class Notification {
|
|||
public static final int MEDTRONIC_PUMP_ALARM = 44;
|
||||
public static final int RILEYLINK_CONNECTION = 45;
|
||||
public static final int PERMISSION_PHONESTATE = 46;
|
||||
public static final int INSIGHT_DATE_TIME_UPDATED = 47;
|
||||
|
||||
|
||||
public int id;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal;
|
||||
|
||||
import info.nightscout.androidaps.events.EventUpdateGui;
|
||||
|
||||
public class EventLocalInsightUpdateGUI extends EventUpdateGui {
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioManager;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Vibrator;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.activities.InsightAlertActivity;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.ConfirmAlertMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control.SnoozeAlertMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetActiveAlertMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service.InsightConnectionService;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.Alert;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertStatus;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertType;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ExceptionTranslator;
|
||||
|
||||
public class InsightAlertService extends Service implements InsightConnectionService.StateCallback {
|
||||
|
||||
private LocalBinder localBinder = new LocalBinder();
|
||||
private boolean connectionRequested;
|
||||
private final Object $alertLock = new Object[0];
|
||||
private Alert alert;
|
||||
private Thread thread;
|
||||
private InsightAlertActivity alertActivity;
|
||||
private Ringtone ringtone;
|
||||
private Vibrator vibrator;
|
||||
private boolean vibrating;
|
||||
private InsightConnectionService connectionService;
|
||||
private long ignoreTimestamp;
|
||||
private AlertType ignoreType;
|
||||
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||
connectionService = ((InsightConnectionService.LocalBinder) binder).getService();
|
||||
connectionService.registerStateCallback(InsightAlertService.this);
|
||||
stateChanged(connectionService.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
connectionService = null;
|
||||
}
|
||||
};
|
||||
|
||||
private void retrieveRingtone() {
|
||||
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
|
||||
ringtone = RingtoneManager.getRingtone(this, uri);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
ringtone.setAudioAttributes(new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
|
||||
.setLegacyStreamType(AudioManager.STREAM_RING).build());
|
||||
} else ringtone.setStreamType(AudioManager.STREAM_RING);
|
||||
}
|
||||
|
||||
public Alert getAlert() {
|
||||
synchronized ($alertLock) {
|
||||
return alert;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAlertActivity(InsightAlertActivity alertActivity) {
|
||||
this.alertActivity = alertActivity;
|
||||
}
|
||||
|
||||
public void ignore(AlertType alertType) {
|
||||
synchronized ($alertLock) {
|
||||
if (alertType == null) {
|
||||
ignoreTimestamp = 0;
|
||||
ignoreType = null;
|
||||
} else {
|
||||
ignoreTimestamp = System.currentTimeMillis();
|
||||
ignoreType = alertType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return localBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
|
||||
bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (thread != null) thread.interrupt();
|
||||
unbindService(serviceConnection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(InsightState state) {
|
||||
if (state == InsightState.CONNECTED) {
|
||||
thread = new Thread(this::queryActiveAlert);
|
||||
thread.start();
|
||||
|
||||
} else if (thread != null) thread.interrupt();
|
||||
}
|
||||
|
||||
private void queryActiveAlert() {
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
Alert alert = connectionService.requestMessage(new GetActiveAlertMessage()).await().getAlert();
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
connectionService.withdrawConnectionRequest(thread);
|
||||
break;
|
||||
}
|
||||
synchronized ($alertLock) {
|
||||
if ((this.alert == null && alert != null)
|
||||
|| (this.alert != null && alert == null)
|
||||
|| (this.alert != null && alert != null && !this.alert.equals(alert))) {
|
||||
if (this.alert != null && (alert == null || this.alert.getAlertId() != alert.getAlertId())) stopAlerting();
|
||||
this.alert = alert;
|
||||
if (alertActivity != null && alert != null)
|
||||
new Handler(Looper.getMainLooper()).post(() -> alertActivity.update(alert));
|
||||
}
|
||||
if (alert == null) {
|
||||
stopAlerting();
|
||||
if (connectionRequested) {
|
||||
connectionService.withdrawConnectionRequest(this);
|
||||
connectionRequested = false;
|
||||
}
|
||||
if (alertActivity != null)
|
||||
new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish());
|
||||
} else if (!(alert.getAlertType() == ignoreType && System.currentTimeMillis() - ignoreTimestamp < 10000)) {
|
||||
if (alert.getAlertStatus() == AlertStatus.ACTIVE) alert();
|
||||
else stopAlerting();
|
||||
if (!connectionRequested) {
|
||||
connectionService.requestConnection(this);
|
||||
connectionRequested = true;
|
||||
}
|
||||
if (alertActivity == null) {
|
||||
Intent intent = new Intent(InsightAlertService.this, InsightAlertActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
new Handler(Looper.getMainLooper()).post(() -> startActivity(intent));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ignored) {
|
||||
connectionService.withdrawConnectionRequest(thread);
|
||||
break;
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (connectionRequested) {
|
||||
connectionService.withdrawConnectionRequest(thread);
|
||||
connectionRequested = false;
|
||||
}
|
||||
if (alertActivity != null)
|
||||
new Handler(Looper.getMainLooper()).post(() -> alertActivity.finish());
|
||||
stopAlerting();
|
||||
thread = null;
|
||||
}
|
||||
|
||||
private void alert() {
|
||||
if (!vibrating) {
|
||||
vibrator.vibrate(new long[] {0, 1000, 1000}, 0);
|
||||
vibrating = true;
|
||||
}
|
||||
if (ringtone == null || !ringtone.isPlaying()) {
|
||||
retrieveRingtone();
|
||||
ringtone.play();
|
||||
}
|
||||
}
|
||||
|
||||
private void stopAlerting() {
|
||||
if (vibrating) {
|
||||
vibrator.cancel();
|
||||
vibrating = false;
|
||||
}
|
||||
if (ringtone != null && ringtone.isPlaying()) ringtone.stop();
|
||||
}
|
||||
|
||||
public void mute() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
SnoozeAlertMessage snoozeAlertMessage = new SnoozeAlertMessage();
|
||||
snoozeAlertMessage.setAlertID(alert.getAlertId());
|
||||
connectionService.requestMessage(snoozeAlertMessage).await();
|
||||
} catch (Exception e) {
|
||||
ExceptionTranslator.makeToast(InsightAlertService.this, e);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public void confirm() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
ConfirmAlertMessage confirmAlertMessage = new ConfirmAlertMessage();
|
||||
confirmAlertMessage.setAlertID(alert.getAlertId());
|
||||
connectionService.requestMessage(confirmAlertMessage).await();
|
||||
} catch (Exception e) {
|
||||
ExceptionTranslator.makeToast(InsightAlertService.this, e);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public class LocalBinder extends Binder {
|
||||
public InsightAlertService getService() {
|
||||
return InsightAlertService.this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,295 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.Common.SubscriberFragment;
|
||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.TBROverNotificationBlock;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBasalRate;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBolus;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveTBR;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.CartridgeStatus;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.TotalDailyDose;
|
||||
import info.nightscout.androidaps.queue.Callback;
|
||||
import info.nightscout.utils.DateUtil;
|
||||
import info.nightscout.utils.DecimalFormatter;
|
||||
|
||||
public class LocalInsightFragment extends SubscriberFragment implements View.OnClickListener {
|
||||
|
||||
private boolean viewsCreated;
|
||||
private Button operatingMode;
|
||||
private Button tbrOverNotification;
|
||||
private Button refresh;
|
||||
private LinearLayout statusItemContainer = null;
|
||||
|
||||
private Callback operatingModeCallback;
|
||||
private Callback tbrOverNotificationCallback;
|
||||
private Callback refreshCallback;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.local_insight_fragment, container, false);
|
||||
statusItemContainer = view.findViewById(R.id.status_item_container);
|
||||
tbrOverNotification = view.findViewById(R.id.tbr_over_notification);
|
||||
tbrOverNotification.setOnClickListener(this);
|
||||
operatingMode = view.findViewById(R.id.operating_mode);
|
||||
operatingMode.setOnClickListener(this);
|
||||
refresh = view.findViewById(R.id.refresh);
|
||||
refresh.setOnClickListener(this);
|
||||
viewsCreated = true;
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
viewsCreated = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == operatingMode) {
|
||||
if (LocalInsightPlugin.getInstance().getOperatingMode() != null) {
|
||||
operatingMode.setEnabled(false);
|
||||
operatingModeCallback = new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
operatingModeCallback = null;
|
||||
updateGUI();
|
||||
});
|
||||
}
|
||||
};
|
||||
switch (LocalInsightPlugin.getInstance().getOperatingMode()) {
|
||||
case PAUSED:
|
||||
case STOPPED:
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().startPump(operatingModeCallback);
|
||||
break;
|
||||
case STARTED:
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().stopPump(operatingModeCallback);
|
||||
}
|
||||
}
|
||||
} else if (v == tbrOverNotification) {
|
||||
TBROverNotificationBlock notificationBlock = LocalInsightPlugin.getInstance().getTBROverNotificationBlock();
|
||||
if (notificationBlock != null) {
|
||||
tbrOverNotification.setEnabled(false);
|
||||
tbrOverNotificationCallback = new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
tbrOverNotificationCallback = null;
|
||||
updateGUI();
|
||||
});
|
||||
}
|
||||
};
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue()
|
||||
.setTBROverNotification(tbrOverNotificationCallback, !notificationBlock.isEnabled());
|
||||
}
|
||||
} else if (v == refresh) {
|
||||
refresh.setEnabled(false);
|
||||
refreshCallback = new Callback() {
|
||||
@Override
|
||||
public void run() {
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
refreshCallback = null;
|
||||
updateGUI();
|
||||
});
|
||||
}
|
||||
};
|
||||
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("InsightRefreshButton", refreshCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onUpdateGUIEvent(EventLocalInsightUpdateGUI event) {
|
||||
updateGUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateGUI() {
|
||||
if (!viewsCreated) return;
|
||||
statusItemContainer.removeAllViews();
|
||||
if (!LocalInsightPlugin.getInstance().isInitialized()) {
|
||||
operatingMode.setVisibility(View.GONE);
|
||||
tbrOverNotification.setVisibility(View.GONE);
|
||||
refresh.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
refresh.setVisibility(View.VISIBLE);
|
||||
refresh.setEnabled(refreshCallback == null);
|
||||
TBROverNotificationBlock notificationBlock = LocalInsightPlugin.getInstance().getTBROverNotificationBlock();
|
||||
tbrOverNotification.setVisibility(notificationBlock == null ? View.GONE : View.VISIBLE);
|
||||
if (notificationBlock != null)
|
||||
tbrOverNotification.setText(notificationBlock.isEnabled() ? R.string.disable_tbr_over_notification : R.string.enable_tbr_over_notification);
|
||||
tbrOverNotification.setEnabled(tbrOverNotificationCallback == null);
|
||||
List<View> statusItems = new ArrayList<>();
|
||||
getConnectionStatusItem(statusItems);
|
||||
getLastConnectedItem(statusItems);
|
||||
getOperatingModeItem(statusItems);
|
||||
getBatteryStatusItem(statusItems);
|
||||
getCartridgeStatusItem(statusItems);
|
||||
getTDDItems(statusItems);
|
||||
getBaseBasalRateItem(statusItems);
|
||||
getTBRItem(statusItems);
|
||||
getBolusItems(statusItems);
|
||||
for (int i = 0; i < statusItems.size(); i++) {
|
||||
statusItemContainer.addView(statusItems.get(i));
|
||||
if (i != statusItems.size() - 1)
|
||||
getLayoutInflater().inflate(R.layout.local_insight_status_delimitter, statusItemContainer);
|
||||
}
|
||||
}
|
||||
|
||||
private View getStatusItem(String label, String value) {
|
||||
View statusItem = getLayoutInflater().inflate(R.layout.local_insight_status_item, null);
|
||||
((TextView) statusItem.findViewById(R.id.label)).setText(label);
|
||||
((TextView) statusItem.findViewById(R.id.value)).setText(value);
|
||||
return statusItem;
|
||||
}
|
||||
|
||||
private void getConnectionStatusItem(List<View> statusItems) {
|
||||
int string = 0;
|
||||
switch (LocalInsightPlugin.getInstance().getConnectionService().getState()) {
|
||||
case NOT_PAIRED:
|
||||
string = R.string.not_paired;
|
||||
break;
|
||||
case DISCONNECTED:
|
||||
string = R.string.disconnected;
|
||||
break;
|
||||
case CONNECTING:
|
||||
case SATL_CONNECTION_REQUEST:
|
||||
case SATL_KEY_REQUEST:
|
||||
case SATL_SYN_REQUEST:
|
||||
case SATL_VERIFY_CONFIRM_REQUEST:
|
||||
case SATL_VERIFY_DISPLAY_REQUEST:
|
||||
case APP_ACTIVATE_PARAMETER_SERVICE:
|
||||
case APP_ACTIVATE_STATUS_SERVICE:
|
||||
case APP_BIND_MESSAGE:
|
||||
case APP_CONNECT_MESSAGE:
|
||||
case APP_FIRMWARE_VERSIONS:
|
||||
case APP_SYSTEM_IDENTIFICATION:
|
||||
case AWAITING_CODE_CONFIRMATION:
|
||||
string = R.string.connecting;
|
||||
break;
|
||||
case CONNECTED:
|
||||
string = R.string.connected;
|
||||
break;
|
||||
case RECOVERING:
|
||||
string = R.string.recovering;
|
||||
break;
|
||||
}
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.insight_status), MainApp.gs(string)));
|
||||
}
|
||||
|
||||
private void getLastConnectedItem(List<View> statusItems) {
|
||||
switch (LocalInsightPlugin.getInstance().getConnectionService().getState()) {
|
||||
case CONNECTED:
|
||||
case NOT_PAIRED:
|
||||
return;
|
||||
default:
|
||||
long lastConnection = LocalInsightPlugin.getInstance().getConnectionService().getLastConnected();
|
||||
if (lastConnection == 0) return;
|
||||
int min = (int) ((System.currentTimeMillis() - lastConnection) / 60000);
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.last_connected), DateUtil.timeString(lastConnection)));
|
||||
}
|
||||
}
|
||||
|
||||
private void getOperatingModeItem(List<View> statusItems) {
|
||||
if (LocalInsightPlugin.getInstance().getOperatingMode() == null) {
|
||||
operatingMode.setVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
int string = 0;
|
||||
operatingMode.setVisibility(View.VISIBLE);
|
||||
operatingMode.setEnabled(operatingModeCallback == null);
|
||||
switch (LocalInsightPlugin.getInstance().getOperatingMode()) {
|
||||
case STARTED:
|
||||
operatingMode.setText(R.string.stop_pump);
|
||||
string = R.string.started;
|
||||
break;
|
||||
case STOPPED:
|
||||
operatingMode.setText(R.string.start_pump);
|
||||
string = R.string.stopped;
|
||||
break;
|
||||
case PAUSED:
|
||||
operatingMode.setText(R.string.start_pump);
|
||||
string = R.string.paused;
|
||||
break;
|
||||
}
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.operating_mode), MainApp.gs(string)));
|
||||
}
|
||||
|
||||
private void getBatteryStatusItem(List<View> statusItems) {
|
||||
if (LocalInsightPlugin.getInstance().getBatteryStatus() == null) return;
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.pump_battery_label),
|
||||
LocalInsightPlugin.getInstance().getBatteryStatus().getBatteryAmount() + "%"));
|
||||
}
|
||||
|
||||
private void getCartridgeStatusItem(List<View> statusItems) {
|
||||
CartridgeStatus cartridgeStatus = LocalInsightPlugin.getInstance().getCartridgeStatus();
|
||||
if (cartridgeStatus == null) return;
|
||||
String status;
|
||||
if (cartridgeStatus.isInserted())
|
||||
status = DecimalFormatter.to2Decimal(LocalInsightPlugin.getInstance().getCartridgeStatus().getRemainingAmount()) + "U";
|
||||
else status = MainApp.gs(R.string.not_inserted);
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.pump_reservoir_label), status));
|
||||
}
|
||||
|
||||
private void getTDDItems(List<View> statusItems) {
|
||||
if (LocalInsightPlugin.getInstance().getTotalDailyDose() == null) return;
|
||||
TotalDailyDose tdd = LocalInsightPlugin.getInstance().getTotalDailyDose();
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_bolus), DecimalFormatter.to2Decimal(tdd.getBolus())));
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_basal), DecimalFormatter.to2Decimal(tdd.getBasal())));
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.tdd_total), DecimalFormatter.to2Decimal(tdd.getBolusAndBasal())));
|
||||
}
|
||||
|
||||
private void getBaseBasalRateItem(List<View> statusItems) {
|
||||
if (LocalInsightPlugin.getInstance().getActiveBasalRate() == null) return;
|
||||
ActiveBasalRate activeBasalRate = LocalInsightPlugin.getInstance().getActiveBasalRate();
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.pump_basebasalrate_label),
|
||||
DecimalFormatter.to2Decimal(activeBasalRate.getActiveBasalRate()) + " U/h (" + activeBasalRate.getActiveBasalProfileName() + ")"));
|
||||
}
|
||||
|
||||
private void getTBRItem(List<View> statusItems) {
|
||||
if (LocalInsightPlugin.getInstance().getActiveTBR() == null) return;
|
||||
ActiveTBR activeTBR = LocalInsightPlugin.getInstance().getActiveTBR();
|
||||
statusItems.add(getStatusItem(MainApp.gs(R.string.pump_tempbasal_label),
|
||||
MainApp.gs(R.string.tbr_formatter, activeTBR.getPercentage(), activeTBR.getInitialDuration() - activeTBR.getRemainingDuration(), activeTBR.getInitialDuration())));
|
||||
}
|
||||
|
||||
private void getBolusItems(List<View> statusItems) {
|
||||
if (LocalInsightPlugin.getInstance().getActiveBoluses() == null) return;
|
||||
for (ActiveBolus activeBolus : LocalInsightPlugin.getInstance().getActiveBoluses()) {
|
||||
String label;
|
||||
switch (activeBolus.getBolusType()) {
|
||||
case MULTIWAVE:
|
||||
label = MainApp.gs(R.string.multiwave_bolus);
|
||||
break;
|
||||
case EXTENDED:
|
||||
label = MainApp.gs(R.string.extended_bolus);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
statusItems.add(getStatusItem(label, MainApp.gs(R.string.eb_formatter, activeBolus.getRemainingAmount(), activeBolus.getInitialAmount(), activeBolus.getRemainingDuration())));
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,257 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.activities;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Html;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.InsightAlertService;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.Alert;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertStatus;
|
||||
|
||||
public class InsightAlertActivity extends AppCompatActivity {
|
||||
|
||||
private Alert alert;
|
||||
private InsightAlertService alertService;
|
||||
|
||||
private ImageView icon;
|
||||
private TextView errorCode;
|
||||
private TextView errorTitle;
|
||||
private TextView errorDescription;
|
||||
private Button mute;
|
||||
private Button confirm;
|
||||
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||
alertService = ((InsightAlertService.LocalBinder) binder).getService();
|
||||
alertService.setAlertActivity(InsightAlertActivity.this);
|
||||
alert = alertService.getAlert();
|
||||
if (alert == null) finish();
|
||||
update(alert);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
alertService = null;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_insight_alert);
|
||||
|
||||
bindService(new Intent(this, InsightAlertService.class), serviceConnection, BIND_AUTO_CREATE);
|
||||
|
||||
icon = findViewById(R.id.icon);
|
||||
errorCode = findViewById(R.id.error_code);
|
||||
errorTitle = findViewById(R.id.error_title);
|
||||
errorDescription = findViewById(R.id.error_description);
|
||||
mute = findViewById(R.id.mute);
|
||||
confirm = findViewById(R.id.confirm);
|
||||
|
||||
setFinishOnTouchOutside(false);
|
||||
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
||||
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
|
||||
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
|
||||
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
|
||||
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
|
||||
layoutParams.screenBrightness = 1.0F;
|
||||
getWindow().setAttributes(layoutParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
alertService.setAlertActivity(null);
|
||||
unbindService(serviceConnection);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public void update(Alert alert) {
|
||||
this.alert = alert;
|
||||
mute.setEnabled(true);
|
||||
mute.setVisibility(alert.getAlertStatus() == AlertStatus.SNOOZED ? View.GONE : View.VISIBLE);
|
||||
confirm.setEnabled(true);
|
||||
int icon = 0;
|
||||
int code = 0;
|
||||
int title = 0;
|
||||
String description = null;
|
||||
switch (alert.getAlertCategory()) {
|
||||
case ERROR:
|
||||
icon = R.drawable.ic_error;
|
||||
break;
|
||||
case MAINTENANCE:
|
||||
icon = R.drawable.ic_maintenance;
|
||||
break;
|
||||
case WARNING:
|
||||
icon = R.drawable.ic_warning;
|
||||
break;
|
||||
case REMINDER:
|
||||
icon = R.drawable.ic_reminder;
|
||||
break;
|
||||
}
|
||||
DecimalFormat decimalFormat = new DecimalFormat("##0.00");
|
||||
int hours = alert.getTBRDuration() / 60;
|
||||
int minutes = alert.getTBRDuration() - hours * 60;
|
||||
switch (alert.getAlertType()) {
|
||||
case REMINDER_01:
|
||||
code = R.string.alert_r1_code;
|
||||
title = R.string.alert_r1_title;
|
||||
break;
|
||||
case REMINDER_02:
|
||||
code = R.string.alert_r2_code;
|
||||
title = R.string.alert_r2_title;
|
||||
break;
|
||||
case REMINDER_03:
|
||||
code = R.string.alert_r3_code;
|
||||
title = R.string.alert_r3_title;
|
||||
break;
|
||||
case REMINDER_04:
|
||||
code = R.string.alert_r4_code;
|
||||
title = R.string.alert_r4_title;
|
||||
break;
|
||||
case REMINDER_07:
|
||||
code = R.string.alert_r7_code;
|
||||
title = R.string.alert_r7_title;
|
||||
description = getString(R.string.alert_r7_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes));
|
||||
break;
|
||||
case WARNING_31:
|
||||
code = R.string.alert_w31_code;
|
||||
title = R.string.alert_w31_title;
|
||||
description = getString(R.string.alert_w31_description, decimalFormat.format(alert.getCartridgeAmount()));
|
||||
break;
|
||||
case WARNING_32:
|
||||
code = R.string.alert_w32_code;
|
||||
title = R.string.alert_w32_title;
|
||||
description = getString(R.string.alert_w32_description);
|
||||
break;
|
||||
case WARNING_33:
|
||||
code = R.string.alert_w33_code;
|
||||
title = R.string.alert_w33_title;
|
||||
description = getString(R.string.alert_w33_description);
|
||||
break;
|
||||
case WARNING_34:
|
||||
code = R.string.alert_w34_code;
|
||||
title = R.string.alert_w34_title;
|
||||
description = getString(R.string.alert_w34_description);
|
||||
break;
|
||||
case WARNING_36:
|
||||
code = R.string.alert_w36_code;
|
||||
title = R.string.alert_w36_title;
|
||||
description = getString(R.string.alert_w36_description, alert.getTBRAmount(), new DecimalFormat("#0").format(hours) + ":" + new DecimalFormat("00").format(minutes));
|
||||
break;
|
||||
case WARNING_38:
|
||||
code = R.string.alert_w38_code;
|
||||
title = R.string.alert_w38_title;
|
||||
description = getString(R.string.alert_w38_description, decimalFormat.format(alert.getProgrammedBolusAmount()), decimalFormat.format(alert.getDeliveredBolusAmount()));
|
||||
break;
|
||||
case WARNING_39:
|
||||
code = R.string.alert_w39_code;
|
||||
title = R.string.alert_w39_title;
|
||||
break;
|
||||
case MAINTENANCE_20:
|
||||
code = R.string.alert_m20_code;
|
||||
title = R.string.alert_m20_title;
|
||||
description = getString(R.string.alert_m20_description);
|
||||
break;
|
||||
case MAINTENANCE_21:
|
||||
code = R.string.alert_m21_code;
|
||||
title = R.string.alert_m21_title;
|
||||
description = getString(R.string.alert_m21_description);
|
||||
break;
|
||||
case MAINTENANCE_22:
|
||||
code = R.string.alert_m22_code;
|
||||
title = R.string.alert_m22_title;
|
||||
description = getString(R.string.alert_m22_description);
|
||||
break;
|
||||
case MAINTENANCE_23:
|
||||
code = R.string.alert_m23_code;
|
||||
title = R.string.alert_m23_title;
|
||||
description = getString(R.string.alert_m23_description);
|
||||
break;
|
||||
case MAINTENANCE_24:
|
||||
code = R.string.alert_m24_code;
|
||||
title = R.string.alert_m24_title;
|
||||
description = getString(R.string.alert_m24_description);
|
||||
break;
|
||||
case MAINTENANCE_25:
|
||||
code = R.string.alert_m25_code;
|
||||
title = R.string.alert_m25_title;
|
||||
description = getString(R.string.alert_m25_description);
|
||||
break;
|
||||
case MAINTENANCE_26:
|
||||
code = R.string.alert_m26_code;
|
||||
title = R.string.alert_m26_title;
|
||||
description = getString(R.string.alert_m26_description);
|
||||
break;
|
||||
case MAINTENANCE_27:
|
||||
code = R.string.alert_m27_code;
|
||||
title = R.string.alert_m27_title;
|
||||
description = getString(R.string.alert_m27_description);
|
||||
break;
|
||||
case MAINTENANCE_28:
|
||||
code = R.string.alert_m28_code;
|
||||
title = R.string.alert_m28_title;
|
||||
description = getString(R.string.alert_m28_description);
|
||||
break;
|
||||
case MAINTENANCE_29:
|
||||
code = R.string.alert_m29_code;
|
||||
title = R.string.alert_m29_title;
|
||||
description = getString(R.string.alert_m29_description);
|
||||
break;
|
||||
case MAINTENANCE_30:
|
||||
code = R.string.alert_m30_code;
|
||||
title = R.string.alert_m30_title;
|
||||
description = getString(R.string.alert_m30_description);
|
||||
break;
|
||||
case ERROR_6:
|
||||
code = R.string.alert_e6_code;
|
||||
title = R.string.alert_e6_title;
|
||||
description = getString(R.string.alert_e6_description);
|
||||
break;
|
||||
case ERROR_10:
|
||||
code = R.string.alert_e10_code;
|
||||
title = R.string.alert_e10_title;
|
||||
description = getString(R.string.alert_e10_description);
|
||||
break;
|
||||
case ERROR_13:
|
||||
code = R.string.alert_e13_code;
|
||||
title = R.string.alert_e13_title;
|
||||
description = getString(R.string.alert_e13_description);
|
||||
break;
|
||||
}
|
||||
this.icon.setImageDrawable(ContextCompat.getDrawable(this, icon));
|
||||
this.errorCode.setText(code);
|
||||
this.errorTitle.setText(title);
|
||||
if (description == null) this.errorDescription.setVisibility(View.GONE);
|
||||
else {
|
||||
this.errorDescription.setVisibility(View.VISIBLE);
|
||||
this.errorDescription.setText(Html.fromHtml(description));
|
||||
}
|
||||
}
|
||||
|
||||
public void muteClicked(View view) {
|
||||
mute.setEnabled(false);
|
||||
alertService.mute();
|
||||
}
|
||||
|
||||
public void confirmClicked(View view) {
|
||||
mute.setEnabled(false);
|
||||
confirm.setEnabled(false);
|
||||
alertService.confirm();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.activities;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service.InsightConnectionService;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ExceptionTranslator;
|
||||
|
||||
public class InsightPairingActivity extends AppCompatActivity implements InsightConnectionService.StateCallback, View.OnClickListener, InsightConnectionService.ExceptionCallback {
|
||||
|
||||
private boolean scanning;
|
||||
private LinearLayout deviceSearchSection;
|
||||
private TextView pleaseWaitSection;
|
||||
private LinearLayout codeCompareSection;
|
||||
private LinearLayout pairingCompletedSection;
|
||||
private Button yes;
|
||||
private Button no;
|
||||
private TextView code;
|
||||
private Button exit;
|
||||
private RecyclerView deviceList;
|
||||
private DeviceAdapter deviceAdapter = new DeviceAdapter();
|
||||
|
||||
private InsightConnectionService service;
|
||||
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||
service = ((InsightConnectionService.LocalBinder) binder).getService();
|
||||
if (service.isPaired()) return;
|
||||
else {
|
||||
service.requestConnection(InsightPairingActivity.this);
|
||||
service.registerStateCallback(InsightPairingActivity.this);
|
||||
service.registerExceptionCallback(InsightPairingActivity.this);
|
||||
stateChanged(service.getState());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_insight_pairing);
|
||||
|
||||
deviceSearchSection = findViewById(R.id.device_search_section);
|
||||
pleaseWaitSection = findViewById(R.id.please_wait_section);
|
||||
codeCompareSection = findViewById(R.id.code_compare_section);
|
||||
pairingCompletedSection = findViewById(R.id.pairing_completed_section);
|
||||
yes = findViewById(R.id.yes);
|
||||
no = findViewById(R.id.no);
|
||||
code = findViewById(R.id.code);
|
||||
exit = findViewById(R.id.exit);
|
||||
deviceList = findViewById(R.id.device_list);
|
||||
|
||||
yes.setOnClickListener(this);
|
||||
no.setOnClickListener(this);
|
||||
exit.setOnClickListener(this);
|
||||
|
||||
deviceList.setLayoutManager(new LinearLayoutManager(this));
|
||||
deviceList.setAdapter(deviceAdapter);
|
||||
|
||||
|
||||
bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (service != null) {
|
||||
service.withdrawConnectionRequest(InsightPairingActivity.this);
|
||||
service.unregisterStateCallback(InsightPairingActivity.this);
|
||||
service.unregisterExceptionCallback(InsightPairingActivity.this);
|
||||
}
|
||||
unbindService(serviceConnection);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (service != null && service.getState() == InsightState.NOT_PAIRED) startBLScan();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
stopBLScan();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(InsightState state) {
|
||||
runOnUiThread(() -> {
|
||||
switch (state) {
|
||||
case NOT_PAIRED:
|
||||
startBLScan();
|
||||
deviceSearchSection.setVisibility(View.VISIBLE);
|
||||
pleaseWaitSection.setVisibility(View.GONE);
|
||||
codeCompareSection.setVisibility(View.GONE);
|
||||
pairingCompletedSection.setVisibility(View.GONE);
|
||||
break;
|
||||
case CONNECTING:
|
||||
case SATL_CONNECTION_REQUEST:
|
||||
case SATL_KEY_REQUEST:
|
||||
case SATL_VERIFY_DISPLAY_REQUEST:
|
||||
case SATL_VERIFY_CONFIRM_REQUEST:
|
||||
case APP_BIND_MESSAGE:
|
||||
stopBLScan();
|
||||
deviceSearchSection.setVisibility(View.GONE);
|
||||
pleaseWaitSection.setVisibility(View.VISIBLE);
|
||||
codeCompareSection.setVisibility(View.GONE);
|
||||
pairingCompletedSection.setVisibility(View.GONE);
|
||||
break;
|
||||
case AWAITING_CODE_CONFIRMATION:
|
||||
stopBLScan();
|
||||
deviceSearchSection.setVisibility(View.GONE);
|
||||
pleaseWaitSection.setVisibility(View.GONE);
|
||||
codeCompareSection.setVisibility(View.VISIBLE);
|
||||
pairingCompletedSection.setVisibility(View.GONE);
|
||||
code.setText(service.getVerificationString());
|
||||
break;
|
||||
case DISCONNECTED:
|
||||
case CONNECTED:
|
||||
stopBLScan();
|
||||
deviceSearchSection.setVisibility(View.GONE);
|
||||
pleaseWaitSection.setVisibility(View.GONE);
|
||||
codeCompareSection.setVisibility(View.GONE);
|
||||
pairingCompletedSection.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startBLScan() {
|
||||
if (!scanning) {
|
||||
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (!bluetoothAdapter.isEnabled()) bluetoothAdapter.enable();
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
|
||||
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
|
||||
registerReceiver(broadcastReceiver, intentFilter);
|
||||
bluetoothAdapter.startDiscovery();
|
||||
scanning = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopBLScan() {
|
||||
if (scanning) {
|
||||
unregisterReceiver(broadcastReceiver);
|
||||
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
|
||||
scanning = false;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == exit) finish();
|
||||
else if (v == yes) service.confirmVerificationString();
|
||||
else if (v == no) service.rejectVerificationString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExceptionOccur(Exception e) {
|
||||
ExceptionTranslator.makeToast(this, e);
|
||||
}
|
||||
|
||||
private void deviceSelected(BluetoothDevice device) {
|
||||
service.pair(device.getAddress());
|
||||
}
|
||||
|
||||
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
|
||||
BluetoothAdapter.getDefaultAdapter().startDiscovery();
|
||||
else if (action.equals(BluetoothDevice.ACTION_FOUND)) {
|
||||
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
deviceAdapter.addDevice(bluetoothDevice);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private class DeviceAdapter extends RecyclerView.Adapter<DeviceAdapter.ViewHolder> {
|
||||
|
||||
private List<BluetoothDevice> bluetoothDevices = new ArrayList<>();
|
||||
|
||||
public void addDevice(BluetoothDevice bluetoothDevice) {
|
||||
if (!bluetoothDevices.contains(bluetoothDevice)) {
|
||||
bluetoothDevices.add(bluetoothDevice);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
bluetoothDevices.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.bluetooth_device, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
BluetoothDevice bluetoothDevice = bluetoothDevices.get(position);
|
||||
holder.deviceName.setText(bluetoothDevice.getName() == null ? bluetoothDevice.getAddress() : bluetoothDevice.getName());
|
||||
holder.deviceName.setOnClickListener((v) -> deviceSelected(bluetoothDevice));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return bluetoothDevices.size();
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private TextView deviceName;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
deviceName = (TextView) itemView;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.activities;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service.InsightConnectionService;
|
||||
|
||||
public class InsightPairingInformationActivity extends AppCompatActivity {
|
||||
|
||||
private InsightConnectionService connectionService;
|
||||
|
||||
private TextView serialNumber;
|
||||
private TextView releaseSWVersion;
|
||||
private TextView uiProcSWVersion;
|
||||
private TextView pcProcSWVersion;
|
||||
private TextView mdTelSWVersion;
|
||||
private TextView safetyProcSWVersion;
|
||||
private TextView btInfoPageVersion;
|
||||
private TextView bluetoothAddress;
|
||||
private TextView systemIdAppendix;
|
||||
private TextView manufacturingDate;
|
||||
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder binder) {
|
||||
connectionService = ((InsightConnectionService.LocalBinder) binder).getService();
|
||||
if (!connectionService.isPaired()) {
|
||||
overridePendingTransition(0, 0);
|
||||
finish();
|
||||
startActivity(new Intent(InsightPairingInformationActivity.this, InsightPairingActivity.class));
|
||||
} else {
|
||||
serialNumber.setText(connectionService.getPumpSystemIdentification().getSerialNumber());
|
||||
manufacturingDate.setText(connectionService.getPumpSystemIdentification().getManufacturingDate());
|
||||
systemIdAppendix.setText(connectionService.getPumpSystemIdentification().getSystemIdAppendix() + "");
|
||||
releaseSWVersion.setText(connectionService.getPumpFirmwareVersions().getReleaseSWVersion());
|
||||
uiProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getUiProcSWVersion());
|
||||
pcProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getPcProcSWVersion());
|
||||
mdTelSWVersion.setText(connectionService.getPumpFirmwareVersions().getMdTelProcSWVersion());
|
||||
safetyProcSWVersion.setText(connectionService.getPumpFirmwareVersions().getSafetyProcSWVersion());
|
||||
btInfoPageVersion.setText(connectionService.getPumpFirmwareVersions().getBtInfoPageVersion());
|
||||
bluetoothAddress.setText(connectionService.getBluetoothAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
connectionService = null;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_insight_pairing_information);
|
||||
serialNumber = findViewById(R.id.serial_number);
|
||||
releaseSWVersion = findViewById(R.id.release_sw_version);
|
||||
uiProcSWVersion = findViewById(R.id.ui_proc_sw_version);
|
||||
pcProcSWVersion = findViewById(R.id.pc_proc_sw_version);
|
||||
mdTelSWVersion = findViewById(R.id.md_tel_sw_version);
|
||||
safetyProcSWVersion = findViewById(R.id.safety_proc_sw_version);
|
||||
btInfoPageVersion = findViewById(R.id.bt_info_page_version);
|
||||
bluetoothAddress = findViewById(R.id.bluetooth_address);
|
||||
systemIdAppendix = findViewById(R.id.system_id_appendix);
|
||||
manufacturingDate = findViewById(R.id.manufacturing_date);
|
||||
bindService(new Intent(this, InsightConnectionService.class), serviceConnection, BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
unbindService(serviceConnection);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
public void deletePairing(View view) {
|
||||
if (connectionService != null) {
|
||||
connectionService.reset();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.IncompatibleAppVersionException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InvalidAppCRCException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.UnknownAppCommandException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.UnknownServiceException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.app_layer_errors.AppLayerErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.app_layer_errors.UnknownAppLayerErrorCodeException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AppCommandIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AppErrorIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ServiceIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.DataMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.Cryptograph;
|
||||
|
||||
public class AppLayerMessage implements Comparable<AppLayerMessage> {
|
||||
|
||||
private static final byte VERSION = 0x20;
|
||||
|
||||
private final MessagePriority messagePriority;
|
||||
private final boolean inCRC;
|
||||
private final boolean outCRC;
|
||||
private final Service service;
|
||||
|
||||
public AppLayerMessage(MessagePriority messagePriority, boolean inCRC, boolean outCRC, Service service) {
|
||||
this.messagePriority = messagePriority;
|
||||
this.inCRC = inCRC;
|
||||
this.outCRC = outCRC;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
protected ByteBuf getData() {
|
||||
return new ByteBuf(0);
|
||||
}
|
||||
|
||||
protected void parse(ByteBuf byteBuf) throws Exception {
|
||||
|
||||
}
|
||||
|
||||
public ByteBuf serialize(Class<? extends AppLayerMessage> clazz) {
|
||||
byte[] data = getData().getBytes();
|
||||
ByteBuf byteBuf = new ByteBuf(4 + data.length + (outCRC ? 2 : 0));
|
||||
byteBuf.putByte(VERSION);
|
||||
byteBuf.putByte(ServiceIDs.IDS.getID(getService()));
|
||||
byteBuf.putUInt16LE(AppCommandIDs.IDS.getID(clazz));
|
||||
byteBuf.putBytes(data);
|
||||
if (outCRC) byteBuf.putUInt16LE(Cryptograph.calculateCRC(data));
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public static AppLayerMessage deserialize(ByteBuf byteBuf) throws Exception {
|
||||
byte version = byteBuf.readByte();
|
||||
byte service = byteBuf.readByte();
|
||||
int command = byteBuf.readUInt16LE();
|
||||
int error = byteBuf.readUInt16LE();
|
||||
Class<? extends AppLayerMessage> clazz = AppCommandIDs.IDS.getType(command);
|
||||
if (clazz == null) throw new UnknownAppCommandException();
|
||||
if (version != VERSION) throw new IncompatibleAppVersionException();
|
||||
AppLayerMessage message = clazz.newInstance();
|
||||
if (ServiceIDs.IDS.getType(service) == null) throw new UnknownServiceException();
|
||||
if (error != 0) {
|
||||
Class<? extends AppLayerErrorException> exceptionClass = AppErrorIDs.IDS.getType(error);
|
||||
if (exceptionClass == null) throw new UnknownAppLayerErrorCodeException(error);
|
||||
else throw exceptionClass.getConstructor(int.class).newInstance(error);
|
||||
}
|
||||
byte[] data = byteBuf.readBytes(byteBuf.getSize() - (message.inCRC ? 2 : 0));
|
||||
if (message.inCRC && Cryptograph.calculateCRC(data) != byteBuf.readUInt16LE()) throw new InvalidAppCRCException();
|
||||
message.parse(ByteBuf.from(data));
|
||||
return message;
|
||||
}
|
||||
|
||||
public static DataMessage wrap(AppLayerMessage message) {
|
||||
DataMessage dataMessage = new DataMessage();
|
||||
dataMessage.setData(message.serialize(message.getClass()));
|
||||
return dataMessage;
|
||||
}
|
||||
|
||||
public static AppLayerMessage unwrap(DataMessage dataMessage) throws Exception {
|
||||
return deserialize(dataMessage.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AppLayerMessage o) {
|
||||
return messagePriority.compareTo(o.messagePriority);
|
||||
}
|
||||
|
||||
public Service getService() {
|
||||
return this.service;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.ParameterBlock;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ParameterBlockIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ReadParameterBlockMessage extends AppLayerMessage {
|
||||
|
||||
private Class<? extends ParameterBlock> parameterBlockId;
|
||||
private ParameterBlock parameterBlock;
|
||||
private Service service;
|
||||
|
||||
public ReadParameterBlockMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Service getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public void setService(Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(2);
|
||||
byteBuf.putUInt16LE(ParameterBlockIDs.IDS.getID(parameterBlockId));
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) throws Exception {
|
||||
parameterBlock = ParameterBlockIDs.IDS.getType(byteBuf.readUInt16LE()).newInstance();
|
||||
byteBuf.shift(2); //Restriction level
|
||||
parameterBlock.parse(byteBuf);
|
||||
}
|
||||
|
||||
public ParameterBlock getParameterBlock() {
|
||||
return this.parameterBlock;
|
||||
}
|
||||
|
||||
public void setParameterBlockId(Class<? extends ParameterBlock> configurationBlockId) {
|
||||
this.parameterBlockId = configurationBlockId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer;
|
||||
|
||||
public enum Service {
|
||||
|
||||
CONNECTION((short) 0x0000, null),
|
||||
STATUS((short) 0x0100, null),
|
||||
HISTORY((short) 0x0200, null),
|
||||
CONFIGURATION((short) 0x0200, "u+5Fhz6Gw4j1Kkas"),
|
||||
PARAMETER((short) 0x0200, null),
|
||||
REMOTE_CONTROL((short) 0x0100, "MAbcV2X6PVjxuz+R");
|
||||
|
||||
private short version;
|
||||
private String servicePassword;
|
||||
|
||||
Service(short version, String servicePassword) {
|
||||
this.version = version;
|
||||
this.servicePassword = servicePassword;
|
||||
}
|
||||
|
||||
public short getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public String getServicePassword() {
|
||||
return this.servicePassword;
|
||||
}
|
||||
|
||||
public void setServicePassword(String servicePassword) {
|
||||
this.servicePassword = servicePassword;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
|
||||
public class CloseConfigurationWriteSessionMessage extends AppLayerMessage {
|
||||
|
||||
public CloseConfigurationWriteSessionMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.CONFIGURATION);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
|
||||
public class OpenConfigurationWriteSessionMessage extends AppLayerMessage {
|
||||
|
||||
public OpenConfigurationWriteSessionMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.CONFIGURATION);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.ParameterBlock;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ParameterBlockIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class WriteConfigurationBlockMessage extends AppLayerMessage {
|
||||
|
||||
private ParameterBlock parameterBlock;
|
||||
private Class<? extends ParameterBlock> configurationBlockId;
|
||||
|
||||
public WriteConfigurationBlockMessage() {
|
||||
super(MessagePriority.NORMAL, false, true, Service.CONFIGURATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf configBlockData = parameterBlock.getData();
|
||||
ByteBuf data = new ByteBuf(4 + configBlockData.getSize());
|
||||
data.putUInt16LE(ParameterBlockIDs.IDS.getID(parameterBlock.getClass()));
|
||||
data.putUInt16LE(31);
|
||||
data.putByteBuf(configBlockData);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) throws Exception {
|
||||
configurationBlockId = ParameterBlockIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
}
|
||||
|
||||
public Class<? extends ParameterBlock> getConfigurationBlockId() {
|
||||
return this.configurationBlockId;
|
||||
}
|
||||
|
||||
public void setParameterBlock(ParameterBlock parameterBlock) {
|
||||
this.parameterBlock = parameterBlock;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ActivateServiceMessage extends AppLayerMessage {
|
||||
|
||||
private byte serviceID;
|
||||
private short version;
|
||||
private byte[] servicePassword;
|
||||
|
||||
public ActivateServiceMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
|
||||
}
|
||||
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
serviceID = byteBuf.readByte();
|
||||
version = byteBuf.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(19);
|
||||
byteBuf.putByte(serviceID);
|
||||
byteBuf.putShort(version);
|
||||
byteBuf.putBytes(servicePassword);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public byte getServiceID() {
|
||||
return this.serviceID;
|
||||
}
|
||||
|
||||
public short getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public void setServiceID(byte serviceID) {
|
||||
this.serviceID = serviceID;
|
||||
}
|
||||
|
||||
public void setVersion(short version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public void setServicePassword(byte[] servicePassword) {
|
||||
this.servicePassword = servicePassword;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class BindMessage extends AppLayerMessage {
|
||||
|
||||
public BindMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
return ByteBuf.from(Hex.decode("3438310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ConnectMessage extends AppLayerMessage {
|
||||
|
||||
public ConnectMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
return ByteBuf.from(Hex.decode("0000080100196000"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class DisconnectMessage extends AppLayerMessage {
|
||||
|
||||
public DisconnectMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
return ByteBuf.from(Hex.decode("0360"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ServiceChallengeMessage extends AppLayerMessage {
|
||||
|
||||
private byte serviceID;
|
||||
private byte[] randomData;
|
||||
private short version;
|
||||
|
||||
public ServiceChallengeMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.CONNECTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
randomData = byteBuf.getBytes(16);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(3);
|
||||
byteBuf.putByte(serviceID);
|
||||
byteBuf.putShort(version);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public byte[] getRandomData() {
|
||||
return this.randomData;
|
||||
}
|
||||
|
||||
public void setServiceID(byte serviceID) {
|
||||
this.serviceID = serviceID;
|
||||
}
|
||||
|
||||
public void setVersion(short version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
|
||||
|
||||
public enum HistoryReadingDirection {
|
||||
|
||||
FORWARD,
|
||||
BACKWARD;
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events.HistoryEvent;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ReadHistoryEventsMessage extends AppLayerMessage {
|
||||
|
||||
private List<HistoryEvent> historyEvents;
|
||||
|
||||
public ReadHistoryEventsMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.HISTORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) throws Exception {
|
||||
historyEvents = new ArrayList<>();
|
||||
byteBuf.shift(2);
|
||||
int frameCount = byteBuf.readUInt16LE();
|
||||
for (int i = 0; i < frameCount; i++) {
|
||||
int length = byteBuf.readUInt16LE();
|
||||
historyEvents.add(HistoryEvent.deserialize(ByteBuf.from(byteBuf.readBytes(length))));
|
||||
}
|
||||
}
|
||||
|
||||
public List<HistoryEvent> getHistoryEvents() {
|
||||
return historyEvents;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.HistoryReadingDirectionIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class StartReadingHistoryMessage extends AppLayerMessage {
|
||||
|
||||
private long offset;
|
||||
private HistoryReadingDirection direction;
|
||||
|
||||
public StartReadingHistoryMessage() {
|
||||
super(MessagePriority.NORMAL, false, true, Service.HISTORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(8);
|
||||
byteBuf.putUInt16LE(31);
|
||||
byteBuf.putUInt16LE(HistoryReadingDirectionIDs.IDS.getID(direction));
|
||||
byteBuf.putUInt32LE(offset);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setOffset(long offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public void setDirection(HistoryReadingDirection direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class StopReadingHistoryMessage extends AppLayerMessage {
|
||||
|
||||
public StopReadingHistoryMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.HISTORY);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class BasalDeliveryChangedEvent extends HistoryEvent {
|
||||
|
||||
private double oldBasalRate;
|
||||
private double newBasalRate;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
oldBasalRate = byteBuf.readUInt32Decimal1000();
|
||||
newBasalRate = byteBuf.readUInt32Decimal1000();
|
||||
}
|
||||
|
||||
public double getOldBasalRate() {
|
||||
return oldBasalRate;
|
||||
}
|
||||
|
||||
public double getNewBasalRate() {
|
||||
return newBasalRate;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BolusType;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BolusTypeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class BolusDeliveredEvent extends HistoryEvent {
|
||||
|
||||
private BolusType bolusType;
|
||||
private int startHour;
|
||||
private int startMinute;
|
||||
private int startSecond;
|
||||
private double immediateAmount;
|
||||
private double extendedAmount;
|
||||
private int duration;
|
||||
private int bolusID;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
bolusType = BolusTypeIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
byteBuf.shift(1);
|
||||
startHour = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
startMinute = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
startSecond = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
immediateAmount = byteBuf.readUInt16Decimal();
|
||||
extendedAmount = byteBuf.readUInt16Decimal();
|
||||
duration = byteBuf.readUInt16LE();
|
||||
byteBuf.shift(2);
|
||||
bolusID = byteBuf.readUInt16LE();
|
||||
}
|
||||
|
||||
public BolusType getBolusType() {
|
||||
return bolusType;
|
||||
}
|
||||
|
||||
public int getStartHour() {
|
||||
return startHour;
|
||||
}
|
||||
|
||||
public int getStartMinute() {
|
||||
return startMinute;
|
||||
}
|
||||
|
||||
public int getStartSecond() {
|
||||
return startSecond;
|
||||
}
|
||||
|
||||
public double getImmediateAmount() {
|
||||
return immediateAmount;
|
||||
}
|
||||
|
||||
public double getExtendedAmount() {
|
||||
return extendedAmount;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public int getBolusID() {
|
||||
return bolusID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BolusType;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BolusTypeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class BolusProgrammedEvent extends HistoryEvent {
|
||||
|
||||
private BolusType bolusType;
|
||||
private double immediateAmount;
|
||||
private double extendedAmount;
|
||||
private int duration;
|
||||
private int bolusID;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
bolusType = BolusTypeIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
immediateAmount = byteBuf.readUInt16Decimal();
|
||||
extendedAmount = byteBuf.readUInt16Decimal();
|
||||
duration = byteBuf.readUInt16LE();
|
||||
byteBuf.shift(4);
|
||||
bolusID = byteBuf.readUInt16LE();
|
||||
}
|
||||
|
||||
|
||||
public BolusType getBolusType() {
|
||||
return bolusType;
|
||||
}
|
||||
|
||||
public double getImmediateAmount() {
|
||||
return immediateAmount;
|
||||
}
|
||||
|
||||
public double getExtendedAmount() {
|
||||
return extendedAmount;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public int getBolusID() {
|
||||
return bolusID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class CannulaFilledEvent extends HistoryEvent {
|
||||
|
||||
private double amount;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
amount = byteBuf.readUInt16Decimal();
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class CartridgeInsertedEvent extends HistoryEvent {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class CartridgeRemovedEvent extends HistoryEvent {
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class DateTimeChangedEvent extends HistoryEvent {
|
||||
|
||||
private int beforeYear;
|
||||
private int beforeMonth;
|
||||
private int beforeDay;
|
||||
private int beforeHour;
|
||||
private int beforeMinute;
|
||||
private int beforeSecond;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
beforeYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte());
|
||||
beforeMonth = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
beforeDay = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
byteBuf.shift(1);
|
||||
beforeHour = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
beforeMinute = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
beforeSecond = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
}
|
||||
|
||||
public int getBeforeYear() {
|
||||
return beforeYear;
|
||||
}
|
||||
|
||||
public int getBeforeMonth() {
|
||||
return beforeMonth;
|
||||
}
|
||||
|
||||
public int getBeforeDay() {
|
||||
return beforeDay;
|
||||
}
|
||||
|
||||
public int getBeforeHour() {
|
||||
return beforeHour;
|
||||
}
|
||||
|
||||
public int getBeforeMinute() {
|
||||
return beforeMinute;
|
||||
}
|
||||
|
||||
public int getBeforeSecond() {
|
||||
return beforeSecond;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class DefaultDateTimeSetEvent extends HistoryEvent {
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class EndOfTBREvent extends HistoryEvent {
|
||||
|
||||
private int startHour;
|
||||
private int startMinute;
|
||||
private int startSecond;
|
||||
private int amount;
|
||||
private int duration;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
byteBuf.shift(1);
|
||||
startHour = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
startMinute = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
startSecond = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
amount = byteBuf.readUInt16LE();
|
||||
duration = byteBuf.readUInt16LE();
|
||||
}
|
||||
|
||||
public int getStartHour() {
|
||||
return startHour;
|
||||
}
|
||||
|
||||
public int getStartMinute() {
|
||||
return startMinute;
|
||||
}
|
||||
|
||||
public int getStartSecond() {
|
||||
return startSecond;
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.HistoryEventIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class HistoryEvent implements Comparable<HistoryEvent> {
|
||||
|
||||
private int eventYear;
|
||||
private int eventMonth;
|
||||
private int eventDay;
|
||||
private int eventHour;
|
||||
private int eventMinute;
|
||||
private int eventSecond;
|
||||
private long eventPosition;
|
||||
|
||||
public static HistoryEvent deserialize(ByteBuf byteBuf) {
|
||||
int eventID = byteBuf.readUInt16LE();
|
||||
Class<? extends HistoryEvent> eventClass = HistoryEventIDs.IDS.getType(eventID);
|
||||
HistoryEvent event = null;
|
||||
if (eventClass == null) event = new HistoryEvent();
|
||||
else {
|
||||
try {
|
||||
event = eventClass.newInstance();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
event.parseHeader(byteBuf);
|
||||
event.parse(byteBuf);
|
||||
return event;
|
||||
}
|
||||
|
||||
public final void parseHeader(ByteBuf byteBuf) {
|
||||
eventYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte());
|
||||
eventMonth = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
eventDay = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
byteBuf.shift(1);
|
||||
eventHour = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
eventMinute = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
eventSecond = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
eventPosition = byteBuf.readUInt32LE();
|
||||
}
|
||||
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
|
||||
}
|
||||
|
||||
public int getEventYear() {
|
||||
return eventYear;
|
||||
}
|
||||
|
||||
public int getEventMonth() {
|
||||
return eventMonth;
|
||||
}
|
||||
|
||||
public int getEventDay() {
|
||||
return eventDay;
|
||||
}
|
||||
|
||||
public int getEventHour() {
|
||||
return eventHour;
|
||||
}
|
||||
|
||||
public int getEventMinute() {
|
||||
return eventMinute;
|
||||
}
|
||||
|
||||
public int getEventSecond() {
|
||||
return eventSecond;
|
||||
}
|
||||
|
||||
public long getEventPosition() {
|
||||
return eventPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(HistoryEvent historyEvent) {
|
||||
return (int) (eventPosition - historyEvent.eventPosition);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AlertType;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertTypeIncrementalIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public abstract class OccurrenceOfAlertEvent extends HistoryEvent {
|
||||
|
||||
private AlertType alertType;
|
||||
private int alertID;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
alertType = AlertTypeIncrementalIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
alertID = byteBuf.readUInt16LE();
|
||||
}
|
||||
|
||||
public AlertType getAlertType() {
|
||||
return alertType;
|
||||
}
|
||||
|
||||
public int getAlertID() {
|
||||
return alertID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class OccurrenceOfErrorEvent extends OccurrenceOfAlertEvent {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class OccurrenceOfMaintenanceEvent extends OccurrenceOfAlertEvent {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class OccurrenceOfWarningEvent extends OccurrenceOfAlertEvent {
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.OperatingMode;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.OperatingModeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class OperatingModeChangedEvent extends HistoryEvent {
|
||||
|
||||
private OperatingMode oldValue;
|
||||
private OperatingMode newValue;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
oldValue = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
newValue = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
}
|
||||
|
||||
|
||||
public OperatingMode getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public OperatingMode getNewValue() {
|
||||
return newValue;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class PowerDownEvent extends HistoryEvent {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
public class PowerUpEvent extends HistoryEvent {
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class SniffingDoneEvent extends HistoryEvent {
|
||||
|
||||
private double amount;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
amount = byteBuf.readUInt16Decimal();
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class StartOfTBREvent extends HistoryEvent {
|
||||
|
||||
private int amount;
|
||||
private int duration;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
amount = byteBuf.readUInt16LE();
|
||||
duration = byteBuf.readUInt16LE();
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.BOCUtil;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class TotalDailyDoseEvent extends HistoryEvent {
|
||||
|
||||
private double basalTotal;
|
||||
private double bolusTotal;
|
||||
private int totalYear;
|
||||
private int totalMonth;
|
||||
private int totalDay;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
basalTotal = byteBuf.readUInt32Decimal100();
|
||||
bolusTotal = byteBuf.readUInt32Decimal100();
|
||||
totalYear = BOCUtil.parseBOC(byteBuf.readByte()) * 100 + BOCUtil.parseBOC(byteBuf.readByte());
|
||||
totalMonth = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
totalDay = BOCUtil.parseBOC(byteBuf.readByte());
|
||||
}
|
||||
|
||||
public double getBasalTotal() {
|
||||
return basalTotal;
|
||||
}
|
||||
|
||||
public double getBolusTotal() {
|
||||
return bolusTotal;
|
||||
}
|
||||
|
||||
public int getTotalYear() {
|
||||
return totalYear;
|
||||
}
|
||||
|
||||
public int getTotalMonth() {
|
||||
return totalMonth;
|
||||
}
|
||||
|
||||
public int getTotalDay() {
|
||||
return totalDay;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.history.history_events;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class TubeFilledEvent extends HistoryEvent {
|
||||
|
||||
private double amount;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
amount = byteBuf.readUInt16Decimal();
|
||||
}
|
||||
|
||||
public double getAmount() {
|
||||
return amount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BasalProfile;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ActiveBasalProfileIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ActiveBRProfileBlock extends ParameterBlock {
|
||||
|
||||
private BasalProfile activeBasalProfile;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
activeBasalProfile = ActiveBasalProfileIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(2);
|
||||
byteBuf.putUInt16LE(ActiveBasalProfileIDs.IDS.getID(activeBasalProfile));
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public BasalProfile getActiveBasalProfile() {
|
||||
return activeBasalProfile;
|
||||
}
|
||||
|
||||
public void setActiveBasalProfile(BasalProfile activeBasalProfile) {
|
||||
this.activeBasalProfile = activeBasalProfile;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile1Block extends BRProfileBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile1NameBlock extends NameBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile2Block extends BRProfileBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile2NameBlock extends NameBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile3Block extends BRProfileBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile3NameBlock extends NameBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile4Block extends BRProfileBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile4NameBlock extends NameBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile5Block extends BRProfileBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class BRProfile5NameBlock extends NameBlock {
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BasalProfileBlock;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public abstract class BRProfileBlock extends ParameterBlock {
|
||||
|
||||
private List<BasalProfileBlock> profileBlocks;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
profileBlocks = new ArrayList<>();
|
||||
for (int i = 0; i < 24; i++) {
|
||||
BasalProfileBlock basalProfileBlock = new BasalProfileBlock();
|
||||
basalProfileBlock.setDuration(byteBuf.readUInt16LE());
|
||||
profileBlocks.add(basalProfileBlock);
|
||||
}
|
||||
for (int i = 0; i < 24; i++) profileBlocks.get(i).setBasalAmount(byteBuf.readUInt16Decimal());
|
||||
Iterator<BasalProfileBlock> iterator = profileBlocks.iterator();
|
||||
while (iterator.hasNext())
|
||||
if (iterator.next().getDuration() == 0)
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(96);
|
||||
for (int i = 0; i < 24; i++) {
|
||||
if (profileBlocks.size() > i) byteBuf.putUInt16LE(profileBlocks.get(i).getDuration());
|
||||
else byteBuf.putUInt16LE(0);
|
||||
}
|
||||
for (int i = 0; i < 24; i++) {
|
||||
if (profileBlocks.size() > i) byteBuf.putUInt16Decimal(profileBlocks.get(i).getBasalAmount());
|
||||
else byteBuf.putUInt16Decimal(0);
|
||||
}
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public List<BasalProfileBlock> getProfileBlocks() {
|
||||
return profileBlocks;
|
||||
}
|
||||
|
||||
public void setProfileBlocks(List<BasalProfileBlock> profileBlocks) {
|
||||
this.profileBlocks = profileBlocks;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class FactoryMaxBasalAmountBlock extends InsulinAmountLimitationBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class FactoryMaxBolusAmountBlock extends InsulinAmountLimitationBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class FactoryMinBasalAmountBlock extends InsulinAmountLimitationBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class FactoryMinBolusAmountBlock extends InsulinAmountLimitationBlock {
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public abstract class InsulinAmountLimitationBlock extends ParameterBlock {
|
||||
|
||||
private double amountLimitation;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
amountLimitation = byteBuf.readUInt16Decimal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(2);
|
||||
byteBuf.putUInt16Decimal(amountLimitation);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public double getAmountLimitation() {
|
||||
return this.amountLimitation;
|
||||
}
|
||||
|
||||
public void setAmountLimitation(double amountLimitation) {
|
||||
this.amountLimitation = amountLimitation;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class MaxBasalAmountBlock extends InsulinAmountLimitationBlock {
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
public class MaxBolusAmountBlock extends InsulinAmountLimitationBlock {
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public abstract class NameBlock extends ParameterBlock {
|
||||
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
name = byteBuf.readUTF16(40);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(42);
|
||||
byteBuf.putUTF16(name, 40);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public abstract class ParameterBlock {
|
||||
|
||||
public abstract void parse(ByteBuf byteBuf);
|
||||
public abstract ByteBuf getData();
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.SystemIdentification;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class SystemIdentificationBlock extends ParameterBlock {
|
||||
|
||||
private SystemIdentification systemIdentification;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
systemIdentification = new SystemIdentification();
|
||||
systemIdentification.setSerialNumber(byteBuf.readUTF16(18));
|
||||
systemIdentification.setSystemIdAppendix(byteBuf.readUInt32LE());
|
||||
systemIdentification.setManufacturingDate(byteBuf.readUTF16(22));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public SystemIdentification getSystemIdentification() {
|
||||
return systemIdentification;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class TBROverNotificationBlock extends ParameterBlock {
|
||||
|
||||
private boolean enabled;
|
||||
private int melody;
|
||||
|
||||
@Override
|
||||
public void parse(ByteBuf byteBuf) {
|
||||
enabled = byteBuf.readBoolean();
|
||||
melody = byteBuf.readUInt16LE();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(4);
|
||||
byteBuf.putBoolean(enabled);
|
||||
byteBuf.putUInt16LE(melody);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class CancelBolusMessage extends AppLayerMessage {
|
||||
|
||||
private int bolusID;
|
||||
|
||||
public CancelBolusMessage() {
|
||||
super(MessagePriority.HIGHEST, false, true, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(2);
|
||||
byteBuf.putUInt16LE(bolusID);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setBolusID(int bolusID) {
|
||||
this.bolusID = bolusID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class CancelTBRMessage extends AppLayerMessage {
|
||||
public CancelTBRMessage() {
|
||||
super(MessagePriority.HIGHER, false, false, Service.REMOTE_CONTROL);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ChangeTBRMessage extends AppLayerMessage {
|
||||
|
||||
private int percentage;
|
||||
private int duration;
|
||||
|
||||
public ChangeTBRMessage() {
|
||||
super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(6);
|
||||
byteBuf.putUInt16LE(percentage);
|
||||
byteBuf.putUInt16LE(duration);
|
||||
byteBuf.putUInt16LE(31);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setPercentage(int percentage) {
|
||||
this.percentage = percentage;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ConfirmAlertMessage extends AppLayerMessage {
|
||||
|
||||
private int alertID;
|
||||
|
||||
public ConfirmAlertMessage() {
|
||||
super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(2);
|
||||
byteBuf.putUInt16LE(alertID);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setAlertID(int alertID) {
|
||||
this.alertID = alertID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BolusType;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BolusTypeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class DeliverBolusMessage extends AppLayerMessage {
|
||||
|
||||
private BolusType bolusType;
|
||||
private double immediateAmount;
|
||||
private double extendedAmount;
|
||||
private int duration;
|
||||
private int bolusId;
|
||||
|
||||
public DeliverBolusMessage() {
|
||||
super(MessagePriority.NORMAL, true, true, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(22);
|
||||
byteBuf.putUInt16LE(805);
|
||||
byteBuf.putUInt16LE(BolusTypeIDs.IDS.getID(bolusType));
|
||||
byteBuf.putUInt16LE(31);
|
||||
byteBuf.putUInt16LE(0);
|
||||
byteBuf.putUInt16Decimal(immediateAmount);
|
||||
byteBuf.putUInt16Decimal(extendedAmount);
|
||||
byteBuf.putUInt16LE(duration);
|
||||
byteBuf.putUInt16LE(0);
|
||||
byteBuf.putUInt16Decimal(immediateAmount);
|
||||
byteBuf.putUInt16Decimal(extendedAmount);
|
||||
byteBuf.putUInt16LE(duration);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) throws Exception {
|
||||
bolusId = byteBuf.readUInt16LE();
|
||||
}
|
||||
|
||||
public void setBolusType(BolusType bolusType) {
|
||||
this.bolusType = bolusType;
|
||||
}
|
||||
|
||||
public void setImmediateAmount(double immediateAmount) {
|
||||
this.immediateAmount = immediateAmount;
|
||||
}
|
||||
|
||||
public void setExtendedAmount(double extendedAmount) {
|
||||
this.extendedAmount = extendedAmount;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public int getBolusId() {
|
||||
return bolusId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.AvailableBolusTypes;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetAvailableBolusTypesMessage extends AppLayerMessage {
|
||||
|
||||
private AvailableBolusTypes availableBolusTypes;
|
||||
|
||||
public GetAvailableBolusTypesMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) throws Exception {
|
||||
availableBolusTypes = new AvailableBolusTypes();
|
||||
availableBolusTypes.setStandardAvailable(byteBuf.readBoolean());
|
||||
availableBolusTypes.setExtendedAvailable(byteBuf.readBoolean());
|
||||
availableBolusTypes.setMultiwaveAvailable(byteBuf.readBoolean());
|
||||
}
|
||||
|
||||
public AvailableBolusTypes getAvailableBolusTypes() {
|
||||
return this.availableBolusTypes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.PumpTime;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class SetDateTimeMessage extends AppLayerMessage {
|
||||
|
||||
private PumpTime pumpTime;
|
||||
|
||||
public SetDateTimeMessage() {
|
||||
super(MessagePriority.NORMAL, false, true, Service.CONFIGURATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(7);
|
||||
byteBuf.putUInt16LE(pumpTime.getYear());
|
||||
byteBuf.putUInt8((short) pumpTime.getMonth());
|
||||
byteBuf.putUInt8((short) pumpTime.getDay());
|
||||
byteBuf.putUInt8((short) pumpTime.getHour());
|
||||
byteBuf.putUInt8((short) pumpTime.getMinute());
|
||||
byteBuf.putUInt8((short) pumpTime.getSecond());
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setPumpTime(PumpTime pumpTime) {
|
||||
this.pumpTime = pumpTime;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.OperatingMode;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.OperatingModeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class SetOperatingModeMessage extends AppLayerMessage {
|
||||
|
||||
private OperatingMode operatingMode;
|
||||
|
||||
public SetOperatingModeMessage() {
|
||||
super(MessagePriority.HIGHEST, false, true, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(2);
|
||||
byteBuf.putUInt16LE(OperatingModeIDs.IDS.getID(operatingMode));
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setOperatingMode(OperatingMode operatingMode) {
|
||||
this.operatingMode = operatingMode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class SetTBRMessage extends AppLayerMessage {
|
||||
|
||||
private int percentage;
|
||||
private int duration;
|
||||
|
||||
public SetTBRMessage() {
|
||||
super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(6);
|
||||
byteBuf.putUInt16LE(percentage);
|
||||
byteBuf.putUInt16LE(duration);
|
||||
byteBuf.putUInt16LE(31);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setPercentage(int percentage) {
|
||||
this.percentage = percentage;
|
||||
}
|
||||
|
||||
public void setDuration(int duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.remote_control;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class SnoozeAlertMessage extends AppLayerMessage {
|
||||
|
||||
private int alertID;
|
||||
|
||||
public SnoozeAlertMessage() {
|
||||
super(MessagePriority.NORMAL, false, true, Service.REMOTE_CONTROL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(2);
|
||||
byteBuf.putUInt16LE(alertID);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setAlertID(int alertID) {
|
||||
this.alertID = alertID;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.Alert;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertCategoryIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertStatusIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.AlertTypeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetActiveAlertMessage extends AppLayerMessage {
|
||||
|
||||
private Alert alert;
|
||||
|
||||
public GetActiveAlertMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
Alert alert = new Alert();
|
||||
alert.setAlertId(byteBuf.readUInt16LE());
|
||||
alert.setAlertCategory(AlertCategoryIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
alert.setAlertType(AlertTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
alert.setAlertStatus(AlertStatusIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
if (alert.getAlertType() != null) {
|
||||
switch (alert.getAlertType()) {
|
||||
case WARNING_38:
|
||||
byteBuf.shift(4);
|
||||
alert.setProgrammedBolusAmount(byteBuf.readUInt16Decimal());
|
||||
alert.setDeliveredBolusAmount(byteBuf.readUInt16Decimal());
|
||||
break;
|
||||
case REMINDER_07:
|
||||
case WARNING_36:
|
||||
byteBuf.shift(2);
|
||||
alert.setTBRAmount(byteBuf.readUInt16LE());
|
||||
alert.setTBRDuration(byteBuf.readUInt16LE());
|
||||
break;
|
||||
case WARNING_31:
|
||||
alert.setCartridgeAmount(byteBuf.readUInt16Decimal());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (alert.getAlertCategory() != null
|
||||
&& alert.getAlertType() != null
|
||||
&& alert.getAlertStatus() != null)
|
||||
this.alert = alert;
|
||||
}
|
||||
|
||||
public Alert getAlert() {
|
||||
return this.alert;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBasalRate;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ActiveBasalProfileIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetActiveBasalRateMessage extends AppLayerMessage {
|
||||
|
||||
private ActiveBasalRate activeBasalRate;
|
||||
|
||||
public GetActiveBasalRateMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
ActiveBasalRate activeBasalRate = new ActiveBasalRate();
|
||||
activeBasalRate.setActiveBasalProfile(ActiveBasalProfileIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
activeBasalRate.setActiveBasalProfileName(byteBuf.readUTF16(30));
|
||||
activeBasalRate.setActiveBasalRate(byteBuf.readUInt16Decimal());
|
||||
if (activeBasalRate.getActiveBasalProfile() != null) this.activeBasalRate = activeBasalRate;
|
||||
}
|
||||
|
||||
public ActiveBasalRate getActiveBasalRate() {
|
||||
return this.activeBasalRate;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveBolus;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ActiveBolusTypeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetActiveBolusesMessage extends AppLayerMessage {
|
||||
|
||||
private List<ActiveBolus> activeBoluses;
|
||||
|
||||
public GetActiveBolusesMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
activeBoluses = new ArrayList<>();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
ActiveBolus activeBolus = new ActiveBolus();
|
||||
activeBolus.setBolusID(byteBuf.readUInt16LE());
|
||||
activeBolus.setBolusType(ActiveBolusTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
byteBuf.shift(2);
|
||||
byteBuf.shift(2);
|
||||
activeBolus.setInitialAmount(byteBuf.readUInt16Decimal());
|
||||
activeBolus.setRemainingAmount(byteBuf.readUInt16Decimal());
|
||||
activeBolus.setRemainingDuration(byteBuf.readUInt16LE());
|
||||
if (activeBolus.getBolusType() != null) activeBoluses.add(activeBolus);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ActiveBolus> getActiveBoluses() {
|
||||
return this.activeBoluses;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.ActiveTBR;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetActiveTBRMessage extends AppLayerMessage {
|
||||
|
||||
private ActiveTBR activeTBR;
|
||||
|
||||
public GetActiveTBRMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
ActiveTBR activeTBR = new ActiveTBR();
|
||||
activeTBR.setPercentage(byteBuf.readUInt16LE());
|
||||
activeTBR.setRemainingDuration(byteBuf.readUInt16LE());
|
||||
activeTBR.setInitialDuration(byteBuf.readUInt16LE());
|
||||
if (activeTBR.getPercentage() != 100) this.activeTBR = activeTBR;
|
||||
}
|
||||
|
||||
public ActiveTBR getActiveTBR() {
|
||||
return this.activeTBR;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.BatteryStatus;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.BatteryTypeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.SymbolStatusIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetBatteryStatusMessage extends AppLayerMessage {
|
||||
|
||||
private BatteryStatus batteryStatus;
|
||||
|
||||
public GetBatteryStatusMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
batteryStatus = new BatteryStatus();
|
||||
batteryStatus.setBatteryType(BatteryTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
batteryStatus.setBatteryAmount(byteBuf.readUInt16LE());
|
||||
batteryStatus.setSymbolStatus(SymbolStatusIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
}
|
||||
|
||||
public BatteryStatus getBatteryStatus() {
|
||||
return this.batteryStatus;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.CartridgeStatus;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.CartridgeTypeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.SymbolStatusIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetCartridgeStatusMessage extends AppLayerMessage {
|
||||
|
||||
private CartridgeStatus cartridgeStatus;
|
||||
|
||||
public GetCartridgeStatusMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
cartridgeStatus = new CartridgeStatus();
|
||||
cartridgeStatus.setInserted(byteBuf.readBoolean());
|
||||
cartridgeStatus.setCartridgeType(CartridgeTypeIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
cartridgeStatus.setSymbolStatus(SymbolStatusIDs.IDS.getType(byteBuf.readUInt16LE()));
|
||||
cartridgeStatus.setRemainingAmount(byteBuf.readUInt16Decimal());
|
||||
}
|
||||
|
||||
public CartridgeStatus getCartridgeStatus() {
|
||||
return this.cartridgeStatus;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.PumpTime;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetDateTimeMessage extends AppLayerMessage {
|
||||
|
||||
private PumpTime pumpTime;
|
||||
|
||||
public GetDateTimeMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
pumpTime = new PumpTime();
|
||||
pumpTime.setYear(byteBuf.readUInt16LE());
|
||||
pumpTime.setMonth(byteBuf.readUInt8());
|
||||
pumpTime.setDay(byteBuf.readUInt8());
|
||||
pumpTime.setHour(byteBuf.readUInt8());
|
||||
pumpTime.setMinute(byteBuf.readUInt8());
|
||||
pumpTime.setSecond(byteBuf.readUInt8());
|
||||
}
|
||||
|
||||
public PumpTime getPumpTime() {
|
||||
return this.pumpTime;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.FirmwareVersions;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetFirmwareVersionsMessage extends AppLayerMessage {
|
||||
|
||||
private FirmwareVersions firmwareVersions;
|
||||
|
||||
public GetFirmwareVersionsMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
firmwareVersions = new FirmwareVersions();
|
||||
firmwareVersions.setReleaseSWVersion(byteBuf.readASCII(13));
|
||||
firmwareVersions.setUiProcSWVersion(byteBuf.readASCII(11));
|
||||
firmwareVersions.setPcProcSWVersion(byteBuf.readASCII(11));
|
||||
firmwareVersions.setMdTelProcSWVersion(byteBuf.readASCII(11));
|
||||
firmwareVersions.setBtInfoPageVersion(byteBuf.readASCII(11));
|
||||
firmwareVersions.setSafetyProcSWVersion(byteBuf.readASCII(11));
|
||||
firmwareVersions.setConfigIndex(byteBuf.readUInt16LE());
|
||||
firmwareVersions.setHistoryIndex(byteBuf.readUInt16LE());
|
||||
firmwareVersions.setStateIndex(byteBuf.readUInt16LE());
|
||||
firmwareVersions.setVocabularyIndex(byteBuf.readUInt16LE());
|
||||
}
|
||||
|
||||
public FirmwareVersions getFirmwareVersions() {
|
||||
return this.firmwareVersions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.OperatingMode;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.OperatingModeIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetOperatingModeMessage extends AppLayerMessage {
|
||||
|
||||
private OperatingMode operatingMode;
|
||||
|
||||
public GetOperatingModeMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
this.operatingMode = OperatingModeIDs.IDS.getType(byteBuf.readUInt16LE());
|
||||
}
|
||||
|
||||
public OperatingMode getOperatingMode() {
|
||||
return this.operatingMode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetPumpStatusRegisterMessage extends AppLayerMessage {
|
||||
|
||||
private boolean operatingModeChanged;
|
||||
private boolean batteryStatusChanged;
|
||||
private boolean cartridgeStatusChanged;
|
||||
private boolean totalDailyDoseChanged;
|
||||
private boolean activeBasalRateChanged;
|
||||
private boolean activeTBRChanged;
|
||||
private boolean activeBolusesChanged;
|
||||
|
||||
public GetPumpStatusRegisterMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
operatingModeChanged = byteBuf.readBoolean();
|
||||
batteryStatusChanged = byteBuf.readBoolean();
|
||||
cartridgeStatusChanged = byteBuf.readBoolean();
|
||||
totalDailyDoseChanged = byteBuf.readBoolean();
|
||||
activeBasalRateChanged = byteBuf.readBoolean();
|
||||
activeTBRChanged = byteBuf.readBoolean();
|
||||
activeBolusesChanged = byteBuf.readBoolean();
|
||||
}
|
||||
|
||||
public boolean isOperatingModeChanged() {
|
||||
return this.operatingModeChanged;
|
||||
}
|
||||
|
||||
public boolean isBatteryStatusChanged() {
|
||||
return this.batteryStatusChanged;
|
||||
}
|
||||
|
||||
public boolean isCartridgeStatusChanged() {
|
||||
return this.cartridgeStatusChanged;
|
||||
}
|
||||
|
||||
public boolean isTotalDailyDoseChanged() {
|
||||
return this.totalDailyDoseChanged;
|
||||
}
|
||||
|
||||
public boolean isActiveBasalRateChanged() {
|
||||
return this.activeBasalRateChanged;
|
||||
}
|
||||
|
||||
public boolean isActiveTBRChanged() {
|
||||
return this.activeTBRChanged;
|
||||
}
|
||||
|
||||
public boolean isActiveBolusesChanged() {
|
||||
return this.activeBolusesChanged;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.TotalDailyDose;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class GetTotalDailyDoseMessage extends AppLayerMessage {
|
||||
|
||||
private TotalDailyDose tdd;
|
||||
|
||||
public GetTotalDailyDoseMessage() {
|
||||
super(MessagePriority.NORMAL, true, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse(ByteBuf byteBuf) {
|
||||
tdd = new TotalDailyDose();
|
||||
tdd.setBolus(byteBuf.readUInt32Decimal100());
|
||||
tdd.setBasal(byteBuf.readUInt32Decimal100());
|
||||
tdd.setBolusAndBasal(byteBuf.readUInt32Decimal100());
|
||||
}
|
||||
|
||||
public TotalDailyDose getTDD() {
|
||||
return this.tdd;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.MessagePriority;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
|
||||
public class ResetPumpStatusRegisterMessage extends AppLayerMessage {
|
||||
|
||||
private boolean operatingModeChanged;
|
||||
private boolean batteryStatusChanged;
|
||||
private boolean cartridgeStatusChanged;
|
||||
private boolean totalDailyDoseChanged;
|
||||
private boolean activeBasalRateChanged;
|
||||
private boolean activeTBRChanged;
|
||||
private boolean activeBolusesChanged;
|
||||
|
||||
public ResetPumpStatusRegisterMessage() {
|
||||
super(MessagePriority.NORMAL, false, false, Service.STATUS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteBuf getData() {
|
||||
ByteBuf byteBuf = new ByteBuf(28);
|
||||
byteBuf.putBoolean(operatingModeChanged);
|
||||
byteBuf.putBoolean(batteryStatusChanged);
|
||||
byteBuf.putBoolean(cartridgeStatusChanged);
|
||||
byteBuf.putBoolean(totalDailyDoseChanged);
|
||||
byteBuf.putBoolean(activeBasalRateChanged);
|
||||
byteBuf.putBoolean(activeTBRChanged);
|
||||
byteBuf.putBoolean(activeBolusesChanged);
|
||||
for (int i = 0; i < 7; i++) byteBuf.putBoolean(false);
|
||||
return byteBuf;
|
||||
}
|
||||
|
||||
public void setOperatingModeChanged(boolean operatingModeChanged) {
|
||||
this.operatingModeChanged = operatingModeChanged;
|
||||
}
|
||||
|
||||
public void setBatteryStatusChanged(boolean batteryStatusChanged) {
|
||||
this.batteryStatusChanged = batteryStatusChanged;
|
||||
}
|
||||
|
||||
public void setCartridgeStatusChanged(boolean cartridgeStatusChanged) {
|
||||
this.cartridgeStatusChanged = cartridgeStatusChanged;
|
||||
}
|
||||
|
||||
public void setTotalDailyDoseChanged(boolean totalDailyDoseChanged) {
|
||||
this.totalDailyDoseChanged = totalDailyDoseChanged;
|
||||
}
|
||||
|
||||
public void setActiveBasalRateChanged(boolean activeBasalRateChanged) {
|
||||
this.activeBasalRateChanged = activeBasalRateChanged;
|
||||
}
|
||||
|
||||
public void setActiveTBRChanged(boolean activeTBRChanged) {
|
||||
this.activeTBRChanged = activeTBRChanged;
|
||||
}
|
||||
|
||||
public void setActiveBolusesChanged(boolean activeBolusesChanged) {
|
||||
this.activeBolusesChanged = activeBolusesChanged;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.CloseConfigurationWriteSessionMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.OpenConfigurationWriteSessionMessage;
|
||||
|
||||
public class ConfigurationMessageRequest<T extends AppLayerMessage> extends MessageRequest<T> {
|
||||
|
||||
private MessageRequest<OpenConfigurationWriteSessionMessage> openRequest;
|
||||
private MessageRequest<CloseConfigurationWriteSessionMessage> closeRequest;
|
||||
|
||||
public ConfigurationMessageRequest(T request, MessageRequest<OpenConfigurationWriteSessionMessage> openRequest, MessageRequest<CloseConfigurationWriteSessionMessage> closeRequest) {
|
||||
super(request);
|
||||
this.openRequest = openRequest;
|
||||
this.closeRequest = closeRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T await() throws Exception {
|
||||
openRequest.await();
|
||||
T response = super.await();
|
||||
closeRequest.await();
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T await(long timeout) throws Exception {
|
||||
openRequest.await(timeout);
|
||||
T response = super.await(timeout);
|
||||
closeRequest.await(timeout);
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,780 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service;
|
||||
|
||||
import android.app.Service;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.crypto.InvalidCipherTextException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
import info.nightscout.androidaps.plugins.PumpCombo.ruffyscripter.BolusProgressReporter;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.ReadParameterBlockMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.CloseConfigurationWriteSessionMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.OpenConfigurationWriteSessionMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.configuration.WriteConfigurationBlockMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.ActivateServiceMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.BindMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.ConnectMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.DisconnectMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.connection.ServiceChallengeMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.parameter_blocks.SystemIdentificationBlock;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.status.GetFirmwareVersionsMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.FirmwareVersions;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.InsightState;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.descriptors.SystemIdentification;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.ConnectionFailedException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.ConnectionLostException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.DisconnectedException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InsightException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InvalidNonceException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.InvalidSatlCommandException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.ReceivedPacketInInvalidStateException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.TimeoutException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.TooChattyPumpException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlCompatibleStateErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlDecryptVerifyFailedErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlIncompatibleVersionErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidCRCErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidCommIdErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidMacErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidMessageTypeErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidNonceErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidPacketErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlInvalidPayloadLengthErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlNoneErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlPairingRejectedException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlUndefinedErrorException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.exceptions.satl_errors.SatlWrongStateException;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.ids.ServiceIDs;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.ConnectionRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.ConnectionResponse;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.DataMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.ErrorMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.KeyRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.KeyResponse;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.SatlMessage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.SynAckResponse;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.SynRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyConfirmRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyConfirmResponse;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyDisplayRequest;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.satl.VerifyDisplayResponse;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ByteBuf;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.ConnectionEstablisher;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.DelayedActionThread;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.InputStreamReader;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.Nonce;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.OutputStreamWriter;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.PairingDataStorage;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.Cryptograph;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.DerivedKeys;
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.utils.crypto.KeyPair;
|
||||
import info.nightscout.utils.SP;
|
||||
|
||||
public class InsightConnectionService extends Service implements ConnectionEstablisher.Callback, InputStreamReader.Callback, OutputStreamWriter.Callback {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(L.PUMPCOMM);
|
||||
|
||||
private static final int BUFFER_SIZE = 1024;
|
||||
private static final long RESPONSE_TIMEOUT = 6000;
|
||||
|
||||
private List<StateCallback> stateCallbacks = new ArrayList<>();
|
||||
private final List<Object> connectionRequests = new ArrayList<>();
|
||||
private List<ExceptionCallback> exceptionCallbacks = new ArrayList<>();
|
||||
private LocalBinder localBinder = new LocalBinder();
|
||||
private PairingDataStorage pairingDataStorage;
|
||||
private InsightState state;
|
||||
private PowerManager.WakeLock wakeLock;
|
||||
private DelayedActionThread disconnectTimer;
|
||||
private DelayedActionThread recoveryTimer;
|
||||
private DelayedActionThread timeoutTimer;
|
||||
private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
private BluetoothDevice bluetoothDevice;
|
||||
private BluetoothSocket bluetoothSocket;
|
||||
private ConnectionEstablisher connectionEstablisher;
|
||||
private InputStreamReader inputStreamReader;
|
||||
private OutputStreamWriter outputStreamWriter;
|
||||
private KeyRequest keyRequest;
|
||||
private ByteBuf buffer = new ByteBuf(BUFFER_SIZE);
|
||||
private String verificationString;
|
||||
private KeyPair keyPair;
|
||||
private byte[] randomBytes;
|
||||
private MessageQueue messageQueue = new MessageQueue();
|
||||
private List<info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service> activatedServices = new ArrayList<>();
|
||||
private long lastDataTime;
|
||||
private long lastConnected;
|
||||
|
||||
KeyPair getKeyPair() {
|
||||
if (keyPair == null) keyPair = Cryptograph.generateRSAKey();
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
byte[] getRandomBytes() {
|
||||
if (randomBytes == null) {
|
||||
randomBytes = new byte[28];
|
||||
new SecureRandom().nextBytes(randomBytes);
|
||||
}
|
||||
return randomBytes;
|
||||
}
|
||||
|
||||
public long getLastConnected() {
|
||||
return lastConnected;
|
||||
}
|
||||
|
||||
public long getLastDataTime() {
|
||||
return lastDataTime;
|
||||
}
|
||||
|
||||
public FirmwareVersions getPumpFirmwareVersions() {
|
||||
return pairingDataStorage.getFirmwareVersions();
|
||||
}
|
||||
|
||||
public SystemIdentification getPumpSystemIdentification() {
|
||||
return pairingDataStorage.getSystemIdentification();
|
||||
}
|
||||
|
||||
public String getBluetoothAddress() {
|
||||
return pairingDataStorage.getMacAddress();
|
||||
}
|
||||
|
||||
public synchronized String getVerificationString() {
|
||||
return verificationString;
|
||||
}
|
||||
|
||||
public synchronized void registerStateCallback(StateCallback stateCallback) {
|
||||
stateCallbacks.add(stateCallback);
|
||||
}
|
||||
|
||||
public synchronized void unregisterStateCallback(StateCallback stateCallback) {
|
||||
stateCallbacks.remove(stateCallback);
|
||||
}
|
||||
|
||||
public synchronized void registerExceptionCallback(ExceptionCallback exceptionCallback) {
|
||||
exceptionCallbacks.add(exceptionCallback);
|
||||
}
|
||||
|
||||
public synchronized void unregisterExceptionCallback(ExceptionCallback exceptionCallback) {
|
||||
exceptionCallbacks.remove(exceptionCallback);
|
||||
}
|
||||
|
||||
public synchronized void confirmVerificationString() {
|
||||
setState(InsightState.SATL_VERIFY_CONFIRM_REQUEST);
|
||||
sendSatlMessage(new VerifyConfirmRequest());
|
||||
}
|
||||
|
||||
public synchronized void rejectVerificationString() {
|
||||
handleException(new SatlPairingRejectedException());
|
||||
}
|
||||
|
||||
public synchronized boolean isPaired() {
|
||||
return pairingDataStorage.isPaired();
|
||||
}
|
||||
|
||||
public synchronized <T extends AppLayerMessage> MessageRequest<T> requestMessage(T message) {
|
||||
MessageRequest<T> messageRequest;
|
||||
if (getState() != InsightState.CONNECTED) {
|
||||
messageRequest = new MessageRequest<>(message);
|
||||
messageRequest.exception = new DisconnectedException();
|
||||
return messageRequest;
|
||||
}
|
||||
if (message instanceof WriteConfigurationBlockMessage) {
|
||||
MessageRequest<OpenConfigurationWriteSessionMessage> openRequest = new MessageRequest<>(new OpenConfigurationWriteSessionMessage());
|
||||
MessageRequest<CloseConfigurationWriteSessionMessage> closeRequest = new MessageRequest<>(new CloseConfigurationWriteSessionMessage());
|
||||
messageRequest = new ConfigurationMessageRequest<>(message, openRequest, closeRequest);
|
||||
messageQueue.enqueueRequest(openRequest);
|
||||
messageQueue.enqueueRequest(messageRequest);
|
||||
messageQueue.enqueueRequest(closeRequest);
|
||||
} else {
|
||||
messageRequest = new MessageRequest<>(message);
|
||||
messageQueue.enqueueRequest(messageRequest);
|
||||
}
|
||||
requestNextMessage();
|
||||
return messageRequest;
|
||||
}
|
||||
|
||||
private void requestNextMessage() {
|
||||
while (messageQueue.getActiveRequest() == null && messageQueue.hasPendingMessages()) {
|
||||
messageQueue.nextRequest();
|
||||
info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service service = messageQueue.getActiveRequest().request.getService();
|
||||
if (service != info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.CONNECTION && !activatedServices.contains(service)) {
|
||||
if (service.getServicePassword() == null) {
|
||||
ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage();
|
||||
activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(service));
|
||||
activateServiceMessage.setVersion(service.getVersion());
|
||||
activateServiceMessage.setServicePassword(new byte[16]);
|
||||
sendAppLayerMessage(activateServiceMessage);
|
||||
} else {
|
||||
ServiceChallengeMessage serviceChallengeMessage = new ServiceChallengeMessage();
|
||||
serviceChallengeMessage.setServiceID(ServiceIDs.IDS.getID(service));
|
||||
serviceChallengeMessage.setVersion(service.getVersion());
|
||||
sendAppLayerMessage(serviceChallengeMessage);
|
||||
}
|
||||
} else sendAppLayerMessage(messageQueue.getActiveRequest().request);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized InsightState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onCreate() {
|
||||
pairingDataStorage = new PairingDataStorage(this);
|
||||
state = pairingDataStorage.isPaired() ? InsightState.DISCONNECTED : InsightState.NOT_PAIRED;
|
||||
wakeLock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidAPS:InsightConnectionService");
|
||||
}
|
||||
|
||||
private void setState(InsightState state) {
|
||||
if (this.state == state) return;
|
||||
if (this.state == InsightState.CONNECTED) lastConnected = System.currentTimeMillis();
|
||||
if ((state == InsightState.DISCONNECTED || state == InsightState.NOT_PAIRED) && wakeLock.isHeld())
|
||||
wakeLock.release();
|
||||
else if (!wakeLock.isHeld()) wakeLock.acquire();
|
||||
this.state = state;
|
||||
for (StateCallback stateCallback : stateCallbacks) stateCallback.stateChanged(state);
|
||||
log.info("Insight state changed: " + state.name());
|
||||
}
|
||||
|
||||
public synchronized void requestConnection(Object lock) {
|
||||
if (connectionRequests.contains(lock)) return;
|
||||
connectionRequests.add(lock);
|
||||
if (disconnectTimer != null) {
|
||||
disconnectTimer.interrupt();
|
||||
disconnectTimer = null;
|
||||
}
|
||||
if (state == InsightState.DISCONNECTED && pairingDataStorage.isPaired()) connect();
|
||||
}
|
||||
|
||||
public synchronized void withdrawConnectionRequest(Object lock) {
|
||||
if (!connectionRequests.contains(lock)) return;
|
||||
connectionRequests.remove(lock);
|
||||
if (connectionRequests.size() == 0) {
|
||||
if (state == InsightState.RECOVERING) {
|
||||
recoveryTimer.interrupt();
|
||||
recoveryTimer = null;
|
||||
setState(InsightState.DISCONNECTED);
|
||||
cleanup();
|
||||
} else if (state != InsightState.DISCONNECTED) {
|
||||
long disconnectTimeout = SP.getInt("insight_disconnect_delay", 5);
|
||||
disconnectTimeout = Math.min(disconnectTimeout, 15);
|
||||
disconnectTimeout = Math.max(disconnectTimeout, 0);
|
||||
log.info("Last connection lock released, will disconnect " + disconnectTimeout + " seconds");
|
||||
disconnectTimer = DelayedActionThread.runDelayed("Disconnect Timer", disconnectTimeout * 1000, this::disconnect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
messageQueue.completeActiveRequest(new ConnectionLostException());
|
||||
messageQueue.completePendingRequests(new ConnectionLostException());
|
||||
if (recoveryTimer != null) {
|
||||
recoveryTimer.interrupt();
|
||||
recoveryTimer = null;
|
||||
}
|
||||
if (disconnectTimer != null) {
|
||||
disconnectTimer.interrupt();
|
||||
disconnectTimer = null;
|
||||
}
|
||||
if (inputStreamReader != null) {
|
||||
inputStreamReader.close();
|
||||
inputStreamReader = null;
|
||||
}
|
||||
if (outputStreamWriter != null) {
|
||||
outputStreamWriter.close();
|
||||
outputStreamWriter = null;
|
||||
}
|
||||
if (connectionEstablisher != null) {
|
||||
connectionEstablisher.close();
|
||||
connectionEstablisher = null;
|
||||
}
|
||||
bluetoothSocket = null;
|
||||
if (timeoutTimer != null) {
|
||||
timeoutTimer.interrupt();
|
||||
timeoutTimer = null;
|
||||
}
|
||||
buffer.clear();
|
||||
verificationString = null;
|
||||
keyPair = null;
|
||||
randomBytes = null;
|
||||
activatedServices.clear();
|
||||
if (!pairingDataStorage.isPaired()) {
|
||||
bluetoothSocket = null;
|
||||
bluetoothDevice = null;
|
||||
pairingDataStorage.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void handleException(Exception e) {
|
||||
switch (state) {
|
||||
case NOT_PAIRED:
|
||||
case DISCONNECTED:
|
||||
case RECOVERING:
|
||||
return;
|
||||
}
|
||||
log.info("Exception occurred: " + e.getClass().getSimpleName());
|
||||
if (pairingDataStorage.isPaired()) {
|
||||
setState(connectionRequests.size() != 0 ? InsightState.RECOVERING : InsightState.DISCONNECTED);
|
||||
cleanup();
|
||||
messageQueue.completeActiveRequest(e);
|
||||
messageQueue.completePendingRequests(e);
|
||||
if (connectionRequests.size() != 0) {
|
||||
if (!(e instanceof ConnectionFailedException)) {
|
||||
connect();
|
||||
} else {
|
||||
int recoveryDuration = SP.getInt("insight_recovery_duration", 5);
|
||||
recoveryDuration = Math.min(recoveryDuration, 20);
|
||||
recoveryDuration = Math.max(recoveryDuration, 0);
|
||||
recoveryTimer = DelayedActionThread.runDelayed("RecoveryTimer", recoveryDuration * 1000, () -> {
|
||||
recoveryTimer = null;
|
||||
synchronized (InsightConnectionService.this) {
|
||||
if (!Thread.currentThread().isInterrupted()) connect();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setState(InsightState.NOT_PAIRED);
|
||||
cleanup();
|
||||
}
|
||||
for (ExceptionCallback exceptionCallback : exceptionCallbacks)
|
||||
exceptionCallback.onExceptionOccur(e);
|
||||
}
|
||||
|
||||
private synchronized void disconnect() {
|
||||
if (state == InsightState.CONNECTED) {
|
||||
sendAppLayerMessage(new DisconnectMessage());
|
||||
sendSatlMessageAndWait(new info.nightscout.androidaps.plugins.PumpInsightLocal.satl.DisconnectMessage());
|
||||
}
|
||||
cleanup();
|
||||
setState(pairingDataStorage.isPaired() ? InsightState.DISCONNECTED : InsightState.NOT_PAIRED);
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
pairingDataStorage.reset();
|
||||
disconnect();
|
||||
}
|
||||
|
||||
public synchronized void pair(String macAddress) {
|
||||
if (pairingDataStorage.isPaired())
|
||||
throw new IllegalStateException("Pump must be unbonded first.");
|
||||
if (connectionRequests.size() == 0)
|
||||
throw new IllegalStateException("A connection lock must be hold for pairing");
|
||||
log.info("Pairing initiated");
|
||||
cleanup();
|
||||
pairingDataStorage.setMacAddress(macAddress);
|
||||
connect();
|
||||
}
|
||||
|
||||
private synchronized void connect() {
|
||||
if (bluetoothDevice == null)
|
||||
bluetoothDevice = bluetoothAdapter.getRemoteDevice(pairingDataStorage.getMacAddress());
|
||||
setState(InsightState.CONNECTING);
|
||||
connectionEstablisher = new ConnectionEstablisher(this, !pairingDataStorage.isPaired(), bluetoothAdapter, bluetoothDevice, bluetoothSocket);
|
||||
connectionEstablisher.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onSocketCreated(BluetoothSocket bluetoothSocket) {
|
||||
this.bluetoothSocket = bluetoothSocket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onConnectionSucceed() {
|
||||
try {
|
||||
inputStreamReader = new InputStreamReader(bluetoothSocket.getInputStream(), this);
|
||||
outputStreamWriter = new OutputStreamWriter(bluetoothSocket.getOutputStream(), this);
|
||||
inputStreamReader.start();
|
||||
outputStreamWriter.start();
|
||||
if (pairingDataStorage.isPaired()) {
|
||||
setState(InsightState.SATL_SYN_REQUEST);
|
||||
sendSatlMessage(new SynRequest());
|
||||
} else {
|
||||
setState(InsightState.SATL_CONNECTION_REQUEST);
|
||||
sendSatlMessage(new ConnectionRequest());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onReceiveBytes(byte[] buffer, int bytesRead) {
|
||||
this.buffer.putBytes(buffer, bytesRead);
|
||||
try {
|
||||
while (SatlMessage.hasCompletePacket(this.buffer)) {
|
||||
SatlMessage satlMessage = SatlMessage.deserialize(this.buffer, pairingDataStorage.getLastNonceReceived(), pairingDataStorage.getIncomingKey());
|
||||
if (pairingDataStorage.getIncomingKey() != null
|
||||
&& pairingDataStorage.getLastNonceReceived() != null
|
||||
&& !pairingDataStorage.getLastNonceReceived().isSmallerThan(satlMessage.getNonce())) {
|
||||
throw new InvalidNonceException();
|
||||
} else processSatlMessage(satlMessage);
|
||||
}
|
||||
} catch (InsightException e) {
|
||||
handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] prepareSatlMessage(SatlMessage satlMessage) {
|
||||
satlMessage.setCommID(pairingDataStorage.getCommId());
|
||||
Nonce nonce = pairingDataStorage.getLastNonceSent();
|
||||
if (nonce != null) {
|
||||
nonce.increment();
|
||||
pairingDataStorage.setLastNonceSent(nonce);
|
||||
satlMessage.setNonce(nonce);
|
||||
}
|
||||
ByteBuf serialized = satlMessage.serialize(satlMessage.getClass(), pairingDataStorage.getOutgoingKey());
|
||||
if (timeoutTimer != null) timeoutTimer.interrupt();
|
||||
timeoutTimer = DelayedActionThread.runDelayed("TimeoutTimer", RESPONSE_TIMEOUT, () -> {
|
||||
timeoutTimer = null;
|
||||
handleException(new TimeoutException());
|
||||
});
|
||||
return serialized.getBytes();
|
||||
}
|
||||
|
||||
private void sendSatlMessage(SatlMessage satlMessage) {
|
||||
if (outputStreamWriter == null) return;
|
||||
outputStreamWriter.write(prepareSatlMessage(satlMessage));
|
||||
}
|
||||
|
||||
private void sendSatlMessageAndWait(SatlMessage satlMessage) {
|
||||
if (outputStreamWriter == null) return;
|
||||
outputStreamWriter.writeAndWait(prepareSatlMessage(satlMessage));
|
||||
}
|
||||
|
||||
private void processSatlMessage(SatlMessage satlMessage) {
|
||||
if (timeoutTimer != null) {
|
||||
timeoutTimer.interrupt();
|
||||
timeoutTimer = null;
|
||||
}
|
||||
pairingDataStorage.setLastNonceReceived(satlMessage.getNonce());
|
||||
if (satlMessage instanceof ConnectionResponse) processConnectionResponse();
|
||||
else if (satlMessage instanceof KeyResponse) processKeyResponse((KeyResponse) satlMessage);
|
||||
else if (satlMessage instanceof VerifyDisplayResponse) processVerifyDisplayResponse();
|
||||
else if (satlMessage instanceof VerifyConfirmResponse)
|
||||
processVerifyConfirmResponse((VerifyConfirmResponse) satlMessage);
|
||||
else if (satlMessage instanceof DataMessage) processDataMessage((DataMessage) satlMessage);
|
||||
else if (satlMessage instanceof SynAckResponse) processSynAckResponse();
|
||||
else if (satlMessage instanceof ErrorMessage)
|
||||
processErrorMessage((ErrorMessage) satlMessage);
|
||||
else handleException(new InvalidSatlCommandException());
|
||||
}
|
||||
|
||||
private void processConnectionResponse() {
|
||||
if (state != InsightState.SATL_CONNECTION_REQUEST) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
keyRequest = new KeyRequest();
|
||||
keyRequest.setPreMasterKey(getKeyPair().getPublicKeyBytes());
|
||||
keyRequest.setRandomBytes(getRandomBytes());
|
||||
setState(InsightState.SATL_KEY_REQUEST);
|
||||
sendSatlMessage(keyRequest);
|
||||
}
|
||||
|
||||
private void processKeyResponse(KeyResponse keyResponse) {
|
||||
if (state != InsightState.SATL_KEY_REQUEST) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
DerivedKeys derivedKeys = Cryptograph.deriveKeys(Cryptograph.combine(keyRequest.getSatlContent(), keyResponse.getSatlContent()),
|
||||
Cryptograph.decryptRSA(getKeyPair().getPrivateKey(), keyResponse.getPreMasterSecret()),
|
||||
getRandomBytes(),
|
||||
keyResponse.getRandomData());
|
||||
pairingDataStorage.setCommId(keyResponse.getCommID());
|
||||
keyRequest = null;
|
||||
randomBytes = null;
|
||||
keyPair = null;
|
||||
verificationString = derivedKeys.getVerificationString();
|
||||
pairingDataStorage.setOutgoingKey(derivedKeys.getOutgoingKey());
|
||||
pairingDataStorage.setIncomingKey(derivedKeys.getIncomingKey());
|
||||
pairingDataStorage.setLastNonceSent(new Nonce());
|
||||
setState(InsightState.SATL_VERIFY_DISPLAY_REQUEST);
|
||||
sendSatlMessage(new VerifyDisplayRequest());
|
||||
} catch (InvalidCipherTextException e) {
|
||||
handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void processVerifyDisplayResponse() {
|
||||
if (state != InsightState.SATL_VERIFY_DISPLAY_REQUEST) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
setState(InsightState.AWAITING_CODE_CONFIRMATION);
|
||||
}
|
||||
|
||||
private void processVerifyConfirmResponse(VerifyConfirmResponse verifyConfirmResponse) {
|
||||
if (state != InsightState.SATL_VERIFY_CONFIRM_REQUEST) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
switch (verifyConfirmResponse.getPairingStatus()) {
|
||||
case CONFIRMED:
|
||||
verificationString = null;
|
||||
setState(InsightState.APP_BIND_MESSAGE);
|
||||
sendAppLayerMessage(new BindMessage());
|
||||
break;
|
||||
case PENDING:
|
||||
try {
|
||||
Thread.sleep(200);
|
||||
sendSatlMessage(new VerifyConfirmRequest());
|
||||
} catch (InterruptedException e) {
|
||||
//Redirect interrupt flag
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
break;
|
||||
case REJECTED:
|
||||
handleException(new SatlPairingRejectedException());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void processSynAckResponse() {
|
||||
if (state != InsightState.SATL_SYN_REQUEST) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
setState(InsightState.APP_CONNECT_MESSAGE);
|
||||
sendAppLayerMessage(new ConnectMessage());
|
||||
}
|
||||
|
||||
private void processErrorMessage(ErrorMessage errorMessage) {
|
||||
switch (errorMessage.getError()) {
|
||||
case INVALID_NONCE:
|
||||
handleException(new SatlInvalidNonceErrorException());
|
||||
break;
|
||||
case INVALID_CRC:
|
||||
handleException(new SatlInvalidCRCErrorException());
|
||||
break;
|
||||
case INVALID_MAC_TRAILER:
|
||||
handleException(new SatlInvalidMacErrorException());
|
||||
break;
|
||||
case DECRYPT_VERIFY_FAILED:
|
||||
handleException(new SatlDecryptVerifyFailedErrorException());
|
||||
break;
|
||||
case INVALID_PAYLOAD_LENGTH:
|
||||
handleException(new SatlInvalidPayloadLengthErrorException());
|
||||
break;
|
||||
case INVALID_MESSAGE_TYPE:
|
||||
handleException(new SatlInvalidMessageTypeErrorException());
|
||||
break;
|
||||
case INCOMPATIBLE_VERSION:
|
||||
handleException(new SatlIncompatibleVersionErrorException());
|
||||
break;
|
||||
case COMPATIBLE_STATE:
|
||||
handleException(new SatlCompatibleStateErrorException());
|
||||
break;
|
||||
case INVALID_COMM_ID:
|
||||
handleException(new SatlInvalidCommIdErrorException());
|
||||
break;
|
||||
case INVALID_PACKET:
|
||||
handleException(new SatlInvalidPacketErrorException());
|
||||
break;
|
||||
case WRONG_STATE:
|
||||
handleException(new SatlWrongStateException());
|
||||
break;
|
||||
case UNDEFINED:
|
||||
handleException(new SatlUndefinedErrorException());
|
||||
break;
|
||||
case NONE:
|
||||
handleException(new SatlNoneErrorException());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void processDataMessage(DataMessage dataMessage) {
|
||||
switch (state) {
|
||||
case CONNECTED:
|
||||
case APP_BIND_MESSAGE:
|
||||
case APP_CONNECT_MESSAGE:
|
||||
case APP_ACTIVATE_PARAMETER_SERVICE:
|
||||
case APP_ACTIVATE_STATUS_SERVICE:
|
||||
case APP_FIRMWARE_VERSIONS:
|
||||
case APP_SYSTEM_IDENTIFICATION:
|
||||
break;
|
||||
default:
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
}
|
||||
try {
|
||||
AppLayerMessage appLayerMessage = AppLayerMessage.unwrap(dataMessage);
|
||||
if (appLayerMessage instanceof BindMessage) processBindMessage();
|
||||
else if (appLayerMessage instanceof ConnectMessage) processConnectMessage();
|
||||
else if (appLayerMessage instanceof ActivateServiceMessage)
|
||||
processActivateServiceMessage();
|
||||
else if (appLayerMessage instanceof DisconnectMessage) ;
|
||||
else if (appLayerMessage instanceof ServiceChallengeMessage)
|
||||
processServiceChallengeMessage((ServiceChallengeMessage) appLayerMessage);
|
||||
else if (appLayerMessage instanceof GetFirmwareVersionsMessage)
|
||||
processFirmwareVersionsMessage((GetFirmwareVersionsMessage) appLayerMessage);
|
||||
else if (appLayerMessage instanceof ReadParameterBlockMessage)
|
||||
processReadParameterBlockMessage((ReadParameterBlockMessage) appLayerMessage);
|
||||
else processGenericAppLayerMessage(appLayerMessage);
|
||||
} catch (Exception e) {
|
||||
if (state != InsightState.CONNECTED) {
|
||||
handleException(e);
|
||||
} else {
|
||||
if (messageQueue.getActiveRequest() == null) {
|
||||
handleException(new TooChattyPumpException());
|
||||
} else {
|
||||
messageQueue.completeActiveRequest(e);
|
||||
requestNextMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processBindMessage() {
|
||||
if (state != InsightState.APP_BIND_MESSAGE) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
setState(InsightState.APP_ACTIVATE_STATUS_SERVICE);
|
||||
ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage();
|
||||
activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.STATUS));
|
||||
activateServiceMessage.setServicePassword(new byte[16]);
|
||||
activateServiceMessage.setVersion(info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.STATUS.getVersion());
|
||||
sendAppLayerMessage(activateServiceMessage);
|
||||
}
|
||||
|
||||
private void processFirmwareVersionsMessage(GetFirmwareVersionsMessage message) {
|
||||
if (state != InsightState.APP_FIRMWARE_VERSIONS) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
pairingDataStorage.setFirmwareVersions(message.getFirmwareVersions());
|
||||
setState(InsightState.APP_ACTIVATE_PARAMETER_SERVICE);
|
||||
ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage();
|
||||
activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.PARAMETER));
|
||||
activateServiceMessage.setServicePassword(new byte[16]);
|
||||
activateServiceMessage.setVersion(info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.PARAMETER.getVersion());
|
||||
sendAppLayerMessage(activateServiceMessage);
|
||||
}
|
||||
|
||||
private void processConnectMessage() {
|
||||
if (state != InsightState.APP_CONNECT_MESSAGE) {
|
||||
handleException(new ReceivedPacketInInvalidStateException());
|
||||
return;
|
||||
}
|
||||
setState(InsightState.CONNECTED);
|
||||
}
|
||||
|
||||
private void processActivateServiceMessage() {
|
||||
if (state == InsightState.APP_ACTIVATE_PARAMETER_SERVICE) {
|
||||
activatedServices.add(info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.PARAMETER);
|
||||
setState(InsightState.APP_SYSTEM_IDENTIFICATION);
|
||||
ReadParameterBlockMessage message = new ReadParameterBlockMessage();
|
||||
message.setParameterBlockId(SystemIdentificationBlock.class);
|
||||
message.setService(info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.PARAMETER);
|
||||
sendAppLayerMessage(message);
|
||||
} else if (state == InsightState.APP_ACTIVATE_STATUS_SERVICE) {
|
||||
activatedServices.add(info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service.STATUS);
|
||||
setState(InsightState.APP_FIRMWARE_VERSIONS);
|
||||
sendAppLayerMessage(new GetFirmwareVersionsMessage());
|
||||
} else {
|
||||
if (messageQueue.getActiveRequest() == null) {
|
||||
handleException(new TooChattyPumpException());
|
||||
} else {
|
||||
activatedServices.add(messageQueue.getActiveRequest().request.getService());
|
||||
sendAppLayerMessage(messageQueue.getActiveRequest().request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processReadParameterBlockMessage(ReadParameterBlockMessage message) {
|
||||
if (state == InsightState.APP_SYSTEM_IDENTIFICATION) {
|
||||
if (!(message.getParameterBlock() instanceof SystemIdentificationBlock)) handleException(new TooChattyPumpException());
|
||||
else {
|
||||
SystemIdentification systemIdentification = ((SystemIdentificationBlock) message.getParameterBlock()).getSystemIdentification();
|
||||
pairingDataStorage.setSystemIdentification(systemIdentification);
|
||||
pairingDataStorage.setPaired(true);
|
||||
log.info("Pairing completed YEE-HAW ♪ ┏(・o・)┛ ♪ ┗( ・o・)┓ ♪");
|
||||
setState(InsightState.CONNECTED);
|
||||
}
|
||||
} else processGenericAppLayerMessage(message);
|
||||
}
|
||||
|
||||
private void processServiceChallengeMessage(ServiceChallengeMessage serviceChallengeMessage) {
|
||||
if (messageQueue.getActiveRequest() == null) {
|
||||
handleException(new TooChattyPumpException());
|
||||
} else {
|
||||
info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.Service service = messageQueue.getActiveRequest().request.getService();
|
||||
ActivateServiceMessage activateServiceMessage = new ActivateServiceMessage();
|
||||
activateServiceMessage.setServiceID(ServiceIDs.IDS.getID(service));
|
||||
activateServiceMessage.setVersion(service.getVersion());
|
||||
activateServiceMessage.setServicePassword(Cryptograph.getServicePasswordHash(service.getServicePassword(), serviceChallengeMessage.getRandomData()));
|
||||
sendAppLayerMessage(activateServiceMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private void processGenericAppLayerMessage(AppLayerMessage appLayerMessage) {
|
||||
if (messageQueue.getActiveRequest() == null) handleException(new TooChattyPumpException());
|
||||
else {
|
||||
try {
|
||||
messageQueue.completeActiveRequest(appLayerMessage);
|
||||
lastDataTime = System.currentTimeMillis();
|
||||
} catch (Exception e) {
|
||||
messageQueue.completeActiveRequest(e);
|
||||
}
|
||||
requestNextMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void sendAppLayerMessage(AppLayerMessage appLayerMessage) {
|
||||
sendSatlMessage(AppLayerMessage.wrap(appLayerMessage));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onConnectionFail(Exception e) {
|
||||
handleException(new ConnectionFailedException());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onErrorWhileReading(Exception e) {
|
||||
handleException(new ConnectionLostException());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onErrorWhileWriting(Exception e) {
|
||||
handleException(new ConnectionLostException());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
disconnect();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return localBinder;
|
||||
}
|
||||
|
||||
public class LocalBinder extends Binder {
|
||||
public InsightConnectionService getService() {
|
||||
return InsightConnectionService.this;
|
||||
}
|
||||
}
|
||||
|
||||
public interface StateCallback {
|
||||
void stateChanged(InsightState state);
|
||||
}
|
||||
|
||||
public interface ExceptionCallback {
|
||||
void onExceptionOccur(Exception e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
|
||||
public class MessageQueue {
|
||||
|
||||
MessageRequest activeRequest;
|
||||
final List<MessageRequest> messageRequests = new ArrayList<>();
|
||||
|
||||
public MessageRequest getActiveRequest() {
|
||||
return activeRequest;
|
||||
}
|
||||
|
||||
public void completeActiveRequest(AppLayerMessage response) {
|
||||
if (activeRequest == null) return;
|
||||
synchronized (activeRequest) {
|
||||
activeRequest.response = response;
|
||||
activeRequest.notifyAll();
|
||||
}
|
||||
activeRequest = null;
|
||||
}
|
||||
|
||||
public void completeActiveRequest(Exception exception) {
|
||||
if (activeRequest == null) return;
|
||||
synchronized (activeRequest) {
|
||||
activeRequest.exception = exception;
|
||||
activeRequest.notifyAll();
|
||||
}
|
||||
activeRequest = null;
|
||||
}
|
||||
|
||||
public void completePendingRequests(Exception exception) {
|
||||
for (MessageRequest messageRequest : messageRequests) {
|
||||
synchronized (messageRequest) {
|
||||
messageRequest.exception = exception;
|
||||
messageRequest.notifyAll();
|
||||
}
|
||||
}
|
||||
messageRequests.clear();
|
||||
}
|
||||
|
||||
public void enqueueRequest(MessageRequest messageRequest) {
|
||||
messageRequests.add(messageRequest);
|
||||
Collections.sort(messageRequests);
|
||||
}
|
||||
|
||||
public void nextRequest() {
|
||||
if (messageRequests.size() != 0) {
|
||||
activeRequest = messageRequests.get(0);
|
||||
messageRequests.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPendingMessages() {
|
||||
return messageRequests.size() != 0;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
activeRequest = null;
|
||||
messageRequests.clear();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.connection_service;
|
||||
|
||||
import info.nightscout.androidaps.plugins.PumpInsightLocal.app_layer.AppLayerMessage;
|
||||
|
||||
public class MessageRequest<T extends AppLayerMessage> implements Comparable<MessageRequest> {
|
||||
|
||||
T request;
|
||||
T response;
|
||||
Exception exception;
|
||||
|
||||
MessageRequest(T request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
public T await() throws Exception {
|
||||
synchronized (this) {
|
||||
while (exception == null && response == null) wait();
|
||||
if (exception != null) throw exception;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
public T await(long timeout) throws Exception {
|
||||
synchronized (this) {
|
||||
while (exception == null && response == null) wait(timeout);
|
||||
if (exception != null) throw exception;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(MessageRequest messageRequest) {
|
||||
return request.compareTo(messageRequest.request);
|
||||
}
|
||||
|
||||
public T getRequest() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
public T getResponse() {
|
||||
return this.response;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return this.exception;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.database;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_INSIGHT_BOLUS_IDS)
|
||||
public class InsightBolusID {
|
||||
|
||||
@DatabaseField(generatedId = true)
|
||||
public Long id;
|
||||
|
||||
@DatabaseField
|
||||
public String pumpSerial;
|
||||
|
||||
@DatabaseField
|
||||
public Long timestamp;
|
||||
|
||||
@DatabaseField
|
||||
public Integer bolusID;
|
||||
|
||||
@DatabaseField
|
||||
public Long startID;
|
||||
|
||||
@DatabaseField
|
||||
public Long endID;
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.database;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_INSIGHT_HISTORY_OFFSETS)
|
||||
public class InsightHistoryOffset {
|
||||
|
||||
@DatabaseField(id = true, canBeNull = false)
|
||||
public String pumpSerial;
|
||||
|
||||
@DatabaseField
|
||||
public long offset;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package info.nightscout.androidaps.plugins.PumpInsightLocal.database;
|
||||
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
|
||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||
|
||||
@DatabaseTable(tableName = DatabaseHelper.DATABASE_INSIGHT_PUMP_IDS)
|
||||
public class InsightPumpID {
|
||||
|
||||
@DatabaseField(generatedId = true)
|
||||
public Long id;
|
||||
|
||||
@DatabaseField
|
||||
public long timestamp;
|
||||
|
||||
@DatabaseField
|
||||
public String eventType;
|
||||
|
||||
@DatabaseField
|
||||
public String pumpSerial;
|
||||
|
||||
@DatabaseField
|
||||
public long eventID;
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue