Medtronic 0.5

- added DailyTotalsDTO and started with work on parsing (522 done)
- split encoding into 3 classes, and added exception when encoding fails
- added code for retries, when in communication with pump
- added analysis of history data for several occassions (profile changed, configuration changed, etc)
- little refactoring all arround
This commit is contained in:
Andy Rozman 2018-12-09 14:44:48 +00:00
parent 3fdbc0400e
commit adc80d5cc7
38 changed files with 2315 additions and 646 deletions

View file

@ -7,18 +7,20 @@
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover. Make sure the path matches the one in the file element or else
the rollover logs are placed in the working directory. -->
<fileNamePattern>${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm-ss, aux}_.%i.zip
<fileNamePattern>${EXT_FILES_DIR}/AndroidAPS._%d{yyyy-MM-dd}_%d{HH-mm}_.%i.zip
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>5MB</maxFileSize>
<maxFileSize>500KB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- keep 30 days' worth of history -->
<maxHistory>120</maxHistory>
<maxHistory>240</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %.-1level/%logger: [%class{0}.%M\(\):%line]: %msg%n</pattern>
<pattern>%d{HH:mm:ss.SSS} [%thread] %.-1level/%logger: [%class{0}.%M\(\):%line]:
%msg%n
</pattern>
</encoder>
</appender>

View file

@ -27,6 +27,7 @@ import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpDriverState;
@ -141,40 +142,40 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
public boolean isConnected() {
if (displayConnectionMessages)
if (displayConnectionMessages && isLoggingEnabled())
LOG.warn("isConnected [PumpPluginAbstract].");
return PumpDriverState.isConnected(pumpState);
}
public boolean isConnecting() {
if (displayConnectionMessages)
if (displayConnectionMessages && isLoggingEnabled())
LOG.warn("isConnecting [PumpPluginAbstract].");
return pumpState == PumpDriverState.Connecting;
}
public void connect(String reason) {
if (displayConnectionMessages)
if (displayConnectionMessages && isLoggingEnabled())
LOG.warn("connect (reason={}) [PumpPluginAbstract] - default (empty) implementation.", reason);
}
public void disconnect(String reason) {
if (displayConnectionMessages)
if (displayConnectionMessages && isLoggingEnabled())
LOG.warn("disconnect (reason={}) [PumpPluginAbstract] - default (empty) implementation.", reason);
}
public void stopConnecting() {
if (displayConnectionMessages)
if (displayConnectionMessages && isLoggingEnabled())
LOG.warn("stopConnecting [PumpPluginAbstract] - default (empty) implementation.");
}
@Override
public boolean isHandshakeInProgress() {
if (displayConnectionMessages)
if (displayConnectionMessages && isLoggingEnabled())
LOG.warn("isHandshakeInProgress [PumpPluginAbstract] - default (empty) implementation.");
return false;
}
@ -182,50 +183,57 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
@Override
public void finishHandshaking() {
if (displayConnectionMessages)
if (displayConnectionMessages && isLoggingEnabled())
LOG.warn("finishHandshaking [PumpPluginAbstract] - default (empty) implementation.");
}
public void getPumpStatus() {
LOG.warn("getPumpStatus [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("getPumpStatus [PumpPluginAbstract] - Not implemented.");
}
// Upload to pump new basal profile
public PumpEnactResult setNewBasalProfile(Profile profile) {
LOG.warn("setNewBasalProfile [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("setNewBasalProfile [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
public boolean isThisProfileSet(Profile profile) {
LOG.warn("isThisProfileSet [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("isThisProfileSet [PumpPluginAbstract] - Not implemented.");
return true;
}
public long lastDataTime() {
LOG.warn("lastDataTime [PumpPluginAbstract].");
if (isLoggingEnabled())
LOG.warn("lastDataTime [PumpPluginAbstract].");
return pumpStatus.lastConnection;
}
public double getBaseBasalRate() {
LOG.warn("getBaseBasalRate [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("getBaseBasalRate [PumpPluginAbstract] - Not implemented.");
return 0.0d;
} // base basal rate, not temp basal
public void stopBolusDelivering() {
LOG.warn("stopBolusDelivering [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("stopBolusDelivering [PumpPluginAbstract] - Not implemented.");
}
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
LOG.warn("setTempBasalAbsolute [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("setTempBasalAbsolute [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@ -233,13 +241,15 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
LOG.warn("setTempBasalPercent [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("setTempBasalPercent [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
LOG.warn("setExtendedBolus [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("setExtendedBolus [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@ -248,13 +258,15 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
// when the cancel request is requested by the user (forced), the pump should always do a real cancel
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
LOG.warn("cancelTempBasal [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("cancelTempBasal [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
public PumpEnactResult cancelExtendedBolus() {
LOG.warn("cancelExtendedBolus [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("cancelExtendedBolus [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@ -266,7 +278,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
// }
public String deviceID() {
LOG.warn("deviceID [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("deviceID [PumpPluginAbstract] - Not implemented.");
return "FakeDevice";
}
@ -281,14 +294,16 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
// Short info for SMS, Wear etc
public boolean isFakingTempsByExtendedBoluses() {
LOG.warn("isFakingTempsByExtendedBoluses [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("isFakingTempsByExtendedBoluses [PumpPluginAbstract] - Not implemented.");
return false;
}
@Override
public PumpEnactResult loadTDDs() {
LOG.warn("loadTDDs [PumpPluginAbstract] - Not implemented.");
if (isLoggingEnabled())
LOG.warn("loadTDDs [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
}
@ -383,7 +398,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
try {
if (detailedBolusInfo.insulin == 0 && detailedBolusInfo.carbs == 0) {
// neither carbs nor bolus requested
LOG.error("deliverTreatment: Invalid input");
if (isLoggingEnabled())
LOG.error("deliverTreatment: Invalid input");
return new PumpEnactResult().success(false).enacted(false).bolusDelivered(0d).carbsDelivered(0d)
.comment(MainApp.gs(R.string.danar_invalidinput));
} else if (detailedBolusInfo.insulin > 0) {
@ -399,7 +415,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
bolusingEvent.percent = 100;
MainApp.bus().post(bolusingEvent);
LOG.debug("deliverTreatment: Carb only treatment.");
if (isLoggingEnabled())
LOG.debug("deliverTreatment: Carb only treatment.");
return new PumpEnactResult().success(true).enacted(true).bolusDelivered(0d)
.carbsDelivered(detailedBolusInfo.carbs).comment(MainApp.gs(R.string.virtualpump_resultok));
@ -411,6 +428,11 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
}
public boolean isLoggingEnabled() {
return L.isEnabled(L.PUMP);
}
protected abstract PumpEnactResult deliverBolus(DetailedBolusInfo detailedBolusInfo);

View file

@ -7,6 +7,7 @@ import android.content.Context;
import info.nightscout.androidaps.plugins.PumpCommon.data.PumpStatus;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFSpy;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.FrequencyScanResults;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.FrequencyTrial;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RFSpyResponse;
@ -14,7 +15,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMes
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioPacket;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioResponse;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RLMessageType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkBLEError;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.RileyLinkServiceData;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.ServiceTaskExecutor;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask;
@ -42,9 +43,9 @@ public abstract class RileyLinkCommunicationManager {
protected long lastGoodReceiverCommunicationTime = 0;
protected PumpStatus pumpStatus;
protected RileyLinkServiceData rileyLinkServiceData;
protected RileyLinkTargetFrequency targetFrequency;
// protected RileyLinkTargetFrequency targetFrequency;
private long nextWakeUpRequired = 0L;
private double[] scanFrequencies;
// private double[] scanFrequencies;
// internal flag
private boolean showPumpMessages = true;
@ -54,8 +55,8 @@ public abstract class RileyLinkCommunicationManager {
public RileyLinkCommunicationManager(Context context, RFSpy rfspy) {
this.context = context;
this.rfspy = rfspy;
this.targetFrequency = RileyLinkUtil.getRileyLinkTargetFrequency();
this.scanFrequencies = targetFrequency.getScanFrequencies();
// this.targetFrequency = RileyLinkUtil.getRileyLinkTargetFrequency();
// this.scanFrequencies = targetFrequency.getScanFrequencies();
this.rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData();
RileyLinkUtil.setRileyLinkCommunicationManager(this);
@ -66,17 +67,17 @@ public abstract class RileyLinkCommunicationManager {
protected abstract void configurePumpSpecificSettings();
public void refreshRileyLinkTargetFrequency() {
if (this.targetFrequency != RileyLinkUtil.getRileyLinkTargetFrequency()) {
this.targetFrequency = RileyLinkUtil.getRileyLinkTargetFrequency();
this.scanFrequencies = targetFrequency.getScanFrequencies();
}
}
// public void refreshRileyLinkTargetFrequency() {
// if (this.targetFrequency != RileyLinkUtil.getRileyLinkTargetFrequency()) {
// this.targetFrequency = RileyLinkUtil.getRileyLinkTargetFrequency();
// this.scanFrequencies = targetFrequency.getScanFrequencies();
// }
//
// }
// All pump communications go through this function.
protected <E extends RLMessage> E sendAndListen(RLMessage msg, int timeout_ms, Class<E> clazz) {
protected <E extends RLMessage> E sendAndListen(RLMessage msg, int timeout_ms, Class<E> clazz)
throws RileyLinkCommunicationException {
if (showPumpMessages) {
LOG.info("Sent:" + ByteUtil.shortHexString(msg.getTxData()));
@ -84,6 +85,8 @@ public abstract class RileyLinkCommunicationManager {
RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(msg.getTxData()), timeout_ms);
RadioResponse radioResponse = rfSpyResponse.getRadioResponse();
E response = createResponseMessage(rfSpyResponse.getRadioResponse().getPayload(), clazz);
if (response.isValid()) {
@ -103,6 +106,10 @@ public abstract class RileyLinkCommunicationManager {
ServiceTaskExecutor.startTask(new WakeAndTuneTask());
timeoutCount = 0;
}
throw new RileyLinkCommunicationException(RileyLinkBLEError.Timeout);
} else if (rfSpyResponse.wasInterrupted()) {
throw new RileyLinkCommunicationException(RileyLinkBLEError.Interrupted);
}
}
@ -127,18 +134,17 @@ public abstract class RileyLinkCommunicationManager {
}
public boolean changeTargetFrequency(RileyLinkTargetFrequency targetFrequency) {
if (this.targetFrequency == targetFrequency) {
return false;
}
this.targetFrequency = targetFrequency;
this.scanFrequencies = targetFrequency.getScanFrequencies();
return true;
}
// public boolean changeTargetFrequency(RileyLinkTargetFrequency targetFrequency) {
//
// if (this.targetFrequency == targetFrequency) {
// return false;
// }
//
// this.targetFrequency = targetFrequency;
// this.scanFrequencies = targetFrequency.getScanFrequencies();
//
// return true;
// }
// FIXME change wakeup
// TODO we might need to fix this. Maybe make pump awake for shorter time (battery factor for pump) - Andy
@ -188,7 +194,7 @@ public abstract class RileyLinkCommunicationManager {
public double tuneForDevice() {
return scanForDevice(scanFrequencies);
return scanForDevice(RileyLinkUtil.getRileyLinkTargetFrequency().getScanFrequencies());
}
@ -201,10 +207,13 @@ public abstract class RileyLinkCommunicationManager {
* @return
*/
public boolean isValidFrequency(double frequency) {
double[] scanFrequencies = RileyLinkUtil.getRileyLinkTargetFrequency().getScanFrequencies();
if (scanFrequencies.length == 1) {
return RileyLinkUtil.isSame(scanFrequencies[0], frequency);
} else {
return (this.scanFrequencies[0] <= frequency && this.scanFrequencies[scanFrequencies.length - 1] >= frequency);
return (scanFrequencies[0] <= frequency && scanFrequencies[scanFrequencies.length - 1] >= frequency);
}
}
@ -238,15 +247,26 @@ public abstract class RileyLinkCommunicationManager {
if (resp.wasTimeout()) {
LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]);
} else if (resp.looksLikeRadioPacket()) {
RadioResponse radioResponse = new RadioResponse(resp.getRaw());
if (radioResponse.isValid()) {
sumRSSI += radioResponse.rssi;
trial.rssiList.add(radioResponse.rssi);
trial.successes++;
} else {
LOG.warn("Failed to parse radio response: " + ByteUtil.shortHexString(resp.getRaw()));
RadioResponse radioResponse = new RadioResponse();
try {
radioResponse.init(resp.getRaw());
if (radioResponse.isValid()) {
sumRSSI += radioResponse.rssi;
trial.rssiList.add(radioResponse.rssi);
trial.successes++;
} else {
LOG.warn("Failed to parse radio response: " + ByteUtil.shortHexString(resp.getRaw()));
trial.rssiList.add(-99);
}
} catch (RileyLinkCommunicationException rle) {
LOG.warn("Failed to decode radio response: " + ByteUtil.shortHexString(resp.getRaw()));
trial.rssiList.add(-99);
}
} else {
LOG.error("scanForPump: raw response is " + ByteUtil.shortHexString(resp.getRaw()));
trial.rssiList.add(-99);
@ -302,15 +322,23 @@ public abstract class RileyLinkCommunicationManager {
if (resp.wasTimeout()) {
LOG.warn("tune_tryFrequency: no pump response at frequency {}", freqMHz);
} else if (resp.looksLikeRadioPacket()) {
RadioResponse radioResponse = new RadioResponse(resp.getRaw());
if (radioResponse.isValid()) {
LOG.warn("tune_tryFrequency: saw response level {} at frequency {}", radioResponse.rssi, freqMHz);
return radioResponse.rssi;
} else {
LOG.warn("tune_tryFrequency: invalid radio response:"
+ ByteUtil.shortHexString(radioResponse.getPayload()));
RadioResponse radioResponse = new RadioResponse();
try {
radioResponse.init(resp.getRaw());
if (radioResponse.isValid()) {
LOG.warn("tune_tryFrequency: saw response level {} at frequency {}", radioResponse.rssi, freqMHz);
return radioResponse.rssi;
} else {
LOG.warn("tune_tryFrequency: invalid radio response:"
+ ByteUtil.shortHexString(radioResponse.getPayload()));
}
} catch (RileyLinkCommunicationException e) {
LOG.warn("Failed to decode radio response: " + ByteUtil.shortHexString(resp.getRaw()));
}
}
return 0;
}

View file

@ -12,7 +12,7 @@ public class RileyLinkConst {
public static final String RileyLinkReady = Prefix + "RileyLink_Ready";
public static final String RileyLinkGattFailed = Prefix + "RileyLink_Gatt_Failed";
// public static final String RileyLinkError = Prefix + "RileyLink_Ready";
// public static final String RileyLinkBLEError = Prefix + "RileyLink_Ready";
public static final String BluetoothConnected = Prefix + "Bluetooth_Connected";
public static final String BluetoothReconnected = Prefix + "Bluetooth_Reconnected";

View file

@ -16,6 +16,8 @@ import android.support.v4.content.LocalBroadcastManager;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkBLE;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.encoding.Encoding4b6b;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.encoding.Encoding4b6bGeoff;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkEncodingType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.data.BleAdvertisedData;
@ -59,6 +61,7 @@ public class RileyLinkUtil {
private static RileyLinkTargetDevice targetDevice;
private static RileyLinkEncodingType encoding;
private static RileyLinkSelectPreference rileyLinkSelectPreference;
private static Encoding4b6b encoding4b6b;
public static void setContext(Context contextIn) {
@ -74,6 +77,10 @@ public class RileyLinkUtil {
public static void setEncoding(RileyLinkEncodingType encoding) {
RileyLinkUtil.encoding = encoding;
if (encoding == RileyLinkEncodingType.FourByteSixByte) {
RileyLinkUtil.encoding4b6b = new Encoding4b6bGeoff();
}
}
@ -316,4 +323,8 @@ public class RileyLinkUtil {
return rileyLinkSelectPreference;
}
public static Encoding4b6b getEncoding4b6b() {
return RileyLinkUtil.encoding4b6b;
}
}

View file

@ -39,7 +39,8 @@ import info.nightscout.androidaps.plugins.PumpCommon.utils.ThreadUtil;
*/
public class RileyLinkBLE {
private static final Logger LOG = LoggerFactory.getLogger(RFTools.class);
private static final Logger LOG = LoggerFactory.getLogger(RileyLinkBLE.class);
private final Context context;
public boolean gattDebugEnabled = true;
boolean manualDisconnect = false;

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkBLEError;
/**
* Created by andy on 11/23/18.
*/
public class RileyLinkCommunicationException extends Throwable {
String extendedErrorText;
private RileyLinkBLEError errorCode;
public RileyLinkCommunicationException(RileyLinkBLEError errorCode, String extendedErrorText) {
super(errorCode.getDescription());
this.errorCode = errorCode;
this.extendedErrorText = extendedErrorText;
}
public RileyLinkCommunicationException(RileyLinkBLEError errorCode) {
super(errorCode.getDescription());
this.errorCode = errorCode;
// this.extendedErrorText = extendedErrorText;
}
}

View file

@ -87,7 +87,7 @@ public class SendAndListen extends RileyLinkCommand {
bytes.add(preambleBuf[3]);
}
return ByteUtil.concat(ByteUtil.fromByteArray(bytes), packetToSend.getEncoded());
return ByteUtil.concat(ByteUtil.getByteArrayFromList(bytes), packetToSend.getEncoded());
}
}

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.command.RileyLinkCommand;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RFSpyRLResponse;
@ -47,9 +48,10 @@ public class RFSpyResponse {
}
public RadioResponse getRadioResponse() {
public RadioResponse getRadioResponse() throws RileyLinkCommunicationException {
if (looksLikeRadioPacket()) {
radioResponse = new RadioResponse(command, raw);
radioResponse = new RadioResponse(command);
radioResponse.init(raw);
} else {
radioResponse = new RadioResponse();
}

View file

@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data;
import org.apache.commons.lang3.NotImplementedException;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFTools;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.CRC;
@ -42,7 +41,7 @@ public class RadioPacket {
case FourByteSixByte: {
byte[] withCRC = getWithCRC();
byte[] encoded = RFTools.encode4b6b(withCRC);
byte[] encoded = RileyLinkUtil.getEncoding4b6b().encode4b6b(withCRC);
return ByteUtil.concat(encoded, (byte)0);
}

View file

@ -5,13 +5,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RFTools;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.command.RileyLinkCommand;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkCommandType;
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.CRC;
import info.nightscout.androidaps.plugins.PumpCommon.utils.FabricUtil;
/**
* Created by geoff on 5/30/16.
@ -33,14 +32,13 @@ public class RadioResponse {
}
public RadioResponse(byte[] rxData) {
init(rxData);
}
// public RadioResponse(byte[] rxData) {
// init(rxData);
// }
public RadioResponse(RileyLinkCommand command, byte[] raw) {
public RadioResponse(RileyLinkCommand command /* , byte[] raw */) {
this.command = command;
init(raw);
// init(raw);
}
@ -63,7 +61,7 @@ public class RadioResponse {
}
public void init(byte[] rxData) {
public void init(byte[] rxData) throws RileyLinkCommunicationException {
if (rxData == null) {
return;
@ -101,23 +99,9 @@ public class RadioResponse {
decodedPayload = encodedPayload;
break;
case FourByteSixByte:
RFTools.DecodeResponseDto decodeResponseDto = RFTools.decode4b6bWithoutException(encodedPayload);
byte[] decodeThis = decodeResponseDto.data;
byte[] decodeThis = RileyLinkUtil.getEncoding4b6b().decode4b6b(encodedPayload);
decodedOK = true;
if (decodeThis == null || decodeThis.length == 0 || decodeResponseDto.errorData != null) {
LOG.error("=============================================================================");
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;
return;
}
decodedPayload = ByteUtil.substring(decodeThis, 0, decodeThis.length - 1);
receivedCRC = decodeThis[decodeThis.length - 1];
byte calculatedCRC = CRC.crc8(decodedPayload);

View file

@ -0,0 +1,16 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.encoding;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
/**
* Created by andy on 11/24/18.
*/
public interface Encoding4b6b {
byte[] encode4b6b(byte[] data);
byte[] decode4b6b(byte[] data) throws RileyLinkCommunicationException;
}

View file

@ -0,0 +1,68 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.encoding;
import org.slf4j.Logger;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.FabricUtil;
/**
* Created by andy on 11/24/18.
*/
public abstract class Encoding4b6bAbstract implements Encoding4b6b {
/**
* encode4b6bMap is an ordered list of translations 6bits -> 4 bits, in order from 0x0 to 0xF
* The 6 bit codes are what is used on the RF side of the RileyLink to communicate
* with a Medtronic pump.
*/
public static final byte[] encode4b6bList = new byte[] {
0x15, 0x31, 0x32, 0x23, 0x34, 0x25, 0x26, 0x16, 0x1a, 0x19, 0x2a, 0x0b, 0x2c, 0x0d, 0x0e, 0x1c };
// 21, 49, 50, 35, 52, 37, 38, 22, 26, 25, 42, 11, 44, 13, 14, 28
public abstract byte[] encode4b6b(byte[] data);
public abstract byte[] decode4b6b(byte[] data) throws RileyLinkCommunicationException;
protected short convertUnsigned(byte x) {
short ss = x;
if (ss < 0) {
ss += 256;
}
return ss;
}
/* O(n) lookup. Run on an O(n) translation of a byte-stream, gives O(n**2) performance. Sigh. */
public static int encode4b6bListIndex(byte b) {
for (int i = 0; i < encode4b6bList.length; i++) {
if (b == encode4b6bList[i]) {
return i;
}
}
return -1;
}
public void writeError(Logger LOG, byte[] raw, String errorData) {
LOG.error("=============================================================================");
LOG.error(" Decoded payload length is zero.");
LOG.error(" encodedPayload: {}", ByteUtil.getHex(raw));
LOG.error(" errors: {}", errorData);
LOG.error("=============================================================================");
FabricUtil.createEvent("MedtronicDecode4b6bError", null);
return;
}
}

View file

@ -0,0 +1,249 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.encoding;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkBLEError;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
/**
* Created by andy on 11/24/18.
*/
public class Encoding4b6bGeoff extends Encoding4b6bAbstract {
public static final Logger LOG = LoggerFactory.getLogger(Encoding4b6bGeoff.class);
public byte[] encode4b6b(byte[] data) {
// if ((data.length % 2) != 0) {
// LOG.error("Warning: data is odd number of bytes");
// }
// use arraylists because byte[] is annoying.
List<Byte> inData = ByteUtil.getListFromByteArray(data);
List<Byte> outData = new ArrayList<>();
int acc = 0;
int bitcount = 0;
int i;
for (i = 0; i < inData.size(); i++) {
acc <<= 6;
acc |= encode4b6bList[(inData.get(i) >> 4) & 0x0f];
bitcount += 6;
acc <<= 6;
acc |= encode4b6bList[inData.get(i) & 0x0f];
bitcount += 6;
while (bitcount >= 8) {
byte outByte = (byte)(acc >> (bitcount - 8) & 0xff);
outData.add(outByte);
bitcount -= 8;
acc &= (0xffff >> (16 - bitcount));
}
}
if (bitcount > 0) {
acc <<= 6;
acc |= 0x14; // marks uneven packet boundary.
bitcount += 6;
if (bitcount >= 8) {
byte outByte = (byte)((acc >> (bitcount - 8)) & 0xff);
outData.add(outByte);
bitcount -= 8;
// acc &= (0xffff >> (16 - bitcount));
}
while (bitcount >= 8) {
outData.add((byte)0);
bitcount -= 8;
}
}
// convert back to byte[]
byte[] rval = ByteUtil.getByteArrayFromList(outData);
return rval;
}
/**
* Decode by Geoff
*
* @param raw
* @return
* @throws NumberFormatException
*/
public byte[] decode4b6b(byte[] raw) throws RileyLinkCommunicationException {
StringBuilder errorMessageBuilder = new StringBuilder();
errorMessageBuilder.append("Input data: " + ByteUtil.getHex(raw) + "\n");
if ((raw.length % 2) != 0) {
errorMessageBuilder.append("Warn: odd number of bytes.\n");
}
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 = encode4b6bListIndex((byte)(highcode));
// take bottom six
int lowcode = (x >> (availableBits - 12)) & 0x3F;
int lowIndex = encode4b6bListIndex((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));
}
}
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.");
writeError(LOG, raw, errorMessageBuilder.toString());
throw new RileyLinkCommunicationException(RileyLinkBLEError.CodingErrors, errorMessageBuilder.toString());
}
return rval;
}
// public static RFTools.DecodeResponseDto decode4b6bWithoutException(byte[] raw) {
// /*
// * if ((raw.length % 2) != 0) {
// * LOG.error("Warning: data is odd number of bytes");
// * }
// */
//
// RFTools.DecodeResponseDto response = new RFTools.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 = encode4b6bListIndex((byte)(highcode));
// // take bottom six
// int lowcode = (x >> (availableBits - 12)) & 0x3F;
// int lowIndex = encode4b6bListIndex((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;
// }
}

View file

@ -0,0 +1,163 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.encoding;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkBLEError;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
/**
* Created by andy on 11/24/18.
*/
public class Encoding4b6bGo extends Encoding4b6bAbstract {
public static final Logger LOG = LoggerFactory.getLogger(Encoding4b6bGo.class);
private static Map<Short, Short> decodeGoMap;
public byte[] encode4b6b(byte[] src) {
// 2 input bytes produce 3 output bytes.
// Odd final input byte, if any, produces 2 output bytes.
int n = src.length;
byte[] dst = new byte[3 * (n / 2) + 2 * (n % 2)];
int j = 0;
for (int i = 0; i < n; i += 2, j = j + 3) {
short x = convertUnsigned(src[i]);
short a = encode4b6bList[hi(4, x)];
short b = encode4b6bList[lo(4, x)];
dst[j] = (byte)(a << 2 | hi(4, b));
if (i + 1 < n) {
short y = convertUnsigned(src[i + 1]);
short c = encode4b6bList[hi(4, y)];
short d = encode4b6bList[lo(4, y)];
dst[j + 1] = (byte)(lo(4, b) << 4 | hi(6, c));
dst[j + 2] = (byte)(lo(2, c) << 6 | d);
} else {
// Fill final nibble with 5 to match pump behavior.
dst[j + 1] = (byte)(lo(4, b) << 4 | 0x5);
}
}
return dst;
}
/**
* Decode from Go code by ecc1. NOT WORKING
*
* @param src
* @return
*/
public byte[] decode4b6b(byte[] src) throws RileyLinkCommunicationException {
int n = src.length;
if (decodeGoMap == null)
initDecodeGo();
StringBuilder errorMessageBuilder = new StringBuilder();
errorMessageBuilder.append("Input data: " + ByteUtil.getHex(src) + "\n");
int codingErrors = 0;
// Check for valid packet length.
if (n % 3 == 1) {
errorMessageBuilder.append("Invalid package length " + n);
codingErrors++;
// return nil, ErrDecoding
}
// 3 input bytes produce 2 output bytes.
// Final 2 input bytes, if any, produce 1 output byte.
byte[] dst = new byte[2 * (n / 3) + (n % 3) / 2];
int j = 0;
for (int i = 0; i < n; i = i + 3, j = j + 2) {
if (i + 1 >= n) {
errorMessageBuilder.append("Overflow in i (" + i + ")");
}
short x = convertUnsigned(src[i]);
short y = convertUnsigned(src[i + 1]);
short a = decode6b_goMap(hi(6, x));
short b = decode6b_goMap(lo(2, x) << 4 | hi(4, y));
if (a == 0xFF || b == 0xFF) {
errorMessageBuilder.append("Error decoding ");
codingErrors++;
}
dst[j] = (byte)(a << 4 | b);
if (i + 2 < n) {
short z = convertUnsigned(src[i + 2]);
short c = decode6b_goMap(lo(4, y) << 2 | hi(2, z));
short d = decode6b_goMap(lo(6, z));
if (c == 0xFF || d == 0xFF) {
errorMessageBuilder.append("Error decoding ");
codingErrors++;
}
dst[j + 1] = (byte)(c << 4 | d);
}
}
if (codingErrors > 0) {
errorMessageBuilder.append("decode4b6b: " + codingErrors + " coding errors encountered.");
writeError(LOG, dst, errorMessageBuilder.toString());
throw new RileyLinkCommunicationException(RileyLinkBLEError.CodingErrors, errorMessageBuilder.toString());
}
return dst;
}
static short hi(int n, short x) {
// x = convertUnsigned(x);
return (short)(x >> (8 - n));
}
static short lo(int n, short x) {
// byte b = (byte)x;
return (short)(x & ((1 << n) - 1));
}
public static void initDecodeGo() {
decodeGoMap = new HashMap<>();
putToMap(0x0B, 0x0B);
putToMap(0x0D, 0x0D);
putToMap(0x0E, 0x0E);
putToMap(0x15, 0x00);
putToMap(0x16, 0x07);
putToMap(0x19, 0x09);
putToMap(0x1A, 0x08);
putToMap(0x1C, 0x0F);
putToMap(0x23, 0x03);
putToMap(0x25, 0x05);
putToMap(0x26, 0x06);
putToMap(0x2A, 0x0A);
putToMap(0x2C, 0x0C);
putToMap(0x31, 0x01);
putToMap(0x32, 0x02);
putToMap(0x34, 0x04);
}
private static short decode6b_goMap(int value) {
short val = (short)value;
if (decodeGoMap.containsKey(val))
return decodeGoMap.get(val);
else
return (short)0xff;
}
private static void putToMap(int val1, int val2) {
decodeGoMap.put((short)val1, (short)val2);
}
}

View file

@ -0,0 +1,136 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.encoding;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
/**
* Created by andy on 11/24/18.
*/
public class Encoding4b6bLoop extends Encoding4b6bAbstract {
public static final Logger LOG = LoggerFactory.getLogger(Encoding4b6bLoop.class);
public Map<Integer, Byte> codesRev = null;
public Encoding4b6bLoop() {
createCodeRev();
}
/**
* This method is almost 1:1 with same method from Loop, only change is unsigning of element and |05 added for
* last byte. It should work better than original one, which is really different than this one.
*
* @param data
* @return
*/
public byte[] encode4b6b(byte[] data) {
List<Byte> buffer = new ArrayList<Byte>();
int bitAccumulator = 0x0;
int bitcount = 0;
for (byte element : data) {
short element2 = element;
if (element2 < 0) {
element2 += 256;
}
bitAccumulator <<= 6;
bitAccumulator |= encode4b6bList[element2 >> 4];
bitcount += 6;
bitAccumulator <<= 6;
bitAccumulator |= encode4b6bList[element2 & 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 | 0x5) & 0xff));
}
return ByteUtil.getByteArrayFromList(buffer);
}
/**
* DOESN'T WORK YET
*
* @param data
* @return
* @throws RileyLinkCommunicationException
*/
public byte[] decode4b6b(byte[] data) throws RileyLinkCommunicationException {
List<Byte> buffer = new ArrayList<Byte>();
int availBits = 0;
int bitAccumulator = 0;
for (byte element2 : data) {
short element = convertUnsigned(element2);
// if (element < 0) {
// element += 255;
// }
if (element == 0) {
break;
}
bitAccumulator = (bitAccumulator << 8) + element;
availBits += 8;
if (availBits >= 12) {
int hiNibble;
int loNibble;
try {
int index = (bitAccumulator >> (availBits - 6));
int index2 = ((bitAccumulator >> (availBits - 12)) & 0b111111);
hiNibble = codesRev.get((bitAccumulator >> (availBits - 6)));
loNibble = codesRev.get(((bitAccumulator >> (availBits - 12)) & 0b111111));
} catch (Exception ex) {
System.out.println("Exception: " + ex.getMessage());
ex.printStackTrace();
return null;
}
int decoded = ((hiNibble << 4) + loNibble);
buffer.add((byte)decoded);
availBits -= 12;
bitAccumulator = bitAccumulator & (0xffff >> (16 - availBits));
}
}
return ByteUtil.getByteArrayFromList(buffer);
}
private void createCodeRev() {
codesRev = new HashMap<>();
for (int i = 0; i < encode4b6bList.length; i++) {
codesRev.put(i, encode4b6bList[i]);
}
}
}

View file

@ -0,0 +1,24 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs;
/**
* Created by andy on 11/24/18.
*/
public enum RileyLinkBLEError {
CodingErrors("Coding Errors encpountered during decode of RileyLink packet."), //
Timeout("Timeout"), //
Interrupted("Interrupted");
private String description;
RileyLinkBLEError(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}

View file

@ -81,7 +81,7 @@ public enum RileyLinkServiceState {
this == RileyLinkServiceState.BluetoothReady || //
this == RileyLinkServiceState.RileyLinkInitializing || //
this == RileyLinkReady
// this == RileyLinkServiceState.RileyLinkError
// this == RileyLinkServiceState.RileyLinkBLEError
);
}

View file

@ -147,7 +147,7 @@ public class RileyLinkBroadcastReceiver extends BroadcastReceiver {
if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) {
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) {
RileyLinkUtil
.setServiceState(RileyLinkServiceState.BluetoothReady, RileyLinkError.RileyLinkUnreachable);
.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.RileyLinkUnreachable);
} else {
RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled);
}
@ -173,15 +173,6 @@ public class RileyLinkBroadcastReceiver extends BroadcastReceiver {
ServiceTaskExecutor.startTask(task);
LOG.info("Announcing RileyLink open For business");
return true;
} else if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) {
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) {
RileyLinkUtil
.setServiceState(RileyLinkServiceState.BluetoothReady, RileyLinkError.RileyLinkUnreachable);
} else {
RileyLinkUtil.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled);
}
return true;
} else if (action.equals(RileyLinkConst.Intents.RileyLinkNewAddressSet)) {
String RileylinkBLEAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, "");

View file

@ -8,6 +8,7 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.defs.RileyLink
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.service.data.ServiceTransport;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicConst;
import info.nightscout.utils.SP;
/**
@ -40,6 +41,11 @@ public class InitializePumpManagerTask extends ServiceTask {
RileyLinkUtil.getRileyLinkServiceData().lastGoodFrequency = lastGoodFrequency;
if (RileyLinkUtil.getRileyLinkTargetFrequency() == null) {
String pumpFrequency = SP.getString(MedtronicConst.Prefs.PumpFrequency, null);
}
if ((lastGoodFrequency > 0.0d)
&& RileyLinkUtil.getRileyLinkCommunicationManager().isValidFrequency(lastGoodFrequency)) {

View file

@ -137,21 +137,41 @@ public class ByteUtil {
}
public static byte[] fromByteArray(List<Byte> byteArray) {
byte[] rval = new byte[byteArray.size()];
for (int i = 0; i < byteArray.size(); i++) {
rval[i] = byteArray.get(i);
// public static byte[] fromByteList(List<Byte> byteArray) {
// byte[] rval = new byte[byteArray.size()];
// for (int i = 0; i < byteArray.size(); i++) {
// rval[i] = byteArray.get(i);
// }
// return rval;
// }
// public static List<Byte> toByteList(byte[] data) {
// ArrayList<Byte> rval = new ArrayList<>(data.length);
// for (int i = 0; i < data.length; i++) {
// rval.add(i, new Byte(data[i]));
// }
// return rval;
// }
public static List<Byte> getListFromByteArray(byte[] array) {
List<Byte> listOut = new ArrayList<Byte>();
for (byte val : array) {
listOut.add(val);
}
return rval;
return listOut;
}
public static ArrayList<Byte> toByteArray(byte[] data) {
ArrayList<Byte> rval = new ArrayList<>(data.length);
for (int i = 0; i < data.length; i++) {
rval.add(i, new Byte(data[i]));
public static byte[] getByteArrayFromList(List<Byte> list) {
byte[] out = new byte[list.size()];
for (int i = 0; i < list.size(); i++) {
out[i] = list.get(i);
}
return rval;
return out;
}
@ -233,17 +253,6 @@ public class ByteUtil {
}
public static List<Byte> getListFromByteArray(byte[] array) {
List<Byte> listOut = new ArrayList<Byte>();
for (byte val : array) {
listOut.add(val);
}
return listOut;
}
public static int makeUnsignedShort(int i, int j) {
int k = (i & 0xff) << 8 | j & 0xff;
return k;
@ -275,19 +284,20 @@ public class ByteUtil {
}
public static byte[] getByteArrayFromList(List<Byte> list) {
byte[] out = new byte[list.size()];
for (int i = 0; i < list.size(); i++) {
out[i] = list.get(i);
}
return out;
public static String getHex(byte abyte0[]) {
return abyte0 != null ? getHex(abyte0, abyte0.length) : null;
}
public static String getHex(byte abyte0[]) {
return abyte0 != null ? getHex(abyte0, abyte0.length) : null;
public static String getString(short abyte0[]) {
StringBuilder sb = new StringBuilder();
for (short i : abyte0) {
sb.append(i);
sb.append(" ");
}
return sb.toString();
}
@ -370,12 +380,17 @@ public class ByteUtil {
}
public static byte[] createByteArray(String dataFull, int startIndex) {
return createByteArray(dataFull, startIndex, dataFull.length());
public static byte[] createByteArrayFromCompactString(String dataFull) {
return createByteArrayFromCompactString(dataFull, 0, dataFull.length());
}
public static byte[] createByteArray(String dataFull, int startIndex, int length) {
public static byte[] createByteArrayFromCompactString(String dataFull, int startIndex) {
return createByteArrayFromCompactString(dataFull, startIndex, dataFull.length());
}
public static byte[] createByteArrayFromCompactString(String dataFull, int startIndex, int length) {
String data = dataFull.substring(startIndex);

View file

@ -231,7 +231,15 @@ public class MedtronicFragment extends SubscriberFragment {
} else if (pumpStatus.rileyLinkServiceState.isConnecting()) {
rileyLinkStatus.setText("{fa-bluetooth-b spin} " + getTranslation(resourceId));
} else if (pumpStatus.rileyLinkServiceState.isError()) {
rileyLinkStatus.setText("{fa-bluetooth-b} " + getTranslation(resourceId));
RileyLinkError rileyLinkError = RileyLinkUtil.getError();
if (rileyLinkError == null)
rileyLinkStatus.setText("{fa-bluetooth-b} " + getTranslation(resourceId));
else
rileyLinkStatus.setText("{fa-bluetooth-b} "
+ getTranslation(rileyLinkError.getResourceId(RileyLinkTargetDevice.MedtronicPump)));
rileyLinkStatus.setTextColor(Color.RED);
} else {
rileyLinkStatus.setText("{fa-bluetooth-b} " + getTranslation(resourceId));
@ -274,8 +282,27 @@ public class MedtronicFragment extends SubscriberFragment {
if (cmd == null)
pumpStatusIconView.setText(" " + MainApp.gs(pumpStatus.pumpDeviceState.getResourceId()));
else
pumpStatusIconView.setText(" " + cmd.name());
else {
Integer resourceId = cmd.getResourceId();
if (cmd == MedtronicCommandType.GetHistoryData) {
if (resourceId == null) {
pumpStatusIconView.setText(String.format(" Get History - Page %d (%d/16)",
MedtronicUtil.pageNumber, MedtronicUtil.frameNumber));
} else {
pumpStatusIconView.setText(MainApp.gs(resourceId, MedtronicUtil.pageNumber,
MedtronicUtil.frameNumber));
}
} else {
if (resourceId == null) {
pumpStatusIconView.setText(" " + cmd.name());
} else {
pumpStatusIconView.setText(" " + getTranslation(resourceId));
}
}
}
}
break;

View file

@ -118,13 +118,15 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
serviceConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
LOG.debug("RileyLinkMedtronicService is disconnected");
if (isLoggingEnabled())
LOG.debug("RileyLinkMedtronicService is disconnected");
medtronicService = null;
}
public void onServiceConnected(ComponentName name, IBinder service) {
LOG.debug("RileyLinkMedtronicService is connected");
if (isLoggingEnabled())
LOG.debug("RileyLinkMedtronicService is connected");
RileyLinkMedtronicService.LocalBinder mLocalBinder = (RileyLinkMedtronicService.LocalBinder)service;
medtronicService = mLocalBinder.getServiceInstance();
@ -134,7 +136,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
SystemClock.sleep(5000);
if (MedtronicUtil.getPumpStatus() != null) {
LOG.debug("Starting Medtronic-RileyLink service");
if (isLoggingEnabled())
LOG.debug("Starting Medtronic-RileyLink service");
if (MedtronicUtil.getPumpStatus().setNotInPreInit()) {
break;
}
@ -170,7 +173,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
pumpStatusLocal.refreshConfiguration();
LOG.debug("initPumpStatusData: {}", this.pumpStatusLocal);
if (isLoggingEnabled())
LOG.debug("initPumpStatusData: {}", this.pumpStatusLocal);
this.pumpStatus = pumpStatusLocal;
@ -182,6 +186,17 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
SP.putLong(MedtronicConst.Statistics.FirstPumpStart, System.currentTimeMillis());
}
migrateSettings();
}
private void migrateSettings() {
if ("US (916 MHz)".equals(SP.getString(MedtronicConst.Prefs.PumpFrequency, null))) {
SP.putString(MedtronicConst.Prefs.PumpFrequency, MainApp.gs(R.string.medtronic_pump_frequency_us_ca));
}
}
@ -193,7 +208,10 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
do {
SystemClock.sleep(60000);
if (doWeHaveAnyStatusNeededRefereshing()) {
Map<MedtronicStatusRefreshType, Long> statusRefresh = workWithStatusRefresh(
StatusRefreshAction.GetData, null, null);
if (doWeHaveAnyStatusNeededRefereshing(statusRefresh)) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Scheduled Status Refresh", null);
}
@ -230,7 +248,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public boolean isInitialized() {
// TODO remove
LOG.debug("MedtronicPumpPlugin::isInitialized");
if (isLoggingEnabled())
LOG.debug("MedtronicPumpPlugin::isInitialized");
return isServiceSet() && isInitialized;
}
@ -245,7 +264,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public boolean isBusy() {
// TODO remove
LOG.debug("MedtronicPumpPlugin::isBusy");
if (isLoggingEnabled())
LOG.debug("MedtronicPumpPlugin::isBusy");
return isServiceSet() && medtronicService.isBusy();
}
@ -253,7 +273,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public boolean isConnected() {
// TODO remove
LOG.debug("MedtronicPumpPlugin::isConnected");
if (isLoggingEnabled())
LOG.debug("MedtronicPumpPlugin::isConnected");
return isServiceSet() && medtronicService.isInitialized();
}
@ -261,7 +282,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public boolean isConnecting() {
// TODO remove
LOG.debug("MedtronicPumpPlugin::isConnecting");
if (isLoggingEnabled())
LOG.debug("MedtronicPumpPlugin::isConnecting");
return !isServiceSet() || !medtronicService.isInitialized();
}
@ -294,7 +316,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (rileyLinkServiceState != RileyLinkServiceState.PumpConnectorReady //
&& rileyLinkServiceState != RileyLinkServiceState.RileyLinkReady //
&& rileyLinkServiceState != RileyLinkServiceState.TuneUpDevice) {
LOG.error("RileyLink unreachable.");
if (isLoggingEnabled())
LOG.error("RileyLink unreachable.");
return false;
}
@ -304,14 +327,18 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private void refreshAnyStatusThatNeedsToBeRefreshed() {
if (!doWeHaveAnyStatusNeededRefereshing()) {
Map<MedtronicStatusRefreshType, Long> statusRefresh = workWithStatusRefresh(StatusRefreshAction.GetData, null,
null);
if (!doWeHaveAnyStatusNeededRefereshing(statusRefresh)) {
return;
}
boolean resetTime = false;
if (isPumpNotReachable()) {
LOG.error("Pump unreachable.");
if (isLoggingEnabled())
LOG.error("Pump unreachable.");
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
return;
@ -322,7 +349,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Set<MedtronicStatusRefreshType> refreshTypesNeededToReschedule = new HashSet<>();
// execute
for (Map.Entry<MedtronicStatusRefreshType, Long> refreshType : statusRefreshMap.entrySet()) {
for (Map.Entry<MedtronicStatusRefreshType, Long> refreshType : statusRefresh.entrySet()) {
if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) {
@ -361,9 +388,9 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
private boolean doWeHaveAnyStatusNeededRefereshing() {
private boolean doWeHaveAnyStatusNeededRefereshing(Map<MedtronicStatusRefreshType, Long> statusRefresh) {
for (Map.Entry<MedtronicStatusRefreshType, Long> refreshType : statusRefreshMap.entrySet()) {
for (Map.Entry<MedtronicStatusRefreshType, Long> refreshType : statusRefresh.entrySet()) {
if (refreshType.getValue() > 0 && System.currentTimeMillis() > refreshType.getValue()) {
return true;
@ -381,7 +408,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private void initializePump(boolean realInit) {
LOG.info(getLogPrefix() + "initializePump - start");
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "initializePump - start");
if (medtronicCommunicationManager == null) {
medtronicCommunicationManager = MedtronicCommunicationManager.getInstance();
@ -394,7 +422,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (isRefresh) {
if (isPumpNotReachable()) {
LOG.error(getLogPrefix() + "initializePump::Pump unreachable.");
if (isLoggingEnabled())
LOG.error(getLogPrefix() + "initializePump::Pump unreachable.");
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
setRefreshButtonEnabled(true);
@ -410,7 +439,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
medtronicUIComm.executeCommand(MedtronicCommandType.PumpModel);
} else {
if (pumpStatusLocal.medtronicDeviceType != MedtronicUtil.getMedtronicPumpModel()) {
LOG.warn(getLogPrefix() + "Configured pump is not the same as one detected.");
if (isLoggingEnabled())
LOG.warn(getLogPrefix() + "Configured pump is not the same as one detected.");
MedtronicUtil.sendNotification(MedtronicNotificationType.PumpTypeNotSame);
}
}
@ -443,7 +473,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
int errorCount = medtronicUIComm.getInvalidResponsesCount();
if (errorCount >= 5) {
LOG.error("Number of error counts was 5 or more. Starting tunning.");
if (isLoggingEnabled())
LOG.error("Number of error counts was 5 or more. Starting tunning.");
setRefreshButtonEnabled(true);
ServiceTaskExecutor.startTask(new WakeAndTuneTask());
return;
@ -523,15 +554,18 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
if (!invalid) {
LOG.debug("Basal profile is same as AAPS one.");
if (isLoggingEnabled())
LOG.debug("Basal profile is same as AAPS one.");
basalProfileChanged = false;
} else {
LOG.debug("Basal profile on Pump is different than the AAPS one.");
if (isLoggingEnabled())
LOG.debug("Basal profile on Pump is different than the AAPS one.");
}
} else {
invalid = true;
LOG.debug("Basal profile NO DATA");
if (isLoggingEnabled())
LOG.debug("Basal profile NO DATA");
}
isBasalProfileInvalid = invalid;
@ -563,7 +597,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private MedtronicPumpStatus getMDTPumpStatus() {
if (pumpStatusLocal == null) {
// FIXME I don't know why this happens
LOG.warn("!!!! Reset Pump Status Local");
if (isLoggingEnabled())
LOG.warn("!!!! Reset Pump Status Local");
pumpStatusLocal = MedtronicUtil.getPumpStatus();
}
@ -602,6 +637,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// TODO display bolus
setRefreshButtonEnabled(true);
if (response) {
// FIXME this needs to be fixed to read info from history
boolean treatmentCreated = TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
@ -613,14 +650,17 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
incrementStatistics(detailedBolusInfo.isSMB ? MedtronicConst.Statistics.SMBBoluses
: MedtronicConst.Statistics.StandardBoluses);
return new PumpEnactResult().success(response) //
.enacted(response) //
.bolusDelivered(detailedBolusInfo.insulin) //
.carbsDelivered(detailedBolusInfo.carbs);
} else {
return new PumpEnactResult().success(false).enacted(false) //
.comment(MainApp.gs(R.string.medtronic_cmd_bolus_could_not_be_delivered));
}
// readPumpHistory();
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(response).enacted(response);
// pump.activity = MainApp.gs(R.string.combo_pump_action_bolusing, detailedBolusInfo.insulin);
// MainApp.bus().post(new EventComboPumpUpdateGUI());
//
@ -769,19 +809,22 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
getMDTPumpStatus();
LOG.info(getLogPrefix() + "setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes);
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes);
// read current TBR
TempBasalPair tbrCurrent = readTBR();
if (tbrCurrent == null) {
LOG.warn(getLogPrefix() + "setTempBasalAbsolute - Could not read current TBR, canceling operation.");
if (isLoggingEnabled())
LOG.warn(getLogPrefix() + "setTempBasalAbsolute - Could not read current TBR, canceling operation.");
finishAction("TBR");
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr));
} else {
LOG.info(getLogPrefix() + "setTempBasalAbsolute: Current Basal: duration: {} min, rate={}",
tbrCurrent.getDurationMinutes(), tbrCurrent.getInsulinRate());
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "setTempBasalAbsolute: Current Basal: duration: {} min, rate={}",
tbrCurrent.getDurationMinutes(), tbrCurrent.getInsulinRate());
}
if (!enforceNew) {
@ -795,7 +838,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
if (sameRate) {
LOG.info(getLogPrefix() + "setTempBasalAbsolute - No enforceNew and same rate. Exiting.");
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "setTempBasalAbsolute - No enforceNew and same rate. Exiting.");
finishAction("TBR");
return new PumpEnactResult().success(true).enacted(false);
}
@ -805,7 +849,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// if TBR is running we will cancel it.
if (tbrCurrent.getInsulinRate() != 0.0f && tbrCurrent.getDurationMinutes() > 0) {
LOG.info(getLogPrefix() + "setTempBasalAbsolute - TBR running - so canceling it.");
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "setTempBasalAbsolute - TBR running - so canceling it.");
// CANCEL
@ -814,14 +859,16 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Boolean response = (Boolean)responseTask2.returnData;
if (response) {
LOG.info(getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled.");
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled.");
} else {
LOG.error(getLogPrefix() + "setTempBasalAbsolute - Cancel TBR failed.");
if (isLoggingEnabled())
LOG.error(getLogPrefix() + "setTempBasalAbsolute - Cancel TBR failed.");
finishAction("TBR");
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr));
.comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr_stop_op));
}
}
@ -831,7 +878,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Boolean response = (Boolean)responseTask.returnData;
LOG.info(getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response);
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response);
if (response) {
// FIXME put this into UIPostProcessor
@ -848,13 +896,19 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStart);
incrementStatistics(MedtronicConst.Statistics.TBRsSet);
finishAction("TBR");
return new PumpEnactResult().success(response).enacted(response) //
.absolute(absoluteRate).duration(durationInMinutes);
} else {
finishAction("TBR");
return new PumpEnactResult().success(response).enacted(response) //
.comment(MainApp.gs(R.string.medtronic_cmd_tbr_could_not_be_delivered));
}
finishAction("TBR");
setRefreshButtonEnabled(true);
return new PumpEnactResult().success(response).enacted(response);
}
@ -871,7 +925,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
private void readPumpHistory() {
LOG.error(getLogPrefix() + "readPumpHistory WIP.");
if (isLoggingEnabled())
LOG.error(getLogPrefix() + "readPumpHistory WIP.");
readPumpHistoryLogic();
@ -894,12 +949,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (medtronicHistoryData.isPumpSuspended(this.pumpState == PumpDriverState.Suspended)) {
scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, -1);
this.pumpState = PumpDriverState.Suspended;
LOG.debug(getLogPrefix() + "isPumpSuspended: true");
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "isPumpSuspended: true");
} else {
if (previousState == PumpDriverState.Suspended) {
this.pumpState = PumpDriverState.Ready;
}
LOG.debug(getLogPrefix() + "isPumpSuspended: false");
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "isPumpSuspended: false");
}
List<PumpHistoryEntry> tdds = medtronicHistoryData.getTDDs();
@ -910,6 +967,7 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
List<PumpHistoryEntry> tdds2 = medtronicHistoryData.getTDDs2();
// FIXME
LOG.debug("TDDs2: {}", gsonInstancePretty.toJson(tdds2));
List<PumpHistoryEntry> treatments = medtronicHistoryData.getTreatments();
@ -954,7 +1012,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (lastPumpHistoryEntry == null) {
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: null");
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: null");
Long lastPumpHistoryEntryTime = SP.getLong(MedtronicConst.Statistics.LastPumpHistoryEntry, 0L);
@ -963,14 +1022,16 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
medtronicHistoryData.setIsInInit(true);
if (lastPumpHistoryEntryTime == 0L) {
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: 0L - targetDate: "
+ targetDate);
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: 0L - targetDate: "
+ targetDate);
targetDate = timeMinus36h;
} else {
LocalDateTime lastHistoryRecordTime = DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime);
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: {} - targetDate: {}",
lastHistoryRecordTime, targetDate);
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntryTime: {} - targetDate: {}",
lastHistoryRecordTime, targetDate);
medtronicHistoryData.setLastHistoryRecordTime(DateTimeUtil.toLocalDateTime(lastPumpHistoryEntryTime));
@ -984,11 +1045,13 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
targetDate = (timeMinus36h.isAfter(lastHistoryRecordTime) ? timeMinus36h : lastHistoryRecordTime);
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): targetDate: " + targetDate);
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): targetDate: " + targetDate);
}
} else {
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - {}",
gsonInstancePretty.toJson(lastPumpHistoryEntry));
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "readPumpHistoryLogic(): lastPumpHistoryEntry: not null - {}",
gsonInstancePretty.toJson(lastPumpHistoryEntry));
medtronicHistoryData.setIsInInit(false);
medtronicHistoryData.setLastHistoryRecordTime(null);
}
@ -1000,7 +1063,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
PumpHistoryEntry latestEntry = historyResult.getLatestEntry();
LOG.debug(getLogPrefix() + "Last entry: " + latestEntry);
if (isLoggingEnabled())
LOG.debug(getLogPrefix() + "Last entry: " + latestEntry);
if (latestEntry == null) // no new history to read
return;
@ -1053,20 +1117,50 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
else
min = 15;
statusRefreshMap.put(refreshType, getTimeInFutureFromMinutes(min));
workWithStatusRefresh(StatusRefreshAction.Add, refreshType, getTimeInFutureFromMinutes(min));
}
break;
case PumpTime:
case Configuration:
case PumpHistory: {
statusRefreshMap.put(refreshType, getTimeInFutureFromMinutes(refreshType.getRefreshTime()
+ additionalTimeInMinutes));
workWithStatusRefresh(StatusRefreshAction.Add, refreshType,
getTimeInFutureFromMinutes(refreshType.getRefreshTime() + additionalTimeInMinutes));
}
break;
}
}
private enum StatusRefreshAction {
Add, //
GetData;
}
private synchronized Map<MedtronicStatusRefreshType, Long> workWithStatusRefresh(StatusRefreshAction action,
MedtronicStatusRefreshType statusRefreshType, Long time) {
switch (action) {
case Add: {
statusRefreshMap.put(statusRefreshType, time);
return null;
}
case GetData: {
Map<MedtronicStatusRefreshType, Long> shallowCopy = new HashMap<>();
shallowCopy.putAll(statusRefreshMap);
return shallowCopy;
}
default:
return null;
}
}
private long getTimeInFutureFromMinutes(int minutes) {
return System.currentTimeMillis() + getTimeInMs(minutes);
@ -1099,7 +1193,8 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
@Override
public PumpEnactResult cancelTempBasal(boolean enforceNew) {
LOG.info(getLogPrefix() + "cancelTempBasal - started");
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "cancelTempBasal - started");
if (isPumpNotReachable()) {
@ -1118,12 +1213,14 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
if (tbrCurrent != null) {
if (tbrCurrent.getInsulinRate() == 0.0f && tbrCurrent.getDurationMinutes() == 0) {
LOG.info(getLogPrefix() + "cancelTempBasal - TBR already canceled.");
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "cancelTempBasal - TBR already canceled.");
finishAction("TBR");
return new PumpEnactResult().success(true).enacted(false);
}
} else {
LOG.warn(getLogPrefix() + "cancelTempBasal - Could not read currect TBR, canceling operation.");
if (isLoggingEnabled())
LOG.warn(getLogPrefix() + "cancelTempBasal - Could not read currect TBR, canceling operation.");
finishAction("TBR");
return new PumpEnactResult().success(false).enacted(false)
.comment(MainApp.gs(R.string.medtronic_cmd_cant_read_tbr));
@ -1133,22 +1230,35 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Boolean response = (Boolean)responseTask2.returnData;
if (response) {
LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR successful.");
} else {
LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR failed.");
}
finishAction("TBR");
return new PumpEnactResult().success(response).enacted(response);
if (response) {
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR successful.");
TemporaryBasal tempBasal = new TemporaryBasal() //
.date(System.currentTimeMillis()) //
.duration(0) //
.source(Source.USER);
TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
return new PumpEnactResult().success(response).enacted(response) //
.isTempCancel(true);
} else {
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR failed.");
return new PumpEnactResult().success(response).enacted(response) //
.comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr));
}
}
@Override
public PumpEnactResult setNewBasalProfile(Profile profile) {
LOG.error(getLogPrefix() + "setNewBasalProfile - WIP.");
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "setNewBasalProfile");
setRefreshButtonEnabled(false);
@ -1180,9 +1290,15 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
Boolean response = (Boolean)responseTask.returnData;
LOG.info(getLogPrefix() + "Basal Profile was set: " + response);
if (isLoggingEnabled())
LOG.info(getLogPrefix() + "Basal Profile was set: " + response);
return new PumpEnactResult().success(response).enacted(response);
if (response) {
return new PumpEnactResult().success(response).enacted(response);
} else {
return new PumpEnactResult().success(response).enacted(response) //
.comment(MainApp.gs(R.string.medtronic_cmd_basal_profile_could_not_be_set));
}
}
@ -1205,7 +1321,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
}
return stringBuilder.length() == 0 ? null : stringBuilder.toString();
}
@ -1236,28 +1351,26 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
// OPERATIONS not supported by Pump or Plugin
@Override
public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
LOG.error("MedtronicPumpPlugin::setExtendedBolus NOT SUPPORTED.");
return OPERATION_NOT_SUPPORTED;
}
@Override
public PumpEnactResult cancelExtendedBolus() {
LOG.warn("cancelExtendedBolus - operation not supported.");
return getOperationNotSupportedWithCustomText(R.string.medtronic_cmd_cancel_bolus_not_supported);
}
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
boolean enforceNew) {
LOG.error("setTempBasalPercent NOT IMPLEMENTED.");
// we will never come here unless somebody has played with configuration in PumpType
return OPERATION_NOT_SUPPORTED;
}
// @Override
// public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) {
// LOG.error("MedtronicPumpPlugin::setExtendedBolus NOT SUPPORTED.");
// return OPERATION_NOT_SUPPORTED;
// }
//
//
// @Override
// public PumpEnactResult cancelExtendedBolus() {
// LOG.warn("cancelExtendedBolus - operation not supported.");
// return getOperationNotSupportedWithCustomText(R.string.medtronic_cmd_cancel_bolus_not_supported);
// }
// @Override
// public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
// boolean enforceNew) {
// LOG.error("setTempBasalPercent NOT IMPLEMENTED.");
// // we will never come here unless somebody has played with configuration in PumpType
// return OPERATION_NOT_SUPPORTED;
// }
// // we don't loadTDD. TDD is read from Pump History
// @Override

View file

@ -13,6 +13,7 @@ import android.os.SystemClock;
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.ble.RFSpy;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.RileyLinkCommunicationException;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RFSpyResponse;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RLMessage;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.data.RadioPacket;
@ -22,12 +23,10 @@ import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.service.tasks.WakeAndTuneTask;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
import info.nightscout.androidaps.plugins.PumpCommon.utils.HexDump;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.data.Page;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.RawHistoryPage;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder;
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.message.ButtonPressCarelinkMessageBody;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.CarelinkLongMessageBody;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.CarelinkShortMessageBody;
import info.nightscout.androidaps.plugins.PumpMedtronic.comm.message.GetHistoryPageCarelinkMessageBody;
@ -42,7 +41,6 @@ import info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.TempBasalPair;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.MedtronicDeviceType;
import info.nightscout.androidaps.plugins.PumpMedtronic.defs.PumpDeviceState;
import info.nightscout.androidaps.plugins.PumpMedtronic.service.RileyLinkMedtronicService;
import info.nightscout.androidaps.plugins.PumpMedtronic.util.MedtronicUtil;
import info.nightscout.utils.SP;
@ -54,8 +52,9 @@ import info.nightscout.utils.SP;
public class MedtronicCommunicationManager extends RileyLinkCommunicationManager {
private static final Logger LOG = LoggerFactory.getLogger(MedtronicCommunicationManager.class);
private static final int MAX_COMMAND_RETRIES = 2;
private static final int MAX_COMMAND_TRIES = 3;
private static final int DEFAULT_TIMEOUT = 2000;
private static final long RILEYLINK_TIMEOUT = 15 * 60 * 1000; // 15 min
static MedtronicCommunicationManager medtronicCommunicationManager;
String errorMessage;
@ -121,17 +120,51 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
for (int retry = 0; retry < 5; retry++) {
LOG.error("isDeviceReachable. Waking pump... " + (retry != 0 ? " (retry " + retry + ")" : ""));
LOG.debug("isDeviceReachable. Waking pump... " + (retry != 0 ? " (retry " + retry + ")" : ""));
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple
RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0,
(byte)200, (byte)0, (byte)0, 25000, (byte)0);
LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(rfSpyResponse.getRaw()));
boolean connected = connectToDevice();
if (connected)
return true;
SystemClock.sleep(1000);
}
if (state != PumpDeviceState.PumpUnreachable)
MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable);
if (!canPreventTuneUp) {
long diff = System.currentTimeMillis() - MedtronicUtil.getPumpStatus().lastConnection;
if (diff > RILEYLINK_TIMEOUT) {
ServiceTaskExecutor.startTask(new WakeAndTuneTask());
}
}
return false;
}
private boolean connectToDevice() {
PumpDeviceState state = MedtronicUtil.getPumpDeviceState();
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple
RFSpyResponse rfSpyResponse = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0, (byte)200,
(byte)0, (byte)0, 25000, (byte)0);
LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(rfSpyResponse.getRaw()));
if (rfSpyResponse.wasTimeout()) {
LOG.error("isDeviceReachable. Failed to find pump (timeout).");
} else if (rfSpyResponse.looksLikeRadioPacket()) {
RadioResponse radioResponse = new RadioResponse();
try {
radioResponse.init(rfSpyResponse.getRaw());
if (rfSpyResponse.wasTimeout()) {
LOG.error("isDeviceReachable. Failed to find pump (timeout).");
} else if (rfSpyResponse.looksLikeRadioPacket()) {
RadioResponse radioResponse = new RadioResponse(rfSpyResponse.getRaw());
if (radioResponse.isValid()) {
PumpMessage pumpResponse = createResponseMessage(radioResponse.getPayload(), PumpMessage.class);
@ -175,20 +208,16 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.warn("isDeviceReachable. Failed to parse radio response: "
+ ByteUtil.shortHexString(rfSpyResponse.getRaw()));
}
} else {
LOG.warn("isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.getRaw()));
} catch (RileyLinkCommunicationException e) {
LOG.warn("isDeviceReachable. Failed to decode radio response: "
+ ByteUtil.shortHexString(rfSpyResponse.getRaw()));
}
SystemClock.sleep(1000);
} else {
LOG.warn("isDeviceReachable. Unknown response: " + ByteUtil.shortHexString(rfSpyResponse.getRaw()));
}
if (state != PumpDeviceState.PumpUnreachable)
MedtronicUtil.setPumpDeviceState(PumpDeviceState.PumpUnreachable);
if (!canPreventTuneUp)
ServiceTaskExecutor.startTask(new WakeAndTuneTask());
return false;
}
@ -242,7 +271,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// FIXME remove debugs - Andy
private PumpMessage runCommandWithArgs(PumpMessage msg) {
private PumpMessage runCommandWithArgs(PumpMessage msg) throws RileyLinkCommunicationException {
if (debugSetCommands)
LOG.debug("Run command with Args: ");
@ -267,75 +296,75 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
@Deprecated
private PumpMessage runCommandWithArgsLong(MedtronicCommandType commandType, byte[] content) {
// @Deprecated
// private PumpMessage runCommandWithArgsLong(MedtronicCommandType commandType, byte[] content) {
//
// LOG.debug("Run command with Args (Long): {}", commandType.name());
//
// PumpMessage rval = null;
// PumpMessage shortMessage = makePumpMessage(commandType, new CarelinkShortMessageBody(new byte[] { 0 }));
// // look for ack from short message
// PumpMessage shortResponse = sendAndListen(shortMessage);
//
// if (shortResponse.commandType != MedtronicCommandType.CommandACK) {
// LOG.error("runCommandWithArgs: Pump did not ack Attention packet");
//
// return new PumpMessage("No ACK after start message.");
// }
//
// int start = 0;
// int frameNr = 1;
// int len = 0;
//
// do {
//
// if (start == 0)
// LOG.debug("Run command with Args(Long): Got ACK response for Attention packet");
// else
// LOG.debug("Run command with Args(Long): Got ACK response for frame #{}", (frameNr - 1));
//
// if (start + 64 > content.length) {
// len = content.length - start;
//
// if (len == 0)
// break;
// } else {
// len = 64;
// }
//
// byte frame[] = new byte[65];
//
// frame[0] = (byte)frameNr;
//
// System.arraycopy(content, start, frame, 1, len);
//
// PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(frame));
//
// rval = sendAndListen(msg);
//
// if (rval.commandType != MedtronicCommandType.CommandACK) {
// LOG.error("runCommandWithArgs(Long): Pump did not ACK frame #{}", frameNr);
//
// return new PumpMessage("No ACK after frame #" + frameNr);
// }
//
// if (len != 64) {
// LOG.debug("Run command with Args(Long): Got ACK response for frame #{}", (frameNr));
// break;
// }
//
// start += 64;
// frameNr++;
//
// } while (true);
//
// return rval;
//
// // return new PumpMessage("No ACK");
// }
LOG.debug("Run command with Args (Long): {}", commandType.name());
PumpMessage rval = null;
PumpMessage shortMessage = makePumpMessage(commandType, new CarelinkShortMessageBody(new byte[] { 0 }));
// look for ack from short message
PumpMessage shortResponse = sendAndListen(shortMessage);
if (shortResponse.commandType != MedtronicCommandType.CommandACK) {
LOG.error("runCommandWithArgs: Pump did not ack Attention packet");
return new PumpMessage("No ACK after start message.");
}
int start = 0;
int frameNr = 1;
int len = 0;
do {
if (start == 0)
LOG.debug("Run command with Args(Long): Got ACK response for Attention packet");
else
LOG.debug("Run command with Args(Long): Got ACK response for frame #{}", (frameNr - 1));
if (start + 64 > content.length) {
len = content.length - start;
if (len == 0)
break;
} else {
len = 64;
}
byte frame[] = new byte[65];
frame[0] = (byte)frameNr;
System.arraycopy(content, start, frame, 1, len);
PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(frame));
rval = sendAndListen(msg);
if (rval.commandType != MedtronicCommandType.CommandACK) {
LOG.error("runCommandWithArgs(Long): Pump did not ACK frame #{}", frameNr);
return new PumpMessage("No ACK after frame #" + frameNr);
}
if (len != 64) {
LOG.debug("Run command with Args(Long): Got ACK response for frame #{}", (frameNr));
break;
}
start += 64;
frameNr++;
} while (true);
return rval;
// return new PumpMessage("No ACK");
}
private PumpMessage runCommandWithFrames(MedtronicCommandType commandType, List<List<Byte>> frames) {
private PumpMessage runCommandWithFrames(MedtronicCommandType commandType, List<List<Byte>> frames)
throws RileyLinkCommunicationException {
LOG.debug("Run command with Frames: {}", commandType.name());
@ -390,6 +419,7 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.debug("Current command: " + MedtronicUtil.getCurrentCommand());
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Active);
boolean doneWithError = false;
for (int pageNumber = 0; pageNumber < 16; pageNumber++) {
@ -401,7 +431,27 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.info("getPumpHistory: Page {}", pageNumber);
// LOG.info("getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData()));
// Ask the pump to transfer history (we get first frame?)
PumpMessage firstResponse = runCommandWithArgs(getHistoryMsg);
PumpMessage firstResponse = null;
boolean failed = false;
for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) {
try {
firstResponse = runCommandWithArgs(getHistoryMsg);
failed = false;
break;
} catch (RileyLinkCommunicationException e) {
LOG.error("First call for PumpHistory failed (retry={})", retries);
failed = true;
}
}
if (failed) {
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping);
return pumpTotalResult;
}
// LOG.info("getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents()));
PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody());
@ -426,6 +476,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
rawHistoryPage.appendData(currentResponse.getFrameData());
// RileyLinkMedtronicService.getInstance().announceProgress(
// ((100 / 16) * currentResponse.getFrameNumber() + 1));
MedtronicUtil.setCurrentCommand(MedtronicCommandType.GetHistoryData, pageNumber,
currentResponse.getFrameNumber());
LOG.info("getPumpHistory: Got frame {} of Page {}", currentResponse.getFrameNumber(), pageNumber);
// Do we need to ask for the next frame?
@ -449,26 +501,49 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
"getPumpHistory: 6 failures in attempting to download frame {} of page {}, giving up.",
expectedFrameNum, pageNumber);
done = true; // failure completion.
doneWithError = true;
}
}
if (!done) {
// ask for next frame
PumpMessage nextMsg = sendAndListen(ackMsg);
currentResponse = new GetHistoryPageCarelinkMessageBody(nextMsg.getMessageBody().getTxData());
PumpMessage nextMsg = null;
for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) {
try {
nextMsg = sendAndListen(ackMsg);
break;
} catch (RileyLinkCommunicationException e) {
LOG.error("Problem acknowledging frame response. (retry={})", retries);
}
}
if (nextMsg != null)
currentResponse = new GetHistoryPageCarelinkMessageBody(nextMsg.getMessageBody().getTxData());
else
LOG.error("We couldn't acknowledge frame from pump, aborting operation.");
}
}
if (rawHistoryPage.getLength() != 1024) {
LOG.warn("getPumpHistory: short page. Expected length of 1024, found length of "
+ rawHistoryPage.getLength());
doneWithError = true;
}
if (!rawHistoryPage.isChecksumOK()) {
LOG.error("getPumpHistory: checksum is wrong");
doneWithError = true;
}
// TODO handle error states
if (doneWithError) {
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping);
return pumpTotalResult;
}
rawHistoryPage.dumpToDebug();
List<PumpHistoryEntry> medtronicHistoryEntries = pumpHistoryDecoder.processPageAndCreateRecords(
@ -496,86 +571,85 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
@Deprecated
public Page getPumpHistoryPage(int pageNumber) {
RawHistoryPage rval = new RawHistoryPage();
if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false);
PumpMessage getHistoryMsg = makePumpMessage(MedtronicCommandType.GetHistoryData,
new GetHistoryPageCarelinkMessageBody(pageNumber));
// LOG.info("getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData()));
// Ask the pump to transfer history (we get first frame?)
PumpMessage firstResponse = runCommandWithArgs(getHistoryMsg);
// LOG.info("getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents()));
PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody());
GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse
.getMessageBody().getTxData());
int expectedFrameNum = 1;
boolean done = false;
// while (expectedFrameNum == currentResponse.getFrameNumber()) {
int failures = 0;
while (!done) {
// examine current response for problems.
byte[] frameData = currentResponse.getFrameData();
if ((frameData != null) && (frameData.length > 0) && currentResponse.getFrameNumber() == expectedFrameNum) {
// success! got a frame.
if (frameData.length != 64) {
LOG.warn("Expected frame of length 64, got frame of length " + frameData.length);
// but append it anyway?
}
// handle successful frame data
rval.appendData(currentResponse.getFrameData());
RileyLinkMedtronicService.getInstance().announceProgress(
((100 / 16) * currentResponse.getFrameNumber() + 1));
LOG.info("getPumpHistoryPage: Got frame " + currentResponse.getFrameNumber());
// Do we need to ask for the next frame?
if (expectedFrameNum < 16) { // This number may not be correct for pumps other than 522/722
expectedFrameNum++;
} else {
done = true; // successful completion
}
} else {
if (frameData == null) {
LOG.error("null frame data, retrying");
} else if (currentResponse.getFrameNumber() != expectedFrameNum) {
LOG.warn("Expected frame number {}, received {} (retrying)", expectedFrameNum,
currentResponse.getFrameNumber());
} else if (frameData.length == 0) {
LOG.warn("Frame has zero length, retrying");
}
failures++;
if (failures == 6) {
LOG.error("6 failures in attempting to download frame {} of page {}, giving up.", expectedFrameNum,
pageNumber);
done = true; // failure completion.
}
}
if (!done) {
// ask for next frame
PumpMessage nextMsg = sendAndListen(ackMsg);
currentResponse = new GetHistoryPageCarelinkMessageBody(nextMsg.getMessageBody().getTxData());
}
}
if (rval.getLength() != 1024) {
LOG.warn("getPumpHistoryPage: short page. Expected length of 1024, found length of " + rval.getLength());
}
if (!rval.isChecksumOK()) {
LOG.error("getPumpHistoryPage: checksum is wrong");
}
rval.dumpToDebug();
Page page = new Page();
// page.parseFrom(rval.getData(),PumpModel.MM522);
// FIXME
page.parseFrom(rval.getData(), MedtronicDeviceType.Medtronic_522);
return page;
}
// @Deprecated
// public Page getPumpHistoryPage(int pageNumber) {
// RawHistoryPage rval = new RawHistoryPage();
//
// if (doWakeUpBeforeCommand)
// wakeUp(receiverDeviceAwakeForMinutes, false);
//
// PumpMessage getHistoryMsg = makePumpMessage(MedtronicCommandType.GetHistoryData,
// new GetHistoryPageCarelinkMessageBody(pageNumber));
// // LOG.info("getPumpHistoryPage("+pageNumber+"): "+ByteUtil.shortHexString(getHistoryMsg.getTxData()));
// // Ask the pump to transfer history (we get first frame?)
// PumpMessage firstResponse = runCommandWithArgs(getHistoryMsg);
// // LOG.info("getPumpHistoryPage("+pageNumber+"): " + ByteUtil.shortHexString(firstResponse.getContents()));
//
// PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody());
// GetHistoryPageCarelinkMessageBody currentResponse = new GetHistoryPageCarelinkMessageBody(firstResponse
// .getMessageBody().getTxData());
// int expectedFrameNum = 1;
// boolean done = false;
// // while (expectedFrameNum == currentResponse.getFrameNumber()) {
// int failures = 0;
// while (!done) {
// // examine current response for problems.
// byte[] frameData = currentResponse.getFrameData();
// if ((frameData != null) && (frameData.length > 0) && currentResponse.getFrameNumber() == expectedFrameNum) {
// // success! got a frame.
// if (frameData.length != 64) {
// LOG.warn("Expected frame of length 64, got frame of length " + frameData.length);
// // but append it anyway?
// }
// // handle successful frame data
// rval.appendData(currentResponse.getFrameData());
// RileyLinkMedtronicService.getInstance().announceProgress(
// ((100 / 16) * currentResponse.getFrameNumber() + 1));
// LOG.info("getPumpHistoryPage: Got frame " + currentResponse.getFrameNumber());
// // Do we need to ask for the next frame?
// if (expectedFrameNum < 16) { // This number may not be correct for pumps other than 522/722
// expectedFrameNum++;
// } else {
// done = true; // successful completion
// }
// } else {
// if (frameData == null) {
// LOG.error("null frame data, retrying");
// } else if (currentResponse.getFrameNumber() != expectedFrameNum) {
// LOG.warn("Expected frame number {}, received {} (retrying)", expectedFrameNum,
// currentResponse.getFrameNumber());
// } else if (frameData.length == 0) {
// LOG.warn("Frame has zero length, retrying");
// }
// failures++;
// if (failures == 6) {
// LOG.error("6 failures in attempting to download frame {} of page {}, giving up.", expectedFrameNum,
// pageNumber);
// done = true; // failure completion.
// }
// }
// if (!done) {
// // ask for next frame
// PumpMessage nextMsg = sendAndListen(ackMsg);
// currentResponse = new GetHistoryPageCarelinkMessageBody(nextMsg.getMessageBody().getTxData());
// }
// }
// if (rval.getLength() != 1024) {
// LOG.warn("getPumpHistoryPage: short page. Expected length of 1024, found length of " + rval.getLength());
// }
// if (!rval.isChecksumOK()) {
// LOG.error("getPumpHistoryPage: checksum is wrong");
// }
//
// rval.dumpToDebug();
//
// Page page = new Page();
// // page.parseFrom(rval.getData(),PumpModel.MM522);
// // FIXME
// page.parseFrom(rval.getData(), MedtronicDeviceType.Medtronic_522);
//
// return page;
// }
// public ArrayList<Page> getAllHistoryPages() {
// ArrayList<Page> pages = new ArrayList<>();
@ -607,18 +681,17 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// See ButtonPressCarelinkMessageBody
public void pressButton(int which) {
if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false);
PumpMessage pressButtonMessage = makePumpMessage(MedtronicCommandType.PushButton,
new ButtonPressCarelinkMessageBody(which));
PumpMessage resp = sendAndListen(pressButtonMessage);
if (resp.commandType != MedtronicCommandType.CommandACK) {
LOG.error("Pump did not ack button press.");
}
}
// public void pressButton(int which) {
// if (doWakeUpBeforeCommand)
// wakeUp(receiverDeviceAwakeForMinutes, false);
//
// PumpMessage pressButtonMessage = makePumpMessage(MedtronicCommandType.PushButton,
// new ButtonPressCarelinkMessageBody(which));
// PumpMessage resp = sendAndListen(pressButtonMessage);
// if (resp.commandType != MedtronicCommandType.CommandACK) {
// LOG.error("Pump did not ack button press.");
// }
// }
@Override
public byte[] createPumpMessageContent(RLMessageType type) {
@ -652,23 +725,22 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
private PumpMessage sendAndGetResponse(MedtronicCommandType commandType) {
private PumpMessage sendAndGetResponse(MedtronicCommandType commandType) throws RileyLinkCommunicationException {
return sendAndGetResponse(commandType, null, DEFAULT_TIMEOUT);
}
private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, int timeoutMs) {
return sendAndGetResponse(commandType, null, timeoutMs);
}
private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData) {
return sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT);
}
// private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, int timeoutMs) {
//
// return sendAndGetResponse(commandType, null, timeoutMs);
// }
//
//
// private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData) {
//
// return sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT);
// }
/**
* Main wrapper method for sending data - (for getting responses)
@ -678,7 +750,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
* @param timeoutMs
* @return
*/
private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData, int timeoutMs) {
private PumpMessage sendAndGetResponse(MedtronicCommandType commandType, byte[] bodyData, int timeoutMs)
throws RileyLinkCommunicationException {
// wakeUp
if (doWakeUpBeforeCommand)
wakeUp(receiverDeviceAwakeForMinutes, false);
@ -702,13 +775,13 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
}
protected PumpMessage sendAndListen(RLMessage msg) {
protected PumpMessage sendAndListen(RLMessage msg) throws RileyLinkCommunicationException {
return sendAndListen(msg, 4000); // 2000
}
// All pump communications go through this function.
protected PumpMessage sendAndListen(RLMessage msg, int timeout_ms) {
protected PumpMessage sendAndListen(RLMessage msg, int timeout_ms) throws RileyLinkCommunicationException {
return sendAndListen(msg, timeout_ms, PumpMessage.class);
}
@ -721,23 +794,30 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
private Object sendAndGetResponseWithCheck(MedtronicCommandType commandType, byte[] bodyData) {
for (int retries = 0; retries < MAX_COMMAND_RETRIES; retries++) {
for (int retries = 0; retries < MAX_COMMAND_TRIES; retries++) {
PumpMessage response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT
+ (DEFAULT_TIMEOUT * retries));
try {
PumpMessage response = null;
String check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength);
response = sendAndGetResponse(commandType, bodyData, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries));
if (check == null) {
String check = checkResponseContent(response, commandType.commandDescription,
commandType.expectedLength);
Object dataResponse = medtronicConverter.convertResponse(commandType, response.getRawContent());
if (check == null) {
LOG.debug("Converted response for {} is {}.", commandType.name(), dataResponse);
Object dataResponse = medtronicConverter.convertResponse(commandType, response.getRawContent());
return dataResponse;
} else {
this.errorMessage = check;
// return null;
LOG.debug("Converted response for {} is {}.", commandType.name(), dataResponse);
return dataResponse;
} else {
this.errorMessage = check;
// return null;
}
} catch (RileyLinkCommunicationException e) {
LOG.warn("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1);
}
}
@ -809,65 +889,74 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
MedtronicCommandType commandType = MedtronicCommandType.GetBasalProfileSTD;
for (int retries = 0; retries <= MAX_COMMAND_RETRIES; retries++) {
for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) {
// create message
PumpMessage msg;
try {
// create message
PumpMessage msg;
// if (bodyData == null)
msg = makePumpMessage(commandType);
// if (bodyData == null)
msg = makePumpMessage(commandType);
// send and wait for response
PumpMessage response = sendAndListen(msg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries));
// send and wait for response
PumpMessage response = null;
// LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent()));
// LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData()));
response = sendAndListen(msg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries));
String check = checkResponseContent(response, commandType.commandDescription, commandType.expectedLength);
// LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getRawContent()));
// LOG.debug("1st Response: " + HexDump.toHexStringDisplayable(response.getMessageBody().getTxData()));
byte[] data = null;
String check = checkResponseContent(response, commandType.commandDescription,
commandType.expectedLength);
int runs = 1;
byte[] data = null;
if (check == null) {
int runs = 1;
data = response.getRawContent();
if (check == null) {
PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody());
data = response.getRawContent();
while (checkIfWeHaveMoreData(commandType, response, data)) {
PumpMessage ackMsg = makePumpMessage(MedtronicCommandType.CommandACK, new PumpAckMessageBody());
runs++;
while (checkIfWeHaveMoreData(commandType, response, data)) {
PumpMessage response2 = sendAndListen(ackMsg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries));
runs++;
// LOG.debug("{} Response: {}", runs, HexDump.toHexStringDisplayable(response2.getRawContent()));
// LOG.debug("{} Response: {}", runs,
// HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData()));
PumpMessage response2 = sendAndListen(ackMsg, DEFAULT_TIMEOUT + (DEFAULT_TIMEOUT * retries));
String check2 = checkResponseContent(response2, commandType.commandDescription,
commandType.expectedLength);
// LOG.debug("{} Response: {}", runs,
// HexDump.toHexStringDisplayable(response2.getRawContent()));
// LOG.debug("{} Response: {}", runs,
// HexDump.toHexStringDisplayable(response2.getMessageBody().getTxData()));
if (check2 == null) {
String check2 = checkResponseContent(response2, commandType.commandDescription,
commandType.expectedLength);
data = ByteUtil.concat(data, ByteUtil.substring(response2.getMessageBody().getTxData(), 1));
if (check2 == null) {
} else {
this.errorMessage = check;
data = ByteUtil.concat(data, ByteUtil.substring(response2.getMessageBody().getTxData(), 1));
} else {
this.errorMessage = check;
}
}
} else {
errorMessage = check;
}
} else {
errorMessage = check;
BasalProfile basalProfile = (BasalProfile)medtronicConverter.convertResponse(commandType, data);
LOG.debug("Converted response for {} is {}.", commandType.name(), basalProfile);
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping);
return basalProfile;
} catch (RileyLinkCommunicationException e) {
LOG.warn("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1);
}
BasalProfile basalProfile = (BasalProfile)medtronicConverter.convertResponse(commandType, data);
LOG.debug("Converted response for {} is {}.", commandType.name(), basalProfile);
MedtronicUtil.setPumpDeviceState(PumpDeviceState.Sleeping);
return basalProfile;
}
LOG.warn("Error reading profile in max retries.");
@ -933,45 +1022,46 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
LOG.info("setBolus: " + units);
if (this.doWakeUpBeforeCommand)
wakeUp(false);
return setCommand(MedtronicCommandType.SetBolus, MedtronicUtil.getBolusStrokes(units));
byte[] body = MedtronicUtil.getBolusStrokes(units);
if (debugSetCommands)
LOG.debug("Set Bolus: Body - {}", HexDump.toHexStringDisplayable(body));
PumpMessage msg = makePumpMessage(MedtronicCommandType.SetBolus, //
new CarelinkLongMessageBody(body));
PumpMessage pumpMessage = runCommandWithArgs(msg);
if (debugSetCommands)
LOG.debug("Set Bolus: {}", pumpMessage.getResponseContent());
return pumpMessage.commandType == MedtronicCommandType.CommandACK;
}
public boolean setTBR(TempBasalPair tbr) {
if (this.doWakeUpBeforeCommand)
wakeUp(false);
LOG.info("setTBR: " + tbr.getDescription());
byte[] body = tbr.getAsRawData();
return setCommand(MedtronicCommandType.SetTemporaryBasal, tbr.getAsRawData());
}
if (debugSetCommands)
LOG.debug("Set TBR: Body - {}", HexDump.toHexStringDisplayable(body));
PumpMessage msg = makePumpMessage(MedtronicCommandType.SetTemporaryBasal, //
new CarelinkLongMessageBody(tbr.getAsRawData()));
private boolean setCommand(MedtronicCommandType commandType, byte[] body) {
PumpMessage pumpMessage = runCommandWithArgs(msg);
for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) {
if (debugSetCommands)
LOG.debug("Set TBR: {}", pumpMessage.getResponseContent());
try {
if (this.doWakeUpBeforeCommand)
wakeUp(false);
return pumpMessage.commandType == MedtronicCommandType.CommandACK;
if (debugSetCommands)
LOG.debug("{}: Body - {}", commandType.getCommandDescription(),
HexDump.toHexStringDisplayable(body));
PumpMessage msg = makePumpMessage(commandType, new CarelinkLongMessageBody(body));
PumpMessage pumpMessage = runCommandWithArgs(msg);
if (debugSetCommands)
LOG.debug("{}: {}", commandType.getCommandDescription(), pumpMessage.getResponseContent());
return pumpMessage.commandType == MedtronicCommandType.CommandACK;
} catch (RileyLinkCommunicationException e) {
LOG.warn("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1);
}
}
return false;
}
@ -992,11 +1082,23 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
List<List<Byte>> basalProfileFrames = MedtronicUtil.getBasalProfileFrames(basalProfile.getRawData());
PumpMessage responseMessage = runCommandWithFrames(MedtronicCommandType.SetBasalProfileSTD, basalProfileFrames);
for (int retries = 0; retries <= MAX_COMMAND_TRIES; retries++) {
// LOG.debug("Set Basal Profile: {}", HexDump.toHexStringDisplayable(responseMessage.getRawContent()));
// PumpMessage responseMessage = null;
try {
PumpMessage responseMessage = runCommandWithFrames(MedtronicCommandType.SetBasalProfileSTD,
basalProfileFrames);
return responseMessage.commandType == MedtronicCommandType.CommandACK;
return responseMessage.commandType == MedtronicCommandType.CommandACK;
} catch (RileyLinkCommunicationException e) {
LOG.warn("Error getting response from RileyLink (error={}, retry={})", e.getMessage(), retries + 1);
}
// LOG.debug("Set Basal Profile: {}", HexDump.toHexStringDisplayable(responseMessage.getRawContent()));
}
return false;
}
@ -1006,33 +1108,31 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
// TODO test
// TODO remove, we will see state from History
public PumpMessage getPumpState() {
PumpMessage response = sendAndGetResponse(MedtronicCommandType.PumpState);
byte[] data = response.getRawContent();
LOG.debug("Pump State: {}", HexDump.toHexStringDisplayable(data));
// 3 TBR running ?
return null;
}
// public PumpMessage getPumpState() {
// PumpMessage response = sendAndGetResponse(MedtronicCommandType.PumpState);
//
// byte[] data = response.getRawContent();
//
// LOG.debug("Pump State: {}", HexDump.toHexStringDisplayable(data));
//
// // 3 TBR running ?
//
// return null;
// }
// TODO remove, we will see bolus status from History
public PumpMessage getBolusStatus() {
PumpMessage response = sendAndGetResponse(MedtronicCommandType.SetBolus, new byte[] { 0x03, 0x00, 0x00, 0x00 },
4000);
byte[] data = response.getRawContent();
LOG.debug("Detect bolus: {}", HexDump.toHexStringDisplayable(data));
// 3 TBR running ?
return null;
}
// public PumpMessage getBolusStatus() {
// PumpMessage response = sendAndGetResponse(MedtronicCommandType.SetBolus, new byte[] { 0x03, 0x00, 0x00, 0x00 },
// 4000);
//
// byte[] data = response.getRawContent();
//
// LOG.debug("Detect bolus: {}", HexDump.toHexStringDisplayable(data));
//
// // 3 TBR running ?
//
// return null;
// }
public PumpMessage cancelBolus() {
// ? maybe suspend and resume

View file

@ -248,7 +248,7 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
return decodeDailyTotals(entry); // Not supported at the moment
case SelectBasalProfile:
return RecordDecodeStatus.Ignored; // Not supported at the moment
return RecordDecodeStatus.OK; // Not supported at the moment
// WORK IN PROGRESS
@ -782,6 +782,10 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
int dayOfMonth = dt[0] & 0x1F;
int year = 2000 + (ByteUtil.asUINT8(dt[1]) & 0x7F);
int hour = 0;
int minutes = 0;
int seconds = 0;
// LocalDate rval = new LocalDate(year, month, dayOfMonth);
// int dayOfMonth = dt[0] & 0x1F;
@ -794,17 +798,22 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
if (dayOfMonth == 32) {
// FIXME remove
LOG.debug("Entry: {} = [{}] {}", entry.getEntryType().name(), ByteUtil.getHex(entry.getRawData()),
entry);
LOG.debug("Entry: Day 32 {} = [{}] {}", entry.getEntryType().name(),
ByteUtil.getHex(entry.getRawData()), entry);
}
if (entry.getEntryType() == PumpHistoryEntryType.EndResultTotals) {
atdate = new LocalDateTime(year, month, dayOfMonth, 23, 59, 59);
hour = 23;
minutes = 59;
seconds = 59;
} else {
atdate = new LocalDateTime(year, month, dayOfMonth, 0, 0);
}
entry.setLocalDateTime(atdate);
entry.setAtechDateTime(DateTimeUtil.toATechDate(year, month, dayOfMonth, hour, minutes, seconds));
} else {
LOG.warn("Unknown datetime format: " + entry.getDateTimeLength());
}
@ -824,16 +833,4 @@ public class MedtronicPumpHistoryDecoder extends MedtronicHistoryDecoder {
return year;
}
// WRITE DATA
// private void writeData(PumpBaseType baseType, CodeEnumWithTranslation subType, ATechDate aTechDate) {
// this.pumpValuesWriter.writeObject(baseType.name() + "_" + subType.getName(), aTechDate);
// }
//
//
// private void writeData(PumpBaseType baseType, CodeEnumWithTranslation subType, String value, ATechDate aTechDate)
// {
// this.pumpValuesWriter.writeObject(baseType.name() + "_" + subType.getName(), aTechDate, value);
// }
}

View file

@ -193,14 +193,14 @@ public class MedtronicUIPostprocessor {
checkValue = settings.get("PCFG_MAX_BOLUS");
if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBolus)) {
LOG.error("Wrong Max Bolus set on Pump (must be {}).", pumpStatus.maxBolus);
LOG.error("Wrong Max Bolus set on Pump (current={}, required={}).", checkValue.value, pumpStatus.maxBolus);
sendNotification(MedtronicNotificationType.PumpWrongMaxBolusSet, pumpStatus.maxBolus);
}
checkValue = settings.get("PCFG_MAX_BASAL");
if (!MedtronicUtil.isSame(Double.parseDouble(checkValue.value), pumpStatus.maxBasal)) {
LOG.error("Wrong Max Basal set on Pump (must be {}).", pumpStatus.maxBasal);
LOG.error("Wrong Max Basal set on Pump (current={}, required={}).", checkValue.value, pumpStatus.maxBasal);
sendNotification(MedtronicNotificationType.PumpWrongMaxBasalSet, pumpStatus.maxBasal);
}

View file

@ -88,11 +88,11 @@ public class MedtronicUITask {
}
break;
case PumpState: {
// TODO maybe remove this, data returned is almost useless
returnData = communicationManager.getPumpState();
}
break;
// case PumpState: {
// // TODO maybe remove this, data returned is almost useless
// returnData = communicationManager.getPumpState();
// }
// break;
// case "RefreshData.GetBolus": {
// returnData = communicationManager.getBolusStatus();

View file

@ -109,6 +109,7 @@ public class MedtronicHistoryData {
}
// FIXME not just 50 records, last 24 hours
public void finalizeNewHistoryRecords() {
List<PumpHistoryEntry> filteredListByLastRecord = getFilteredListByLastRecord((PumpHistoryEntryType)null);
@ -151,6 +152,13 @@ public class MedtronicHistoryData {
// TODO This logic might not be working correctly
public boolean isPumpSuspended(Boolean wasPumpSuspended) {
if (true)
return false;
List<PumpHistoryEntry> newAndAll = new ArrayList<>();
newAndAll.addAll(this.allHistory);
newAndAll.addAll(this.newHistory);
if (wasPumpSuspended == null) { // suspension status not known
List<PumpHistoryEntry> items = getFilteredItems(PumpHistoryEntryType.Bolus, //
@ -200,6 +208,9 @@ public class MedtronicHistoryData {
} else {
if (items.size() == 0)
return wasPumpSuspended == null ? false : wasPumpSuspended;
PumpHistoryEntry pumpHistoryEntry = items.get(0);
if (pumpHistoryEntry.getEntryType() == PumpHistoryEntryType.NoDeliveryAlarm || //

View file

@ -115,6 +115,61 @@ public class DailyTotalsDTO {
private void decodeData523(byte[] data) {
LOG.debug("Can't decode DailyTotals523: Body={}", ByteUtil.getHex(data));
// 0x6E 0xB1 0x92
// 0x05 0x00 0x80 0x00 0x00 0x01 0x00 0x00 0x00 0x9A 0x00 0x50 0x34 0x00 0x4A 0x30 0x00 0x0B 0x00
// 0x24 0x00 0x00 0x00 0x00 0x00 0x26 0x01 0x00 0x00 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00 0x80 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0x05 0x00 0x80 0x00 0x00 0x01 0x00 0x00 0x00 0x9A 0x00 0x50 0x34 0x00 0x4A 0x30 0x00 0x0B 0x00
// 0x24 0x00 0x00 0x00 0x00 0x00 0x26 0x01 0x00 0x00
// 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 19:31:40.314 [Thread-47]
// D/info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder:
// [MedtronicPumpHistoryDecoder.decodeDailyTotals():447]: PumpHistoryRecord [type=DailyTotals523 [110, 0x6E],
// DT: 16.11.2018 00:00:00, length=1,2,49(52), data={Raw Data=0x6E 0xB0 0x92 0x05 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00 0x00 0x55 0x00 0x55 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}]
// 19:31:40.318 [Thread-47] D/info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.DailyTotalsDTO:
// [DailyTotalsDTO.decodeData523():117]: Can't decode DailyTotals523: Body=0x05 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00 0x00 0x55 0x00 0x55 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 19:31:40.320 [Thread-47]
// W/info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder:
// [MedtronicPumpHistoryDecoder.createRecords():181]: #0 WIP PumpHistoryRecord [type=DailyTotals523 [110, 0x6E],
// DT: 16.11.2018 00:00:00, length=1,2,49(52), data={Raw Data=0x6E 0xB0 0x92 0x05 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00 0x00 0x55 0x00 0x55 0x64 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}]
// 19:31:40.341 [Thread-47]
// D/info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder:
// [MedtronicPumpHistoryDecoder.decodeDateTime():793]: DT: 2018 11 17
// 19:31:40.342 [Thread-47]
// D/info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder:
// [MedtronicPumpHistoryDecoder.decodeDateTime():793]: DT: 2018 11 17
// 19:31:40.342 [Thread-47]
// D/info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder:
// [MedtronicPumpHistoryDecoder.decodeDailyTotals():446]: DailyTotals523 - 0x6E 0xB1 0x92 0x05 0x00 0x80 0x00
// 0x00 0x01 0x00 0x00 0x00 0x9A 0x00 0x50 0x34 0x00 0x4A 0x30 0x00 0x0B 0x00 0x24 0x00 0x00 0x00 0x00 0x00 0x26
// 0x01 0x00 0x00 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00
// 19:31:40.343 [Thread-47]
// D/info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder:
// [MedtronicPumpHistoryDecoder.decodeDailyTotals():447]: PumpHistoryRecord [type=DailyTotals523 [110, 0x6E],
// DT: 17.11.2018 00:00:00, length=1,2,49(52), data={Raw Data=0x6E 0xB1 0x92 0x05 0x00 0x80 0x00 0x00 0x01 0x00
// 0x00 0x00 0x9A 0x00 0x50 0x34 0x00 0x4A 0x30 0x00 0x0B 0x00 0x24 0x00 0x00 0x00 0x00 0x00 0x26 0x01 0x00 0x00
// 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}]
// 19:31:40.343 [Thread-47] D/info.nightscout.androidaps.plugins.PumpMedtronic.data.dto.DailyTotalsDTO:
// [DailyTotalsDTO.decodeData523():117]: Can't decode DailyTotals523: Body=0x05 0x00 0x80 0x00 0x00 0x01 0x00
// 0x00 0x00 0x9A 0x00 0x50 0x34 0x00 0x4A 0x30 0x00 0x0B 0x00 0x24 0x00 0x00 0x00 0x00 0x00 0x26 0x01 0x00 0x00
// 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 19:31:40.344 [Thread-47]
// W/info.nightscout.androidaps.plugins.PumpMedtronic.comm.history.pump.MedtronicPumpHistoryDecoder:
// [MedtronicPumpHistoryDecoder.createRecords():181]: #60 WIP PumpHistoryRecord [type=DailyTotals523 [110,
// 0x6E], DT: 17.11.2018 00:00:00, length=1,2,49(52), data={Raw Data=0x6E 0xB1 0x92 0x05 0x00 0x80 0x00 0x00
// 0x01 0x00 0x00 0x00 0x9A 0x00 0x50 0x34 0x00 0x4A 0x30 0x00 0x0B 0x00 0x24 0x00 0x00 0x00 0x00 0x00 0x26 0x01
// 0x00 0x00 0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x80 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00
// 0x00}]
}

View file

@ -142,6 +142,22 @@ public class TempBasalPair {
}
public String getDescription() {
String desc = "";
if (isPercent) {
desc = "Rate=" + insulinRate + "%";
} else {
desc = "Rate=" + insulinRate + " U";
}
desc += ", Duration=" + durationMinutes + " min";
return desc;
}
@Override
public String toString() {
return "TempBasalPair [" + "Rate=" + insulinRate + ", DurationMinutes=" + durationMinutes + ", IsPercent="

View file

@ -43,10 +43,10 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
PushButton(0x5b, "Push Button", MinimedTargetType.ActionCommand, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), // 91
RFPowerOn(93, "RF Power On", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(
1, 10)), //
1, 10)), //
RFPowerOff(93, "RF Power Off", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(
0, 0)), //
0, 0)), //
SetSuspend(77, "Set Suspend", MinimedTargetType.InitCommand, MedtronicDeviceType.All, MinimedCommandParameterType.FixedParameters, getByteArray(1)), //
@ -58,7 +58,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
// 511 (InitCommand = 2, Config 7, Data = 1(+3)
DetectBolus(75, "Detect Bolus", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_511, MinimedCommandParameterType.FixedParameters, getByteArray(
0, 0, 0)), //
0, 0, 0)), //
RemoteControlIds(118, "Remote Control Ids", MinimedTargetType.PumpConfiguration_NA, MedtronicDeviceType.All, MinimedCommandParameterType.NoParameters), //
@ -79,7 +79,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
ReadTemporaryBasal(0x98, "Read Temporary Basal", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 5), // 152
SetTemporaryBasal(76, "Set Temp Basal Rate (bolus detection only)", MinimedTargetType.InitCommand, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, getByteArray(
0, 0, 0)),
0, 0, 0)),
// util.getCommand(MinimedCommand.SET_TEMPORARY_BASAL).allowedRetries
// = 0;
@ -109,10 +109,10 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
GetBasalProfileSTD(146, "Get Profile Standard", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8, 1), // 146
GetBasalProfileA(147, "Get Profile A", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 9), // 147
// FIXME
// FIXME
GetBasalProfileB(148, "Get Profile B", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 10), // 148
// FIXME
// FIXME
SetBasalProfileSTD(0x6f, "Set Profile Standard", MinimedTargetType.PumpConfiguration, MedtronicDeviceType.Medtronic_512andHigher, MinimedCommandParameterType.NoParameters, 192, 1, 8), // 111
@ -154,7 +154,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
// Fake Commands
CancelTBR(), ;
CancelTBR(),;
static Map<Byte, MedtronicCommandType> mapByCode;
@ -176,6 +176,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
public byte[] commandParameters = null;
public int commandParametersCount = 0;
public int maxRecords = 1;
private Integer resourceId;
public int command_type = 0;
public int allowedRetries = 2;
public int maxAllowedTime = 2000;
@ -193,33 +194,33 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType) {
MinimedCommandParameterType parameterType) {
this(code, description, targetType, devices, parameterType, 64, 1, 0, 0, 0, 0);
}
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, int expectedLength) {
MinimedCommandParameterType parameterType, int expectedLength) {
this(code, description, targetType, devices, parameterType, 64, 1, 0, 0, 0, expectedLength);
}
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) {
MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) {
this(code, description, targetType, devices, parameterType, recordLength, maxRecords, 0, 0, commandType, 0);
}
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType,
int expectedLength) {
MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType,
int expectedLength) {
this(code, description, targetType, devices, parameterType, recordLength, maxRecords, 0, 0, commandType,
expectedLength);
expectedLength);
}
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, byte[] cmd_params) {
MinimedCommandParameterType parameterType, byte[] cmd_params) {
this(code, description, targetType, devices, parameterType, 0, 1, 0, 0, 11, 0);
this.commandParameters = cmd_params;
@ -228,7 +229,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, byte[] cmd_params, int expectedLength) {
MinimedCommandParameterType parameterType, byte[] cmd_params, int expectedLength) {
this(code, description, targetType, devices, parameterType, 0, 1, 0, 0, 11, expectedLength);
this.commandParameters = cmd_params;
@ -237,7 +238,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType) {
MinimedCommandParameterType parameterType) {
this(code, description, devices, parameterType, 64, 1, 0, null);
}
@ -245,35 +246,36 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices,
MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) {
MinimedCommandParameterType parameterType, int recordLength, int maxRecords, int commandType) {
this(code, description, devices, parameterType, recordLength, maxRecords, 0, null);
}
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int expectedLength) {
MinimedCommandParameterType parameterType, int expectedLength) {
this(code, description, devices, parameterType, 64, 1, expectedLength, null);
}
// NEW
MedtronicCommandType(int code, String description, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int expectedLength, int resourceId) {
MinimedCommandParameterType parameterType, int expectedLength, int resourceId) {
this(code, description, devices, parameterType, 64, 1, expectedLength, resourceId);
}
// NEW
MedtronicCommandType(int code, String description,
MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int expectedLength,
Integer resourceId) {
this.commandCode = (byte)code;
MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int expectedLength,
Integer resourceId) {
this.commandCode = (byte) code;
this.commandDescription = description;
this.devices = devices;
this.recordLength = recordLength;
this.maxRecords = max_recs;
this.resourceId = resourceId;
this.commandParametersCount = 0;
this.allowedRetries = 2;
@ -289,9 +291,9 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
@Deprecated
MedtronicCommandType(int code, String description, MinimedTargetType targetType, MedtronicDeviceType devices, //
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int addy, //
int addy_len, int cmd_type, int expectedLength) {
this.commandCode = (byte)code;
MinimedCommandParameterType parameterType, int recordLength, int max_recs, int addy, //
int addy_len, int cmd_type, int expectedLength) {
this.commandCode = (byte) code;
this.commandDescription = description;
this.targetType = targetType;
this.devices = devices;
@ -326,7 +328,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
byte[] array = new byte[data.length];
for (int i = 0; i < data.length; i++) {
array[i] = (byte)data[i];
array[i] = (byte) data[i];
}
return array;
@ -398,7 +400,7 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
*/
public String getFullCommandDescription() {
return "Command [name=" + this.name() + ", id=" + this.commandCode + ",description=" + this.commandDescription
+ "] ";
+ "] ";
}
@ -446,6 +448,15 @@ public enum MedtronicCommandType implements Serializable // , MinimedCommandType
return name();
}
public String getCommandDescription() {
return this.commandDescription;
}
public Integer getResourceId() {
return resourceId;
}
public enum MinimedCommandParameterType {
NoParameters, //
FixedParameters, //

View file

@ -124,7 +124,7 @@ public class MedtronicPumpStatus extends PumpStatus {
medtronicPumpMap.put("754", PumpType.Medtronic_554_754_Veo);
frequencies = new String[2];
frequencies[0] = MainApp.gs(R.string.medtronic_pump_frequency_us);
frequencies[0] = MainApp.gs(R.string.medtronic_pump_frequency_us_ca);
frequencies[1] = MainApp.gs(R.string.medtronic_pump_frequency_worldwide);
}
@ -139,6 +139,8 @@ public class MedtronicPumpStatus extends PumpStatus {
if (this.medtronicDeviceTypeMap == null)
createMedtronicDeviceTypeMap();
this.errorDescription = "-";
String serialNr = SP.getString(MedtronicConst.Prefs.PumpSerial, null);
if (serialNr == null) {
@ -188,6 +190,7 @@ public class MedtronicPumpStatus extends PumpStatus {
this.errorDescription = MainApp.gs(R.string.medtronic_error_pump_frequency_invalid);
return;
} else {
// if (this.pumpFrequency == null || !this.pumpFrequency.equals(pumpFrequency))
this.pumpFrequency = pumpFrequency;
this.isFrequencyUS = pumpFrequency.equals(frequencies[0]);
@ -195,9 +198,10 @@ public class MedtronicPumpStatus extends PumpStatus {
RileyLinkTargetFrequency.Medtronic_US
: RileyLinkTargetFrequency.Medtronic_WorldWide;
if (targetFrequency == newTargetFrequency) {
if (targetFrequency != newTargetFrequency) {
RileyLinkUtil.setRileyLinkTargetFrequency(newTargetFrequency);
targetFrequencyChanged = true;
targetFrequency = newTargetFrequency;
// targetFrequencyChanged = true;
}
}
@ -206,11 +210,13 @@ public class MedtronicPumpStatus extends PumpStatus {
String rileyLinkAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, null);
if (rileyLinkAddress == null) {
LOG.debug("RileyLink address invalid: null");
this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid);
return;
} else {
if (!rileyLinkAddress.matches(regexMac)) {
this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid);
LOG.debug("RileyLink address invalid: {}", rileyLinkAddress);
} else {
if (!rileyLinkAddress.equals(this.rileyLinkAddress)) {
this.rileyLinkAddress = rileyLinkAddress;
@ -248,13 +254,13 @@ public class MedtronicPumpStatus extends PumpStatus {
rileyLinkAddressChanged = false;
}
if (targetFrequencyChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
RileyLinkUtil.setRileyLinkTargetFrequency(targetFrequency);
RileyLinkUtil.getRileyLinkCommunicationManager().refreshRileyLinkTargetFrequency();
targetFrequencyChanged = false;
}
// if (targetFrequencyChanged && !inPreInit && MedtronicUtil.getMedtronicService() != null) {
// RileyLinkUtil.setRileyLinkTargetFrequency(targetFrequency);
// // RileyLinkUtil.getRileyLinkCommunicationManager().refreshRileyLinkTargetFrequency();
// targetFrequencyChanged = false;
// }
return (!rileyLinkAddressChanged && !serialChanged && !targetFrequencyChanged);
return (!rileyLinkAddressChanged && !serialChanged); // && !targetFrequencyChanged);
}
@ -271,7 +277,7 @@ public class MedtronicPumpStatus extends PumpStatus {
}
if (val > defaultValueDouble) {
SP.putString(MedtronicConst.Prefs.MaxBolus, defaultValue);
SP.putString(key, defaultValue);
val = defaultValueDouble;
}

View file

@ -10,14 +10,12 @@ import android.os.Binder;
import android.os.IBinder;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
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.RileyLinkUtil;
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.defs.RileyLinkEncodingType;
import info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble.defs.RileyLinkTargetFrequency;
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.service.RileyLinkService;
@ -86,15 +84,16 @@ public class RileyLinkMedtronicService extends RileyLinkService {
}
// FIXME remove this, it needs to be set in PumpConfiguration not here
@Override
protected void determineRileyLinkTargetFrequency() {
boolean hasUSFrequency = SP.getString(MedtronicConst.Prefs.PumpFrequency,
MainApp.gs(R.string.medtronic_pump_frequency_us)).equals(MainApp.gs(R.string.medtronic_pump_frequency_us));
if (hasUSFrequency)
RileyLinkUtil.setRileyLinkTargetFrequency(RileyLinkTargetFrequency.Medtronic_US);
else
RileyLinkUtil.setRileyLinkTargetFrequency(RileyLinkTargetFrequency.Medtronic_WorldWide);
// boolean hasUSFrequency = SP.getString(MedtronicConst.Prefs.PumpFrequency,
// MainApp.gs(R.string.medtronic_pump_frequency_us)).equals(MainApp.gs(R.string.medtronic_pump_frequency_us));
//
// if (hasUSFrequency)
// RileyLinkUtil.setRileyLinkTargetFrequency(RileyLinkTargetFrequency.Medtronic_US);
// else
// RileyLinkUtil.setRileyLinkTargetFrequency(RileyLinkTargetFrequency.Medtronic_WorldWide);
}

View file

@ -1,15 +1,15 @@
package info.nightscout.androidaps.plugins.PumpMedtronic.util;
import org.joda.time.LocalTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.joda.time.LocalTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification;
import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification;
@ -71,8 +71,8 @@ public class MedtronicUtil extends RileyLinkUtil {
public static byte[] getByteArrayFromUnsignedShort(int shortValue, boolean returnFixedSize) {
byte highByte = (byte)(shortValue >> 8 & 0xFF);
byte lowByte = (byte)(shortValue & 0xFF);
byte highByte = (byte) (shortValue >> 8 & 0xFF);
byte lowByte = (byte) (shortValue & 0xFF);
if (highByte > 0) {
return createByteArray(highByte, lowByte);
@ -106,7 +106,7 @@ public class MedtronicUtil extends RileyLinkUtil {
public static double decodeBasalInsulin(int i) {
return (double)i / 40.0d;
return (double) i / 40.0d;
}
@ -149,7 +149,7 @@ public class MedtronicUtil extends RileyLinkUtil {
scrollRate = 1;
}
int strokes = (int)(amount * ((strokesPerUnit * 1.0d) / (scrollRate * 1.0d))) * scrollRate;
int strokes = (int) (amount * ((strokesPerUnit * 1.0d) / (scrollRate * 1.0d))) * scrollRate;
byte[] body = ByteUtil.fromHexString(String.format("%02x%0" + (2 * length) + "x", length, strokes));
@ -159,7 +159,7 @@ public class MedtronicUtil extends RileyLinkUtil {
public static byte[] createCommandBody(byte[] input) {
return ByteUtil.concat((byte)input.length, input);
return ByteUtil.concat((byte) input.length, input);
}
@ -187,7 +187,7 @@ public class MedtronicUtil extends RileyLinkUtil {
scrollRate = 2;
}
int strokes = (int)(amount * (strokesPerUnit / (scrollRate * 1.0d)));
int strokes = (int) (amount * (strokesPerUnit / (scrollRate * 1.0d)));
strokes *= scrollRate;
@ -198,18 +198,18 @@ public class MedtronicUtil extends RileyLinkUtil {
public static void sendNotification(MedtronicNotificationType notificationType) {
Notification notification = new Notification( //
notificationType.getNotificationType(), //
MainApp.gs(notificationType.getResourceId()), //
notificationType.getNotificationUrgency());
notificationType.getNotificationType(), //
MainApp.gs(notificationType.getResourceId()), //
notificationType.getNotificationUrgency());
MainApp.bus().post(new EventNewNotification(notification));
}
public static void sendNotification(MedtronicNotificationType notificationType, Object... parameters) {
Notification notification = new Notification( //
notificationType.getNotificationType(), //
MainApp.gs(notificationType.getResourceId(), parameters), //
notificationType.getNotificationUrgency());
notificationType.getNotificationType(), //
MainApp.gs(notificationType.getResourceId(), parameters), //
notificationType.getNotificationUrgency());
MainApp.bus().post(new EventNewNotification(notification));
}
@ -225,21 +225,21 @@ public class MedtronicUtil extends RileyLinkUtil {
public static byte[] buildCommandPayload(MedtronicCommandType commandType, byte[] parameters) {
return buildCommandPayload((byte)commandType.commandCode, parameters);
return buildCommandPayload((byte) commandType.commandCode, parameters);
}
public static byte[] buildCommandPayload(byte commandType, byte[] parameters) {
// A7 31 65 51 C0 00 52
byte commandLength = (byte)(parameters == null ? 2 : 2 + parameters.length);
byte commandLength = (byte) (parameters == null ? 2 : 2 + parameters.length);
ByteBuffer sendPayloadBuffer = ByteBuffer.allocate(ENVELOPE_SIZE + commandLength); // + CRC_SIZE
sendPayloadBuffer.order(ByteOrder.BIG_ENDIAN);
byte[] serialNumberBCD = RileyLinkUtil.getRileyLinkServiceData().pumpIDBytes;
sendPayloadBuffer.put((byte)0xA7);
sendPayloadBuffer.put((byte) 0xA7);
sendPayloadBuffer.put(serialNumberBCD[0]);
sendPayloadBuffer.put(serialNumberBCD[1]);
sendPayloadBuffer.put(serialNumberBCD[2]);
@ -247,9 +247,9 @@ public class MedtronicUtil extends RileyLinkUtil {
sendPayloadBuffer.put(commandType);
if (parameters == null) {
sendPayloadBuffer.put((byte)0x00);
sendPayloadBuffer.put((byte) 0x00);
} else {
sendPayloadBuffer.put((byte)parameters.length); // size
sendPayloadBuffer.put((byte) parameters.length); // size
for (byte val : parameters) {
sendPayloadBuffer.put(val);
@ -298,7 +298,7 @@ public class MedtronicUtil extends RileyLinkUtil {
List<Byte> frameData = ByteUtil.getListFromByteArray(substring);
if (isEmptyFrame(frameData)) {
byte b = (byte)frame;
byte b = (byte) frame;
// b |= 0x80;
b |= 0b1000_0000;
// b |= doneBit;
@ -311,7 +311,7 @@ public class MedtronicUtil extends RileyLinkUtil {
done = true;
} else {
frameData.add(0, (byte)frame);
frameData.add(0, (byte) frame);
}
// System.out.println("Subarray: " + ByteUtil.getCompactString(substring));
@ -330,7 +330,7 @@ public class MedtronicUtil extends RileyLinkUtil {
if (!lastFrame) {
List<Byte> frameData = new ArrayList<>();
byte b = (byte)frame;
byte b = (byte) frame;
b |= 0b1000_0000;
// b |= doneBit;
@ -352,7 +352,7 @@ public class MedtronicUtil extends RileyLinkUtil {
int missing = BIG_FRAME_LENGTH - frameData.size();
for (int i = 0; i < missing; i++) {
frameData.add((byte)0x00);
frameData.add((byte) 0x00);
}
}
@ -411,7 +411,7 @@ public class MedtronicUtil extends RileyLinkUtil {
public static MedtronicCommunicationManager getMedtronicCommunicationManager() {
return (MedtronicCommunicationManager)RileyLinkUtil.rileyLinkCommunicationManager;
return (MedtronicCommunicationManager) RileyLinkUtil.rileyLinkCommunicationManager;
}
@ -448,6 +448,20 @@ public class MedtronicUtil extends RileyLinkUtil {
}
public static int pageNumber;
public static int frameNumber;
public static void setCurrentCommand(MedtronicCommandType currentCommand, int pageNumber_, int frameNumber_) {
pageNumber = pageNumber_;
frameNumber = frameNumber_;
if (MedtronicUtil.currentCommand != currentCommand) {
setCurrentCommand(currentCommand);
}
MainApp.bus().post(new EventMedtronicDeviceStatusChange(pumpDeviceState));
}
public static boolean isSame(Double d1, Double d2) {
double diff = d1 - d2;

View file

@ -158,7 +158,7 @@
</string-array>
<string-array name="medtronicPumpFreqArray">
<item>@string/medtronic_pump_frequency_us</item>
<item>@string/medtronic_pump_frequency_us_ca</item>
<item>@string/medtronic_pump_frequency_worldwide</item>
</string-array>

View file

@ -1231,7 +1231,7 @@
<string name="medtronic_pump_frequency">Pump Frequency</string>
<string name="medtronic_pump_max_bolus">Max Bolus on Pump</string>
<string name="medtronic_pump_max_basal">Max Basal on Pump</string>
<string name="medtronic_pump_frequency_us">US (916 MHz)</string>
<string name="medtronic_pump_frequency_us_ca">US &amp; Canada (916 MHz)</string>
<string name="medtronic_pump_frequency_worldwide">Worldwide (868 Mhz)</string>
<string name="rileylink_mac_address">RileyLink MAC Address</string>
<string name="rileylink_scanner_selected_device">Selected</string>
@ -1317,8 +1317,12 @@
<!-- <string name="medtronic_cmd_profile_not_set">Remote Basal profile setting is not supported. Please modify Basal profile on your pump manually.</string> -->
<string name="medtronic_cmd_cancel_bolus_not_supported">Remote cancel of Bolus is not supported. If you wish to cancel bolus, go to pump put it in suspend and then resume. This will cancel the bolus.</string>
<string name="medtronic_cmd_cant_read_tbr">Could not read current TBR.</string>
<string name="medtronic_cmd_cant_cancel_tbr">Could not cancel current TBR. Stopping operation.</string>
<string name="medtronic_cmd_cant_cancel_tbr_stop_op">Could not cancel current TBR. Stopping operation.</string>
<string name="medtronic_cmd_set_profile_pattern_overflow">Profile set failed, because following patterns, have too big basal rate: %1$s</string>
<string name="medtronic_cmd_bolus_could_not_be_delivered">Bolus could not be delivered.</string>
<string name="medtronic_cmd_tbr_could_not_be_delivered">TBR could not be set.</string>
<string name="medtronic_cmd_cant_cancel_tbr">Could not cancel current TBR.</string>
<string name="medtronic_cmd_basal_profile_could_not_be_set">Basal profile could not be set.</string>
<string name="pump_no_connection_h">No connection for %1$d hour(s) %2$d min</string>

View file

@ -0,0 +1,345 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import android.util.Log;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
/**
* Created by andy on 11/21/18.
*/
@RunWith(Parameterized.class)
public class RFToolsParametrizedUTest {
private static final String TAG = "RFToolsUTest";
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays
.asList(new Object[][] { //
{ ByteUtil.createByteArrayFromCompactString("00"), ByteUtil.createByteArrayFromCompactString("5555") },
//
{
ByteUtil.createByteArrayFromCompactString("0000"),
ByteUtil.createByteArrayFromCompactString("555555") }, //
{
ByteUtil.createByteArrayFromCompactString("A71289865D00BE"),
ByteUtil.createByteArrayFromCompactString("A96C726996A694D5552CE5") }, //
{
ByteUtil.createByteArrayFromCompactString("A7128986060015"),
ByteUtil.createByteArrayFromCompactString("A96C726996A6566555C655") }, //
{
ByteUtil.createByteArrayFromCompactString("A7128986150956"),
ByteUtil.createByteArrayFromCompactString("A96C726996A6C655599665") }, //
{
ByteUtil.createByteArrayFromCompactString("A71289868D00B0"),
ByteUtil.createByteArrayFromCompactString("A96C726996A668D5552D55") }, //
{
ByteUtil
.createByteArrayFromCompactString("A71289868D090337323200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000039"),
ByteUtil
.createByteArrayFromCompactString("A96C726996A668D5595638D68F28F25555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555558D95")
//
}, //
});
}
@Parameterized.Parameter
// first data value (0) is default
public/* NOT private */byte[] decoded;
@Parameterized.Parameter(1)
public/* NOT private */byte[] encoded;
// @Test
public void testEncodeGeoff() {
/*
* {0xa7} -> {0xa9, 0x60}
* {0xa7, 0x12} -> {0xa9, 0x6c, 0x72}
* {0xa7, 0x12, 0xa7} -> {0xa9, 0x6c, 0x72, 0xa9, 0x60}
*/
/* test compare */
// byte[] s1 = { 0, 1, 2 };
// byte[] s2 = { 2, 1, 0, 3 };
// byte[] s3 = { 0, 1, 2, 3 };
// if (ByteUtil.compare(s1, s1) != 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s2) >= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s2, s1) <= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s3) >= 0) {
// LOG.error("test: compare failed.");
// }
// testCompose(new byte[] {(byte)0xa7, (byte)0xa7});
byte[] bs = RFTools.encode4b6b(new byte[] { (byte)0xa7 });
byte[] out = new byte[] { (byte)(0xa9), 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12, (byte)0xa7 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72, (byte)0xa9, 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
}
// @Test
public void testEncodeGo() {
/*
* {0xa7} -> {0xa9, 0x60}
* {0xa7, 0x12} -> {0xa9, 0x6c, 0x72}
* {0xa7, 0x12, 0xa7} -> {0xa9, 0x6c, 0x72, 0xa9, 0x60}
*/
/* test compare */
// byte[] s1 = { 0, 1, 2 };
// byte[] s2 = { 2, 1, 0, 3 };
// byte[] s3 = { 0, 1, 2, 3 };
// if (ByteUtil.compare(s1, s1) != 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s2) >= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s2, s1) <= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s3) >= 0) {
// LOG.error("test: compare failed.");
// }
// testCompose(new byte[] {(byte)0xa7, (byte)0xa7});
byte[] bs = RFTools.encode4b6b_go(new byte[] { (byte)0xa7 });
byte[] out = new byte[] { (byte)(0xa9), 0x65 };
System.out.println("EncodeGo: " + ByteUtil.getHex(bs));
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b_go(new byte[] { (byte)0xa7, 0x12 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b_go(new byte[] { (byte)0xa7, 0x12, (byte)0xa7 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72, (byte)0xa9, 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
}
// @Test
public void testDecodeGo() {
// testCompose(new byte[] {(byte)0xa7, (byte)0xa7});
byte[] bs = RFTools.encode4b6b(new byte[] { (byte)0xa7 });
byte[] out = new byte[] { (byte)(0xa9), 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
}
byte[] back = RFTools.decode4b6b(out);
if (ByteUtil.compare(back, bs) != 0) {
Log.e(
TAG,
"decode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
}
back = RFTools.decode4b6b(out);
if (ByteUtil.compare(back, bs) != 0) {
Log.e(
TAG,
"decode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12, (byte)0xa7 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72, (byte)0xa9, 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
}
back = RFTools.decode4b6b(out);
if (ByteUtil.compare(back, bs) != 0) {
Log.e(
TAG,
"decode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
return;
}
// @Test
// public void ttt_decodeGo() {
//
// RFTools.DecodeResponseDto decodeResponseDto = RFTools.decode6b4b_go(new byte[] {
// (byte)0xF9, (byte)0xE9, 0x63, (byte)0x9E, 0x7F, (byte)0xE6, 0x79, 0x5F, -1, (byte)0xCF, (byte)0xF0 });
//
// if (decodeResponseDto.errorData != null) {
// Log.e(TAG, decodeResponseDto.errorData);
// Assert.assertTrue(false);
// } else {
// Assert.assertTrue(true);
// System.out.println("Response: " + ByteUtil.getHex(decodeResponseDto.data));
// }
//
// }
// @Test
public void testParametrizedGeoffEncode() {
byte[] encodedX = RFTools.encode4b6b(this.decoded);
// if (ByteUtil.compare(encodedX, this.encoded) != 0) {
// Assert.assertEquals(encodedX, encoded);
// }
Assert.assertArrayEquals(encodedX, encoded);
}
@Test
public void geoffDecode() {
byte[] decodedX = RFTools.decode4b6b(this.encoded);
Assert.assertArrayEquals(decoded, decodedX);
}
@Test
public void goDecode() {
RFTools.DecodeResponseDto decodeResponseDto = RFTools.decode4b6b_go(this.encoded);
Assert.assertNull(decodeResponseDto.errorData);
System.out.println("Result: " + ByteUtil.getHex(decodeResponseDto.data));
System.out.println("Expected: " + ByteUtil.getHex(decoded));
Assert.assertArrayEquals(decoded, decodeResponseDto.data);
}
// @Test
public void loopDecode() {
byte[] data = RFTools.decode4b6b_loop(this.encoded);
// RFTools.DecodeResponseDto decodeResponseDto
// Assert.assertNull(decodeResponseDto.errorData);
System.out.println("Result: " + ByteUtil.getHex(data));
System.out.println("Expected: " + ByteUtil.getHex(decoded));
Assert.assertArrayEquals(decoded, data);
}
@Test
public void geoffEncode() {
byte[] encodedX = RFTools.encode4b6b(this.decoded);
Assert.assertArrayEquals(encoded, encodedX);
}
@Test
public void goEncode() {
byte[] encodedX = RFTools.encode4b6b_go(this.decoded);
System.out.println("Result: " + ByteUtil.getHex(encodedX));
System.out.println("Expected: " + ByteUtil.getHex(encoded));
Assert.assertArrayEquals(encoded, encodedX);
}
@Test
public void loopEncode() {
byte[] encodedX = RFTools.encode4b6b_loop(this.decoded);
System.out.println("Result: " + ByteUtil.getHex(encodedX));
System.out.println("Expected: " + ByteUtil.getHex(encoded));
Assert.assertArrayEquals(encoded, encodedX);
}
private short[] createShortArray(byte[] data) {
short[] outData = new short[data.length];
for (int i = 0; i < data.length; i++) {
short d = data[i];
if (d < 0) {
d += 256;
}
outData[i] = d;
}
return outData;
}
}

View file

@ -0,0 +1,224 @@
package info.nightscout.androidaps.plugins.PumpCommon.hw.rileylink.ble;
import junit.framework.Assert;
import org.junit.Test;
import android.util.Log;
import info.nightscout.androidaps.plugins.PumpCommon.utils.ByteUtil;
/**
* Created by andy on 11/21/18.
*/
public class RFToolsUTest {
private static final String TAG = "RFToolsUTest";
@Test
public void testEncodeGeoff() {
/*
* {0xa7} -> {0xa9, 0x60}
* {0xa7, 0x12} -> {0xa9, 0x6c, 0x72}
* {0xa7, 0x12, 0xa7} -> {0xa9, 0x6c, 0x72, 0xa9, 0x60}
*/
/* test compare */
// byte[] s1 = { 0, 1, 2 };
// byte[] s2 = { 2, 1, 0, 3 };
// byte[] s3 = { 0, 1, 2, 3 };
// if (ByteUtil.compare(s1, s1) != 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s2) >= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s2, s1) <= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s3) >= 0) {
// LOG.error("test: compare failed.");
// }
// testCompose(new byte[] {(byte)0xa7, (byte)0xa7});
byte[] bs = RFTools.encode4b6b(new byte[] { (byte)0xa7 });
byte[] out = new byte[] { (byte)(0xa9), 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12, (byte)0xa7 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72, (byte)0xa9, 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
}
@Test
public void testEncodeGo() {
/*
* {0xa7} -> {0xa9, 0x60}
* {0xa7, 0x12} -> {0xa9, 0x6c, 0x72}
* {0xa7, 0x12, 0xa7} -> {0xa9, 0x6c, 0x72, 0xa9, 0x60}
*/
/* test compare */
// byte[] s1 = { 0, 1, 2 };
// byte[] s2 = { 2, 1, 0, 3 };
// byte[] s3 = { 0, 1, 2, 3 };
// if (ByteUtil.compare(s1, s1) != 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s2) >= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s2, s1) <= 0) {
// LOG.error("test: compare failed.");
// }
// if (ByteUtil.compare(s1, s3) >= 0) {
// LOG.error("test: compare failed.");
// }
// testCompose(new byte[] {(byte)0xa7, (byte)0xa7});
byte[] bs = RFTools.encode4b6b_go(new byte[] { (byte)0xa7 });
byte[] out = new byte[] { (byte)(0xa9), 0x65 };
System.out.println("EncodeGo: " + ByteUtil.getHex(bs));
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b_go(new byte[] { (byte)0xa7, 0x12 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b_go(new byte[] { (byte)0xa7, 0x12, (byte)0xa7 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72, (byte)0xa9, 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
}
@Test
public void testDecodeGo() {
// testCompose(new byte[] {(byte)0xa7, (byte)0xa7});
byte[] bs = RFTools.encode4b6b(new byte[] { (byte)0xa7 });
byte[] out = new byte[] { (byte)(0xa9), 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
}
byte[] back = RFTools.decode4b6b(out);
if (ByteUtil.compare(back, bs) != 0) {
Log.e(
TAG,
"decode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
}
back = RFTools.decode4b6b(out);
if (ByteUtil.compare(back, bs) != 0) {
Log.e(
TAG,
"decode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
bs = RFTools.encode4b6b(new byte[] { (byte)0xa7, 0x12, (byte)0xa7 });
out = new byte[] { (byte)(0xa9), 0x6c, 0x72, (byte)0xa9, 0x65 };
if (ByteUtil.compare(bs, out) != 0) {
Log.e(
TAG,
"encode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
}
back = RFTools.decode4b6b(out);
if (ByteUtil.compare(back, bs) != 0) {
Log.e(
TAG,
"decode Data failed: expected " + ByteUtil.shortHexString(out) + " but got "
+ ByteUtil.shortHexString(bs));
Assert.fail();
}
return;
}
@Test
public void ttt_decodeGo() {
RFTools.DecodeResponseDto decodeResponseDto = RFTools
.decode4b6b_go(new byte[] {
(byte)0xF9, (byte)0xE9, 0x63, (byte)0x9E, 0x7F, (byte)0xE6, 0x79, 0x5F, (byte)0xFF, (byte)0xCF,
(byte)0xF0 });
if (decodeResponseDto.errorData != null) {
Log.e(TAG, decodeResponseDto.errorData);
Assert.assertTrue(false);
} else {
Assert.assertTrue(true);
System.out.println("Response: " + ByteUtil.getHex(decodeResponseDto.data));
}
}
@Test
public void goTest() {
System.out.println(RFTools.hi(4, (short)0xa7));
}
}