[0.4.1-SNAPSHOT]
- little change in scanning - added error checking into RadioResponse and BasalProfile, also added events - disabled quick scan - synchronized RileyLink state changes - proofed MedtronicConverter - fixed 10 errors found on fabric - fixed SetBasalProfile, after merge
This commit is contained in:
parent
03e38158f4
commit
5b9bd2adfc
24 changed files with 506 additions and 113 deletions
|
@ -64,7 +64,7 @@ android {
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
versionCode 1500
|
versionCode 1500
|
||||||
// dev_version: 2.0i
|
// dev_version: 2.0i
|
||||||
version "medtronic-0.4.0-snapshot"
|
version "medtronic-0.4"
|
||||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||||
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
|
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'
|
||||||
|
|
|
@ -66,7 +66,9 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
|
<activity android:name=".plugins.PumpDanaRS.activities.PairingHelperActivity" />
|
||||||
<activity android:name=".HistoryBrowseActivity" />
|
|
||||||
|
<activity android:name=".activities.HistoryBrowseActivity" />
|
||||||
|
|
||||||
<activity android:name=".plugins.PumpCommon.dialog.RileyLinkBLEScanActivity">
|
<activity android:name=".plugins.PumpCommon.dialog.RileyLinkBLEScanActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />
|
<action android:name="info.nightscout.androidaps.plugins.PumpCommon.dialog.RileyLinkBLEScanActivity" />
|
||||||
|
@ -201,7 +203,8 @@
|
||||||
android:theme="@style/AppTheme.NoActionBar"
|
android:theme="@style/AppTheme.NoActionBar"
|
||||||
android:label="@string/title_activity_setup_wizard" />
|
android:label="@string/title_activity_setup_wizard" />
|
||||||
|
|
||||||
<activity android:name=".activities.SingleFragmentActivity"
|
<activity
|
||||||
|
android:name=".activities.SingleFragmentActivity"
|
||||||
android:theme="@style/AppTheme" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".plugins.Maintenance.activities.LogSettingActivity"></activity>
|
<activity android:name=".plugins.Maintenance.activities.LogSettingActivity"></activity>
|
||||||
|
|
||||||
|
|
|
@ -469,6 +469,11 @@ public class MainApp extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isEngineeringMode() {
|
||||||
|
return engineeringMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean isDev() {
|
public static boolean isDev() {
|
||||||
return devBranch;
|
return devBranch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,9 +222,11 @@ public abstract class RileyLinkCommunicationManager {
|
||||||
trial.successes++;
|
trial.successes++;
|
||||||
} else {
|
} else {
|
||||||
LOG.warn("Failed to parse radio response: " + ByteUtil.shortHexString(resp.getRaw()));
|
LOG.warn("Failed to parse radio response: " + ByteUtil.shortHexString(resp.getRaw()));
|
||||||
|
trial.rssiList.add(-99);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.error("scanForPump: raw response is " + ByteUtil.shortHexString(resp.getRaw()));
|
LOG.error("scanForPump: raw response is " + ByteUtil.shortHexString(resp.getRaw()));
|
||||||
|
trial.rssiList.add(-99);
|
||||||
}
|
}
|
||||||
trial.tries++;
|
trial.tries++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,11 +83,6 @@ public class RileyLinkUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static RileyLinkServiceState getServiceState() {
|
|
||||||
return RileyLinkUtil.rileyLinkServiceData.serviceState;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void setServiceState(RileyLinkServiceState newState) {
|
public static void setServiceState(RileyLinkServiceState newState) {
|
||||||
setServiceState(newState, null);
|
setServiceState(newState, null);
|
||||||
}
|
}
|
||||||
|
@ -98,16 +93,38 @@ public class RileyLinkUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static RileyLinkServiceState getServiceState() {
|
||||||
|
return workWithServiceState(null, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void setServiceState(RileyLinkServiceState newState, RileyLinkError errorCode) {
|
public static void setServiceState(RileyLinkServiceState newState, RileyLinkError errorCode) {
|
||||||
|
workWithServiceState(newState, errorCode, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static synchronized RileyLinkServiceState workWithServiceState(RileyLinkServiceState newState,
|
||||||
|
RileyLinkError errorCode, boolean set) {
|
||||||
|
|
||||||
|
if (set) {
|
||||||
|
|
||||||
RileyLinkUtil.rileyLinkServiceData.serviceState = newState;
|
RileyLinkUtil.rileyLinkServiceData.serviceState = newState;
|
||||||
RileyLinkUtil.rileyLinkServiceData.errorCode = errorCode;
|
RileyLinkUtil.rileyLinkServiceData.errorCode = errorCode;
|
||||||
|
|
||||||
LOG.warn("RileyLink State Changed: {} {}", newState,
|
LOG.warn("RileyLink State Changed: {} {}", newState, errorCode == null ? "" : " - Error State: "
|
||||||
errorCode == null ? "" : " - Error State: " + errorCode.name());
|
+ errorCode.name());
|
||||||
|
|
||||||
RileyLinkUtil.historyRileyLink.add(new RLHistoryItem(RileyLinkUtil.rileyLinkServiceData.serviceState,
|
RileyLinkUtil.historyRileyLink.add(new RLHistoryItem(RileyLinkUtil.rileyLinkServiceData.serviceState,
|
||||||
RileyLinkUtil.rileyLinkServiceData.errorCode, targetDevice));
|
RileyLinkUtil.rileyLinkServiceData.errorCode, targetDevice));
|
||||||
MainApp.bus().post(new EventMedtronicDeviceStatusChange(newState, errorCode));
|
MainApp.bus().post(new EventMedtronicDeviceStatusChange(newState, errorCode));
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return RileyLinkUtil.rileyLinkServiceData.serviceState;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble;
|
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -160,6 +161,63 @@ public class RFTools {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static byte[] encode4b6b_newtest(byte[] data) {
|
||||||
|
|
||||||
|
List<Byte> buffer = new ArrayList<Byte>();
|
||||||
|
int bitAccumulator = 0x0;
|
||||||
|
int bitcount = 0;
|
||||||
|
|
||||||
|
for (byte element : data) {
|
||||||
|
bitAccumulator <<= 6;
|
||||||
|
bitAccumulator |= codes[element >> 4];
|
||||||
|
bitcount += 6;
|
||||||
|
|
||||||
|
bitAccumulator <<= 6;
|
||||||
|
bitAccumulator |= codes[element & 0x0f];
|
||||||
|
bitcount += 6;
|
||||||
|
|
||||||
|
while (bitcount >= 8) {
|
||||||
|
buffer.add((byte)((bitAccumulator >> (bitcount - 8)) & 0xff));
|
||||||
|
bitcount -= 8;
|
||||||
|
bitAccumulator &= (0xffff >> (16 - bitcount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bitcount > 0) {
|
||||||
|
bitAccumulator <<= (8 - bitcount);
|
||||||
|
buffer.add((byte)((bitAccumulator) & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ByteUtil.getByteArrayFromList(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public func encode4b6b() -> [UInt8] {
|
||||||
|
// var buffer = [UInt8]()
|
||||||
|
// var bitAccumulator = 0x0
|
||||||
|
// var bitcount = 0
|
||||||
|
// for byte in self {
|
||||||
|
// bitAccumulator <<= 6
|
||||||
|
// bitAccumulator |= codes[Int(byte >> 4)]
|
||||||
|
// bitcount += 6
|
||||||
|
//
|
||||||
|
// bitAccumulator <<= 6
|
||||||
|
// bitAccumulator |= codes[Int(byte & 0x0f)]
|
||||||
|
// bitcount += 6
|
||||||
|
//
|
||||||
|
// while bitcount >= 8 {
|
||||||
|
// buffer.append(UInt8(bitAccumulator >> (bitcount-8)) & 0xff)
|
||||||
|
// bitcount -= 8
|
||||||
|
// bitAccumulator &= (0xffff >> (16-bitcount))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if bitcount > 0 {
|
||||||
|
// bitAccumulator <<= (8-bitcount)
|
||||||
|
// buffer.append(UInt8(bitAccumulator) & 0xff)
|
||||||
|
// }
|
||||||
|
// return buffer
|
||||||
|
// }
|
||||||
|
|
||||||
public static void test() {
|
public static void test() {
|
||||||
/*
|
/*
|
||||||
* {0xa7} -> {0xa9, 0x60}
|
* {0xa7} -> {0xa9, 0x60}
|
||||||
|
@ -272,6 +330,96 @@ public class RFTools {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static DecodeResponseDto decode4b6bWithoutException(byte[] raw) {
|
||||||
|
/*
|
||||||
|
* if ((raw.length % 2) != 0) {
|
||||||
|
* LOG.error("Warning: data is odd number of bytes");
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
DecodeResponseDto response = new DecodeResponseDto();
|
||||||
|
|
||||||
|
StringBuilder errorMessageBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
errorMessageBuilder.append("Input data: " + ByteUtil.getHex(raw) + "\n");
|
||||||
|
|
||||||
|
if ((raw.length % 2) != 0) {
|
||||||
|
errorMessageBuilder.append("Warn: odd number of bytes.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] rval = new byte[] {};
|
||||||
|
int availableBits = 0;
|
||||||
|
int codingErrors = 0;
|
||||||
|
int x = 0;
|
||||||
|
// Log.w(TAG,"decode4b6b: untested code");
|
||||||
|
// Log.w(TAG,String.format("Decoding %d bytes: %s",raw.length,ByteUtil.shortHexString(raw)));
|
||||||
|
for (int i = 0; i < raw.length; i++) {
|
||||||
|
int unsignedValue = raw[i];
|
||||||
|
if (unsignedValue < 0) {
|
||||||
|
unsignedValue += 256;
|
||||||
|
}
|
||||||
|
x = (x << 8) + unsignedValue;
|
||||||
|
availableBits += 8;
|
||||||
|
if (availableBits >= 12) {
|
||||||
|
// take top six
|
||||||
|
int highcode = (x >> (availableBits - 6)) & 0x3F;
|
||||||
|
int highIndex = codeIndex((byte)(highcode));
|
||||||
|
// take bottom six
|
||||||
|
int lowcode = (x >> (availableBits - 12)) & 0x3F;
|
||||||
|
int lowIndex = codeIndex((byte)(lowcode));
|
||||||
|
// special case at end of transmission on uneven boundaries:
|
||||||
|
if ((highIndex >= 0) && (lowIndex >= 0)) {
|
||||||
|
byte decoded = (byte)((highIndex << 4) + lowIndex);
|
||||||
|
rval = ByteUtil.concat(rval, decoded);
|
||||||
|
/*
|
||||||
|
* LOG.debug(String.format(
|
||||||
|
* "i=%d,x=0x%08X,0x%02X->0x%02X, 0x%02X->0x%02X, result: 0x%02X, %d bits remaining, errors %d, bytes remaining: %s"
|
||||||
|
* ,
|
||||||
|
* i,x,highcode,highIndex, lowcode,
|
||||||
|
* lowIndex,decoded,availableBits,codingErrors,ByteUtil.shortHexString
|
||||||
|
* (ByteUtil.substring(raw,i+1,raw.length-i-1))));
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
// LOG.debug(String.format("i=%d,x=%08X, coding error: highcode=0x%02X, lowcode=0x%02X, %d bits remaining",i,x,highcode,lowcode,availableBits));
|
||||||
|
errorMessageBuilder.append(String.format(
|
||||||
|
"decode4b6b: i=%d,x=%08X, coding error: highcode=0x%02X, lowcode=0x%02X, %d bits remaining.\n",
|
||||||
|
i, x, highcode, lowcode, availableBits));
|
||||||
|
codingErrors++;
|
||||||
|
}
|
||||||
|
|
||||||
|
availableBits -= 12;
|
||||||
|
x = x & (0x0000ffff >> (16 - availableBits));
|
||||||
|
} else {
|
||||||
|
// LOG.debug(String.format("i=%d, skip: x=0x%08X, available bits %d",i,x,availableBits));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (availableBits != 0) {
|
||||||
|
if ((availableBits == 4) && (x == 0x05)) {
|
||||||
|
// normal end
|
||||||
|
} else {
|
||||||
|
LOG.error("decode4b6b: failed clean decode -- extra bits available (not marker)(" + availableBits + ")");
|
||||||
|
errorMessageBuilder.append("decode4b6b: failed clean decode -- extra bits available (not marker)("
|
||||||
|
+ availableBits + ")\n");
|
||||||
|
codingErrors++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// also normal end.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codingErrors > 0) {
|
||||||
|
LOG.error("decode4b6b: " + codingErrors + " coding errors encountered.");
|
||||||
|
errorMessageBuilder.append("decode4b6b: " + codingErrors + " coding errors encountered.");
|
||||||
|
|
||||||
|
response.errorData = errorMessageBuilder.toString();
|
||||||
|
} else {
|
||||||
|
response.data = rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String toHexString(byte[] array) {
|
public static String toHexString(byte[] array) {
|
||||||
return toHexString(array, 0, array.length);
|
return toHexString(array, 0, array.length);
|
||||||
}
|
}
|
||||||
|
@ -290,4 +438,10 @@ public class RFTools {
|
||||||
return new String(buf);
|
return new String(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class DecodeResponseDto {
|
||||||
|
|
||||||
|
public byte[] data;
|
||||||
|
public String errorData;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,15 @@ public class FrequencyScanResults {
|
||||||
|
|
||||||
|
|
||||||
public void sort() {
|
public void sort() {
|
||||||
Collections.sort(trials, (trial1, trial2) -> trial1.averageRSSI.compareTo(trial2.averageRSSI));
|
Collections.sort(trials, (trial1, trial2) -> {
|
||||||
|
int res = trial1.averageRSSI.compareTo(trial2.averageRSSI);
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
return (int)(trial1.frequencyMHz - trial2.frequencyMHz);
|
||||||
|
} else
|
||||||
|
return res;
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.Riley
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkFirmwareVersion;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkFirmwareVersion;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
|
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC;
|
import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpCommon.utils.FabricUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by geoff on 5/30/16.
|
* Created by geoff on 5/30/16.
|
||||||
|
@ -100,13 +101,19 @@ public class RadioResponse {
|
||||||
decodedPayload = encodedPayload;
|
decodedPayload = encodedPayload;
|
||||||
break;
|
break;
|
||||||
case FourByteSixByte:
|
case FourByteSixByte:
|
||||||
LOG.debug("encodedPayload: {}", ByteUtil.getHex(encodedPayload));
|
RFTools.DecodeResponseDto decodeResponseDto = RFTools.decode4b6bWithoutException(encodedPayload);
|
||||||
byte[] decodeThis = RFTools.decode4b6b(encodedPayload);
|
byte[] decodeThis = decodeResponseDto.data;
|
||||||
LOG.debug("decodedPayload: {}", ByteUtil.getHex(decodeThis));
|
|
||||||
decodedOK = true;
|
decodedOK = true;
|
||||||
|
|
||||||
if (decodeThis == null || decodeThis.length == 0) {
|
if (decodeThis == null || decodeThis.length == 0 || decodeResponseDto.errorData != null) {
|
||||||
|
LOG.error("=============================================================================");
|
||||||
LOG.error(" Decoded payload length is zero.");
|
LOG.error(" Decoded payload length is zero.");
|
||||||
|
LOG.error(" encodedPayload: {}", ByteUtil.getHex(encodedPayload));
|
||||||
|
LOG.error(" errors: {}", decodeResponseDto.errorData);
|
||||||
|
LOG.error("=============================================================================");
|
||||||
|
|
||||||
|
FabricUtil.createEvent("MedtronicDecode4b6bError", null);
|
||||||
|
|
||||||
decodedOK = false;
|
decodedOK = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by andy on 5/19/18.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public enum RileyLinkTargetDevice {
|
|
||||||
MedtronicPump, //
|
|
||||||
Omnipod, //
|
|
||||||
;
|
|
||||||
}
|
|
|
@ -7,11 +7,9 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkCommunicationManager;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst;
|
||||||
|
@ -19,19 +17,12 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkEncodingType;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkEncodingType;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkFirmwareVersion;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkError;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkTargetDevice;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceNotification;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceResult;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceResult;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.data.ServiceTransport;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.DiscoverGattServicesTask;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.InitializePumpManagerTask;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTask;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask;
|
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
@ -254,20 +245,22 @@ public abstract class RileyLinkService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
double newFrequency;
|
double newFrequency;
|
||||||
if ((lastGoodFrequency > 0.0d) && getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) {
|
// if ((lastGoodFrequency > 0.0d) && getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) {
|
||||||
LOG.info("Checking for pump near last saved frequency of {}MHz", lastGoodFrequency);
|
// LOG.info("Checking for pump near last saved frequency of {}MHz", lastGoodFrequency);
|
||||||
// we have an old frequency, so let's start there.
|
// // we have an old frequency, so let's start there.
|
||||||
newFrequency = getDeviceCommunicationManager().quickTuneForPump(lastGoodFrequency);
|
// newFrequency = getDeviceCommunicationManager().quickTuneForPump(lastGoodFrequency);
|
||||||
if (newFrequency == 0.0) {
|
// if (newFrequency == 0.0) {
|
||||||
// quick scan failed to find pump. Try full scan
|
// // quick scan failed to find pump. Try full scan
|
||||||
LOG.warn("Failed to find pump near last saved frequency, doing full scan");
|
// LOG.warn("Failed to find pump near last saved frequency, doing full scan");
|
||||||
|
// newFrequency = getDeviceCommunicationManager().tuneForDevice();
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// LOG.warn("No saved frequency for pump, doing full scan.");
|
||||||
|
// // we don't have a saved frequency, so do the full scan.
|
||||||
|
// newFrequency = getDeviceCommunicationManager().tuneForDevice();
|
||||||
|
// }
|
||||||
|
|
||||||
newFrequency = getDeviceCommunicationManager().tuneForDevice();
|
newFrequency = getDeviceCommunicationManager().tuneForDevice();
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG.warn("No saved frequency for pump, doing full scan.");
|
|
||||||
// we don't have a saved frequency, so do the full scan.
|
|
||||||
newFrequency = getDeviceCommunicationManager().tuneForDevice();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((newFrequency != 0.0) && (newFrequency != lastGoodFrequency)) {
|
if ((newFrequency != 0.0) && (newFrequency != lastGoodFrequency)) {
|
||||||
LOG.info("Saving new pump frequency of {}MHz", newFrequency);
|
LOG.info("Saving new pump frequency of {}MHz", newFrequency);
|
||||||
|
@ -277,13 +270,12 @@ public abstract class RileyLinkService extends Service {
|
||||||
rileyLinkServiceData.lastTuneUpTime = System.currentTimeMillis();
|
rileyLinkServiceData.lastTuneUpTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
getRileyLinkCommunicationManager().clearNotConnectedCount();
|
|
||||||
|
|
||||||
if (newFrequency == 0.0d) {
|
if (newFrequency == 0.0d) {
|
||||||
// error tuning pump, pump not present ??
|
// error tuning pump, pump not present ??
|
||||||
RileyLinkUtil
|
RileyLinkUtil
|
||||||
.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.TuneUpOfDeviceFailed);
|
.setServiceState(RileyLinkServiceState.PumpConnectorError, RileyLinkError.TuneUpOfDeviceFailed);
|
||||||
} else {
|
} else {
|
||||||
|
getRileyLinkCommunicationManager().clearNotConnectedCount();
|
||||||
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorReady);
|
RileyLinkUtil.setServiceState(RileyLinkServiceState.PumpConnectorReady);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,6 +347,9 @@ public class ByteUtil {
|
||||||
|
|
||||||
|
|
||||||
public static String getCompactString(byte[] data) {
|
public static String getCompactString(byte[] data) {
|
||||||
|
if (data == null)
|
||||||
|
return "null";
|
||||||
|
|
||||||
String vval2 = ByteUtil.getHex(data);
|
String vval2 = ByteUtil.getHex(data);
|
||||||
vval2 = vval2.replace(" 0x", "");
|
vval2 = vval2.replace(" 0x", "");
|
||||||
vval2 = vval2.replace("0x", "");
|
vval2 = vval2.replace("0x", "");
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package info.nightscout.androidaps.plugins.PumpCommon.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by andy on 10/25/18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.joda.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is simple version of ATechDate, limited only to one format (yyyymmddHHMIss)
|
||||||
|
*/
|
||||||
|
public class DateTimeUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DateTime is packed as long: yyyymmddHHMMss
|
||||||
|
*
|
||||||
|
* @param atechDateTime
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static LocalDateTime toLocalDateTime(long atechDateTime) {
|
||||||
|
int year = (int)(atechDateTime / 10000000000L);
|
||||||
|
atechDateTime -= year * 10000000000L;
|
||||||
|
|
||||||
|
int month = (int)(atechDateTime / 100000000L);
|
||||||
|
atechDateTime -= month * 100000000L;
|
||||||
|
|
||||||
|
int dayOfMonth = (int)(atechDateTime / 1000000L);
|
||||||
|
atechDateTime -= dayOfMonth * 1000000L;
|
||||||
|
|
||||||
|
int hourOfDay = (int)(atechDateTime / 10000L);
|
||||||
|
atechDateTime -= hourOfDay * 10000L;
|
||||||
|
|
||||||
|
int minute = (int)(atechDateTime / 100L);
|
||||||
|
atechDateTime -= minute * 100L;
|
||||||
|
|
||||||
|
int second = (int)atechDateTime;
|
||||||
|
|
||||||
|
return new LocalDateTime(year, month, dayOfMonth, minute, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static long toATechDate(LocalDateTime ldt) {
|
||||||
|
long atechDateTime = 0L;
|
||||||
|
|
||||||
|
atechDateTime += ldt.getYear() * 10000000000L;
|
||||||
|
atechDateTime += ldt.getMonthOfYear() * 100000000L;
|
||||||
|
atechDateTime += ldt.getDayOfMonth() * 1000000L;
|
||||||
|
atechDateTime += ldt.getHourOfDay() * 10000L;
|
||||||
|
atechDateTime += ldt.getMinuteOfHour() * 100L;
|
||||||
|
atechDateTime += ldt.getSecondOfMinute();
|
||||||
|
|
||||||
|
return atechDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package info.nightscout.androidaps.plugins.PumpCommon.utils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.crashlytics.android.answers.AnswersEvent;
|
||||||
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.BuildConfig;
|
||||||
|
import info.nightscout.utils.FabricPrivacy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by andy on 10/26/18.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FabricUtil {
|
||||||
|
|
||||||
|
public static void createEvent(String eventName, Map<String, String> map) {
|
||||||
|
|
||||||
|
CustomEvent customEvent = new CustomEvent("MedtronicDecode4b6bError") //
|
||||||
|
.putCustomAttribute("buildversion", BuildConfig.BUILDVERSION) //
|
||||||
|
.putCustomAttribute("version", BuildConfig.VERSION);
|
||||||
|
|
||||||
|
int attributes = 2;
|
||||||
|
boolean interrupted = false;
|
||||||
|
|
||||||
|
if (map != null) {
|
||||||
|
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||||
|
|
||||||
|
int part = 1;
|
||||||
|
|
||||||
|
if (interrupted)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (final String token : Splitter.fixedLength(AnswersEvent.MAX_STRING_LENGTH).split(entry.getValue())) {
|
||||||
|
|
||||||
|
if (attributes == AnswersEvent.MAX_NUM_ATTRIBUTES) {
|
||||||
|
interrupted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
customEvent.putCustomAttribute(entry.getKey() + "_" + part, token);
|
||||||
|
attributes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FabricPrivacy.getInstance().logCustom(customEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,8 +5,6 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.joda.time.DateTime;
|
|
||||||
import org.joda.time.Hours;
|
|
||||||
import org.joda.time.LocalDateTime;
|
import org.joda.time.LocalDateTime;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -40,8 +38,10 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkConst
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLinkServiceState;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor;
|
||||||
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask;
|
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpCommon.utils.DateTimeUtil;
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.MedtronicCommunicationManager;
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryResult;
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUIComm;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUIComm;
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUITask;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.ui.MedtronicUITask;
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.data.MedtronicHistoryData;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.data.MedtronicHistoryData;
|
||||||
|
@ -884,24 +884,51 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
|
||||||
|
|
||||||
private void readPumpHistoryLogic() {
|
private void readPumpHistoryLogic() {
|
||||||
|
|
||||||
Long lastPumpHistoryEntryTime = null;
|
LocalDateTime targetDate = null;
|
||||||
|
|
||||||
// TODO read History
|
// TODO read History
|
||||||
|
// if (lastPumpHistoryEntry == null) {
|
||||||
|
// lastPumpHistoryEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, null);
|
||||||
|
// }
|
||||||
|
|
||||||
if (lastPumpHistoryEntry == null) {
|
if (lastPumpHistoryEntry == null) {
|
||||||
lastPumpHistoryEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (firstRun) {
|
Long lastPumpHistoryEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, null);
|
||||||
DateTime dt = new DateTime();
|
|
||||||
dt.minus(Hours.hours(36));
|
|
||||||
|
|
||||||
if (lastPumpHistoryEntry == null && lastPumpHistoryEntryTime == null) {
|
LocalDateTime timeMinus36h = new LocalDateTime();
|
||||||
|
timeMinus36h = timeMinus36h.minusHours(36);
|
||||||
|
|
||||||
|
if (lastPumpHistoryEntryTime == null) {
|
||||||
|
targetDate = timeMinus36h;
|
||||||
} else {
|
} else {
|
||||||
|
LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime);
|
||||||
|
|
||||||
|
medtronicHistoryData.setLastHistoryRecordTime(DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime));
|
||||||
|
|
||||||
|
lastHistoryRecordTime = lastHistoryRecordTime.minusHours(12); // we get last 12 hours of history to
|
||||||
|
// determine pump state
|
||||||
|
// (we don't process that data), we process only
|
||||||
|
|
||||||
|
if (timeMinus36h.isAfter(lastHistoryRecordTime)) {
|
||||||
|
targetDate = timeMinus36h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
targetDate = (timeMinus36h.isAfter(lastHistoryRecordTime) ? timeMinus36h : lastHistoryRecordTime);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME read history
|
||||||
|
|
||||||
|
PumpHistoryResult historyResult = new PumpHistoryResult(null, null);
|
||||||
|
|
||||||
|
PumpHistoryEntry latestEntry = historyResult.getLatestEntry();
|
||||||
|
|
||||||
|
if (latestEntry == null) // no new history to read
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.lastPumpHistoryEntry = latestEntry;
|
||||||
|
SP.putLong(MedtronicConst.Statistics.LastPumpHistoryEntry,
|
||||||
|
DateTimeUtil.toATechDate(latestEntry.getLocalDateTime()));
|
||||||
|
|
||||||
// determine if first run, if yes detrmine how much of update do we need
|
// determine if first run, if yes detrmine how much of update do we need
|
||||||
// first run:
|
// first run:
|
||||||
|
|
|
@ -135,7 +135,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
|
||||||
rfSpyResponse.wasTimeout());
|
rfSpyResponse.wasTimeout());
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
rememberLastGoodDeviceCommunicationTime();
|
// rememberLastGoodDeviceCommunicationTime();
|
||||||
|
|
||||||
// radioResponse.rssi;
|
// radioResponse.rssi;
|
||||||
Object dataResponse = medtronicConverter.convertResponse(MedtronicCommandType.PumpModel,
|
Object dataResponse = medtronicConverter.convertResponse(MedtronicCommandType.PumpModel,
|
||||||
|
@ -774,9 +774,9 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
|
||||||
|
|
||||||
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel);
|
Object responseObject = sendAndGetResponseWithCheck(MedtronicCommandType.PumpModel);
|
||||||
|
|
||||||
if (!MedtronicUtil.isModelSet()) {
|
// if (!MedtronicUtil.isModelSet()) {
|
||||||
MedtronicUtil.setMedtronicPumpModel((MedtronicDeviceType)responseObject);
|
// MedtronicUtil.setMedtronicPumpModel((MedtronicDeviceType)responseObject);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return responseObject == null ? null : (MedtronicDeviceType)responseObject;
|
return responseObject == null ? null : (MedtronicDeviceType)responseObject;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,12 @@ public class MedtronicConverter {
|
||||||
|
|
||||||
public Object convertResponse(MedtronicCommandType commandType, byte[] rawContent) {
|
public Object convertResponse(MedtronicCommandType commandType, byte[] rawContent) {
|
||||||
|
|
||||||
|
if ((rawContent == null || rawContent.length < 1) && commandType != MedtronicCommandType.PumpModel) {
|
||||||
|
LOG.warn("Content is empty or too shor, no data to convert (type={},isNull={},length={})",
|
||||||
|
commandType.name(), rawContent == null, rawContent == null ? "-" : rawContent.length);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
LOG.debug("Raw response before convert: " + HexDump.toHexStringDisplayable(rawContent));
|
LOG.debug("Raw response before convert: " + HexDump.toHexStringDisplayable(rawContent));
|
||||||
|
|
||||||
this.pumpModel = MedtronicUtil.getMedtronicPumpModel();
|
this.pumpModel = MedtronicUtil.getMedtronicPumpModel();
|
||||||
|
@ -53,7 +59,7 @@ public class MedtronicConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetBatteryStatus: {
|
case GetBatteryStatus: {
|
||||||
return decodeBatteryStatus(rawContent);
|
return decodeBatteryStatus(rawContent); // 1
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetBasalProfileSTD:
|
case GetBasalProfileSTD:
|
||||||
|
@ -63,7 +69,7 @@ public class MedtronicConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
case ReadTemporaryBasal: {
|
case ReadTemporaryBasal: {
|
||||||
return new TempBasalPair(rawContent);
|
return new TempBasalPair(rawContent); // 5
|
||||||
}
|
}
|
||||||
|
|
||||||
case Settings_512: {
|
case Settings_512: {
|
||||||
|
@ -75,7 +81,7 @@ public class MedtronicConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
case SetBolus: {
|
case SetBolus: {
|
||||||
return rawContent;
|
return rawContent; // 1
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
|
@ -88,13 +94,21 @@ public class MedtronicConverter {
|
||||||
|
|
||||||
|
|
||||||
private MedtronicDeviceType decodeModel(byte[] rawContent) {
|
private MedtronicDeviceType decodeModel(byte[] rawContent) {
|
||||||
|
|
||||||
|
if ((rawContent == null || rawContent.length < 4)) {
|
||||||
|
LOG.warn("Error reading PumpModel, returning Unknown_Device");
|
||||||
|
return MedtronicDeviceType.Unknown_Device;
|
||||||
|
}
|
||||||
|
|
||||||
String rawModel = StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3));
|
String rawModel = StringUtil.fromBytes(ByteUtil.substring(rawContent, 1, 3));
|
||||||
MedtronicDeviceType pumpModel = MedtronicDeviceType.getByDescription(rawModel);
|
MedtronicDeviceType pumpModel = MedtronicDeviceType.getByDescription(rawModel);
|
||||||
LOG.debug("PumpModel: [raw={}, resolved={}]", rawModel, pumpModel.name());
|
LOG.debug("PumpModel: [raw={}, resolved={}]", rawModel, pumpModel.name());
|
||||||
|
|
||||||
if (pumpModel != MedtronicDeviceType.Unknown_Device) {
|
if (pumpModel != MedtronicDeviceType.Unknown_Device) {
|
||||||
|
if (!MedtronicUtil.isModelSet()) {
|
||||||
MedtronicUtil.setMedtronicPumpModel(pumpModel);
|
MedtronicUtil.setMedtronicPumpModel(pumpModel);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return pumpModel;
|
return pumpModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.slf4j.LoggerFactory;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* History page contains data, sorted from oldest to newest
|
* History page contains data, sorted from newest to oldest (0=newest..n=oldest)
|
||||||
*/
|
*/
|
||||||
public class PumpHistoryResult {
|
public class PumpHistoryResult {
|
||||||
|
|
||||||
|
@ -107,6 +107,19 @@ public class PumpHistoryResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return latest entry (entry with highest date time)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public PumpHistoryEntry getLatestEntry() {
|
||||||
|
if (this.validEntries == null || this.validEntries.size() == 0)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return this.validEntries.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isSearchRequired() {
|
public boolean isSearchRequired() {
|
||||||
return searchType != SearchType.None;
|
return searchType != SearchType.None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,22 +122,6 @@ public class MedtronicUITask {
|
||||||
BasalProfile profile = (BasalProfile)parameters[0];
|
BasalProfile profile = (BasalProfile)parameters[0];
|
||||||
|
|
||||||
returnData = communicationManager.setBasalProfile(profile);
|
returnData = communicationManager.setBasalProfile(profile);
|
||||||
// Float amount = getAmount();
|
|
||||||
//
|
|
||||||
// if (amount != null) {
|
|
||||||
//
|
|
||||||
// BasalProfile profile = new BasalProfile();
|
|
||||||
//
|
|
||||||
// int basalStrokes1 = MedtronicUtil.getBasalStrokesInt(amount);
|
|
||||||
// int basalStrokes2 = MedtronicUtil.getBasalStrokesInt(amount * 2);
|
|
||||||
//
|
|
||||||
// for (int i = 0; i < 24; i++) {
|
|
||||||
// profile.addEntry(new BasalProfileEntry(i % 2 == 0 ? basalStrokes1 : basalStrokes2, i * 2));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// returnData = communicationManager.setBasalProfile(profile);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -231,6 +215,7 @@ public class MedtronicUITask {
|
||||||
return (responseType == MedtronicUIResponseType.Data);
|
return (responseType == MedtronicUIResponseType.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Object getParameter(int index) {
|
public Object getParameter(int index) {
|
||||||
return parameters[index];
|
return parameters[index];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package info.nightscout.androidaps.plugins.PumpMedtronic.data;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.joda.time.LocalDateTime;
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +17,7 @@ public class MedtronicHistoryData {
|
||||||
private boolean suspended = false;
|
private boolean suspended = false;
|
||||||
private boolean relevantConfigurationChanged = false;
|
private boolean relevantConfigurationChanged = false;
|
||||||
private boolean basalProfileChanged = true;
|
private boolean basalProfileChanged = true;
|
||||||
|
private LocalDateTime lastHistoryRecordTime;
|
||||||
|
|
||||||
|
|
||||||
public MedtronicHistoryData() {
|
public MedtronicHistoryData() {
|
||||||
|
@ -49,4 +52,15 @@ public class MedtronicHistoryData {
|
||||||
basalProfileChanged = true; // FIXME when this works this should reset to false
|
basalProfileChanged = true; // FIXME when this works this should reset to false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setLastHistoryRecordTime(LocalDateTime lastHistoryRecordTime) {
|
||||||
|
|
||||||
|
this.lastHistoryRecordTime = lastHistoryRecordTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LocalDateTime getLastHistoryRecordTime() {
|
||||||
|
|
||||||
|
return lastHistoryRecordTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@ import org.joda.time.Instant;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
|
||||||
|
import info.nightscout.androidaps.plugins.PumpCommon.utils.FabricUtil;
|
||||||
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
|
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,6 +112,22 @@ public class BasalProfile {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String basalProfileToString() {
|
||||||
|
StringBuffer sb = new StringBuffer("Basal Profile [");
|
||||||
|
List<BasalProfileEntry> entries = getEntries();
|
||||||
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
|
BasalProfileEntry entry = entries.get(i);
|
||||||
|
String startString = entry.startTime.toString("HH:mm");
|
||||||
|
|
||||||
|
sb.append(String.format("%s=%.3f, ", startString, entry.rate));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("]");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: this function must be expanded to include changes in which profile is in use.
|
// TODO: this function must be expanded to include changes in which profile is in use.
|
||||||
// and changes to the profiles themselves.
|
// and changes to the profiles themselves.
|
||||||
public BasalProfileEntry getEntryForTime(Instant when) {
|
public BasalProfileEntry getEntryForTime(Instant when) {
|
||||||
|
@ -217,14 +236,27 @@ public class BasalProfile {
|
||||||
|
|
||||||
public Double[] getProfilesByHour() {
|
public Double[] getProfilesByHour() {
|
||||||
|
|
||||||
List<BasalProfileEntry> entries = getEntries();
|
List<BasalProfileEntry> entries = null;
|
||||||
|
|
||||||
if (entries.size() == 0) {
|
try {
|
||||||
|
entries = getEntries();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LOG.error("=============================================================================");
|
||||||
|
LOG.error(" Error generating entries. Ex.: " + ex, ex);
|
||||||
|
LOG.error(" rawBasalValues: " + ByteUtil.getHex(this.getRawData()));
|
||||||
|
LOG.error("=============================================================================");
|
||||||
|
|
||||||
|
FabricUtil.createEvent("MedtronicBasalProfileGetByHourError", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries == null || entries.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Double[] basalByHour = new Double[24];
|
Double[] basalByHour = new Double[24];
|
||||||
|
|
||||||
|
PumpType pumpType = MedtronicUtil.getPumpStatus().pumpType;
|
||||||
|
|
||||||
for (int i = 0; i < entries.size(); i++) {
|
for (int i = 0; i < entries.size(); i++) {
|
||||||
BasalProfileEntry current = entries.get(i);
|
BasalProfileEntry current = entries.get(i);
|
||||||
|
|
||||||
|
@ -247,7 +279,10 @@ public class BasalProfile {
|
||||||
// System.out.println("Current time: " + currentTime + " Next Time: " + lastHour);
|
// System.out.println("Current time: " + currentTime + " Next Time: " + lastHour);
|
||||||
|
|
||||||
for (int j = currentTime; j < lastHour; j++) {
|
for (int j = currentTime; j < lastHour; j++) {
|
||||||
|
if (pumpType == null)
|
||||||
basalByHour[j] = current.rate;
|
basalByHour[j] = current.rate;
|
||||||
|
else
|
||||||
|
basalByHour[j] = pumpType.determineCorrectBasalSize(current.rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +305,6 @@ public class BasalProfile {
|
||||||
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getBasalProfileAsString();
|
return basalProfileToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,8 +156,14 @@ public class RileyLinkMedtronicService extends RileyLinkService {
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Using pump ID " + pumpID);
|
LOG.info("Using pump ID " + pumpID);
|
||||||
|
|
||||||
|
String oldId = rileyLinkServiceData.pumpID;
|
||||||
|
|
||||||
rileyLinkServiceData.setPumpID(pumpID, pumpIDBytes);
|
rileyLinkServiceData.setPumpID(pumpID, pumpIDBytes);
|
||||||
|
|
||||||
|
if (oldId != null && !oldId.equals(pumpID)) {
|
||||||
|
MedtronicUtil.setMedtronicPumpModel(null); // if we change pumpId, model probably changed too
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -422,9 +422,9 @@ public class MedtronicUtil extends RileyLinkUtil {
|
||||||
|
|
||||||
|
|
||||||
public static void setMedtronicPumpModel(MedtronicDeviceType medtronicPumpModel) {
|
public static void setMedtronicPumpModel(MedtronicDeviceType medtronicPumpModel) {
|
||||||
if (medtronicPumpModel != null && medtronicPumpModel != MedtronicDeviceType.Unknown_Device) {
|
// if (medtronicPumpModel != null && medtronicPumpModel != MedtronicDeviceType.Unknown_Device) {
|
||||||
MedtronicUtil.medtronicPumpModel = medtronicPumpModel;
|
MedtronicUtil.medtronicPumpModel = medtronicPumpModel;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package info.nightscout.utils;
|
package info.nightscout.utils;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import com.crashlytics.android.Crashlytics;
|
import com.crashlytics.android.Crashlytics;
|
||||||
import com.crashlytics.android.answers.Answers;
|
import com.crashlytics.android.answers.Answers;
|
||||||
import com.crashlytics.android.answers.CustomEvent;
|
import com.crashlytics.android.answers.CustomEvent;
|
||||||
|
@ -10,14 +12,12 @@ import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by jamorham on 21/02/2018.
|
* Created by jamorham on 21/02/2018.
|
||||||
* <p>
|
* <p>
|
||||||
* Some users do not wish to be tracked, Fabric Answers and Crashlytics do not provide an easy way
|
* Some users do not wish to be tracked, Fabric Answers and Crashlytics do not provide an easy way to disable them and
|
||||||
* to disable them and make calls from a potentially invalid singleton reference. This wrapper
|
* make calls from a potentially invalid singleton reference. This wrapper emulates the methods but ignores the request
|
||||||
* emulates the methods but ignores the request if the instance is null or invalid.
|
* if the instance is null or invalid.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class FabricPrivacy {
|
public class FabricPrivacy {
|
||||||
|
@ -33,12 +33,14 @@ public class FabricPrivacy {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static synchronized void initSelf() {
|
private static synchronized void initSelf() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new FabricPrivacy();
|
instance = new FabricPrivacy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Crashlytics logException
|
// Crashlytics logException
|
||||||
public static void logException(Throwable throwable) {
|
public static void logException(Throwable throwable) {
|
||||||
try {
|
try {
|
||||||
|
@ -49,6 +51,7 @@ public class FabricPrivacy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Crashlytics log
|
// Crashlytics log
|
||||||
public static void log(String msg) {
|
public static void log(String msg) {
|
||||||
try {
|
try {
|
||||||
|
@ -59,6 +62,7 @@ public class FabricPrivacy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Crashlytics log
|
// Crashlytics log
|
||||||
public static void log(int priority, String tag, String msg) {
|
public static void log(int priority, String tag, String msg) {
|
||||||
try {
|
try {
|
||||||
|
@ -69,10 +73,15 @@ public class FabricPrivacy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean fabricEnabled() {
|
public static boolean fabricEnabled() {
|
||||||
|
if (MainApp.isEngineeringMode())
|
||||||
|
return true;
|
||||||
|
|
||||||
return SP.getBoolean("enable_fabric", true);
|
return SP.getBoolean("enable_fabric", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Answers logCustom
|
// Answers logCustom
|
||||||
public void logCustom(CustomEvent event) {
|
public void logCustom(CustomEvent event) {
|
||||||
try {
|
try {
|
||||||
|
@ -87,8 +96,10 @@ public class FabricPrivacy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void uploadDailyStats() {
|
public static void uploadDailyStats() {
|
||||||
if (!fabricEnabled()) return;
|
if (!fabricEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
long lastUploadDay = SP.getLong(MainApp.gs(R.string.key_plugin_stats_report_timestamp), 0L);
|
long lastUploadDay = SP.getLong(MainApp.gs(R.string.key_plugin_stats_report_timestamp), 0L);
|
||||||
|
|
||||||
|
@ -106,6 +117,7 @@ public class FabricPrivacy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void uploadPluginStats() {
|
private static void uploadPluginStats() {
|
||||||
CustomEvent pluginStats = new CustomEvent("PluginStats");
|
CustomEvent pluginStats = new CustomEvent("PluginStats");
|
||||||
pluginStats.putCustomAttribute("version", BuildConfig.VERSION);
|
pluginStats.putCustomAttribute("version", BuildConfig.VERSION);
|
||||||
|
@ -123,6 +135,7 @@ public class FabricPrivacy {
|
||||||
getInstance().logCustom(pluginStats);
|
getInstance().logCustom(pluginStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void uploadAppUsageType() {
|
private static void uploadAppUsageType() {
|
||||||
CustomEvent type = new CustomEvent("AppUsageType");
|
CustomEvent type = new CustomEvent("AppUsageType");
|
||||||
if (Config.NSCLIENT)
|
if (Config.NSCLIENT)
|
||||||
|
|
|
@ -3,7 +3,7 @@ RileyLinkAAPS
|
||||||
|
|
||||||
|
|
||||||
Medtronic
|
Medtronic
|
||||||
- set basal profile (try to get to work - see new Loop code)
|
+ set basal profile (try to get to work - see new Loop code)
|
||||||
- read history
|
- read history
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue