正在查看: xDrip+ v04633772025.07.16 应用的 MedtrumCollectionService.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
正在查看: xDrip+ v04633772025.07.16 应用的 MedtrumCollectionService.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
package com.eveningoutpost.dexdrip.cgm.medtrum;
import android.annotation.SuppressLint;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.PowerManager;
import android.text.SpannableString;
import android.util.Pair;
import androidx.appcompat.R$styleable;
import com.eveningoutpost.dexdrip.Home;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.AnnexARx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.AuthRx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.AuthTx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.BackFillRx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.BackFillTx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.BaseMessage;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.CalibrateRx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.CalibrateTx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.ConnParamRx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.ConnParamTx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.InboundStream;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.StatusRx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.StatusTx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.TimeRx;
import com.eveningoutpost.dexdrip.cgm.medtrum.messages.TimeTx;
import com.eveningoutpost.dexdrip.importedlibraries.usbserial.driver.UsbId;
import com.eveningoutpost.dexdrip.importedlibraries.usbserial.util.HexDump;
import com.eveningoutpost.dexdrip.models.ActiveBluetoothDevice;
import com.eveningoutpost.dexdrip.models.BgReading;
import com.eveningoutpost.dexdrip.models.JoH;
import com.eveningoutpost.dexdrip.models.Prediction;
import com.eveningoutpost.dexdrip.models.TransmitterData;
import com.eveningoutpost.dexdrip.models.UserError;
import com.eveningoutpost.dexdrip.services.JamBaseBluetoothService;
import com.eveningoutpost.dexdrip.ui.helpers.Span;
import com.eveningoutpost.dexdrip.utilitymodels.BgGraphBuilder;
import com.eveningoutpost.dexdrip.utilitymodels.Inevitable;
import com.eveningoutpost.dexdrip.utilitymodels.PersistentStore;
import com.eveningoutpost.dexdrip.utilitymodels.Pref;
import com.eveningoutpost.dexdrip.utilitymodels.RxBleProvider;
import com.eveningoutpost.dexdrip.utilitymodels.StatusItem;
import com.eveningoutpost.dexdrip.utils.BtCallBack;
import com.eveningoutpost.dexdrip.utils.DexCollectionType;
import com.eveningoutpost.dexdrip.utils.DisconnectReceiver;
import com.eveningoutpost.dexdrip.utils.bt.Subscription;
import com.eveningoutpost.dexdrip.utils.framework.WakeLockTrampoline;
import com.eveningoutpost.dexdrip.xdrip;
import com.polidea.rxandroidble2.RxBleClient;
import com.polidea.rxandroidble2.RxBleConnection;
import com.polidea.rxandroidble2.RxBleDevice;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import java.security.InvalidAlgorithmParameterException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class MedtrumCollectionService extends JamBaseBluetoothService implements BtCallBack {
private static final String STATIC_TAG = "MedtrumCollectionService";
private static volatile String address = "";
private static volatile Subscription connectionSubscription = null;
private static long failover_time = 0;
private static volatile Subscription indicationSubscription = null;
public static volatile String lastErrorState = "";
public static volatile String lastState = "Not running";
private static long last_wake_up_time;
private static volatile Subscription notificationSubscription;
private static long retry_time;
private static Scanner scanner;
private static long serial;
private static PendingIntent serviceFailoverIntent;
private static PendingIntent serviceIntent;
private static volatile Subscription stateSubscription;
private volatile RxBleDevice bleDevice;
private volatile RxBleConnection connection;
private static volatile STATE state = STATE.INIT;
private static volatile STATE last_automata_state = STATE.CLOSED;
private static volatile boolean listen_connected = false;
private static long retry_backoff = 0;
private static long lastRecordTime = -1;
private static volatile long lastInteractionTime = -1;
private static int requestedBackfillSize = 0;
private static AnnexARx lastAnnex = null;
private static long wakeup_time = 0;
private static long wakeup_jitter = 0;
private static long max_wakeup_jitter = 0;
protected String TAG = getClass().getSimpleName();
private final RxBleClient rxBleClient = RxBleProvider.getSingleton();
public static ObservableSource lambda$enable_features_and_listen$1(Observable observable) throws Exception {
return observable;
}
public static ObservableSource lambda$enable_features_and_listen$5(Observable observable) throws Exception {
return observable;
}
public enum STATE {
INIT("Initializing"),
SCAN("Scanning"),
CONNECT("Waiting connect"),
ENABLE("Enabling"),
DISCOVER("Examining"),
SET_TIME("Setting Time"),
SET_CONN_PARAM("Setting Parameters"),
CALIBRATE("Check Calibration"),
LISTEN("Listening"),
GET_DATA("Getting Data"),
CLOSE("Sleeping"),
CLOSED("Deep Sleeping");
private static List<STATE> sequence;
private final String str;
static {
STATE state = ENABLE;
STATE state2 = SET_TIME;
STATE state3 = SET_CONN_PARAM;
STATE state4 = CALIBRATE;
STATE state5 = LISTEN;
STATE state6 = GET_DATA;
ArrayList arrayList = new ArrayList();
sequence = arrayList;
arrayList.add(state);
sequence.add(state6);
sequence.add(state2);
sequence.add(state3);
sequence.add(state4);
sequence.add(state5);
}
STATE(String str) {
this.str = str;
}
public String getString() {
return this.str;
}
public STATE next() {
try {
List<STATE> list = sequence;
return list.get(list.indexOf(this) + 1);
} catch (Exception unused) {
return LISTEN;
}
}
}
@Override
public synchronized boolean automata() {
PowerManager.WakeLock wakeLock;
try {
if (last_automata_state == state && !JoH.ratelimit("jam-g5-dupe-auto", 2)) {
UserError.Log.d(this.TAG, "Ignoring duplicate automata state within 2 seconds: " + state);
}
switch (AnonymousClass1.$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[state.ordinal()]) {
case 1:
initialize();
break;
case 2:
scan_for_device();
break;
case 3:
connect_to_device();
break;
case 4:
retry_backoff = 0L;
enable_features_and_listen();
break;
case 5:
changeState(state.next());
break;
case 6:
check_calibrate();
break;
case 7:
get_data();
break;
case 8:
if (JoH.pratelimit("medtrum-set-time-" + serial, 60)) {
sendTx(new TimeTx());
break;
} else {
changeState(state.next());
break;
}
case 9:
sendTx(new ConnParamTx());
break;
case 10:
stopConnect();
setRetryTimer();
state = STATE.CLOSED;
break;
case 11:
setRetryTimer();
break;
case 12:
status("Listening");
if (notificationSubscription == null || notificationSubscription.isUnsubscribed()) {
changeState(STATE.SCAN);
break;
}
break;
}
} finally {
JoH.releaseWakeLock(wakeLock);
}
last_automata_state = state;
wakeLock = JoH.getWakeLock("jam-g5-automata", UsbId.SILABS_CP2102);
return true;
}
private void initialize() {
long serial2 = Medtrum.getSerial();
serial = serial2;
if (serial2 != 0) {
changeState(STATE.SCAN);
return;
}
if (JoH.ratelimit("medtrum-cannot-start", R$styleable.AppCompatTheme_windowFixedWidthMajor)) {
UserError.Log.e(this.TAG, "Medtrum cannot start without serial number - please rescan");
}
JoH.static_toast_long("Medtrum cannot start without serial number - please rescan");
}
private void scan_for_device() {
status(xdrip.gs(2131756235));
UserError.Log.d(this.TAG, "Scanning for device");
scanner.setAddress(address).scan();
}
private void connect_to_device() {
if (JoH.quietratelimit("medtrum-connect-cooldown", 2)) {
status("Connecting");
UserError.Log.d(this.TAG, "Connecting to device: " + address);
connect_to_device(false);
}
}
private synchronized void enable_features_and_listen() {
UserError.Log.d(this.TAG, "enable features - enter");
stopListening();
if (this.connection != null) {
Observable observable = this.connection.setupNotification(Const.CGM_CHARACTERISTIC_NOTIFY);
TimeUnit timeUnit = TimeUnit.SECONDS;
notificationSubscription = new Subscription(observable.timeout(7200L, timeUnit).observeOn(Schedulers.newThread()).doOnNext(new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$enable_features_and_listen$0((Observable) obj);
}
}).flatMap(new Function() {
public final Object apply(Object obj) {
ObservableSource lambda$enable_features_and_listen$1;
lambda$enable_features_and_listen$1 = MedtrumCollectionService.lambda$enable_features_and_listen$1((Observable) obj);
return lambda$enable_features_and_listen$1;
}
}).subscribe(new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$enable_features_and_listen$2((byte[]) obj);
}
}, new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$enable_features_and_listen$3((Throwable) obj);
}
}));
final InboundStream inboundStream = new InboundStream();
indicationSubscription = new Subscription(this.connection.setupIndication(Const.CGM_CHARACTERISTIC_INDICATE).timeout(7200L, timeUnit).observeOn(Schedulers.newThread()).doOnNext(new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$enable_features_and_listen$4((Observable) obj);
}
}).flatMap(new Function() {
public final Object apply(Object obj) {
ObservableSource lambda$enable_features_and_listen$5;
lambda$enable_features_and_listen$5 = MedtrumCollectionService.lambda$enable_features_and_listen$5((Observable) obj);
return lambda$enable_features_and_listen$5;
}
}).subscribe(new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$enable_features_and_listen$7(inboundStream, (byte[]) obj);
}
}, new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$enable_features_and_listen$8((Throwable) obj);
}
}));
} else {
UserError.Log.e(this.TAG, "Connection null when trying to set notifications");
}
}
public void lambda$enable_features_and_listen$0(Observable observable) throws Exception {
UserError.Log.d(this.TAG, "Notifications enabled");
}
public void lambda$enable_features_and_listen$2(byte[] bArr) throws Exception {
PowerManager.WakeLock wakeLock = JoH.getWakeLock("medtrum-receive-n", UsbId.SILABS_CP2102);
try {
UserError.Log.d(this.TAG, "Received notification bytes: " + JoH.bytesToHex(bArr));
lastInteractionTime = JoH.tsl();
setFailOverTimer();
lastAnnex = new AnnexARx(bArr);
UserError.Log.d(this.TAG, "Notification: " + lastAnnex.toS());
createRecordFromAnnexData(lastAnnex);
backFillIfNeeded(lastAnnex);
} finally {
JoH.releaseWakeLock(wakeLock);
}
}
public void lambda$enable_features_and_listen$3(Throwable th) throws Exception {
UserError.Log.d(this.TAG, "notification throwable: " + th);
}
public void lambda$enable_features_and_listen$4(Observable observable) throws Exception {
UserError.Log.d(this.TAG, "Indications enabled");
sendTx(new AuthTx(serial));
}
public void lambda$enable_features_and_listen$7(final InboundStream inboundStream, byte[] bArr) throws Exception {
PowerManager.WakeLock wakeLock = JoH.getWakeLock("medtrum-receive-i", UsbId.SILABS_CP2102);
try {
UserError.Log.d(this.TAG, "Received indication bytes: " + JoH.bytesToHex(bArr));
if (inboundStream.hasSomeData() && JoH.msSince(lastInteractionTime) > 10000) {
UserError.Log.d(this.TAG, "Resetting stream due to earlier timeout");
}
lastInteractionTime = JoH.tsl();
inboundStream.push(bArr);
if (!checkAndProcessInboundStream(inboundStream)) {
Inevitable.task("mt-reset-stream-no-data", 3000L, new Runnable() {
@Override
public final void run() {
MedtrumCollectionService.this.lambda$enable_features_and_listen$6(inboundStream);
}
});
}
} finally {
JoH.releaseWakeLock(wakeLock);
}
}
public void lambda$enable_features_and_listen$6(InboundStream inboundStream) {
if (inboundStream.hasSomeData()) {
UserError.Log.d(this.TAG, "Resetting stream as incomplete after 3s");
inboundStream.reset();
}
}
public void lambda$enable_features_and_listen$8(Throwable th) throws Exception {
UserError.Log.d(this.TAG, "indication throwable: " + th);
}
private boolean checkAndProcessInboundStream(InboundStream inboundStream) {
if (!inboundStream.isComplete()) {
return false;
}
final byte[] byteSequence = inboundStream.getByteSequence();
inboundStream.reset();
Inevitable.task("mt-stream-done:" + JoH.tsl(), 50L, new Runnable() {
@Override
public final void run() {
MedtrumCollectionService.this.lambda$checkAndProcessInboundStream$9(byteSequence);
}
});
return true;
}
private synchronized void connect_to_device(boolean z) {
if (state == STATE.CONNECT) {
if (address != null && address.length() > 6) {
status("Connecting");
stopConnect();
this.bleDevice = this.rxBleClient.getBleDevice(address);
stateSubscription = new Subscription(this.bleDevice.observeConnectionStateChanges().subscribeOn(Schedulers.io()).subscribe(new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.onConnectionStateChange((RxBleConnection.RxBleConnectionState) obj);
}
}, new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$connect_to_device$10((Throwable) obj);
}
}));
listen_connected = false;
connectionSubscription = new Subscription(this.bleDevice.establishConnection(false).timeout(7200L, TimeUnit.SECONDS).subscribeOn(Schedulers.io()).subscribe(new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.onConnectionReceived((RxBleConnection) obj);
}
}, new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.onConnectionFailure((Throwable) obj);
}
}));
} else {
UserError.Log.wtf(this.TAG, "No transmitter mac address!");
changeState(STATE.SCAN);
}
} else {
UserError.Log.wtf(this.TAG, "Attempt to connect when not in CONNECT state");
}
}
public void lambda$connect_to_device$10(Throwable th) throws Exception {
UserError.Log.wtf(this.TAG, "Got Error from state subscription: " + th);
}
private void get_data() {
status("Asking for data");
sendTx(new StatusTx());
}
private void check_calibrate() {
Pair<Long, Integer> calibration = Medtrum.getCalibration();
if (calibration != null) {
status("Calibrating");
try {
sendTx(new CalibrateTx(serial, ((Long) calibration.first).longValue(), ((Integer) calibration.second).intValue()));
return;
} catch (InvalidAlgorithmParameterException e) {
UserError.Log.wtf(this.TAG, "Cannot calibrate: " + e);
return;
}
}
changeState(state.next());
}
private void sendTx(final BaseMessage baseMessage) {
if (this.connection != null) {
try {
this.connection.writeCharacteristic(Const.CGM_CHARACTERISTIC_INDICATE, JamBaseBluetoothService.nn(baseMessage.getByteSequence())).subscribe(new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$sendTx$11(baseMessage, (byte[]) obj);
}
}, new Consumer() {
public final void accept(Object obj) {
MedtrumCollectionService.this.lambda$sendTx$12(baseMessage, (Throwable) obj);
}
});
} catch (NullPointerException e) {
UserError.Log.e(this.TAG, "Race condition when writing characteristic: " + e);
}
}
}
public void lambda$sendTx$11(BaseMessage baseMessage, byte[] bArr) throws Exception {
UserError.Log.d(this.TAG, "Wrote " + baseMessage.getClass().getSimpleName() + " request: ");
}
public void lambda$sendTx$12(BaseMessage baseMessage, Throwable th) throws Exception {
UserError.Log.e(this.TAG, "Failed to write " + baseMessage.getClass().getSimpleName() + " " + th);
}
public void lambda$checkAndProcessInboundStream$9(byte[] bArr) {
String str;
boolean z;
if (bArr == null) {
UserError.Log.e(this.TAG, "Was passed null in parseInbound");
}
if (bArr.length < 2) {
UserError.Log.e(this.TAG, "Packet too short");
return;
}
int i = bArr[1] & 255;
if (i == 5) {
AuthRx authRx = new AuthRx(bArr);
if (authRx.isValid()) {
status("Authenticated");
} else {
errorStatus("AUTHENTICATION FAILED!");
if (JoH.ratelimit("medtrum-auth-fail", 600)) {
UserError.Log.wtf(this.TAG, "Auth packet failure: " + serial + authRx.toS());
}
}
changeState(state.next());
return;
}
if (i == 10) {
UserError.Log.d(this.TAG, "Got connection parameter reply");
ConnParamRx connParamRx = new ConnParamRx(bArr);
status("Parameter reply");
if (!connParamRx.isValid()) {
UserError.Log.e(this.TAG, "Got invalid connection parameter reply msg");
}
changeState(state.next());
return;
}
if (i == 87) {
TimeRx timeRx = new TimeRx(bArr);
StringBuilder sb = new StringBuilder();
sb.append("Got time set reply: ");
sb.append(timeRx.isValid() ? "VALID" : "INVALID");
String sb2 = sb.toString();
if (timeRx.isValid()) {
status("Set time");
UserError.Log.d(this.TAG, sb2);
} else {
status("Error setting time");
UserError.Log.e(this.TAG, sb2);
}
changeState(STATE.SET_CONN_PARAM);
return;
}
switch (i) {
case 64:
UserError.Log.d(this.TAG, "Got calibration reply");
Medtrum.clearCalibration();
CalibrateRx calibrateRx = new CalibrateRx(bArr);
if (calibrateRx.isOk()) {
str = "Calibration OK";
} else {
str = "Calibration Error " + calibrateRx.getErrorCode();
}
status(str);
UserError.Log.ueh(this.TAG, str);
JoH.static_toast_long(str);
changeState(state.next());
break;
case androidx.constraintlayout.widget.R$styleable.ConstraintSet_layout_constraintVertical_bias:
StatusRx statusRx = new StatusRx(bArr);
UserError.Log.d(this.TAG, statusRx.toS());
if (statusRx.isValid()) {
lastAnnex = statusRx.getAnnex();
statusRx.getAnnex().processForTimeKeeper(serial);
createRecordFromAnnexData(statusRx.getAnnex());
z = backFillIfNeeded(statusRx.getAnnex());
} else {
z = false;
}
changeState(state.next(), z ? 1500 : 100);
break;
case 66:
UserError.Log.d(this.TAG, "Got backfill reply");
status("Got back fill");
processBackFillPacket(bArr);
break;
default:
UserError.Log.d(this.TAG, "Unknown inbound opcode: " + i);
UserError.Log.e(this.TAG, "Received unknown inbound packet: " + HexDump.dumpHexString(bArr));
break;
}
}
private void processBackFillPacket(byte[] bArr) {
BackFillRx backFillRx;
String str;
BackFillRx backFillRx2 = new BackFillRx(bArr);
UserError.Log.d(this.TAG, backFillRx2.toS());
if (backFillRx2.isOk()) {
List<Integer> rawList = backFillRx2.getRawList();
if (rawList != null) {
int i = 0;
boolean z = false;
while (i < rawList.size()) {
long timeStampFromTickCounter = TimeKeeper.timeStampFromTickCounter(serial, backFillRx2.sequenceStart + i);
UserError.Log.d(this.TAG, "Backsie: id:" + (backFillRx2.sequenceStart + i) + " raw:" + rawList.get(i) + " @ " + JoH.dateTimeText(timeStampFromTickCounter));
long msSince = JoH.msSince(timeStampFromTickCounter);
if (msSince > 21600000 || msSince < 0) {
backFillRx = backFillRx2;
UserError.Log.wtf(this.TAG, "Backfill timestamp unrealistic: " + JoH.dateTimeText(timeStampFromTickCounter) + " (ignored)");
} else {
double glucose = backFillRx2.getGlucose(rawList.get(i).intValue());
int sensorRawEmulateDex = backFillRx2.getSensorRawEmulateDex(rawList.get(i).intValue());
if (BgReading.getForPreciseTimestamp(timeStampFromTickCounter, 150000L) == null) {
if (isNative()) {
if (glucose > BgReading.BESTOFFSET) {
backFillRx = backFillRx2;
str = "Medtrum2nd";
BgReading.bgReadingInsertMedtrum(glucose, timeStampFromTickCounter, "Backfill", sensorRawEmulateDex);
UserError.Log.d(this.TAG, "Adding native backfilled reading: " + JoH.dateTimeText(timeStampFromTickCounter) + " " + BgGraphBuilder.unitized_string_static(glucose));
} else {
backFillRx = backFillRx2;
str = "Medtrum2nd";
}
double d = sensorRawEmulateDex;
BgReading createFromRawNoSave = BgReading.createFromRawNoSave(null, null, d, d, timeStampFromTickCounter);
double d2 = createFromRawNoSave.calculated_value;
if (d2 > BgReading.BESTOFFSET) {
Prediction.create(createFromRawNoSave.timestamp, (int) d2, str).save();
}
} else {
backFillRx = backFillRx2;
if (glucose > BgReading.BESTOFFSET) {
Prediction.create(timeStampFromTickCounter, (int) glucose, "Medtrum2nd").save();
}
double d3 = sensorRawEmulateDex;
BgReading create = BgReading.create(d3, d3, xdrip.getAppContext(), Long.valueOf(timeStampFromTickCounter));
if (create != null) {
UserError.Log.d(this.TAG, "Backfilled BgReading created: " + create.uuid + " " + JoH.dateTimeText(create.timestamp));
} else {
UserError.Log.d(this.TAG, "BgReading null!");
}
}
Inevitable.task("backfill-ui-update", 3000L, new Runnable() {
@Override
public final void run() {
Home.staticRefreshBGChartsOnIdle();
}
});
z = true;
} else {
backFillRx = backFillRx2;
}
}
i++;
backFillRx2 = backFillRx;
}
if (z || rawList.size() >= requestedBackfillSize || !JoH.ratelimit("mt-backfill-repeat", 60)) {
return;
}
UserError.Log.d(this.TAG, "Requesting additional backfill with offset: " + rawList.size());
backFillIfNeeded(lastAnnex, rawList.size());
return;
}
return;
}
UserError.Log.e(this.TAG, "Backfill data reports not ok");
}
private boolean backFillIfNeeded(AnnexARx annexARx) {
return backFillIfNeeded(annexARx, 0);
}
private boolean backFillIfNeeded(AnnexARx annexARx, int i) {
Pair<Long, Long> check;
if (annexARx != null && annexARx.isStateOkForBackFill() && (check = BackfillAssessor.check()) != null) {
int tickCounterFromTimeStamp = TimeKeeper.tickCounterFromTimeStamp(serial, ((Long) check.first).longValue());
int tickCounterFromTimeStamp2 = TimeKeeper.tickCounterFromTimeStamp(serial, ((Long) check.second).longValue());
int i2 = annexARx.sensorAge;
if (tickCounterFromTimeStamp2 >= i2) {
tickCounterFromTimeStamp2 = i2 - 1;
}
if (tickCounterFromTimeStamp < 62) {
tickCounterFromTimeStamp = 62;
}
if (tickCounterFromTimeStamp2 < 1) {
tickCounterFromTimeStamp2 = 1;
}
int i3 = tickCounterFromTimeStamp + i;
if (i3 != tickCounterFromTimeStamp2 && tickCounterFromTimeStamp2 > i3) {
if (tickCounterFromTimeStamp2 - i3 > 30) {
tickCounterFromTimeStamp2 = i3 + 30;
}
UserError.Log.d(this.TAG, "Ask backfill: start: " + i3 + " end: " + tickCounterFromTimeStamp2);
requestedBackfillSize = tickCounterFromTimeStamp2 - i3;
sendTx(new BackFillTx(i3, tickCounterFromTimeStamp2));
return true;
}
UserError.Log.d(this.TAG, "Not backfilling with start and end tick at: " + i3 + " " + tickCounterFromTimeStamp2);
}
return false;
}
private boolean isNative() {
return Pref.getBooleanDefaultFalse("medtrum_use_native");
}
private void createRecordFromAnnexData(AnnexARx annexARx) {
if (annexARx == null) {
return;
}
status("Got data");
if (lastRecordTime == 0) {
lastRecordTime = PersistentStore.getLong("mtc-last-record-time");
}
if (JoH.msSince(lastRecordTime) > 280000) {
UserError.Log.d(this.TAG, "Creating transmitter data from record annex");
TransmitterData create = TransmitterData.create(annexARx.getSensorRawEmulateDex(), annexARx.getSensorRawEmulateDex(), annexARx.getBatteryPercent(), JoH.tsl());
if (create != null) {
long j = create.timestamp;
lastRecordTime = j;
PersistentStore.setLong("mtc-last-record-time", j);
if (create.raw_data > BgReading.BESTOFFSET) {
if (annexARx.getState() == SensorState.Ok || annexARx.getState() == SensorState.NotCalibrated) {
double calculatedGlucose = annexARx.calculatedGlucose();
if (isNative()) {
if (calculatedGlucose > BgReading.BESTOFFSET) {
BgReading.bgReadingInsertMedtrum(calculatedGlucose, JoH.tsl(), null, create.raw_data);
} else if (annexARx.getState() == SensorState.NotCalibrated) {
UserError.Log.d(this.TAG, "Just adding raw data");
BgReading.create(create.raw_data, create.filtered_data, xdrip.getAppContext(), Long.valueOf(create.timestamp));
}
double d = create.raw_data;
BgReading createFromRawNoSave = BgReading.createFromRawNoSave(null, null, d, d, create.timestamp);
double d2 = createFromRawNoSave.calculated_value;
if (d2 > BgReading.BESTOFFSET) {
Prediction.create(createFromRawNoSave.timestamp, (int) d2, "Medtrum2nd").save();
UserError.Log.d(this.TAG, "Created secondary trace for value: " + createFromRawNoSave.calculated_value);
return;
}
return;
}
if (calculatedGlucose > BgReading.BESTOFFSET) {
Prediction.create(JoH.tsl(), (int) calculatedGlucose, "Medtrum2nd").save();
UserError.Log.d(this.TAG, "Saving extra data");
}
BgReading create2 = BgReading.create(create.raw_data, create.filtered_data, xdrip.getAppContext(), Long.valueOf(create.timestamp));
if (create2 != null) {
UserError.Log.d(this.TAG, "BgReading created: " + create2.uuid + " " + JoH.dateTimeText(create2.timestamp));
return;
}
UserError.Log.d(this.TAG, "BgReading null!");
return;
}
UserError.Log.d(this.TAG, "Ignoring due to sensor state: " + annexARx.getState());
return;
}
UserError.Log.d(this.TAG, "Raw data was invalid so not proceeding");
return;
}
return;
}
UserError.Log.d(this.TAG, "Not creating data record so close to previous");
}
static class AnonymousClass1 {
static final int[] $SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE;
static final int[] $SwitchMap$com$polidea$rxandroidble2$RxBleConnection$RxBleConnectionState;
static {
int[] iArr = new int[RxBleConnection.RxBleConnectionState.values().length];
$SwitchMap$com$polidea$rxandroidble2$RxBleConnection$RxBleConnectionState = iArr;
try {
iArr[RxBleConnection.RxBleConnectionState.CONNECTING.ordinal()] = 1;
} catch (NoSuchFieldError unused) {
}
try {
$SwitchMap$com$polidea$rxandroidble2$RxBleConnection$RxBleConnectionState[RxBleConnection.RxBleConnectionState.CONNECTED.ordinal()] = 2;
} catch (NoSuchFieldError unused2) {
}
try {
$SwitchMap$com$polidea$rxandroidble2$RxBleConnection$RxBleConnectionState[RxBleConnection.RxBleConnectionState.DISCONNECTING.ordinal()] = 3;
} catch (NoSuchFieldError unused3) {
}
try {
$SwitchMap$com$polidea$rxandroidble2$RxBleConnection$RxBleConnectionState[RxBleConnection.RxBleConnectionState.DISCONNECTED.ordinal()] = 4;
} catch (NoSuchFieldError unused4) {
}
int[] iArr2 = new int[STATE.values().length];
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE = iArr2;
try {
iArr2[STATE.INIT.ordinal()] = 1;
} catch (NoSuchFieldError unused5) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.SCAN.ordinal()] = 2;
} catch (NoSuchFieldError unused6) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.CONNECT.ordinal()] = 3;
} catch (NoSuchFieldError unused7) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.ENABLE.ordinal()] = 4;
} catch (NoSuchFieldError unused8) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.DISCOVER.ordinal()] = 5;
} catch (NoSuchFieldError unused9) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.CALIBRATE.ordinal()] = 6;
} catch (NoSuchFieldError unused10) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.GET_DATA.ordinal()] = 7;
} catch (NoSuchFieldError unused11) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.SET_TIME.ordinal()] = 8;
} catch (NoSuchFieldError unused12) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.SET_CONN_PARAM.ordinal()] = 9;
} catch (NoSuchFieldError unused13) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.CLOSE.ordinal()] = 10;
} catch (NoSuchFieldError unused14) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.CLOSED.ordinal()] = 11;
} catch (NoSuchFieldError unused15) {
}
try {
$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[STATE.LISTEN.ordinal()] = 12;
} catch (NoSuchFieldError unused16) {
}
}
}
public synchronized void onConnectionStateChange(RxBleConnection.RxBleConnectionState rxBleConnectionState) {
String str = "Unknown";
int i = AnonymousClass1.$SwitchMap$com$polidea$rxandroidble2$RxBleConnection$RxBleConnectionState[rxBleConnectionState.ordinal()];
if (i == 1) {
str = "Connecting";
} else if (i == 2) {
str = "Connected";
retry_backoff = 0L;
} else if (i == 3) {
str = "Disconnecting";
} else if (i == 4) {
str = "Disconnected";
status("Disconnected");
changeState(STATE.CLOSE);
}
status(str);
if (str.equals("Disconnecting")) {
tryGattRefresh(this.connection);
}
}
public void onConnectionReceived(RxBleConnection rxBleConnection) {
listen_connected = true;
status("Connected");
this.connection = rxBleConnection;
if (rxBleConnection != null) {
changeState(STATE.ENABLE);
} else {
UserError.Log.d(this.TAG, "New connection null!");
changeState(STATE.CLOSE);
}
}
public void onConnectionFailure(Throwable th) {
if (listen_connected) {
status("Disconnected");
} else {
status("Connection failure");
}
UserError.Log.d(this.TAG, "Connection Disconnected/Failed: " + th);
stopConnect();
changeState(STATE.CLOSE);
setRetryTimer();
}
private synchronized void stopConnect() {
UserError.Log.d(this.TAG, "Stopping connection with: " + address);
stopListening();
if (connectionSubscription != null) {
connectionSubscription.unsubscribe();
}
if (stateSubscription != null) {
stateSubscription.unsubscribe();
}
}
private void stopListening() {
if (indicationSubscription != null) {
indicationSubscription.unsubscribe();
}
if (notificationSubscription != null) {
notificationSubscription.unsubscribe();
}
}
public void changeState(STATE state2) {
changeState(state2, 100);
}
public void changeState(STATE state2, int i) {
if ((state == STATE.CLOSED || state == STATE.CLOSE) && state2 == STATE.CLOSE) {
UserError.Log.d(this.TAG, "Not closing as already closed");
return;
}
if (state2 != state) {
UserError.Log.d(this.TAG, "Changing state from: " + state + " to " + state2);
state = state2;
background_automata(i);
return;
}
UserError.Log.d(this.TAG, "Not changing state as already in state: " + state2);
}
@Override
public void onCreate() {
super.onCreate();
if (scanner == null) {
scanner = new Scanner();
}
scanner.setTag(this.TAG);
scanner.addCallBack(this, this.TAG);
DisconnectReceiver.addCallBack(this, this.TAG);
UserError.Log.d(this.TAG, "SERVICE CREATED - SERVICE CREATED");
JamBaseBluetoothService.enableBuggySamsungIfNeeded(this.TAG);
}
@Override
public void onDestroy() {
try {
scanner.stop();
} catch (Exception unused) {
}
stopConnect();
DisconnectReceiver.removeCallBack(this.TAG);
wakeup_time = 0L;
last_automata_state = STATE.CLOSED;
status("Stopped");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int i, int i2) {
xdrip.checkAppContext(getApplicationContext());
if (shouldServiceRun()) {
PowerManager.WakeLock wakeLock = JoH.getWakeLock("medtrum-start-service", 600000);
try {
UserError.Log.d(this.TAG, "WAKE UP WAKE UP WAKE UP WAKE UP @ " + JoH.dateTimeText(JoH.tsl()) + " State: " + state);
setFailOverTimer();
long j = wakeup_time;
if (j > 0) {
long msSince = JoH.msSince(j);
wakeup_jitter = msSince;
if (msSince < 0) {
UserError.Log.d(this.TAG, "Woke up Early..");
} else if (msSince > 1000) {
UserError.Log.d(this.TAG, "Wake up, time jitter: " + JoH.niceTimeScalar(wakeup_jitter));
if (wakeup_jitter > 10000 && !JoH.buggy_samsung && JoH.isSamsung()) {
UserError.Log.wtf(this.TAG, "Enabled wake workaround due to jitter of: " + JoH.niceTimeScalar(wakeup_jitter));
JoH.buggy_samsung = true;
PersistentStore.incrementLong("buggy-samsung-enabled");
max_wakeup_jitter = 0L;
} else {
max_wakeup_jitter = Math.max(max_wakeup_jitter, wakeup_jitter);
}
}
wakeup_time = 0L;
}
retry_time = 0L;
last_wake_up_time = JoH.tsl();
try {
address = ActiveBluetoothDevice.first().address;
} catch (NullPointerException unused) {
}
processInitialState();
background_automata();
return 1;
} finally {
JoH.releaseWakeLock(wakeLock);
}
}
UserError.Log.d(this.TAG, "Should not be running so shutting down");
stopSelf();
return 2;
}
private void processInitialState() {
int i = AnonymousClass1.$SwitchMap$com$eveningoutpost$dexdrip$cgm$medtrum$MedtrumCollectionService$STATE[state.ordinal()];
if (i == 1 || i == 2) {
return;
}
if (i == 10 || i == 11) {
UserError.Log.d(this.TAG, "Changing from initial state of " + state + " to INIT");
state = STATE.INIT;
return;
}
if (JoH.msSince(lastInteractionTime) > 300000) {
UserError.Log.d(this.TAG, "Changing from initial state of " + state + " to INIT due to interaction timeout");
state = STATE.INIT;
}
}
@Override
public void btCallback(String str, String str2) {
UserError.Log.d(this.TAG, "Processing callback: " + str + " :: " + str2);
if (str.equals(address)) {
str2.hashCode();
switch (str2) {
case "SCAN_FAILED":
status("Scan Failed!");
changeState(STATE.CONNECT);
break;
case "SCAN_TIMEOUT":
status("Scan timed out");
changeState(STATE.CONNECT);
break;
case "SCAN_FOUND":
changeState(STATE.CONNECT);
break;
case "DISCONNECTED":
changeState(STATE.CLOSE);
break;
default:
UserError.Log.e(this.TAG, "Unknown status callback for: " + str + " with " + str2);
break;
}
}
UserError.Log.d(this.TAG, "Ignoring: " + str2 + " for " + str + " as we are using: " + address);
}
private static void status(String str) {
lastState = str + " " + JoH.hourMinuteString();
UserError.Log.d(STATIC_TAG, "Status: " + lastState);
}
private static void errorStatus(String str) {
lastErrorState = str + " " + JoH.hourMinuteString();
UserError.Log.e(STATIC_TAG, lastErrorState);
}
@SuppressLint({"ObsoleteSdkInt"})
private static boolean shouldServiceRun() {
return DexCollectionType.getDexCollectionType().equals(DexCollectionType.Medtrum);
}
private void setRetryTimer() {
Inevitable.task("mt-set-retry", 500L, new Runnable() {
@Override
public final void run() {
MedtrumCollectionService.this.setRetryTimerReal();
}
});
}
public void setRetryTimerReal() {
if (shouldServiceRun()) {
long whenToRetryNext = whenToRetryNext();
UserError.Log.d(this.TAG, "setRetryTimer: Restarting in: " + (whenToRetryNext / 1000) + " seconds");
PendingIntent pendingIntent = WakeLockTrampoline.getPendingIntent(getClass(), 1015);
serviceIntent = pendingIntent;
retry_time = JoH.wakeUpIntent(this, whenToRetryNext, pendingIntent);
wakeup_time = JoH.tsl() + whenToRetryNext;
return;
}
UserError.Log.d(this.TAG, "Not setting retry timer as service should not be running");
}
private void setFailOverTimer() {
if (shouldServiceRun()) {
if (JoH.quietratelimit("mt-failover-cooldown", 30)) {
UserError.Log.d(this.TAG, "setFailOverTimer: Restarting in: 420 seconds");
PendingIntent pendingIntent = WakeLockTrampoline.getPendingIntent(getClass(), 1016);
serviceFailoverIntent = pendingIntent;
failover_time = JoH.wakeUpIntent(this, 420000L, pendingIntent);
return;
}
return;
}
UserError.Log.d(this.TAG, "Not setting retry timer as service should not be running");
}
private static long whenToRetryNext() {
long j = retry_backoff + 1000;
retry_backoff = j;
if (j > 60000) {
retry_backoff = 60000L;
}
return retry_backoff + 10000;
}
public static SpannableString nanoStatus() {
if (JoH.emptyString(lastErrorState)) {
return null;
}
return Span.colorSpan(lastErrorState, StatusItem.Highlight.CRITICAL.color());
}
public static List<StatusItem> megaStatus() {
if (lastAnnex == null) {
lastAnnex = Medtrum.getLastAdvertAnnex();
}
ArrayList arrayList = new ArrayList();
arrayList.add(new StatusItem("Phone Service State", lastState));
if (!JoH.emptyString(lastErrorState)) {
arrayList.add(new StatusItem("Error", lastErrorState, StatusItem.Highlight.BAD));
}
if (lastAnnex != null) {
arrayList.add(new StatusItem("Battery", lastAnnex.getBatteryPercent() + "%"));
AnnexARx annexARx = lastAnnex;
if (annexARx.charging) {
arrayList.add(new StatusItem("Charging", annexARx.charged ? "Charged" : "On charge"));
}
String description = lastAnnex.getState().getDescription();
SensorState state2 = lastAnnex.getState();
SensorState sensorState = SensorState.Ok;
arrayList.add(new StatusItem("Sensor State", description, state2 == sensorState ? StatusItem.Highlight.GOOD : StatusItem.Highlight.NORMAL));
if (lastAnnex.getState() == SensorState.WarmingUp1) {
arrayList.add(new StatusItem("Warm up", "Initial warm up", StatusItem.Highlight.NOTICE));
} else if (lastAnnex.getState() == SensorState.WarmingUp2) {
long sensorAgeInMs = (7200000 - lastAnnex.getSensorAgeInMs()) / 60000;
if (sensorAgeInMs > -1 && sensorAgeInMs < 121) {
arrayList.add(new StatusItem("Warmup left", sensorAgeInMs + " mins", StatusItem.Highlight.NOTICE));
}
}
if (lastAnnex.getSensorAgeInMs() > 0) {
arrayList.add(new StatusItem("Sensor Age", lastAnnex.getNiceSensorAge()));
}
if (lastAnnex.sensorGood) {
arrayList.add(new StatusItem("Sensor", "Good", StatusItem.Highlight.GOOD));
}
if (lastAnnex.sensorError) {
arrayList.add(new StatusItem("Sensor Error", "Error", StatusItem.Highlight.BAD));
}
if (lastAnnex.sensorFail) {
arrayList.add(new StatusItem("Sensor Fail", "FAILED", StatusItem.Highlight.CRITICAL));
}
if (lastAnnex.calibrationErrorA) {
arrayList.add(new StatusItem("Calibration Error", "Error A", StatusItem.Highlight.BAD));
}
if (lastAnnex.calibrationErrorB) {
arrayList.add(new StatusItem("Calibration Error", "Error B", StatusItem.Highlight.BAD));
}
Pair<Long, Integer> calibration = Medtrum.getCalibration();
if (calibration != null) {
arrayList.add(new StatusItem("Blood test", BgGraphBuilder.unitized_string_with_units_static(((Integer) calibration.second).intValue()) + " @ " + JoH.hourMinuteString(((Long) calibration.first).longValue()), StatusItem.Highlight.NOTICE));
}
long j = serial;
String str = "";
if (j != 0) {
int version = Medtrum.getVersion(j);
arrayList.add(new StatusItem("Serial", "" + serial));
if (version > 0) {
arrayList.add(new StatusItem("Firmware", "v" + JoH.qs(version / 100.0d, 2)));
}
}
if (lastAnnex.getState() == sensorState || lastAnnex.getState() == SensorState.NotCalibrated) {
arrayList.add(new StatusItem("Slope", JoH.qs(lastAnnex.calibrationSlope / 1000.0d, 3) + " (" + JoH.qs(1.0d / (lastAnnex.calibrationSlope / 1000.0d), 2) + ")"));
arrayList.add(new StatusItem("Intercept", Integer.valueOf(lastAnnex.calibrationIntercept)));
arrayList.add(new StatusItem("Raw Data", Integer.valueOf(lastAnnex.sensorRaw)));
}
if (lastAnnex.getState() == sensorState) {
StringBuilder sb = new StringBuilder();
sb.append(BgGraphBuilder.unitized_string_with_units_static(lastAnnex.calculatedGlucose()));
if (!lastAnnex.recent()) {
str = " @ " + JoH.niceTimeScalarShort(JoH.msSince(lastAnnex.created));
}
sb.append(str);
arrayList.add(new StatusItem("Last Glucose", sb.toString(), lastAnnex.recent() ? StatusItem.Highlight.NORMAL : StatusItem.Highlight.NOTICE));
}
long j2 = retry_time;
if (j2 != 0) {
arrayList.add(new StatusItem("Wake up in", JoH.niceTimeScalar(JoH.msTill(j2))));
}
long j3 = failover_time;
if (j3 != 0) {
arrayList.add(new StatusItem("System check in", JoH.niceTimeScalar(JoH.msTill(j3))));
}
if (Home.get_engineering_mode()) {
arrayList.add(new StatusItem("Brain State", state.getString()));
arrayList.add(new StatusItem("Last Interaction", JoH.niceTimeScalar(JoH.msSince(lastInteractionTime))));
arrayList.add(new StatusItem("Last Wake Up", JoH.niceTimeScalar(JoH.msSince(last_wake_up_time))));
}
} else {
arrayList.add(new StatusItem("Status Information", "Nothing Yet", StatusItem.Highlight.NOTICE));
}
return arrayList;
}
public static boolean isRunning() {
return (lastState.equals("Not Running") || lastState.startsWith("Stop")) ? false : true;
}
public static boolean isCollecting() {
return JoH.msSince(lastInteractionTime) < 300000;
}
public static void calibratePing() {
if (shouldServiceRun()) {
state = STATE.CALIBRATE;
JoH.startService(MedtrumCollectionService.class);
}
}
}