- refactored BasalProfile functionality
- extended SetProfile command
- fixed processing of settings for 554
This commit is contained in:
Andy Rozman 2019-01-31 23:09:39 +00:00
parent 9c08bfb8bf
commit 78abf7299a
13 changed files with 243 additions and 24 deletions

View file

@ -64,7 +64,7 @@ android {
multiDexEnabled true
versionCode 1500
// dev_version: 2.0
version "medtronic-0.6"
version "medtronic-0.7.0-SNAPSHOT"
buildConfigField "String", "VERSION", '"' + version + '"'
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
buildConfigField "String", "HEAD", '"' + generateGitBuild() + '"'

View file

@ -380,11 +380,21 @@ public class ByteUtil {
}
// 000300050100C800A0
public static byte[] createByteArrayFromCompactString(String dataFull) {
return createByteArrayFromCompactString(dataFull, 0, dataFull.length());
}
// 00 03 00 05 01 00 C8 00 A0
public static byte[] createByteArrayFromString(String dataFull) {
String data = dataFull.replace(" ", "");
return createByteArrayFromCompactString(data, 0, data.length());
}
public static byte[] createByteArrayFromCompactString(String dataFull, int startIndex) {
return createByteArrayFromCompactString(dataFull, startIndex, dataFull.length());
}

View file

@ -8,7 +8,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -58,6 +57,7 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.data.MedtronicHistoryDat
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfileEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BasalProfileStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCustomActionType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicNotificationType;
@ -215,11 +215,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
do {
SystemClock.sleep(60000);
Map<MedtronicStatusRefreshType, Long> statusRefresh = workWithStatusRefresh(
StatusRefreshAction.GetData, null, null);
if (this.isInitialized) {
if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Scheduled Status Refresh", null);
Map<MedtronicStatusRefreshType, Long> statusRefresh = workWithStatusRefresh(
StatusRefreshAction.GetData, null, null);
if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Scheduled Status Refresh", null);
}
}
} while (serviceRunning);
@ -508,6 +511,12 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public boolean isThisProfileSet(Profile profile) {
return isThisProfileSet_New(profile);
}
@Deprecated
public boolean isThisProfileSet_Old(Profile profile) {
if (!this.isInitialized) {
return true;
@ -573,13 +582,26 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
public boolean isThisProfileSet_New(Profile profile) {
LOG.debug("isThisProfileSet: basalInitalized={}", getMDTPumpStatus().basalProfileStatus);
if (getMDTPumpStatus().basalProfileStatus != BasalProfileStatus.ProfileOK)
return true;
return isProfileSame(profile);
}
private boolean isProfileSame(Profile profile) {
boolean invalid = false;
Double[] basalsByHour = getMDTPumpStatus().basalsByHour;
if (isLoggingEnabled())
LOG.debug("Current Basals (h): " + (basalsByHour == null ? "null" : StringUtils.join(basalsByHour, " ")));
LOG.debug("Current Basals (h): "
+ (basalsByHour == null ? "null" : BasalProfile.getProfilesByHourToString(basalsByHour)));
int index = 0;
@ -596,7 +618,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
invalid = true;
}
stringBuilder.append(basalValue.value);
stringBuilder.append(String.format("%.3f", basalValue.value));
stringBuilder.append(" ");
}
@ -948,8 +970,10 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1);
}
if (medtronicHistoryData.hasBasalProfileChanged()) {
this.basalProfileChanged = true;
if (this.getMDTPumpStatus().basalProfileStatus != BasalProfileStatus.NotInitialized
&& medtronicHistoryData.hasBasalProfileChanged()) {
medtronicHistoryData.processLastBasalProfileChange(getMDTPumpStatus());
// this.basalProfileChanged = true;
}
PumpDriverState previousState = this.pumpState;

View file

@ -398,9 +398,14 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
rval = sendAndListen(msg);
// LOG.debug("PumpResponse: " + rval);
if (rval.commandType != MedtronicCommandType.CommandACK) {
LOG.error("runCommandWithFrames: Pump did not ACK frame #{}", frameNr);
LOG.error("Run command with Frames FAILED (command={}, response={})", commandType.name(),
rval.toString());
return new PumpMessage("No ACK after frame #" + frameNr);
} else {
LOG.debug("Run command with Frames: Got ACK response for frame #{}", (frameNr));
@ -909,8 +914,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent()));
LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData()));
String check = checkResponseContent(response, commandType.commandDescription,
commandType.getRecordLength());
String check = checkResponseContent(response, commandType.commandDescription, 1);
byte[] data = null;
@ -932,8 +936,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.debug("{} Response: {}", runs,
HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData()));
String check2 = checkResponseContent(response2, commandType.commandDescription,
commandType.getRecordLength());
String check2 = checkResponseContent(response2, commandType.commandDescription, 1);
if (check2 == null) {

View file

@ -256,8 +256,16 @@ public class MedtronicConverter {
rd[getSettingIndexMaxBasal() + 1])), PumpConfigurationGroup.Basal, map);
addSettingToMap("CFG_BASE_CLOCK_MODE", rd[getSettingIndexTimeDisplayFormat()] == 0 ? "12h" : "24h",
PumpConfigurationGroup.General, map);
addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] != 0 ? 50 : 100), PumpConfigurationGroup.Insulin, map);
LOG.debug("Insulin concentration: " + rd[9]);
if (MedtronicDeviceType.isSameDevice(pumpModel, MedtronicDeviceType.Medtronic_523andHigher)) {
addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] == 0 ? 50 : 100), PumpConfigurationGroup.Insulin,
map);
LOG.debug("Insulin concentration: " + rd[9]);
} else {
addSettingToMap("PCFG_INSULIN_CONCENTRATION", "" + (rd[9] != 0 ? 50 : 100), PumpConfigurationGroup.Insulin,
map);
LOG.debug("Insulin concentration: " + rd[9]);
}
addSettingToMap("PCFG_BASAL_PROFILES_ENABLED", parseResultEnable(rd[10]), PumpConfigurationGroup.Basal, map);
if (rd[10] == 1) {
@ -343,7 +351,7 @@ public class MedtronicConverter {
public float getStrokesPerUnit(boolean isBasal) {
return isBasal ? 40.0f : pumpModel.getBolusStrokes();
return isBasal ? 40.0f : 10; // pumpModel.getBolusStrokes();
}

View file

@ -101,7 +101,7 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte
}
public String getDecodedData() {
public String getDecodedDataAsString() {
if (decodedData == null)
if (isNoDataEntry())
return "No data";
@ -122,6 +122,11 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte
}
public Map<String, Object> getDecodedData() {
return this.decodedData;
}
public boolean showRaw() {
return getEntryTypeName().equals("EndResultTotals");
}
@ -165,7 +170,7 @@ public abstract class MedtronicHistoryEntry implements MedtronicHistoryEntryInte
boolean hasData = hasData();
if (hasData) {
sb.append(", data=" + getDecodedData());
sb.append(", data=" + getDecodedDataAsString());
}
if (hasData && !showRaw()) {

View file

@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BatteryStatusDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BasalProfileStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicNotificationType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicUIResponseType;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
@ -62,6 +63,7 @@ public class MedtronicUIPostprocessor {
if (profilesByHour != null) {
pumpStatus.basalsByHour = profilesByHour;
pumpStatus.basalProfileStatus = BasalProfileStatus.ProfileOK;
} else {
uiTask.responseType = MedtronicUIResponseType.Error;
uiTask.errorDescription = "No profile found.";

View file

@ -18,6 +18,8 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.Medtro
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntry;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryEntryType;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.PumpHistoryResult;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.BasalProfile;
import info.nightscout.androidaps.plugins.PumpMedtronic.driver.MedtronicPumpStatus;
//import info.nightscout.androidaps.plugins.PumpMedtronic.MedtronicPumpPlugin;
@ -304,8 +306,8 @@ public class MedtronicHistoryData {
* entryType == PumpHistoryEntryType.DailyTotals523 || //
* entryType == PumpHistoryEntryType.EndResultTotals
*/
public boolean hasBasalProfileChanged() {
@Deprecated
public boolean hasBasalProfileChanged_Old() {
List<PumpHistoryEntry> filteredItems = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile);
@ -322,6 +324,58 @@ public class MedtronicHistoryData {
}
public boolean hasBasalProfileChanged() {
List<PumpHistoryEntry> filteredItems = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile);
LOG.debug("hasBasalProfileChanged. Items: " + filteredItems);
return (filteredItems.size() > 0);
}
public void processLastBasalProfileChange(MedtronicPumpStatus mdtPumpStatus) {
// FIXME
List<PumpHistoryEntry> filteredItems = getFilteredItems(PumpHistoryEntryType.ChangeBasalProfile_NewProfile);
LOG.debug("processLastBasalProfileChange. Items: " + filteredItems);
PumpHistoryEntry newProfile = null;
Long lastDate = null;
if (filteredItems.size() == 1) {
newProfile = filteredItems.get(0);
} else if (filteredItems.size() > 1) {
for (PumpHistoryEntry filteredItem : filteredItems) {
if (lastDate == null || lastDate < filteredItem.atechDateTime) {
newProfile = filteredItem;
lastDate = newProfile.atechDateTime;
}
}
}
if (newProfile != null) {
LOG.debug("processLastBasalProfileChange. item found, setting new basalProfileLocally: " + newProfile);
BasalProfile basalProfile = (BasalProfile)newProfile.getDecodedData().get("Object");
mdtPumpStatus.basalsByHour = basalProfile.getProfilesByHour();
}
// boolean profileChanged = ((filteredItems.size() - basalProfileChangedInternally) > 0);
// LOG.error("Profile changed:" + profileChanged);
// this.basalProfileChangedInternally = 0;
// return profileChanged;
}
public boolean hasPumpTimeChanged() {
return getStateFromFilteredList(PumpHistoryEntryType.NewTimeSet, //

View file

@ -253,7 +253,13 @@ public class BasalProfile {
}
if (entries == null || entries.size() == 0) {
return null;
Double[] basalByHour = new Double[24];
for (int i = 0; i < 24; i++) {
basalByHour[i] = 0.0d;
}
return basalByHour;
}
Double[] basalByHour = new Double[24];
@ -293,6 +299,20 @@ public class BasalProfile {
}
public static String getProfilesByHourToString(Double[] data) {
StringBuilder stringBuilder = new StringBuilder();
for (Double value : data) {
stringBuilder.append(String.format("%.3f", value));
stringBuilder.append(" ");
}
return stringBuilder.toString();
}
public byte[] getRawData() {
return this.mRawData;
}

View file

@ -0,0 +1,14 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.defs;
/**
* Created by andy on 1/20/19.
*/
public enum BasalProfileStatus {
NotInitialized, //
ProfileOK, //
ProfileChanged, //
;
}

View file

@ -20,6 +20,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
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.RileyLinkServiceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.BasalProfileStatus;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
@ -67,6 +68,8 @@ public class MedtronicPumpStatus extends PumpStatus {
private Map<String, MedtronicDeviceType> medtronicDeviceTypeMap = null;
private RileyLinkTargetFrequency targetFrequency;
private boolean targetFrequencyChanged = false;
// public boolean isBasalInitalized = false;
public BasalProfileStatus basalProfileStatus;
public MedtronicPumpStatus(PumpDescription pumpDescription) {
@ -227,8 +230,12 @@ public class MedtronicPumpStatus extends PumpStatus {
maxBolus = checkParameterValue(MedtronicConst.Prefs.MaxBolus, "25.0", 25.0d);
LOG.debug("Max Bolus from AAPS settings is " + maxBolus);
maxBasal = checkParameterValue(MedtronicConst.Prefs.MaxBasal, "35.0", 35.0d);
LOG.debug("Max Basal from AAPS settings is " + maxBasal);
startService();
} catch (Exception ex) {

View file

@ -0,0 +1,39 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.comm;
import java.util.Map;
import org.junit.Test;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.PumpSettingDTO;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
/**
* Created by andy on 1/30/19.
*/
public class MedtronicConverterUTest {
MedtronicConverter converter = new MedtronicConverter();
// 00 03 00 05 01 00 C8 00 A0 01 01 00 01 00 00 64 01 05 00 14 00 64 01 00 00
@Test
public void testDecoding554() {
byte[] data = ByteUtil
.createByteArrayFromString("00 03 00 05 01 00 C8 00 A0 01 01 00 01 00 00 64 01 05 00 14 00 64 01 00 00");
MedtronicUtil.setMedtronicPumpModel(MedtronicDeviceType.Medtronic_554_Veo);
Map<String, PumpSettingDTO> settings = (Map<String, PumpSettingDTO>)converter.convertResponse(
MedtronicCommandType.Settings, data);
for (PumpSettingDTO pumpSettingDTO : settings.values()) {
System.out.println("" + pumpSettingDTO.key + " = " + pumpSettingDTO.value);
}
// byte[] data = new byte[] { 00 03 00 05 01 00 C8 00 A0 01 01 00 01 00 00 64 01 05 00 14 00 64 01 00 00 };
}
}

View file

@ -4,7 +4,6 @@ import static org.powermock.api.mockito.PowerMockito.when;
import junit.framework.Assert;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -89,6 +88,8 @@ public class BasalProfileUTest {
Assert.assertTrue(MedtronicUtil.isSame(0.5d, profilesByHour[22]));
Assert.assertTrue(MedtronicUtil.isSame(0.5d, profilesByHour[23]));
System.out.println("Basals by hour: "
+ (profilesByHour == null ? "null" : BasalProfile.getProfilesByHourToString(profilesByHour)));
}
@ -106,7 +107,39 @@ public class BasalProfileUTest {
Double[] profilesByHour = basalProfile.getProfilesByHour();
System.out.println("Basals by hour: "
+ (profilesByHour == null ? "null" : StringUtils.join(profilesByHour, " ")));
+ (profilesByHour == null ? "null" : BasalProfile.getProfilesByHourToString(profilesByHour)));
}
@Test
public void testProfileByDayZero() {
BasalProfile basalProfile = new BasalProfile();
byte[] data = { //
0x00 };
basalProfile.setRawData(data);
Double[] profilesByHour = basalProfile.getProfilesByHour();
System.out.println("Basals by hour: "
+ (profilesByHour == null ? "null" : BasalProfile.getProfilesByHourToString(profilesByHour)));
}
@Test
public void testProfileByDayZeroZero3F() {
BasalProfile basalProfile = new BasalProfile();
byte[] data = { //
0x00, 0x00, 0x3f };
basalProfile.setRawData(data);
Double[] profilesByHour = basalProfile.getProfilesByHour();
System.out.println("Basals by hour: "
+ (profilesByHour == null ? "null" : BasalProfile.getProfilesByHourToString(profilesByHour)));
}