basic danar comm

This commit is contained in:
Milos Kozak 2016-07-08 00:17:02 +02:00
parent a172e9630f
commit dc3eb80d52
54 changed files with 2935 additions and 4 deletions

View file

@ -53,4 +53,5 @@ dependencies {
compile 'org.slf4j:slf4j-api:1.7.12'
compile 'com.jjoe64:graphview:4.0.1'
compile 'com.eclipsesource.j2v8:j2v8:3.1.6@aar'
compile 'com.joanzapata.iconify:android-iconify-fontawesome:2.1.1'
}

View file

@ -26,4 +26,9 @@ public class Config {
public static final boolean logConstraintsChanges = true;
public static final boolean logTempBasalsCut = true;
public static final boolean logNSUpload = true;
// DanaR specific
public static final boolean logDanaBTComm = true;
public static final boolean logDanaMessageDetail = true;
public static final boolean logDanaSerialEngine = true;
}

View file

@ -15,6 +15,8 @@ import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.fonts.FontAwesomeModule;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
@ -64,6 +66,7 @@ public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Iconify.with(new FontAwesomeModule());
LocaleHelper.onCreate(this, "en");
checkEula();
setContentView(R.layout.activity_main);

View file

@ -52,6 +52,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, HistoryRecord.class);
} catch (SQLException e) {
log.error(DatabaseHelper.class.getName(), "Can't create database", e);
throw new RuntimeException(e);
@ -65,6 +66,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, TempBasal.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, HistoryRecord.class, true);
onCreate(database, connectionSource);
} catch (SQLException e) {
log.error(DatabaseHelper.class.getName(), "Can't drop databases", e);
@ -93,6 +95,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
log.debug("Before Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "Treatments"));
getWritableDatabase().delete("Treatments", "timeIndex" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After Treatments size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "Treatments"));
log.debug("Before History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "History"));
getWritableDatabase().delete("History", "recordDate" + " < '" + (new Date().getTime() - Constants.hoursToKeepInDatabase * 60 * 60 * 1000L) + "'", null);
log.debug("After History size: " + DatabaseUtils.queryNumEntries(getReadableDatabase(), "History"));
}
public void resetDatabases() {
@ -100,9 +106,11 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
TableUtils.dropTable(connectionSource, TempBasal.class, true);
TableUtils.dropTable(connectionSource, Treatment.class, true);
TableUtils.dropTable(connectionSource, BgReading.class, true);
TableUtils.dropTable(connectionSource, HistoryRecord.class, true);
TableUtils.createTableIfNotExists(connectionSource, TempBasal.class);
TableUtils.createTableIfNotExists(connectionSource, Treatment.class);
TableUtils.createTableIfNotExists(connectionSource, BgReading.class);
TableUtils.createTableIfNotExists(connectionSource, HistoryRecord.class);
MainApp.bus().post(new EventNewBG());
MainApp.bus().post(new EventTreatmentChange());
MainApp.bus().post(new EventTempBasalChange());
@ -130,11 +138,13 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
}
public Dao<BgReading, Long> getDaoBgReadings() throws SQLException {
//SQLiteDatabase db = getReadableDatabase();
//log.debug("BgReadings size: " + DatabaseUtils.queryNumEntries(db, "BgReadings"));
return getDao(BgReading.class);
}
public Dao<HistoryRecord, String> getDaoHistory() throws SQLException {
return getDao(HistoryRecord.class);
}
/*
* Return last BgReading from database or null if db is empty
*/

View file

@ -0,0 +1,171 @@
package info.nightscout.androidaps.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import java.util.Date;
@DatabaseTable(tableName = "History")
public class HistoryRecord {
@DatabaseField(useGetSet = true)
private String _id;
@DatabaseField(useGetSet = true)
private byte recordCode;
@DatabaseField(id = true, useGetSet = true)
private String bytes;
@DatabaseField(useGetSet = true)
private long recordDate;
@DatabaseField(useGetSet = true)
private double recordValue;
@DatabaseField(useGetSet = true)
private String bolusType;
@DatabaseField(useGetSet = true)
private String stringRecordValue;
@DatabaseField(useGetSet = true)
private int recordDuration;
@DatabaseField(useGetSet = true)
private double recordDailyBasal;
@DatabaseField(useGetSet = true)
private double recordDailyBolus;
@DatabaseField(useGetSet = true)
private String recordAlarm;
public HistoryRecord() {
this.recordDate = 0;
this.recordValue = 0.0;
this.bolusType = "None";
this.recordCode = 0x0F;
this.bytes = new String();
this._id = null;
}
public void setRecordDate(Date dtRecordDate) {
this.recordDate = dtRecordDate.getTime();
}
public long getRecordDate() {
return this.recordDate;
}
public void setRecordDate(long dtRecordDate) {
this.recordDate = dtRecordDate;
}
public double getRecordValue() {
return this.recordValue;
}
public void setRecordValue(double dRecordValue) {
this.recordValue = dRecordValue;
}
public String getBolusType() {
return this.bolusType;
}
public void setBolusType(String strRecordType) {
this.bolusType = strRecordType;
}
public String getStringRecordValue() {
return this.stringRecordValue;
}
public void setStringRecordValue(String strRecordValue) {
this.stringRecordValue = strRecordValue;
}
public byte getRecordCode() {
return this.recordCode;
}
public void setRecordCode(byte cRecordCode) {
this.recordCode = cRecordCode;
}
public int getRecordDuration() {
return this.recordDuration;
}
public void setRecordDuration(int dRecordDuraion) {
this.recordDuration = dRecordDuraion;
}
public double getRecordDailyBasal() {
return this.recordDailyBasal;
}
public void setRecordDailyBasal(double dRecordDailyBasal) {
this.recordDailyBasal = dRecordDailyBasal;
}
public double getRecordDailyBolus() {
return this.recordDailyBolus;
}
public void setRecordDailyBolus(double dRecordDailyBolus) {
this.recordDailyBolus = dRecordDailyBolus;
}
public int getRecordLevel(double dExLow, double dLow, double dHigh, double dExHigh) {
if (this.recordValue < dExLow)
return 0;
if (this.recordValue < dLow)
return 1;
if (this.recordValue < dHigh)
return 2;
return this.recordValue < dExHigh ? 3 : 4;
}
public String getRecordAlarm() {
return this.recordAlarm;
}
public void setRecordAlarm(String strAlarm) {
this.recordAlarm = strAlarm;
}
public String get_id() {
return this._id;
}
public void set_id(String _id) {
this._id = _id;
}
public void setBytes(byte[] raw) {
this.bytes = bytesToHex(raw);
}
public void setBytes(String bytes) {
this.bytes = bytes;
}
public String getBytes() {
return this.bytes;
}
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}

View file

@ -1,21 +1,528 @@
package info.nightscout.androidaps.plugins.DanaR;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import com.j256.ormlite.dao.Dao;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainActivity;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.Services.AlertService;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.plugins.DanaR.comm.*;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusProgress;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
import info.nightscout.client.data.NSProfile;
import info.nightscout.utils.ToastUtils;
/**
* Created by mike on 07.07.2016.
*/
public class DanaConnection {
private static Logger log = LoggerFactory.getLogger(DanaConnection.class);
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
public String devName = SP.getString("danar_bt_name", "");
Handler mHandler;
public static HandlerThread mHandlerThread;
private final Bus mBus;
private SerialEngine mSerialEngine;
private InputStream mInputStream;
private OutputStream mOutputStream;
private BluetoothSocket mRfcommSocket;
private BluetoothDevice mDevice;
PowerManager.WakeLock mWakeLock;
private Treatment bolusingTreatment = null;
private DanaRFragment danaRFragment;
private DanaRPump danaRPump;
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
private static ScheduledFuture<?> scheduledDisconnection = null;
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
public DanaConnection(Bus bus) {
danaRFragment = (DanaRFragment) MainActivity.getSpecificPlugin(DanaRFragment.class);
danaRFragment.setDanaConnection(this);
danaRPump = danaRFragment.getDanaRPump();
mHandlerThread = new HandlerThread(DanaConnection.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
getSelectedPump();
this.mBus = bus;
createRfCommSocket();
PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DanaConnection");
}
public void connectIfNotConnected(String reason) {
private void createRfCommSocket() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter != null) {
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
for (BluetoothDevice device : devices) {
String dName = device.getName();
if (devName.equals(dName)) {
mDevice = device;
try {
mRfcommSocket = mDevice.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
log.error("Error creating socket: ", e);
}
break;
}
}
registerBTdisconnectionBroadcastReceiver();
} else {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.nobtadapter));
}
if (mDevice == null) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound));
}
}
private void registerBTdisconnectionBroadcastReceiver() {
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
log.debug("Device has disconnected " + device.getName());//Device has disconnected
if (mDevice.getName().equals(device.getName())) {
if (mRfcommSocket != null) {
try {
mInputStream.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
try {
mOutputStream.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
try {
mRfcommSocket.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
}
mBus.post(new EventDanaRConnectionStatus(false, false, 0));
}
}
}
};
MainApp.instance().getApplicationContext().registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
}
public synchronized void connectIfNotConnected(String callerName) {
mWakeLock.acquire();
long startTime = System.currentTimeMillis();
short connectionAttemptCount = 0;
if (!(isConnected())) {
long timeToConnectTimeSoFar = 0;
while (!(isConnected())) {
timeToConnectTimeSoFar = (System.currentTimeMillis() - startTime) / 1000;
mBus.post(new EventDanaRConnectionStatus(true, false, connectionAttemptCount));
connectBT();
if (Config.logDanaBTComm)
log.debug("connectIfNotConnected waiting " + timeToConnectTimeSoFar + "s attempts:" + connectionAttemptCount + " caller:" + callerName);
connectionAttemptCount++;
if (timeToConnectTimeSoFar / 60 > 15 || connectionAttemptCount > 180) {
Intent alarmServiceIntent = new Intent(MainApp.instance().getApplicationContext(), AlertService.class);
alarmServiceIntent.putExtra("alarmText", MainApp.sResources.getString(R.string.connectionerror)); //TODO: hardcoded string
MainApp.instance().getApplicationContext().startService(alarmServiceIntent);
}
waitMsec(1000);
}
if (Config.logDanaBTComm)
log.debug("connectIfNotConnected took " + timeToConnectTimeSoFar + "s attempts:" + connectionAttemptCount);
} else {
mBus.post(new EventDanaRConnectionStatus(false, true, 0));
}
mWakeLock.release();
}
private synchronized void connectBT() {
if (mDevice == null) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.devicenotfound));
return;
}
if (mRfcommSocket == null) {
try {
mRfcommSocket = mDevice.createRfcommSocketToServiceRecord(SPP_UUID);
} catch (IOException e) {
log.error("Error creating socket: ", e);
}
if (mRfcommSocket == null) {
log.warn("connectBT() mRfcommSocket is null");
return;
}
}
if (!mRfcommSocket.isConnected()) {
try {
mRfcommSocket.connect();
if (Config.logDanaBTComm)
log.debug("Connected");
mOutputStream = mRfcommSocket.getOutputStream();
mInputStream = mRfcommSocket.getInputStream();
if (mSerialEngine != null) {
mSerialEngine.stopLoop();
}
mSerialEngine = new SerialEngine(this, mInputStream, mOutputStream, mRfcommSocket);
mBus.post(new EventDanaRConnectionStatus(false, true, 0));
} catch (IOException e) {
log.warn("connectBT() ConnectionStatusEvent attempt failed: " + e.getMessage());
mRfcommSocket = null;
}
}
if (isConnected()) {
mBus.post(new EventDanaRConnectionStatus(false, true, 0));
pingStatus();
}
}
public void scheduleDisconnection() {
class DisconnectRunnable implements Runnable {
public void run() {
disconnect("scheduleDisconnection");
scheduledDisconnection = null;
}
}
// prepare task for execution in 5 sec
// cancel waiting task to prevent sending multiple disconnections
if (scheduledDisconnection != null)
scheduledDisconnection.cancel(false);
Runnable task = new DisconnectRunnable();
scheduledDisconnection = worker.schedule(task, 3, TimeUnit.SECONDS);
}
public void disconnect(String from) {
if (mRfcommSocket.isConnected()) {
try {
mInputStream.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
try {
mOutputStream.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
try {
mRfcommSocket.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
if (Config.logDanaBTComm)
log.debug("Disconnecting " + from);
} else {
if (Config.logDanaBTComm)
log.debug("Already disconnected " + from);
}
}
public boolean isConnected() {
return mRfcommSocket != null && mRfcommSocket.isConnected();
}
private void pingStatus() {
try {
MsgStatus statusMsg = new MsgStatus();
MsgStatusBasic statusBasicMsg = new MsgStatusBasic();
MsgStatusTempBasal tempStatusMsg = new MsgStatusTempBasal();
MsgStatusBolusExtended exStatusMsg = new MsgStatusBolusExtended();
mSerialEngine.sendMessage(statusMsg);
mSerialEngine.sendMessage(statusBasicMsg);
mSerialEngine.sendMessage(tempStatusMsg);
mSerialEngine.sendMessage(exStatusMsg);
if (danaRPump.isNewPump) {
mSerialEngine.sendMessage(new MsgSettingShippingInfo());
mSerialEngine.sendMessage(new MsgCheckValue());
}
if (!statusMsg.received) {
mSerialEngine.sendMessage(statusMsg);
}
if (!statusBasicMsg.received) {
mSerialEngine.sendMessage(statusBasicMsg);
}
if (!tempStatusMsg.received) {
// Load of status of current basal rate failed, give one more try
mSerialEngine.sendMessage(tempStatusMsg);
}
if (!exStatusMsg.received) {
// Load of status of current extended bolus failed, give one more try
mSerialEngine.sendMessage(exStatusMsg);
}
// Check we have really current status of pump
if (!statusMsg.received || !statusBasicMsg.received || !tempStatusMsg.received || !exStatusMsg.received) {
waitMsec(10 * 1000);
log.debug("pingStatus failed");
connectIfNotConnected("pingStatus fail");
pingStatus();
return;
}
/* TODO
statusEvent.timeLastSync = statusEvent.time;
if (statusEvent.tempBasalInProgress) {
try {
Dao<TempBasal, Long> daoTempBasals = MainApp.getDbHelper().getDaoTempBasals();
TempBasal tempBasal = new TempBasal();
tempBasal.duration = statusEvent.tempBasalTotalSec / 60;
tempBasal.percent = statusEvent.tempBasalRatio;
tempBasal.timeStart = statusEvent.tempBasalStart;
tempBasal.timeEnd = null;
tempBasal.baseRatio = (int) (statusEvent.currentBasal * 100);
tempBasal.tempRatio = (int) (statusEvent.currentBasal * 100 * statusEvent.tempBasalRatio / 100d);
tempBasal.isExtended = false;
// log.debug("TempBasal in progress record "+tempBasal);
daoTempBasals.createOrUpdate(tempBasal);
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
} else {
try {
Dao<TempBasal, Long> daoTempBasals = MainApp.getDbHelper().getDaoTempBasals();
TempBasal tempBasalLast = getTempBasalLast(daoTempBasals, false);
if (tempBasalLast != null) {
// log.debug("tempBasalLast " + tempBasalLast);
if (tempBasalLast.timeEnd == null || tempBasalLast.timeEnd.getTime() > new Date().getTime()) {
tempBasalLast.timeEnd = new Date();
if (tempBasalLast.timeEnd.getTime() > tempBasalLast.getPlannedTimeEnd().getTime()) {
tempBasalLast.timeEnd = tempBasalLast.getPlannedTimeEnd();
}
// log.debug("tempBasalLast updated to " + tempBasalLast);
daoTempBasals.update(tempBasalLast);
}
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
}
if (statusEvent.isExtendedInProgress) {
try {
Dao<TempBasal, Long> daoTempBasals = MainApp.getDbHelper().getDaoTempBasals();
TempBasal tempBasal = new TempBasal();
tempBasal.duration = statusEvent.extendedBolusMinutes;
tempBasal.percent = (int) ((statusEvent.extendedBolusAbsoluteRate + statusEvent.currentBasal) / statusEvent.currentBasal * 100);
tempBasal.timeStart = statusEvent.extendedBolusStart;
tempBasal.timeEnd = null;
tempBasal.baseRatio = (int) (statusEvent.currentBasal * 100);
tempBasal.tempRatio = (int) (statusEvent.extendedBolusAbsoluteRate * 100 + statusEvent.currentBasal * 100);
tempBasal.isExtended = true;
// log.debug("TempBasal Extended in progress record "+tempBasal);
daoTempBasals.createOrUpdate(tempBasal);
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
} else {
try {
Dao<TempBasal, Long> daoTempBasals = MainApp.getDbHelper().getDaoTempBasals();
TempBasal tempBasalLast = getTempBasalLast(daoTempBasals, true);
if (tempBasalLast != null) {
log.debug("tempBasalLast Extended " + tempBasalLast);
if (tempBasalLast.timeEnd == null || tempBasalLast.timeEnd.getTime() > new Date().getTime()) {
tempBasalLast.timeEnd = new Date();
if (tempBasalLast.timeEnd.getTime() > tempBasalLast.getPlannedTimeEnd().getTime()) {
tempBasalLast.timeEnd = tempBasalLast.getPlannedTimeEnd();
}
// log.debug("tempBasalLast Extended updated to " + tempBasalLast);
daoTempBasals.update(tempBasalLast);
}
}
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
}
synchronized (this) {
this.notify();
}
mBus.post(statusEvent);
*/
} catch (Exception e) {
log.error("err", e);
}
}
public void tempBasal(int percent, int durationInHours) {
MsgSetTempBasalStart msg = new MsgSetTempBasalStart(percent, durationInHours);
mSerialEngine.sendMessage(msg);
pingStatus();
}
public void tempBasalStop() {
MsgSetTempBasalStop msg = new MsgSetTempBasalStop();
mSerialEngine.sendMessage(msg);
pingStatus();
}
public void extendedBolus(double rate, int durationInHalfHours) {
MsgSetExtendedBolusStart msgStartExt = new MsgSetExtendedBolusStart(rate / 2 * durationInHalfHours, (byte) (durationInHalfHours & 0xFF));
mSerialEngine.sendMessage(msgStartExt);
pingStatus();
}
public void extendedBolusStop() {
MsgSetExtendedBolusStop msg = new MsgSetExtendedBolusStop();
mSerialEngine.sendMessage(msg);
pingStatus();
}
public void stop() {
try {
mInputStream.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
try {
mOutputStream.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
try {
mRfcommSocket.close();
} catch (Exception e) {
log.debug(e.getMessage());
}
if (mSerialEngine != null) mSerialEngine.stopLoop();
}
public void bolus(Double amount, Treatment t) {
bolusingTreatment = t;
MsgBolusStart start = new MsgBolusStart(amount);
MsgBolusProgress progress = new MsgBolusProgress(MainApp.bus(), amount, t);
MsgBolusStop stop = new MsgBolusStop(MainApp.bus(), amount, t);
mSerialEngine.sendMessage(start);
while (!stop.stopped && !start.failed) {
waitMsec(100);
}
bolusingTreatment = null;
pingStatus();
}
public void bolusStop() {
Treatment lastBolusingTreatment = bolusingTreatment;
if (Config.logDanaBTComm)
log.debug("bolusStop >>>>> @ " + (bolusingTreatment == null ? "" : bolusingTreatment.insulin));
MsgBolusStop stop = new MsgBolusStop();
stop.forced = true;
mSerialEngine.sendMessage(stop);
while (!stop.stopped) {
mSerialEngine.sendMessage(stop);
waitMsec(200);
}
// and update ns status to last amount
waitMsec(60000);
EventDanaRBolusProgress be = EventDanaRBolusProgress.getInstance();
be.sStatus = "";
mBus.post(be);
}
public void carbsEntry(int amount) {
Calendar time = Calendar.getInstance();
MsgSetCarbsEntry msg = new MsgSetCarbsEntry(time, amount);
mSerialEngine.sendMessage(msg);
//pingStatus();
}
public void updateBasalsInPump(final NSProfile profile) {
double[] basal = buildDanaRProfileRecord(profile);
connectIfNotConnected("updateBasalsInPump");
MsgSetBasalProfile msgSet = new MsgSetBasalProfile((byte) 0, basal);
mSerialEngine.sendMessage(msgSet);
MsgSetActivateBasalProfile msgActivate = new MsgSetActivateBasalProfile((byte) 0);
mSerialEngine.sendMessage(msgActivate);
pingStatus();
}
public double[] buildDanaRProfileRecord(NSProfile nsProfile) {
double[] record = new double[24];
for (Integer hour = 0; hour < 24; hour++) {
double value = nsProfile.getBasal(hour * 60 * 60);
if (Config.logDanaMessageDetail)
log.debug("NS basal value for " + hour + ":00 is " + value);
record[hour] = value;
}
return record;
}
@Subscribe
public void onStatusEvent(final EventPreferenceChange pch) {
getSelectedPump();
createRfCommSocket();
}
private void getSelectedPump() {
devName = SP.getString("danar_bt_name", "");
}
public void waitMsec(long msecs) {
try {
Thread.sleep(msecs);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

View file

@ -1,13 +1,21 @@
package info.nightscout.androidaps.plugins.DanaR;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.squareup.otto.Subscribe;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@ -15,16 +23,23 @@ import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.TempBasal;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRConnectionStatus;
import info.nightscout.client.data.NSProfile;
public class DanaRFragment extends Fragment implements PluginBase, PumpInterface {
private static Logger log = LoggerFactory.getLogger(DanaRFragment.class);
Handler mHandler;
public static HandlerThread mHandlerThread;
private static DanaConnection sDanaConnection = null;
private static DanaRPump sDanaRPump = new DanaRPump();
boolean fragmentEnabled = true;
boolean fragmentVisible = true;
boolean visibleNow = false;
TextView connectionText;
public static DanaConnection getDanaConnection() {
return sDanaConnection;
}
@ -33,7 +48,16 @@ public class DanaRFragment extends Fragment implements PluginBase, PumpInterface
sDanaConnection = con;
}
public static DanaRPump getDanaRPump() {
return sDanaRPump;
}
public DanaRFragment() {
mHandlerThread = new HandlerThread(DanaRFragment.class.getSimpleName());
mHandlerThread.start();
this.mHandler = new Handler(mHandlerThread.getLooper());
registerBus();
}
public static DanaRFragment newInstance() {
@ -41,6 +65,15 @@ public class DanaRFragment extends Fragment implements PluginBase, PumpInterface
return fragment;
}
private void registerBus() {
try {
MainApp.bus().unregister(this);
} catch (RuntimeException x) {
// Ignore
}
MainApp.bus().register(this);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -50,9 +83,46 @@ public class DanaRFragment extends Fragment implements PluginBase, PumpInterface
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.danar_fragment, container, false);
connectionText = (TextView) view.findViewById(R.id.danar_connection);
connectionText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHandler.post(new Runnable() {
@Override
public void run() {
if (getDanaConnection() != null)
getDanaConnection().connectIfNotConnected("Connect request from GUI");
else
log.error("Connect req from GUI: getDanaConnection() is null");
}}
);
}
});
return view;
}
@Subscribe
public void onStatusEvent(final EventDanaRConnectionStatus c) {
Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (c.sConnecting) {
connectionText.setText("{fa-bluetooth-b spin} " + c.sConnectionAttemptNo);
} else {
if (c.sConnected) {
connectionText.setText("{fa-bluetooth}");
} else {
connectionText.setText("{fa-bluetooth-b}");
}
}
}
}
);
}
}
// Plugin base interface
@Override
public int getType() {
@ -179,4 +249,7 @@ public class DanaRFragment extends Fragment implements PluginBase, PumpInterface
public String deviceID() {
return null;
}
private void updateGUI() {
}
}

View file

@ -0,0 +1,81 @@
package info.nightscout.androidaps.plugins.DanaR;
import java.util.Date;
/**
* Created by mike on 04.07.2016.
*/
public class DanaRPump {
public static final int UNITS_MGDL = 0;
public static final int UNITS_MMOL = 1;
// Info
public String serialNumber = "";
public Date shippingDate = new Date(0);
public String shippingCountry = "";
public boolean isNewPump = false;
public int accessCode = -1;
public Date pumpTime = new Date(0);
// Status
public boolean pumpSuspended;
public boolean calculatorEnabled;
public double dailyTotalUnits;
public int dailyMaxRate;
public double iob;
public double reservoirRemainingUnits;
public int batteryRemaining;
public boolean bolusBlocked;
public Date lastBolusTime = new Date(0);
public double lastBolusAmount;
public double currentBasal;
public boolean isTempBasalInProgress;
public int tempBasalPercent;
public int tempBasalRemainingMin;
public int tempBasalTotalSec;
public Date tempBasalStart;
public boolean isExtendedInProgress;
public int extendedBolusMinutes;
public double extendedBolusAmount;
public double extendedBolusAbsoluteRate;
public int extendedBolusSoFarInMinutes;
public Date extendedBolusStart;
public int extendedBolusRemainingMinutes;
// Profile
public int units;
public int easyBasalMode;
public boolean basal48Enable = false;
public int currentCIR;
public int currentCF;
public int currentAI;
public int currentTarget;
public int currentAIDR;
public int morningCIR;
public int morningCF;
public int afternoonCIR;
public int afternoonCF;
public int eveningCIR;
public int eveningCF;
public int nightCIR;
public int nightCF;
public class PumpProfile {
public double[] basalValue = new double[48];
}
public int activeProfile = 0;
public PumpProfile[] pumpProfiles = new PumpProfile[4];
//Limits
public double maxBolus;
public double maxBasal;
public double dailyMax;
}

View file

@ -0,0 +1,202 @@
package info.nightscout.androidaps.plugins.DanaR;
import android.bluetooth.BluetoothSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.comm.DanaRMessage;
import info.nightscout.androidaps.plugins.DanaR.comm.DanaRMessageHashTable;
import info.nightscout.utils.CRC;
/**
* Created by mike on 04.07.2016.
*/
public class SerialEngine extends Thread {
private static Logger log = LoggerFactory.getLogger(SerialEngine.class);
private final InputStream mInputStream;
private final OutputStream mOutputStream;
private BluetoothSocket mRfcommSocket;
private final DanaConnection mDc;
private boolean mKeepRunning = true;
private byte[] mReadBuff = new byte[0];
private HashMap<Integer, DanaRMessage> mOutputQueue = new HashMap<Integer, DanaRMessage>();
public SerialEngine(DanaConnection dc, InputStream inputStream, OutputStream outputStream, BluetoothSocket rfcommSocket) {
super("SerialEngine"); // Thread name
mInputStream = inputStream;
mOutputStream = outputStream;
mRfcommSocket = rfcommSocket;
mDc = dc;
this.start();
}
@Override
public final void run() {
try {
while (mKeepRunning) {
int availableBytes = mInputStream.available();
// Ask for 1024 byte (or more if available)
byte[] newData = new byte[Math.max(1024, availableBytes)];
int gotBytes = mInputStream.read(newData);
// When we are here there is some new data available
// add newData to mReadBuff
byte[] newReadBuff = new byte[mReadBuff.length + gotBytes];
System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length);
System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes);
mReadBuff = newReadBuff;
if (mReadBuff.length < 3) {
continue;
} // 3rd byte is packet size packet still not complete
// process all messages we already got
while (mReadBuff.length > 3) {
if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) {
int length = (mReadBuff[2] & 0xFF) + 7;
// Check if we have enough data
if (mReadBuff.length < length) {
break;
}
if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) {
log.error("wrong packet lenght=" + length + " data " + DanaRMessage.toHexString(mReadBuff));
mDc.disconnect("wrong packet");
break;
}
short crc = CRC.getCrc16(mReadBuff, 3, length - 7);
byte crcByte0 = (byte) (crc >> 8 & 0xFF);
byte crcByte1 = (byte) (crc & 0xFF);
byte crcByte0received = mReadBuff[length - 4];
byte crcByte1received = mReadBuff[length - 3];
if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) {
log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received));
mDc.disconnect("crc error");
break;
}
// Packet is verified here. extract data
byte[] extractedBuff = new byte[length];
System.arraycopy(mReadBuff, 0, extractedBuff, 0, length);
// remove extracted data from read buffer
byte[] unprocessedData = new byte[mReadBuff.length - length];
System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length);
mReadBuff = unprocessedData;
int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00);
// Check if message is out queue. if yes use it
DanaRMessage message = mOutputQueue.get(command);
// if not get it from hash table
if (message == null)
message = DanaRMessageHashTable.findMessage(command);
if (Config.logDanaMessageDetail)
log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff));
mDc.scheduleDisconnection();
// process the message content
message.received = true;
message.handleMessage(extractedBuff);
mOutputQueue.remove(message.getCommand());
synchronized (message) {
message.notify();
}
} else {
log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + DanaRMessage.toHexString(mReadBuff));
}
}
}
} catch (Throwable x) {
if (x instanceof IOException || "socket closed".equals(x.getMessage())) {
if (Config.logDanaSerialEngine) log.info("Thread run " + x.getMessage());
} else {
if (Config.logDanaSerialEngine) log.error("Thread run ", x);
}
mKeepRunning = false;
}
try {
mInputStream.close();
} catch (Exception e) {
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
}
try {
mOutputStream.close();
} catch (Exception e) {
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
}
try {
mRfcommSocket.close();
} catch (Exception e) {
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
}
try {
System.runFinalization();
} catch (Exception e) {
if (Config.logDanaSerialEngine) log.debug(e.getMessage());
}
}
public synchronized void sendMessage(DanaRMessage message) {
mOutputQueue.put(message.getCommand(), message);
byte[] messageBytes = message.getRawMessageBytes();
if (Config.logDanaSerialEngine)
log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes));
try {
// Wait until input stream is empty
while (mInputStream.available() > 0) {
if (Config.logDanaSerialEngine) log.debug("Waiting for empty input stream");
synchronized (this.mInputStream) {
mInputStream.notify();
}
Thread.sleep(100);
}
mOutputStream.write(messageBytes);
} catch (Exception e) {
log.error("sendMessage exception: ", e);
e.printStackTrace();
}
synchronized (mInputStream) {
mInputStream.notify();
}
synchronized (message) {
try {
message.wait(5000);
} catch (InterruptedException e) {
log.error("sendMessage InterruptedException", e);
e.printStackTrace();
}
}
if (mOutputQueue.containsKey(message.getCommand())) {
log.error("Reply not received " + message.getMessageName());
mOutputQueue.remove(message.getCommand());
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
mDc.scheduleDisconnection();
}
public void stopLoop() {
mKeepRunning = false;
}
}

View file

@ -0,0 +1,173 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import android.annotation.TargetApi;
import android.os.Build;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.utils.CRC;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/*
* 00 01 02 03 04 05 06
*
* 7E 7E len F1 CMD SUB data CRC CRC 2E 2E
*/
public class DanaRMessage {
private static Logger log = LoggerFactory.getLogger(DanaRMessage.class);
private byte[] buffer = new byte[512];
private int position = 6;
public boolean received = false;
public boolean failed = false;
public void SetCommand(int cmd) {
this.buffer[4] = (byte) (cmd >> 8 & 0xFF);
this.buffer[5] = (byte) (cmd & 0xFF);
}
public void AddParamByte(byte data) {
this.buffer[this.position++] = data;
}
public void AddParamInt(int data) {
this.buffer[this.position++] = (byte) (data >> 8 & 0xFF);
this.buffer[this.position++] = (byte) (data & 0xFF);
}
public void AddParamDate(GregorianCalendar date) {
AddParamByte((byte) (date.get(Calendar.YEAR) - 1900 - 100));
AddParamByte((byte) (date.get(Calendar.MONTH) + 1));
AddParamByte((byte) (date.get(Calendar.DAY_OF_MONTH)));
AddParamByte((byte) (date.get(Calendar.HOUR)));
AddParamByte((byte) (date.get(Calendar.MINUTE)));
}
public byte[] getRawMessageBytes() {
this.buffer[0] = (byte) 0x7E;
this.buffer[1] = (byte) 0x7E;
int length = this.position - 3;
this.buffer[2] = (byte) length;
this.buffer[3] = (byte) 0xf1;
this.AddParamInt(CRC.getCrc16(this.buffer, 3, length));
this.buffer[length + 5] = (byte) 0x2E;
this.buffer[length + 6] = (byte) 0x2E;
return Arrays.copyOf(buffer, length + 7);
}
public String getMessageName() {
return DanaRMessageNames.getName(getCommand());
}
public void handleMessage(byte[] bytes) {
if (Config.logDanaMessageDetail) {
if (bytes.length > 6) {
int command = (bytes[5] & 0xFF) | ((bytes[4] << 8) & 0xFF00);
log.debug("UNPROCESSED MSG: " + getMessageName() + " Command: " + String.format("%04X", command) + " Data: " + toHexString(bytes));
} else {
log.debug("MISFORMATTED MSG: " + toHexString(bytes));
}
}
}
public int getCommand() {
int command = byeFromRawBuff(buffer, 5) | (byeFromRawBuff(buffer, 4) << 8);
return command;
}
public static int byeFromRawBuff(byte[] buff, int offset) {
return buff[offset] & 0xFF;
}
public static int intFromBuff(byte[] buff, int offset, int length) {
offset += 6;
switch (length) {
case 1:
return byeFromRawBuff(buff, offset);
case 2:
return (byeFromRawBuff(buff, offset) << 8) + byeFromRawBuff(buff, offset + 1);
case 3:
return (byeFromRawBuff(buff, offset + 2) << 16) + (byeFromRawBuff(buff, offset + 1) << 8) + byeFromRawBuff(buff, offset);
case 4:
return (byeFromRawBuff(buff, offset + 3) << 24) + (byeFromRawBuff(buff, offset + 2) << 16) + (byeFromRawBuff(buff, offset + 1) << 8) + byeFromRawBuff(buff, offset);
}
return 0;
}
public static Date dateTimeFromBuff(byte[] buff, int offset) {
Date date =
new Date(
100 + intFromBuff(buff, offset, 1),
intFromBuff(buff, offset + 1, 1) - 1,
intFromBuff(buff, offset + 2, 1),
intFromBuff(buff, offset + 3, 1),
intFromBuff(buff, offset + 4, 1),
0
);
return date;
}
public static Date dateTimeSecFromBuff(byte[] buff, int offset) {
Date date =
new Date(
100 + intFromBuff(buff, offset, 1),
intFromBuff(buff, offset + 1, 1) - 1,
intFromBuff(buff, offset + 2, 1),
intFromBuff(buff, offset + 3, 1),
intFromBuff(buff, offset + 4, 1),
intFromBuff(buff, offset + 5, 1)
);
return date;
}
public static Date dateFromBuff(byte[] buff, int offset) {
Date date =
new Date(
100 + intFromBuff(buff, offset, 1),
intFromBuff(buff, offset + 1, 1) - 1,
intFromBuff(buff, offset + 2, 1)
);
return date;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String stringFromBuff(byte[] buff, int offset, int length) {
byte[] strbuff = new byte[length];
System.arraycopy(buff, offset + 6, strbuff, 0, length);
return new String(strbuff, StandardCharsets.UTF_8);
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String asciiStringFromBuff(byte[] buff, int offset, int length) {
byte[] strbuff = new byte[length];
System.arraycopy(buff, offset + 6, strbuff, 0, length);
for (int pos = 0; pos < length; pos++)
strbuff[pos] += 65; // "A"
return new String(strbuff, StandardCharsets.UTF_8);
}
public static String toHexString(byte[] buff) {
StringBuffer sb = new StringBuffer();
int count = 0;
for (byte element : buff) {
sb.append(String.format("%02x ", element));
if (++count % 4 == 0) sb.append(" ");
}
return sb.toString();
}
}

View file

@ -0,0 +1,71 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
/**
* Created by mike on 28.05.2016.
*/
public class DanaRMessageHashTable {
private static Logger log = LoggerFactory.getLogger(DanaRMessageHashTable.class);
public static HashMap<Integer, DanaRMessage> messages = null;
static {
if (messages == null) {
messages = new HashMap<Integer, DanaRMessage>();
put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP
put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA
put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS
put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING
put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE
put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I
put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I
put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS
put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO
put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO
put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO
put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION
put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S
put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S
put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP
put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP
put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S
put(new MsgOcclusion()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS
put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT
put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT
put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I
put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I
put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I
put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL
put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I
put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY
put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I
put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS
put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER
put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE
put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S
put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S
put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL
put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE
put(new MsgCheckValue()); // 0xF0F1 CMD_PUMP_CHECK_VALUE
}
}
public static void put(DanaRMessage message) {
int command = message.getCommand();
//String name = DanaRMessageNames.getName(command);
messages.put(command, message);
//log.debug(String.format("%04x ", command) + " " + name);
}
public static DanaRMessage findMessage(Integer command) {
if (messages.containsKey(command)) {
return messages.get(command);
} else {
return new DanaRMessage();
}
}
}

View file

@ -0,0 +1,163 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
/**
* Created by mike on 28.05.2016.
*/
public class DanaRMessageNames {
private static Logger log = LoggerFactory.getLogger(DanaRMessageNames.class);
public static HashMap<Integer,String> messageNames;
static {
messageNames = new HashMap<Integer,String>();
messageNames.put(0x3001, "CMD_CONNECT");
messageNames.put(0x3002, "CMD_DISCONNECT");
messageNames.put(0x3101, "CMD_HISTORY_MEAL_INS");
messageNames.put(0x3102, "CMD_HISTORY_DAY_INS");
messageNames.put(0x3103, "CMD_HISTORY_AIR_SUB");
messageNames.put(0x3104, "CMD_HISTORY_GLUCOSE");
messageNames.put(0x3105, "CMD_HISTORY_ALARM");
messageNames.put(0x3106, "CMD_HISTORY_ERROR");
messageNames.put(0x3107, "CMD_HISTORY_CARBOHY");
messageNames.put(0x3108, "CMD_HISTORY_REFILL");
messageNames.put(0x3109, "CMD_HISTORY_SUSPEND");
messageNames.put(0x310a, "CMD_HISTORY_BASAL_HOUR");
messageNames.put(0x310b, "CMD_HISTORY_TB");
messageNames.put(0x31f1, "CMD_HISTORY_DONT_USED");
messageNames.put(0x31f2, "CMD_HISTORY_LAST_T_R");
messageNames.put(0x31f3, "CMD_HISTORY_LAST_T_S");
messageNames.put(0x0501, "CMD_HISPAGE_MEAL_INS");
messageNames.put(0x0502, "CMD_HISPAGE_DAY_INS");
messageNames.put(0x0503, "CMD_HISPAGE_AIR_SUB");
messageNames.put(0x0504, "CMD_HISPAGE_GLUCOSE");
messageNames.put(0x0505, "CMD_HISPAGE_ALARM");
messageNames.put(0x0506, "CMD_HISPAGE_ERROR");
messageNames.put(0x0507, "CMD_HISPAGE_CARBOHY");
messageNames.put(0x0508, "CMD_HISPAGE_REFILL");
messageNames.put(0x050a, "CMD_HISPAGE_DAILTY_PRE_DATA");
messageNames.put(0x050b, "CMD_HISPAGE_BOLUS_AVG");
messageNames.put(0x050c, "CMD_HISPAGE_BASAL_RECORD");
messageNames.put(0x050d, "CMD_HISPAGE_TB");
messageNames.put(0x3201, "CMD_SETTING_V_MEAL_INS_I");
messageNames.put(0x3202, "CMD_SETTING_V_Based_INS_I");
messageNames.put(0x3203, "CMD_SETTING_V_MEAL_SETTING_I");
messageNames.put(0x3204, "CMD_SETTING_V_CCC_I");
messageNames.put(0x3205, "CMD_SETTING_V_MAX_VALUE_I");
messageNames.put(0x3206, "CMD_SETTING_V_BASAL_PROFILE_ALL");
messageNames.put(0x3207, "CMD_SETTING_V_SHIPPING_I");
messageNames.put(0x3208, "CMD_SETTING_V_CLOGGIN_SENS_I");
messageNames.put(0x3209, "CMD_SETTING_V_GLUCOSEandEASY");
messageNames.put(0x320a, "CMD_SETTING_V_TIME_I");
messageNames.put(0x320b, "CMD_SETTING_V_USER_OPTIONS");
messageNames.put(0x320c, "CMD_SETTING_V_PROFILE_NUMBER");
messageNames.put(0x320d, "CMD_SETTING_V_CIR_CF_VALUE");
messageNames.put(0x3301, "CMD_SETTING_MEAL_INS_S");
messageNames.put(0x3302, "CMD_SETTING_Based_INS_S");
messageNames.put(0x3303, "CMD_SETTING_MEAL_SETTING_S");
messageNames.put(0x3304, "CMD_SETTING_CCC_S");
messageNames.put(0x3305, "CMD_SETTING_MAX_VALUE_S");
messageNames.put(0x3306, "CMD_SETTING_BASAL_PROFILE_S");
messageNames.put(0x3307, "CMD_SETTING_SHIPPING_S");
messageNames.put(0x3308, "CMD_SETTING_CLOGGIN_SENS_S");
messageNames.put(0x3309, "CMD_SETTING_GLUCOSEandEASY_S");
messageNames.put(0x330a, "CMD_SETTING_TIME_S");
messageNames.put(0x330b, "CMD_SETTING_USER_OPTIONS_S");
messageNames.put(0x330c, "CMD_SETTING_PROFILE_NUMBER_S");
messageNames.put(0x330d, "CMD_SETTING_CIR_CF_VALUE_S");
messageNames.put(0x0101, "CMD_MEALINS_STOP");
messageNames.put(0x0102, "CMD_MEALINS_START_DATA");
messageNames.put(0x0103, "CMD_MEALINS_START_NODATA");
messageNames.put(0x0104, "CMD_MEALINS_START_DATA_SPEED");
messageNames.put(0x0105, "CMD_MEALINS_START_NODATA_SPEED");
messageNames.put(0x0201, "CMD_PUMP_ACT_INS_VALUE");
messageNames.put(0x0202, "CMD_PUMP_THIS_REMAINDER_MEAL_INS");
messageNames.put(0x0203, "CMD_PUMP_BASE_SET");
messageNames.put(0x0204, "CMD_PUMP_CALCULATION_SETTING");
messageNames.put(0x0205, "CMD_PUMP_EXERCISE_MODE");
messageNames.put(0x0206, "CMD_PUMP_MEAL_INS_I");
messageNames.put(0x0207, "CMD_PUMP_EXPANS_INS_I");
messageNames.put(0x0208, "CMD_PUMP_EXPANS_INS_RQ");
messageNames.put(0x0209, "CMD_PUMP_DUAL_INS_RQ");
messageNames.put(0x020a, "CMD_PUMP_INITVIEW_I");
messageNames.put(0x020b, "CMD_PUMP_STATUS");
messageNames.put(0x020c, "CMD_PUMP_CAR_N_CIR");
messageNames.put(0x0301, "CMD_PUMPINIT_TIME_INFO");
messageNames.put(0x0302, "CMD_PUMPINIT_BOLUS_INFO");
messageNames.put(0x0303, "CMD_PUMPINIT_INIT_INFO");
messageNames.put(0x0304, "CMD_PUMPINIT_OPTION");
messageNames.put(0x0401, "CMD_PUMPSET_EXERCISE_S");
messageNames.put(0x0402, "CMD_PUMPSET_HIS_S");
messageNames.put(0x0403, "CMD_PUMPSET_EXERCISE_STOP");
messageNames.put(0x0404, "CMD_PUMPSET_PAUSE");
messageNames.put(0x0405, "CMD_PUMPSET_PAUSE_STOP");
messageNames.put(0x0406, "CMD_PUMPSET_EXPANS_INS_STOP");
messageNames.put(0x0407, "CMD_PUMPSET_EXPANS_INS_S");
messageNames.put(0x0408, "CMD_PUMPSET_DUAL_S");
messageNames.put(0x0409, "CMD_PUMPSET_EASY_OFF");
messageNames.put(0x0601, "CMD_PUMPOWAY_SYSTEM_STATUS");
messageNames.put(0x0602, "CMD_PUMPOWAY_GLUCOSE_ALARM");
messageNames.put(0x0603, "CMD_PUMPOWAY_LOW_INSULIN_ALARM");
messageNames.put(0x0610, "CMD_PUMP_ALARM_TIEOUT");
messageNames.put(0x0701, "CMD_MSGRECEP_TAKE_SUGAR");
messageNames.put(0x0702, "CMD_MSGRECEP_GO_TO_DOCTOR");
messageNames.put(0x0703, "CMD_MSGRECEP_CALL_TO_CAREGIVER");
messageNames.put(0x0704, "CMD_MSGRECEP_CHECK_GLUCOSE_AGAIN");
messageNames.put(0x0705, "CMD_MSGRECEP_CALL_TO_HOME");
messageNames.put(0x0706, "CMD_MSGRECEP_DO_DELIVER");
messageNames.put(0x0801, "CMD_MSGSEND_YES_I_DO");
messageNames.put(0x0802, "CMD_MSGSEND_NO_I_CANNOT");
messageNames.put(0x0803, "CMD_MSGSEND_CALL_TO_ME_MOM");
messageNames.put(0x0804, "CMD_MSGSEND_DO_NOT_INFUSE");
messageNames.put(0x0901, "CMD_FILL_REFILL_COUNT");
messageNames.put(0x0902, "CMD_FILL_PRIME_CHECK");
messageNames.put(0x0903, "CMD_FILL_PRIME_END");
messageNames.put(0x0904, "CMD_FILL_PRIME_STOP");
messageNames.put(0x0905, "CMD_FILL_PRIME_PAUSE");
messageNames.put(0x0906, "CMD_FILL_PRIME_RATE");
messageNames.put(0x41f2, "CMD_HISTORY_ALL");
messageNames.put(0x42f2, "CMD_HISTORY_NEW");
messageNames.put(0x41f1, "CMD_HISTORY_ALL_DONE");
messageNames.put(0x42f1, "CMD_HISTORY_NEW_DONE");
messageNames.put(0xF0F1, "CMD_PUMP_CHECK_VALUE");
messageNames.put(0xF0F2, "CMD_PUMP_TIMECHANGE_CHECK");
messageNames.put(0xF0F3, "CMD_PUMP_TIMECHANGE_CLEAR");
messageNames.put(0x43F2, "CMD_HISTORY_DATEOVER_ALL");
messageNames.put(0x4300, "CMD_HISTORY_DATEOVER_DONE");
}
public static String getName(Integer command) {
if (messageNames.containsKey(command))
return messageNames.get(command);
else {
log.debug("Unknown command: " + String.format("%04X", command));
return "UNKNOWN_COMMAND";
}
}
}

View file

@ -0,0 +1,19 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
/**
* Created by mike on 28.05.2016.
*/
public class DanaRRecordTypes {
public static final byte RECORD_TYPE_BOLUS = (byte) 0x01;
public static final byte RECORD_TYPE_DAILY = (byte) 0x02;
public static final byte RECORD_TYPE_PRIME = (byte) 0x03;
public static final byte RECORD_TYPE_ERROR = (byte) 0x04;
public static final byte RECORD_TYPE_ALARM = (byte) 0x05;
public static final byte RECORD_TYPE_GLUCOSE = (byte) 0x06;
public static final byte RECORD_TYPE_CARBO = (byte) 0x08;
public static final byte RECORD_TYPE_REFILL = (byte) 0x09;
public static final byte RECORD_TYPE_SUSPEND = (byte) 0x0B;
public static final byte RECORD_TYPE_BASALHOUR = (byte) 0x0C;
public static final byte RECORD_TYPE_TB = (byte) 0x0D;
public static final byte RECORD_TYPE_TEMP_BASAL = (byte) 0x14;
}

View file

@ -0,0 +1,50 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import com.squareup.otto.Bus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusProgress;
public class MsgBolusProgress extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgBolusProgress.class);
public static final DecimalFormat bolusNumberFormat = new DecimalFormat("0.0");
private static Bus bus = null;
private static Treatment t;
private static double amount;
public int progress = -1;
public MsgBolusProgress() {
SetCommand(0x0202);
}
public MsgBolusProgress(Bus bus, double amount, Treatment t) {
this();
this.amount = amount;
this.t = t;
this.bus = bus;
}
@Override
public void handleMessage(byte[] bytes) {
progress = intFromBuff(bytes, 0, 2);
Double done = (amount * 100 - progress) / 100d;
t.insulin = done;
EventDanaRBolusProgress bolusingEvent = EventDanaRBolusProgress.getInstance();
bolusingEvent.sStatus = "Delivering " + bolusNumberFormat.format(done) + "U";
bolusingEvent.t = t;
if (Config.logDanaMessageDetail) {
log.debug("Bolus remaining: " + progress + " delivered: " + done);
}
bus.post(bolusingEvent);
}
}

View file

@ -0,0 +1,31 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
public class MsgBolusStart extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgBolusStart.class);
public MsgBolusStart() {
SetCommand(0x0102);
}
public MsgBolusStart(double amount) {
this();
AddParamInt((int) (amount * 100));
}
@Override
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 2) {
failed = true;
log.debug("Messsage response: " + result + " FAILED!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Messsage response: " + result);
}
}
}

View file

@ -0,0 +1,45 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import com.squareup.otto.Bus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusProgress;
public class MsgBolusStop extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgBolusStop.class);
private static Treatment t;
private static Double amount;
private static Bus bus = null;
public static boolean stopped = false;
public static boolean forced = false;
public MsgBolusStop() {
SetCommand(0x0101);
stopped = false;
}
public MsgBolusStop(Bus bus, Double amount, Treatment t) {
this();
this.bus = bus;
this.t = t;
this.amount = amount;
forced = false;
}
@Override
public void handleMessage(byte[] bytes) {
EventDanaRBolusProgress bolusingEvent = EventDanaRBolusProgress.getInstance();
stopped = true;
if (!forced) {
t.insulin = amount;
bolusingEvent.sStatus = "Delivered";
} else {
bolusingEvent.sStatus = "Stopped";
}
bus.post(bolusingEvent);
}
}

View file

@ -0,0 +1,31 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
/**
* Created by mike on 30.06.2016.
*/
public class MsgCheckValue extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgCheckValue.class);
public MsgCheckValue() {
SetCommand(0xF0F1);
}
@Override
public void handleMessage(byte[] bytes) {
int a = intFromBuff(bytes, 0, 1);
int b = intFromBuff(bytes, 1, 1);
if (a != 3 || b <= 0) {
// another message will follow
} else {
}
if (Config.logDanaMessageDetail)
log.debug("Response: " + String.format("%02X ", a) + String.format("%02X ", b));
}
}

View file

@ -0,0 +1,117 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import com.j256.ormlite.dao.Dao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.Date;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.db.HistoryRecord;
public class MsgHistoryAll extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgHistoryAll.class);
public MsgHistoryAll() {
SetCommand(0x41F2);
}
@Override
public void handleMessage(byte[] bytes) {
byte recordCode = (byte) intFromBuff(bytes, 0, 1);
Date date = dateFromBuff(bytes, 1); // 3 bytes
Date datetime = dateTimeFromBuff(bytes, 1); // 5 bytes
Date datetimewihtsec = dateTimeSecFromBuff(bytes, 1); // 6 bytes
byte paramByte5 = (byte) intFromBuff(bytes, 4, 1);
byte paramByte6 = (byte) intFromBuff(bytes, 5, 1);
byte paramByte7 = (byte) intFromBuff(bytes, 6, 1);
byte paramByte8 = (byte) intFromBuff(bytes, 7, 1);
double value = (double) intFromBuff(bytes, 8, 2);
HistoryRecord historyRecord = new HistoryRecord();
historyRecord.setRecordCode(recordCode);
historyRecord.setBytes(bytes);
switch (recordCode) {
case DanaRRecordTypes.RECORD_TYPE_BOLUS:
historyRecord.setRecordDate(datetime);
switch (0xF0 & paramByte8) {
case 0xA0:
historyRecord.setBolusType("DS");
break;
case 0xC0:
historyRecord.setBolusType("E");
break;
case 0x80:
historyRecord.setBolusType("S");
break;
case 0x90:
historyRecord.setBolusType("DE");
break;
default:
historyRecord.setBolusType("None");
break;
}
historyRecord.setRecordDuration(((int) paramByte8 & 0x0F) * 60 + (int) paramByte7);
historyRecord.setRecordValue(value * 0.01);
break;
case DanaRRecordTypes.RECORD_TYPE_DAILY:
historyRecord.setRecordDate(date);
historyRecord.setRecordDailyBasal((double) ((int) paramByte5 * 0xFF + (int) paramByte6) * 0.01);
historyRecord.setRecordDailyBolus((double) ((int) paramByte7 * 0xFF + (int) paramByte8) / 0.01);
break;
case DanaRRecordTypes.RECORD_TYPE_PRIME:
case DanaRRecordTypes.RECORD_TYPE_ERROR:
case DanaRRecordTypes.RECORD_TYPE_REFILL:
case DanaRRecordTypes.RECORD_TYPE_BASALHOUR:
case DanaRRecordTypes.RECORD_TYPE_TB:
historyRecord.setRecordDate(datetimewihtsec);
historyRecord.setRecordValue(value * 0.01);
break;
case DanaRRecordTypes.RECORD_TYPE_GLUCOSE:
case DanaRRecordTypes.RECORD_TYPE_CARBO:
historyRecord.setRecordDate(datetimewihtsec);
historyRecord.setRecordValue(value);
break;
case DanaRRecordTypes.RECORD_TYPE_ALARM:
historyRecord.setRecordDate(datetimewihtsec);
String strAlarm = "None";
switch ((int) paramByte8) {
case 67:
strAlarm = "Check";
break;
case 79:
strAlarm = "Occlusion";
break;
case 66:
strAlarm = "Low Battery";
break;
case 83:
strAlarm = "Shutdown";
break;
}
historyRecord.setRecordAlarm(strAlarm);
historyRecord.setRecordValue(value * 0.01);
break;
case DanaRRecordTypes.RECORD_TYPE_SUSPEND:
historyRecord.setRecordDate(datetimewihtsec);
String strRecordValue = "Off";
if ((int) paramByte8 == 79)
strRecordValue = "On";
historyRecord.setStringRecordValue(strRecordValue);
break;
}
try {
Dao<HistoryRecord, String> daoHistoryRecords = MainApp.getDbHelper().getDaoHistory();
daoHistoryRecords.createIfNotExists(historyRecord);
} catch (SQLException e) {
log.error(e.getMessage(), e);
}
return;
}
}

View file

@ -0,0 +1,13 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
public class MsgHistoryAllDone extends DanaRMessage {
public MsgHistoryAllDone() {
SetCommand(0x41F1);
}
@Override
public void handleMessage(byte[] bytes) {
}
}

View file

@ -0,0 +1,36 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MsgInitConnStatusBasic extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBasic.class);
public MsgInitConnStatusBasic() {
SetCommand(0x0303);
}
@Override
public void handleMessage(byte[] bytes) {
int a = intFromBuff(bytes, 0, 1);
int b = intFromBuff(bytes, 1, 1);
int c = intFromBuff(bytes, 2, 1);
int d = intFromBuff(bytes, 3, 1);
int e = intFromBuff(bytes, 4, 1);
int f = intFromBuff(bytes, 5, 1);
int g = intFromBuff(bytes, 6, 1);
int h = intFromBuff(bytes, 7, 1);
int i = intFromBuff(bytes, 8, 1);
int j = intFromBuff(bytes, 9, 1);
int k = intFromBuff(bytes, 10, 1);
int l = intFromBuff(bytes, 11, 1);
int m = intFromBuff(bytes, 12, 1);
int n = intFromBuff(bytes, 13, 1);
int o;
try {
o = intFromBuff(bytes, 21, 1);
} catch (Exception ex) {
o = 0;
}
}
}

View file

@ -0,0 +1,24 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by mike on 28.05.2016.
*/
public class MsgInitConnStatusBolus extends DanaRMessage{
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusBolus.class);
public MsgInitConnStatusBolus() {
SetCommand(0x0302);
}
@Override
public void handleMessage(byte[] bytes) {
int a1 = intFromBuff(bytes, 0, 1);
int a2 = intFromBuff(bytes, 1, 1);
int c = intFromBuff(bytes, 8, 2);
int d = c / 100;
int e = intFromBuff(bytes, 10, 2);
}
}

View file

@ -0,0 +1,38 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
/**
* Created by mike on 28.05.2016.
*/
public class MsgInitConnStatusOption extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusOption.class);
public MsgInitConnStatusOption() {
SetCommand(0x0304);
}
@Override
public void handleMessage(byte[] bytes) {
int a = intFromBuff(bytes, 0, 1);
int b = intFromBuff(bytes, 1, 1);
int c = intFromBuff(bytes, 2, 1);
int d = intFromBuff(bytes, 3, 1);
int e = intFromBuff(bytes, 4, 1);
int f = intFromBuff(bytes, 5, 1);
int g = intFromBuff(bytes, 6, 1);
int h = intFromBuff(bytes, 7, 1);
int i = intFromBuff(bytes, 8, 1);
if (bytes.length >= 21) {
DanaRFragment.getDanaRPump().accessCode = intFromBuff(bytes, 9, 2) ^ 0x3463;
DanaRFragment.getDanaRPump().isNewPump = true;
if (Config.logDanaMessageDetail)
log.debug("Pump password: " + DanaRFragment.getDanaRPump().accessCode);
}
}
}

View file

@ -0,0 +1,24 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Config;
public class MsgInitConnStatusTime extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgInitConnStatusTime.class);
public MsgInitConnStatusTime() {
SetCommand(0x0301);
}
@Override
public void handleMessage(byte[] bytes) {
Date time = dateTimeSecFromBuff(bytes, 0);
if (Config.logDanaMessageDetail)
log.debug("Pump time: " + time);
}
}

View file

@ -0,0 +1,60 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.plugins.DanaR.events.EventDanaRBolusProgress;
import info.nightscout.client.data.DbLogger;
import info.nightscout.utils.DateUtil;
public class MsgOcclusion extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgOcclusion.class);
public MsgOcclusion() {
SetCommand(0x0601);
}
@Override
public void handleMessage(byte[] bytes) {
if (Config.logDanaMessageDetail)
log.debug("Oclusion detected");
EventDanaRBolusProgress bolusingEvent = EventDanaRBolusProgress.getInstance();
MsgBolusStop.stopped = true;
bolusingEvent.sStatus = "Oclusion";
MainApp.bus().post(bolusingEvent);
sendToNSClient();
}
public void sendToNSClient() {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", "Announcement");
data.put("created_at", DateUtil.toISOString(new Date()));
data.put("notes", "Occlusion detected");
data.put("isAnnouncement", true);
} catch (JSONException e) {
e.printStackTrace();
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString(), MsgOcclusion.class);
}
}

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
public class MsgPCCommStart extends DanaRMessage {
public MsgPCCommStart() {
SetCommand(0x3001);
}
}

View file

@ -0,0 +1,7 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
public class MsgPCCommStop extends DanaRMessage {
public MsgPCCommStop() {
SetCommand(0x3002);
}
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
public class MsgSetActivateBasalProfile extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSetActivateBasalProfile.class);
public MsgSetActivateBasalProfile() {
SetCommand(0x330C);
}
// index 0-3
public MsgSetActivateBasalProfile(byte index) {
this();
AddParamByte(index);
if (Config.logDanaMessageDetail)
log.debug("Activate basal profile: " + index);
}
@Override
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 1) {
failed = true;
log.debug("Activate basal profile result: " + result + " FAILED!!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Activate basal profile result: " + result);
}
}
}

View file

@ -0,0 +1,39 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
public class MsgSetBasalProfile extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSetBasalProfile.class);
public MsgSetBasalProfile() {
SetCommand(0x3306);
}
// index 0-3
public MsgSetBasalProfile(byte index, double[] values) {
this();
AddParamByte(index);
for (Integer i = 0; i < 24; i++) {
AddParamInt((int) (values[i] * 100));
}
if (Config.logDanaMessageDetail)
log.debug("Set basal profile: " + index);
}
@Override
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 1) {
failed = true;
log.debug("Set basal profile result: " + result + " FAILED!!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Set basal profile result: " + result);
}
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Calendar;
import info.nightscout.androidaps.Config;
public class MsgSetCarbsEntry extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSetCarbsEntry.class);
public MsgSetCarbsEntry() {
SetCommand(0x0402);
}
public MsgSetCarbsEntry(Calendar time, int amount) {
this();
AddParamByte((byte) DanaRRecordTypes.RECORD_TYPE_CARBO);
AddParamByte((byte) (time.get(Calendar.YEAR) % 100));
AddParamByte((byte) (time.get(Calendar.MONTH) + 1));
AddParamByte((byte) (time.get(Calendar.DAY_OF_MONTH)));
AddParamByte((byte) (time.get(Calendar.HOUR_OF_DAY)));
AddParamByte((byte) (time.get(Calendar.MINUTE)));
AddParamByte((byte) (time.get(Calendar.SECOND)));
AddParamByte((byte) 0x43); //??
AddParamInt(amount);
if (Config.logDanaMessageDetail)
log.debug("Set carb entry: " + amount + " date " + time.toString());
}
@Override
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 1) {
failed = true;
log.debug("Set carb entry result: " + result + " FAILED!!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Set carb entry result: " + result);
}
}
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
public class MsgSetExtendedBolusStart extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgBolusStart.class);
public MsgSetExtendedBolusStart() {
SetCommand(0x0407);
}
public MsgSetExtendedBolusStart(double amount, byte halfhours) {
this();
AddParamInt((int) (amount * 100));
AddParamByte(halfhours);
if (Config.logDanaMessageDetail)
log.debug("Set extended bolus start: " + amount + " halfhours " + halfhours);
}
@Override
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 1) {
failed = true;
log.debug("Set extended bolus start result: " + result + " FAILED!!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Set extended bolus start result: " + result);
}
}
}

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
public class MsgSetExtendedBolusStop extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSetExtendedBolusStop.class);
public MsgSetExtendedBolusStop() {
SetCommand(0x0406);
if (Config.logDanaMessageDetail)
log.debug("Set extended bolus stop");
}
@Override
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 1) {
failed = true;
log.debug("Set extended bolus stop result: " + result + " FAILED!!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Set extended bolus stop result: " + result);
}
}
}

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
public class MsgSetTempBasalStart extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSetTempBasalStart.class);
public MsgSetTempBasalStart() {
SetCommand(0x0401);
}
public MsgSetTempBasalStart(int percent, int durationInHours) {
this();
AddParamByte((byte) (percent & 255));
AddParamByte((byte) (durationInHours & 255));
if (Config.logDanaMessageDetail)
log.debug("Temp basal start percent: " + percent + " duration hours: " + durationInHours);
}
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 1) {
failed = true;
log.debug("Set temp basal start result: " + result + " FAILED!!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Set temp basal start result: " + result);
}
}
}

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
public class MsgSetTempBasalStop extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSetTempBasalStop.class);
public MsgSetTempBasalStop() {
SetCommand(0x0403);
if (Config.logDanaMessageDetail)
log.debug("Temp basal stop");
}
public void handleMessage(byte[] bytes) {
int result = intFromBuff(bytes, 0, 1);
if (result != 1) {
failed = true;
log.debug("Set temp basal stop result: " + result + " FAILED!!!");
} else {
if (Config.logDanaMessageDetail)
log.debug("Set temp basal stop result: " + result);
}
}
}

View file

@ -0,0 +1,25 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingActiveProfile extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingBasal.class);
public MsgSettingActiveProfile() {
SetCommand(0x320C);
}
public void handleMessage(byte[] bytes) {
DanaRFragment.getDanaRPump().activeProfile = intFromBuff(bytes, 0, 1);
if (Config.logDanaMessageDetail)
log.debug("Active profile number: " + DanaRFragment.getDanaRPump().activeProfile);
}
}

View file

@ -0,0 +1,31 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingBasal extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingBasal.class);
public MsgSettingBasal() {
SetCommand(0x3202);
}
public void handleMessage(byte[] bytes) {
for (int index = 0; index < 24; index++) {
int basal = intFromBuff(bytes, 2 * index, 2);
if (basal < 10) basal = 0;
DanaRFragment.getDanaRPump().pumpProfiles[DanaRFragment.getDanaRPump().activeProfile].basalValue[index] = basal / 100d;
}
if (Config.logDanaMessageDetail)
for (int index = 0; index < 24; index++) {
log.debug("Basal " + String.format("%02d", index) + "h: " + DanaRFragment.getDanaRPump().pumpProfiles[DanaRFragment.getDanaRPump().activeProfile].basalValue[index]);
}
}
}

View file

@ -0,0 +1,61 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingBasalProfileAll extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingBasalProfileAll.class);
public MsgSettingBasalProfileAll() {
SetCommand(0x3206);
}
public void handleMessage(byte[] bytes) {
if (DanaRFragment.getDanaRPump().basal48Enable) {
for (int profile = 0; profile < 4; profile++) {
int position = intFromBuff(bytes, 107 * profile, 1);
for (int index = 0; index < 48; index++) {
int basal = intFromBuff(bytes, 107 * profile + 2 * index + 1, 2);
if (basal < 10) basal = 0;
DanaRFragment.getDanaRPump().pumpProfiles[position].basalValue[index] = basal / 100d;
}
}
} else {
for (int profile = 0; profile < 4; profile++) {
int position = intFromBuff(bytes, 59 * profile, 1);
for (int index = 0; index < 24; index++) {
int basal = intFromBuff(bytes, 59 * profile + 2 * index + 1, 2);
if (basal < 10) basal = 0;
DanaRFragment.getDanaRPump().pumpProfiles[position].basalValue[index] = basal / 100d;
}
}
}
if (Config.logDanaMessageDetail) {
if (DanaRFragment.getDanaRPump().basal48Enable) {
for (int profile = 0; profile < 4; profile++) {
for (int index = 0; index < 24; index++) {
log.debug("Basal profile " + profile + ": " + String.format("%02d", index) + "h: " + DanaRFragment.getDanaRPump().pumpProfiles[profile].basalValue[index]);
}
}
} else {
for (int profile = 0; profile < 4; profile++) {
for (int index = 0; index < 48; index++) {
log.debug("Basal profile " + profile + ": " +
String.format("%02d", (index / 2)) +
":" + String.format("%02d", (index % 2) * 30) + " : " +
DanaRFragment.getDanaRPump().pumpProfiles[profile].basalValue[index]);
}
}
}
}
}
}

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingGlucose extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingGlucose.class);
public MsgSettingGlucose() {
SetCommand(0x3209);
}
public void handleMessage(byte[] bytes) {
DanaRFragment.getDanaRPump().units = intFromBuff(bytes, 0, 1);
DanaRFragment.getDanaRPump().easyBasalMode = intFromBuff(bytes, 1, 1);
if (Config.logDanaMessageDetail) {
log.debug("Pump units: " + (DanaRFragment.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
log.debug("Easy basal mode: " + DanaRFragment.getDanaRPump().easyBasalMode);
}
}
}

View file

@ -0,0 +1,32 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingMaxValues extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingMaxValues.class);
public MsgSettingMaxValues() {
SetCommand(0x3205);
}
public void handleMessage(byte[] bytes) {
DanaRFragment.getDanaRPump().maxBolus = intFromBuff(bytes, 0, 2) / 100d;
DanaRFragment.getDanaRPump().maxBasal = intFromBuff(bytes, 2, 2) / 100d;
DanaRFragment.getDanaRPump().dailyMax = intFromBuff(bytes, 4, 2) / 100d;
if (Config.logDanaMessageDetail) {
log.debug("Max bolus: " + DanaRFragment.getDanaRPump().maxBolus);
log.debug("Max basal: " + DanaRFragment.getDanaRPump().maxBasal);
log.debug("Max daily max: " + DanaRFragment.getDanaRPump().dailyMax);
}
}
}

View file

@ -0,0 +1,44 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingProfileRatios extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatios.class);
public MsgSettingProfileRatios() {
SetCommand(0x3204);
}
public void handleMessage(byte[] bytes) {
if (DanaRFragment.getDanaRPump().units == DanaRPump.UNITS_MGDL) {
DanaRFragment.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
DanaRFragment.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2);
DanaRFragment.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100;
DanaRFragment.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2);
DanaRFragment.getDanaRPump().currentAIDR = intFromBuff(bytes, 6, 1);
} else {
DanaRFragment.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
DanaRFragment.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100;
DanaRFragment.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100;
DanaRFragment.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100;
DanaRFragment.getDanaRPump().currentAIDR = intFromBuff(bytes, 6, 1);
}
if (Config.logDanaMessageDetail) {
log.debug("Pump units (saved): " + (DanaRFragment.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
log.debug("Current pump CIR: " + DanaRFragment.getDanaRPump().currentCIR);
log.debug("Current pump CF: " + DanaRFragment.getDanaRPump().currentCF);
log.debug("Current pump AI: " + DanaRFragment.getDanaRPump().currentAI);
log.debug("Current pump target: " + DanaRFragment.getDanaRPump().currentTarget);
log.debug("Current pump AIDR: " + DanaRFragment.getDanaRPump().currentAIDR);
}
}
}

View file

@ -0,0 +1,54 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingProfileRatiosAll extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingProfileRatiosAll.class);
public MsgSettingProfileRatiosAll() {
SetCommand(0x320D);
}
public void handleMessage(byte[] bytes) {
if (DanaRFragment.getDanaRPump().units == DanaRPump.UNITS_MGDL) {
DanaRFragment.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2);
DanaRFragment.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2);
DanaRFragment.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2);
DanaRFragment.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2);
DanaRFragment.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2);
DanaRFragment.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2);
DanaRFragment.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2);
DanaRFragment.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2);
} else {
DanaRFragment.getDanaRPump().morningCIR = intFromBuff(bytes, 0, 2);
DanaRFragment.getDanaRPump().morningCF = intFromBuff(bytes, 2, 2) / 100;
DanaRFragment.getDanaRPump().afternoonCIR = intFromBuff(bytes, 4, 2);
DanaRFragment.getDanaRPump().afternoonCF = intFromBuff(bytes, 6, 2) / 100;
DanaRFragment.getDanaRPump().eveningCIR = intFromBuff(bytes, 8, 2);
DanaRFragment.getDanaRPump().eveningCF = intFromBuff(bytes, 10, 2) / 100;
DanaRFragment.getDanaRPump().nightCIR = intFromBuff(bytes, 12, 2);
DanaRFragment.getDanaRPump().nightCF = intFromBuff(bytes, 14, 2) / 100;
}
if (Config.logDanaMessageDetail) {
log.debug("Pump units: " + (DanaRFragment.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
log.debug("Current pump morning CIR: " + DanaRFragment.getDanaRPump().morningCIR);
log.debug("Current pump morning CF: " + DanaRFragment.getDanaRPump().morningCF);
log.debug("Current pump afternoon CIR: " + DanaRFragment.getDanaRPump().afternoonCIR);
log.debug("Current pump afternoon CF: " + DanaRFragment.getDanaRPump().afternoonCF);
log.debug("Current pump evening CIR: " + DanaRFragment.getDanaRPump().eveningCIR);
log.debug("Current pump evening CF: " + DanaRFragment.getDanaRPump().eveningCF);
log.debug("Current pump night CIR: " + DanaRFragment.getDanaRPump().nightCIR);
log.debug("Current pump night CF: " + DanaRFragment.getDanaRPump().nightCF);
}
}
}

View file

@ -0,0 +1,34 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
public class MsgSettingPumpTime extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingPumpTime.class);
public MsgSettingPumpTime() {
SetCommand(0x320A);
}
public void handleMessage(byte[] bytes) {
Date time =
new Date(
100 + intFromBuff(bytes, 5, 1),
intFromBuff(bytes, 4, 1) - 1,
intFromBuff(bytes, 3, 1),
intFromBuff(bytes, 2, 1),
intFromBuff(bytes, 1, 1),
intFromBuff(bytes, 0, 1)
);
if (Config.logDanaMessageDetail)
log.debug("Pump time: " + time);
DanaRFragment.getDanaRPump().pumpTime = time;
}
}

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingShippingInfo extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingShippingInfo.class);
public MsgSettingShippingInfo() {
SetCommand(0x3207);
}
public void handleMessage(byte[] bytes) {
DanaRFragment.getDanaRPump().serialNumber = stringFromBuff(bytes, 0, 10);
DanaRFragment.getDanaRPump().shippingDate = dateFromBuff(bytes, 10);
DanaRFragment.getDanaRPump().shippingCountry = asciiStringFromBuff(bytes, 13, 3);
if (Config.logDanaMessageDetail) {
log.debug("Serial number: " + DanaRFragment.getDanaRPump().serialNumber);
log.debug("Shipping date: " + DanaRFragment.getDanaRPump().shippingDate);
log.debug("Shipping country: " + DanaRFragment.getDanaRPump().shippingCountry);
}
}
}

View file

@ -0,0 +1,20 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Created by mike on 05.07.2016.
*/
public class MsgSettingUserOptions extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgSettingShippingInfo.class);
public MsgSettingUserOptions() {
SetCommand(0x320B);
}
public void handleMessage(byte[] bytes) {
}
}

View file

@ -0,0 +1,37 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
public class MsgStatus extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgStatus.class);
public MsgStatus() {
SetCommand(0x020B);
}
public void handleMessage(byte[] bytes) {
DanaRFragment.getDanaRPump().dailyTotalUnits = intFromBuff(bytes, 0, 3) / 750d;
DanaRFragment.getDanaRPump().isExtendedInProgress = intFromBuff(bytes, 3, 1) == 1;
DanaRFragment.getDanaRPump().extendedBolusMinutes = intFromBuff(bytes, 4, 2);
DanaRFragment.getDanaRPump().extendedBolusAmount = intFromBuff(bytes, 6, 2) / 100d;
DanaRFragment.getDanaRPump().lastBolusTime = dateTimeFromBuff(bytes, 8);
DanaRFragment.getDanaRPump().lastBolusAmount = intFromBuff(bytes, 13, 2) / 100d;
DanaRFragment.getDanaRPump().iob = intFromBuff(bytes, 15, 2) / 100d;
if (Config.logDanaMessageDetail) {
log.debug("Daily total: " + DanaRFragment.getDanaRPump().dailyTotalUnits);
log.debug("Is extended bolus running: " + DanaRFragment.getDanaRPump().isExtendedInProgress);
log.debug("Extended bolus min: " + DanaRFragment.getDanaRPump().extendedBolusMinutes);
log.debug("Extended bolus amount: " + DanaRFragment.getDanaRPump().extendedBolusAmount);
log.debug("Last bolus time: " + DanaRFragment.getDanaRPump().lastBolusTime);
log.debug("Last bolus amount: " + DanaRFragment.getDanaRPump().lastBolusAmount);
log.debug("IOB: " + DanaRFragment.getDanaRPump().iob);
}
}
}

View file

@ -0,0 +1,54 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
public class MsgStatusBasic extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgStatusBasic.class);
public MsgStatusBasic() {
SetCommand(0x020A);
}
public void handleMessage(byte[] bytes) {
boolean pumpSuspended = intFromBuff(bytes, 0, 1) == 1;
boolean calculatorEnabled = intFromBuff(bytes, 1, 1) == 1;
double dailyTotalUnits = intFromBuff(bytes, 2, 3) / 750d;
int dailyMaxRate = intFromBuff(bytes, 5, 2);
double reservoirRemainingUnits = intFromBuff(bytes, 7, 3) / 750d;
boolean bolusBlocked = intFromBuff(bytes, 10, 1) == 1;
double currentBasal = intFromBuff(bytes, 11, 2) / 100d;
int tempBasalPercent = intFromBuff(bytes, 13, 1);
boolean isExtendedInProgress = intFromBuff(bytes, 14, 1) == 1;
boolean isTempBasalInProgress = intFromBuff(bytes, 15, 1) == 1;
int batteryRemaining = intFromBuff(bytes, 20, 1);
DanaRFragment.getDanaRPump().pumpSuspended = pumpSuspended;
DanaRFragment.getDanaRPump().calculatorEnabled = calculatorEnabled;
DanaRFragment.getDanaRPump().dailyTotalUnits = dailyTotalUnits;
DanaRFragment.getDanaRPump().dailyMaxRate = dailyMaxRate;
DanaRFragment.getDanaRPump().reservoirRemainingUnits = reservoirRemainingUnits;
DanaRFragment.getDanaRPump().bolusBlocked = bolusBlocked;
DanaRFragment.getDanaRPump().currentBasal = currentBasal;
DanaRFragment.getDanaRPump().tempBasalPercent = tempBasalPercent;
DanaRFragment.getDanaRPump().isExtendedInProgress = isExtendedInProgress;
DanaRFragment.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress;
DanaRFragment.getDanaRPump().batteryRemaining = batteryRemaining;
if (Config.logDanaMessageDetail) {
log.debug("Pump suspended: " + pumpSuspended);
log.debug("Calculator enabled: " + calculatorEnabled);
log.debug("Daily total units: " + dailyTotalUnits);
log.debug("Daily max rate: " + dailyMaxRate);
log.debug("Reservoir remaining units: " + reservoirRemainingUnits);
log.debug("Bolus blocked: " + bolusBlocked);
log.debug("Current basal: " + currentBasal);
log.debug("Current temp basal percent: " + tempBasalPercent);
log.debug("Is extended bolus running: " + isExtendedInProgress);
log.debug("Is temp basal running: " + isTempBasalInProgress);
}
}
}

View file

@ -0,0 +1,56 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import android.support.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
public class MsgStatusBolusExtended extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgStatusBolusExtended.class);
public MsgStatusBolusExtended() {
SetCommand(0x0207);
}
public void handleMessage(byte[] bytes) {
boolean isExtendedInProgress = intFromBuff(bytes, 0, 1) == 1;
int extendedBolusHalfHours = intFromBuff(bytes, 1, 1);
int extendedBolusMinutes = extendedBolusHalfHours * 30;
double extendedBolusAmount = intFromBuff(bytes, 2, 2) / 100d;
int extendedBolusSoFarInSecs = intFromBuff(bytes, 4, 3);
int extendedBolusSoFarInMinutes = extendedBolusSoFarInSecs / 60;
double extendedBolusAbsoluteRate = isExtendedInProgress ? extendedBolusAmount / extendedBolusMinutes * 60 : 0d;
Date extendedBolusStart = isExtendedInProgress ? getDateFromSecAgo(extendedBolusSoFarInSecs) : new Date(0);
int extendedBolusRemainingMinutes = extendedBolusMinutes - extendedBolusSoFarInMinutes;
DanaRFragment.getDanaRPump().isExtendedInProgress = isExtendedInProgress;
DanaRFragment.getDanaRPump().extendedBolusMinutes = extendedBolusMinutes;
DanaRFragment.getDanaRPump().extendedBolusAmount = extendedBolusAmount;
DanaRFragment.getDanaRPump().extendedBolusSoFarInMinutes = extendedBolusSoFarInMinutes;
DanaRFragment.getDanaRPump().extendedBolusAbsoluteRate = extendedBolusAbsoluteRate;
DanaRFragment.getDanaRPump().extendedBolusStart = extendedBolusStart;
DanaRFragment.getDanaRPump().extendedBolusRemainingMinutes = extendedBolusRemainingMinutes;
if (Config.logDanaMessageDetail) {
log.debug("Is extended bolus running: " + isExtendedInProgress);
log.debug("Extended bolus min: " + extendedBolusMinutes);
log.debug("Extended bolus amount: " + extendedBolusAmount);
log.debug("Extended bolus so far in minutes: " + extendedBolusSoFarInMinutes);
log.debug("Extended bolus absolute rate: " + extendedBolusAbsoluteRate);
log.debug("Extended bolus start: " + extendedBolusStart);
log.debug("Extended bolus remaining minutes: " + extendedBolusRemainingMinutes);
}
}
@NonNull
private Date getDateFromSecAgo(int tempBasalAgoSecs) {
return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000);
}
}

View file

@ -0,0 +1,42 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
import info.nightscout.androidaps.plugins.DanaR.DanaRPump;
/**
* Created by mike on 05.07.2016.
*/
public class MsgStatusProfile extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgStatusProfile.class);
public MsgStatusProfile() {
SetCommand(0x0204);
}
public void handleMessage(byte[] bytes) {
if (DanaRFragment.getDanaRPump().units == DanaRPump.UNITS_MGDL) {
DanaRFragment.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
DanaRFragment.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2);
DanaRFragment.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100;
DanaRFragment.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2);
} else {
DanaRFragment.getDanaRPump().currentCIR = intFromBuff(bytes, 0, 2);
DanaRFragment.getDanaRPump().currentCF = intFromBuff(bytes, 2, 2) / 100;
DanaRFragment.getDanaRPump().currentAI = intFromBuff(bytes, 4, 2) / 100;
DanaRFragment.getDanaRPump().currentTarget = intFromBuff(bytes, 6, 2) / 100;
}
if (Config.logDanaMessageDetail) {
log.debug("Pump units (saved): " + (DanaRFragment.getDanaRPump().units == DanaRPump.UNITS_MGDL ? "MGDL" : "MMOL"));
log.debug("Current pump CIR: " + DanaRFragment.getDanaRPump().currentCIR);
log.debug("Current pump CF: " + DanaRFragment.getDanaRPump().currentCF);
log.debug("Current pump AI: " + DanaRFragment.getDanaRPump().currentAI);
log.debug("Current pump target: " + DanaRFragment.getDanaRPump().currentTarget);
log.debug("Current pump AIDR: " + DanaRFragment.getDanaRPump().currentAIDR);
}
}
}

View file

@ -0,0 +1,47 @@
package info.nightscout.androidaps.plugins.DanaR.comm;
import android.support.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.plugins.DanaR.DanaRFragment;
public class MsgStatusTempBasal extends DanaRMessage {
private static Logger log = LoggerFactory.getLogger(MsgStatusTempBasal.class);
public MsgStatusTempBasal() {
SetCommand(0x0205);
}
public void handleMessage(byte[] bytes) {
boolean isTempBasalInProgress = intFromBuff(bytes, 0, 1) == 1;
int tempBasalPercent = intFromBuff(bytes, 1, 1);
int tempBasalTotalSec = intFromBuff(bytes, 2, 1) * 60 * 60;
int tempBasalRunningSeconds = intFromBuff(bytes, 3, 3);
int tempBasalRemainingMin = (tempBasalTotalSec - tempBasalRunningSeconds) / 60;
Date tempBasalStart = isTempBasalInProgress ? getDateFromTempBasalSecAgo(tempBasalRunningSeconds) : new Date(0);
DanaRFragment.getDanaRPump().isTempBasalInProgress = isTempBasalInProgress;
DanaRFragment.getDanaRPump().tempBasalPercent = tempBasalPercent;
DanaRFragment.getDanaRPump().tempBasalRemainingMin = tempBasalRemainingMin;
DanaRFragment.getDanaRPump().tempBasalTotalSec = tempBasalTotalSec;
DanaRFragment.getDanaRPump().tempBasalStart = tempBasalStart;
if (Config.logDanaMessageDetail) {
log.debug("Is temp basal running: " + isTempBasalInProgress);
log.debug("Current temp basal percent: " + tempBasalPercent);
log.debug("Current temp basal remaining min: " + tempBasalRemainingMin);
log.debug("Current temp basal total sec: " + tempBasalTotalSec);
log.debug("Current temp basal start: " + tempBasalStart);
}
}
@NonNull
private Date getDateFromTempBasalSecAgo(int tempBasalAgoSecs) {
return new Date((long) (Math.ceil(new Date().getTime() / 1000d) - tempBasalAgoSecs) * 1000);
}
}

View file

@ -0,0 +1,55 @@
package info.nightscout.androidaps.plugins.DanaR.events;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.Services.Intents;
import info.nightscout.androidaps.db.Treatment;
import info.nightscout.client.data.DbLogger;
public class EventDanaRBolusProgress {
private static Logger log = LoggerFactory.getLogger(EventDanaRBolusProgress.class);
public String sStatus = "";
public Treatment t = null;
private static EventDanaRBolusProgress eventDanaRBolusProgress = null;
public EventDanaRBolusProgress() {
}
public static EventDanaRBolusProgress getInstance() {
if(eventDanaRBolusProgress == null) {
eventDanaRBolusProgress = new EventDanaRBolusProgress();
}
return eventDanaRBolusProgress;
}
public void sendToNSClient() {
if (t == null || t._id == null || t._id.equals("")) return;
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbUpdate");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("status", sStatus);
} catch (JSONException e) {
e.printStackTrace();
}
bundle.putString("data", data.toString());
bundle.putString("_id", t._id);
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString(), EventDanaRBolusProgress.class);
}
}

View file

@ -0,0 +1,19 @@
package info.nightscout.androidaps.plugins.DanaR.events;
public class EventDanaRConnectionStatus {
public boolean sConnecting = false;
public boolean sConnected = false;
public int sConnectionAttemptNo =0;
public EventDanaRConnectionStatus(boolean connecting, boolean connected, int connectionAttemptNo) {
sConnecting = connecting;
sConnected = connected;
if(connectionAttemptNo!=0)
sConnectionAttemptNo = connectionAttemptNo;
}
public EventDanaRConnectionStatus() {
}
}

View file

@ -0,0 +1,38 @@
package info.nightscout.utils;
public final class CRC {
private static int[] CRC16_TABLE = new int[]{
0, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad,
0xe1ce, 0xf1ef, 0x1231, 0x210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a,
0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,
0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x840, 0x1861,
0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7,
0x6a96, 0x1a71, 0xa50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0xc60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a,
0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0xe70, 0xff9f, 0xefbe, 0xdfdd,
0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0xa1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c,
0xe37f, 0xf35e, 0x2b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589,
0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa,
0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x8e1,
0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37,
0x7a16, 0xaf1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26,
0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0xcc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9,
0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0xed1, 0x1ef0};
public static short getCrc16(byte[] content, int offset, int length) {
int value = 0;
for (int pos = offset; pos < offset + length; pos++) {
value = unsignedShort((value << 8) ^ CRC16_TABLE[((value >>> 8) ^ content[pos]) & 0xff]);
}
return unsignedShort(value);
}
public static short unsignedShort(int value) {
return (short) ((short) value & 0xFFFF);
}
}

View file

@ -4,4 +4,15 @@
android:layout_height="match_parent"
tools:context="info.nightscout.androidaps.plugins.DanaR.DanaRFragment">
<com.joanzapata.iconify.widget.IconTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:layout_weight="1.02"
android:gravity="center_vertical|right"
android:text="B"
android:textSize="20dp"
android:id="@+id/danar_connection"
android:layout_gravity="center_vertical" />
</FrameLayout>

Binary file not shown.

View file

@ -224,5 +224,8 @@
<string name="end_user_license_agreement_text">MUST NOT BE USED TO MAKE MEDICAL DECISIONS. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.</string>
<string name="end_user_license_agreement_i_understand">I UNDERSTAND AND AGREE</string>
<string name="save">Save</string>
<string name="nobtadapter">No bluetooth adapter found</string>
<string name="devicenotfound">Selected device not found</string>
<string name="connectionerror">Pump connection error</string>
</resources>