RFSpyReader -> kt
This commit is contained in:
parent
b00a9bac8e
commit
88072ea752
3 changed files with 102 additions and 140 deletions
|
@ -20,6 +20,7 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||||
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract
|
import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
import info.nightscout.androidaps.plugins.pump.common.events.EventRefreshButtonState
|
import info.nightscout.androidaps.plugins.pump.common.events.EventRefreshButtonState
|
||||||
|
@ -54,8 +55,6 @@ import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil.Comp
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.TimeChangeType
|
import info.nightscout.androidaps.utils.TimeChangeType
|
||||||
import info.nightscout.androidaps.interfaces.ResourceHelper
|
|
||||||
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus
|
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
|
@ -306,12 +305,8 @@ class MedtronicPumpPlugin @Inject constructor(
|
||||||
private val isPumpNotReachable: Boolean
|
private val isPumpNotReachable: Boolean
|
||||||
get() {
|
get() {
|
||||||
val rileyLinkServiceState = rileyLinkServiceData.rileyLinkServiceState
|
val rileyLinkServiceState = rileyLinkServiceData.rileyLinkServiceState
|
||||||
if (rileyLinkServiceState == null) {
|
if (rileyLinkServiceState != RileyLinkServiceState.PumpConnectorReady
|
||||||
aapsLogger.debug(LTag.PUMP, "RileyLink unreachable. RileyLinkServiceState is null.")
|
&& rileyLinkServiceState != RileyLinkServiceState.RileyLinkReady
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (rileyLinkServiceState != RileyLinkServiceState.PumpConnectorReady //
|
|
||||||
&& rileyLinkServiceState != RileyLinkServiceState.RileyLinkReady //
|
|
||||||
&& rileyLinkServiceState != RileyLinkServiceState.TuneUpDevice
|
&& rileyLinkServiceState != RileyLinkServiceState.TuneUpDevice
|
||||||
) {
|
) {
|
||||||
aapsLogger.debug(LTag.PUMP, "RileyLink unreachable.")
|
aapsLogger.debug(LTag.PUMP, "RileyLink unreachable.")
|
||||||
|
@ -998,11 +993,7 @@ class MedtronicPumpPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun workWithStatusRefresh(
|
private fun workWithStatusRefresh(action: StatusRefreshAction, statusRefreshType: MedtronicStatusRefreshType?, time: Long?): Map<MedtronicStatusRefreshType, Long>? {
|
||||||
action: StatusRefreshAction, //
|
|
||||||
statusRefreshType: MedtronicStatusRefreshType?, //
|
|
||||||
time: Long?
|
|
||||||
): Map<MedtronicStatusRefreshType, Long>? {
|
|
||||||
return when (action) {
|
return when (action) {
|
||||||
StatusRefreshAction.Add -> {
|
StatusRefreshAction.Add -> {
|
||||||
statusRefreshMap[statusRefreshType!!] = time!!
|
statusRefreshMap[statusRefreshType!!] = time!!
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble;
|
|
||||||
|
|
||||||
import android.os.SystemClock;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes;
|
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType;
|
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult;
|
|
||||||
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
|
|
||||||
import info.nightscout.androidaps.plugins.pump.common.utils.ThreadUtil;
|
|
||||||
import info.nightscout.shared.logging.AAPSLogger;
|
|
||||||
import info.nightscout.shared.logging.LTag;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by geoff on 5/26/16.
|
|
||||||
*/
|
|
||||||
public class RFSpyReader {
|
|
||||||
|
|
||||||
private final AAPSLogger aapsLogger;
|
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
|
||||||
private final RileyLinkBLE rileyLinkBle;
|
|
||||||
private final Semaphore waitForRadioData = new Semaphore(0, true);
|
|
||||||
private final LinkedBlockingQueue<byte[]> mDataQueue = new LinkedBlockingQueue<>();
|
|
||||||
private int acquireCount = 0;
|
|
||||||
private int releaseCount = 0;
|
|
||||||
private boolean stopAtNull = true;
|
|
||||||
|
|
||||||
|
|
||||||
RFSpyReader(AAPSLogger aapsLogger, RileyLinkBLE rileyLinkBle) {
|
|
||||||
this.aapsLogger = aapsLogger;
|
|
||||||
this.rileyLinkBle = rileyLinkBle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void setRileyLinkEncodingType(RileyLinkEncodingType encodingType) {
|
|
||||||
aapsLogger.debug("setRileyLinkEncodingType: " + encodingType);
|
|
||||||
stopAtNull = !(encodingType == RileyLinkEncodingType.Manchester || //
|
|
||||||
encodingType == RileyLinkEncodingType.FourByteSixByteRileyLink);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This timeout must be coordinated with the length of the RFSpy radio operation or Bad Things Happen.
|
|
||||||
byte[] poll(int timeout_ms) {
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, ThreadUtil.sig() + "Entering poll at t==" + SystemClock.uptimeMillis() + ", timeout is " + timeout_ms
|
|
||||||
+ " mDataQueue size is " + mDataQueue.size());
|
|
||||||
|
|
||||||
if (mDataQueue.isEmpty()) {
|
|
||||||
try {
|
|
||||||
// block until timeout or data available.
|
|
||||||
// returns null if timeout.
|
|
||||||
byte[] dataFromQueue = mDataQueue.poll(timeout_ms, TimeUnit.MILLISECONDS);
|
|
||||||
if (dataFromQueue != null) {
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Got data [" + ByteUtil.shortHexString(dataFromQueue) + "] at t=="
|
|
||||||
+ SystemClock.uptimeMillis());
|
|
||||||
} else {
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, "Got data [null] at t==" + SystemClock.uptimeMillis());
|
|
||||||
}
|
|
||||||
return dataFromQueue;
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "poll: Interrupted waiting for data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Call this from the "response count" notification handler.
|
|
||||||
void newDataIsAvailable() {
|
|
||||||
releaseCount++;
|
|
||||||
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, ThreadUtil.sig() + "waitForRadioData released(count=" + releaseCount + ") at t="
|
|
||||||
+ SystemClock.uptimeMillis());
|
|
||||||
waitForRadioData.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void start() {
|
|
||||||
executor.execute(() -> {
|
|
||||||
UUID serviceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO);
|
|
||||||
UUID radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA);
|
|
||||||
BLECommOperationResult result;
|
|
||||||
//noinspection InfiniteLoopStatement
|
|
||||||
while (true) {
|
|
||||||
try {
|
|
||||||
acquireCount++;
|
|
||||||
waitForRadioData.acquire();
|
|
||||||
aapsLogger.debug(LTag.PUMPBTCOMM, ThreadUtil.sig() + "waitForRadioData acquired (count=" + acquireCount + ") at t="
|
|
||||||
+ SystemClock.uptimeMillis());
|
|
||||||
SystemClock.sleep(100);
|
|
||||||
SystemClock.sleep(1);
|
|
||||||
result = rileyLinkBle.readCharacteristicBlocking(serviceUUID, radioDataUUID);
|
|
||||||
SystemClock.sleep(100);
|
|
||||||
|
|
||||||
if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) {
|
|
||||||
if (stopAtNull) {
|
|
||||||
// only data up to the first null is valid
|
|
||||||
for (int i = 0; i < result.value.length; i++) {
|
|
||||||
if (result.value[i] == 0) {
|
|
||||||
result.value = ByteUtil.substring(result.value, 0, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mDataQueue.add(result.value);
|
|
||||||
} else if (result.resultCode == BLECommOperationResult.RESULT_INTERRUPTED) {
|
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "Read operation was interrupted");
|
|
||||||
} else if (result.resultCode == BLECommOperationResult.RESULT_TIMEOUT) {
|
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "Read operation on Radio Data timed out");
|
|
||||||
} else if (result.resultCode == BLECommOperationResult.RESULT_BUSY) {
|
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "FAIL: RileyLinkBLE reports operation already in progress");
|
|
||||||
} else if (result.resultCode == BLECommOperationResult.RESULT_NONE) {
|
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "FAIL: got invalid result code: " + result.resultCode);
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
aapsLogger.error(LTag.PUMPBTCOMM, "Interrupted while waiting for data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble
|
||||||
|
|
||||||
|
import android.os.SystemClock
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.GattAttributes
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.operations.BLECommOperationResult
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.utils.ThreadUtil
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue
|
||||||
|
import java.util.concurrent.Semaphore
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by geoff on 5/26/16.
|
||||||
|
*/
|
||||||
|
class RFSpyReader internal constructor(private val aapsLogger: AAPSLogger, private val rileyLinkBle: RileyLinkBLE) {
|
||||||
|
|
||||||
|
private var executor = Executors.newSingleThreadExecutor()
|
||||||
|
private val waitForRadioData = Semaphore(0, true)
|
||||||
|
private val mDataQueue = LinkedBlockingQueue<ByteArray>()
|
||||||
|
private var acquireCount = 0
|
||||||
|
private var releaseCount = 0
|
||||||
|
private var stopAtNull = true
|
||||||
|
fun setRileyLinkEncodingType(encodingType: RileyLinkEncodingType) {
|
||||||
|
aapsLogger.debug("setRileyLinkEncodingType: $encodingType")
|
||||||
|
stopAtNull = !(encodingType == RileyLinkEncodingType.Manchester || encodingType == RileyLinkEncodingType.FourByteSixByteRileyLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This timeout must be coordinated with the length of the RFSpy radio operation or Bad Things Happen.
|
||||||
|
fun poll(timeout_ms: Int): ByteArray? {
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "${ThreadUtil.sig()}Entering poll at t==${SystemClock.uptimeMillis()}, timeout is $timeout_ms mDataQueue size is ${mDataQueue.size}")
|
||||||
|
if (mDataQueue.isEmpty()) {
|
||||||
|
try {
|
||||||
|
// block until timeout or data available.
|
||||||
|
// returns null if timeout.
|
||||||
|
val dataFromQueue = mDataQueue.poll(timeout_ms.toLong(), TimeUnit.MILLISECONDS)
|
||||||
|
if (dataFromQueue != null)
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Got data [${ByteUtil.shortHexString(dataFromQueue)}] at t==${SystemClock.uptimeMillis()}")
|
||||||
|
else
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "Got data [null] at t==" + SystemClock.uptimeMillis())
|
||||||
|
return dataFromQueue
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "poll: Interrupted waiting for data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call this from the "response count" notification handler.
|
||||||
|
fun newDataIsAvailable() {
|
||||||
|
releaseCount++
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "${ThreadUtil.sig()}waitForRadioData released(count=$releaseCount) at t=${SystemClock.uptimeMillis()}")
|
||||||
|
waitForRadioData.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun start() {
|
||||||
|
executor.execute {
|
||||||
|
val serviceUUID = UUID.fromString(GattAttributes.SERVICE_RADIO)
|
||||||
|
val radioDataUUID = UUID.fromString(GattAttributes.CHARA_RADIO_DATA)
|
||||||
|
var result: BLECommOperationResult
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
acquireCount++
|
||||||
|
waitForRadioData.acquire()
|
||||||
|
aapsLogger.debug(LTag.PUMPBTCOMM, "${ThreadUtil.sig()}waitForRadioData acquired (count=$acquireCount) at t=${SystemClock.uptimeMillis()}")
|
||||||
|
SystemClock.sleep(100)
|
||||||
|
result = rileyLinkBle.readCharacteristicBlocking(serviceUUID, radioDataUUID)
|
||||||
|
SystemClock.sleep(100)
|
||||||
|
if (result.resultCode == BLECommOperationResult.RESULT_SUCCESS) {
|
||||||
|
if (stopAtNull) {
|
||||||
|
// only data up to the first null is valid
|
||||||
|
for (i in result.value.indices) {
|
||||||
|
if (result.value[i].toInt() == 0) {
|
||||||
|
result.value = ByteUtil.substring(result.value, 0, i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDataQueue.add(result.value)
|
||||||
|
} else if (result.resultCode == BLECommOperationResult.RESULT_INTERRUPTED)
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "Read operation was interrupted")
|
||||||
|
else if (result.resultCode == BLECommOperationResult.RESULT_TIMEOUT)
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "Read operation on Radio Data timed out")
|
||||||
|
else if (result.resultCode == BLECommOperationResult.RESULT_BUSY)
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "FAIL: RileyLinkBLE reports operation already in progress")
|
||||||
|
else if (result.resultCode == BLECommOperationResult.RESULT_NONE)
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "FAIL: got invalid result code: ${result.resultCode}")
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
aapsLogger.error(LTag.PUMPBTCOMM, "Interrupted while waiting for data")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue