use of com.eveningoutpost.dexdrip.Models.JoH.bytesToHex in project xDrip by NightscoutFoundation.
the class MiBandService method ProcessAuthCommands.
@SuppressLint("CheckResult")
private void ProcessAuthCommands(RxBleConnection connection, byte[] value) {
if (value[0] == AUTH_RESPONSE && value[1] == AUTH_SEND_KEY && (value[2] & 0x0f) == AUTH_SUCCESS) {
// get random key from band
connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthKeyRequest()).subscribe(val -> {
if (d)
UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ1: " + JoH.bytesToHex(val));
}, throwable -> {
UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ1: " + throwable);
});
} else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_REQUEST_RANDOM_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
byte[] tmpValue = Arrays.copyOfRange(value, 3, 19);
try {
byte[] authReply = authorisation.calculateAuthReply(tmpValue);
// get random key from band
connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authReply).subscribe(val -> {
if (d)
UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ2: " + JoH.bytesToHex(val));
}, throwable -> {
UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ2: " + throwable);
});
} catch (Exception e) {
JoH.static_toast_long(e.getMessage());
UserError.Log.e(TAG, (e.getMessage()));
changeState(AUTHORIZE_FAILED);
}
} else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_SEND_ENCRYPTED_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
isNeedToAuthenticate = false;
if (MiBand.getPersistentAuthMac().isEmpty()) {
MiBand.setPersistentAuthMac(MiBand.getMac());
MiBand.setPersistentAuthKey(JoH.bytesToHex(authorisation.getLocalKey()), MiBand.getPersistentAuthMac());
String msg = "MiBand was successfully authenticated";
JoH.static_toast_long(msg);
UserError.Log.e(TAG, msg);
}
if (authSubscription != null) {
authSubscription.unsubscribe();
}
changeNextState();
} else if (value[0] == AUTH_RESPONSE && (((value[2] & 0x0f) == AUTH_FAIL) || (value[2] == AUTH_MIBAND4_FAIL) || (value[2] == AUTH_MIBAND4_CODE_FAIL))) {
MiBand.setPersistentAuthKey("", MiBand.getPersistentAuthMac());
if (authSubscription != null) {
authSubscription.unsubscribe();
}
String msg = "Cannot authorize miband, please recheck Auth code";
JoH.static_toast_long(msg);
UserError.Log.e(TAG, msg);
changeState(AUTHORIZE_FAILED);
}
}
use of com.eveningoutpost.dexdrip.Models.JoH.bytesToHex in project xDrip-plus by jamorham.
the class MiBandService method processFirmwareCommands.
@SuppressLint("CheckResult")
private void processFirmwareCommands(byte[] value, boolean isSeqCommand) {
RxBleConnection connection = I.connection;
FirmwareOperations.SequenceType seq = firmware.getSequence();
if (d)
UserError.Log.d(TAG, "processFirmwareCommands: " + bytesToHex(value) + ": seq:" + seq.toString());
if (isSeqCommand) {
switch(seq) {
case SET_NIGHTMODE:
{
if (true) {
isNeedToRestoreNightMode = true;
DisplayControllMessageMiband3_4 dispControl = new DisplayControllMessageMiband3_4();
Calendar sheduledCalendar = Calendar.getInstance();
sheduledCalendar.set(Calendar.HOUR_OF_DAY, 0);
sheduledCalendar.set(Calendar.MINUTE, 0);
Date sheduledDate = sheduledCalendar.getTime();
connection.writeCharacteristic(dispControl.getCharacteristicUUID(), dispControl.setNightModeCmd(Sheduled, sheduledDate, sheduledDate)).subscribe(valB -> {
UserError.Log.d(TAG, "Wrote nigntmode, got: " + JoH.bytesToHex(valB));
firmware.nextSequence();
processFirmwareCommands(null, true);
}, throwable -> {
UserError.Log.e(TAG, "Could not write nigntmode: " + throwable);
firmware.nextSequence();
processFirmwareCommands(null, true);
});
} else {
firmware.nextSequence();
processFirmwareCommands(null, true);
}
break;
}
case PREPARE_UPLOAD:
{
connection.writeCharacteristic(firmware.getFirmwareCharacteristicUUID(), firmware.prepareFWUploadInitCommand()).subscribe(valB -> {
UserError.Log.d(TAG, "Wrote prepareFWUploadInitCommand, got: " + JoH.bytesToHex(valB));
}, throwable -> {
UserError.Log.e(TAG, "Could not write prepareFWUploadInitCommand: " + throwable);
resetFirmwareState(false);
});
firmware.nextSequence();
break;
}
}
return;
} else {
if (value.length != 3 && value.length != 11) {
UserError.Log.e(TAG, "Notifications should be 3 or 11 bytes long.");
return;
}
boolean success = value[2] == OperationCodes.SUCCESS;
if (value[0] == OperationCodes.RESPONSE && success) {
try {
switch(value[1]) {
case OperationCodes.COMMAND_FIRMWARE_INIT:
{
if (seq == FirmwareOperations.SequenceType.TRANSFER_FW_START) {
connection.writeCharacteristic(firmware.getFirmwareCharacteristicUUID(), firmware.getFirmwareStartCommand()).subscribe(valB -> {
UserError.Log.d(TAG, "Wrote Start command, got: " + JoH.bytesToHex(valB));
}, throwable -> {
UserError.Log.e(TAG, "Could not write Start command: " + throwable);
resetFirmwareState(false);
});
firmware.nextSequence();
} else if (seq == FirmwareOperations.SequenceType.TRANSFER_SEND_WF_INFO) {
connection.writeCharacteristic(firmware.getFirmwareCharacteristicUUID(), firmware.sendFwInfo()).subscribe(valB -> {
UserError.Log.d(TAG, "Wrote sendFwInfo, got: " + JoH.bytesToHex(valB));
}, throwable -> {
UserError.Log.e(TAG, "Could not write firmware info: " + throwable);
resetFirmwareState(false);
});
firmware.nextSequence();
break;
}
break;
}
case OperationCodes.COMMAND_FIRMWARE_START_DATA:
{
sendFirmwareData();
break;
}
case OperationCodes.COMMAND_FIRMWARE_CHECKSUM:
{
firmware.nextSequence();
if (firmware.getFirmwareType() == FirmwareOperations.FirmwareType.FIRMWARE) {
// send reboot
} else {
UserError.Log.e(TAG, "Watch Face has been installed successfully");
resetFirmwareState(true);
}
break;
}
case OperationCodes.COMMAND_FIRMWARE_REBOOT:
{
UserError.Log.e(TAG, "Reboot command successfully sent.");
resetFirmwareState(true);
break;
}
default:
{
resetFirmwareState(false, "Unexpected response during firmware update");
}
}
} catch (Exception ex) {
resetFirmwareState(false);
}
} else {
String errorMessage = null;
Boolean sendBGNotification = false;
if (value[2] == OperationCodes.LOW_BATTERY_ERROR) {
errorMessage = "Cannot upload watchface, low battery, please charge device";
sendBGNotification = true;
} else if (value[2] == OperationCodes.TIMER_RUNNING) {
errorMessage = "Cannot upload watchface, timer running on band";
} else if (value[2] == OperationCodes.ON_CALL) {
errorMessage = "Cannot upload watchface, call in progress";
} else {
errorMessage = "Unexpected notification during firmware update:" + JoH.bytesToHex(value);
}
resetFirmwareState(false, errorMessage);
if (sendBGNotification) {
emptyQueue();
JoH.startService(MiBandService.class, "function", "update_bg_as_notification");
changeState(SLEEP);
}
}
}
}
use of com.eveningoutpost.dexdrip.Models.JoH.bytesToHex in project xDrip-plus by jamorham.
the class MiBandService method ProcessAuthCommands.
@SuppressLint("CheckResult")
private void ProcessAuthCommands(RxBleConnection connection, byte[] value) {
if (value[0] == AUTH_RESPONSE && value[1] == AUTH_SEND_KEY && (value[2] & 0x0f) == AUTH_SUCCESS) {
// get random key from band
connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthKeyRequest()).subscribe(val -> {
if (d)
UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ1: " + JoH.bytesToHex(val));
}, throwable -> {
UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ1: " + throwable);
});
} else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_REQUEST_RANDOM_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
byte[] tmpValue = Arrays.copyOfRange(value, 3, 19);
try {
byte[] authReply = authorisation.calculateAuthReply(tmpValue);
// get random key from band
connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authReply).subscribe(val -> {
if (d)
UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ2: " + JoH.bytesToHex(val));
}, throwable -> {
UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ2: " + throwable);
});
} catch (Exception e) {
JoH.static_toast_long(e.getMessage());
UserError.Log.e(TAG, (e.getMessage()));
changeState(AUTHORIZE_FAILED);
}
} else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_SEND_ENCRYPTED_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
isNeedToAuthenticate = false;
if (MiBand.getPersistentAuthMac().isEmpty()) {
MiBand.setPersistentAuthMac(MiBand.getMac());
MiBand.setPersistentAuthKey(JoH.bytesToHex(authorisation.getLocalKey()), MiBand.getPersistentAuthMac());
String msg = "MiBand was successfully authenticated";
JoH.static_toast_long(msg);
UserError.Log.e(TAG, msg);
}
if (authSubscription != null) {
authSubscription.unsubscribe();
}
changeNextState();
} else if (value[0] == AUTH_RESPONSE && (((value[2] & 0x0f) == AUTH_FAIL) || (value[2] == AUTH_MIBAND4_FAIL) || (value[2] == AUTH_MIBAND4_CODE_FAIL))) {
MiBand.setPersistentAuthKey("", MiBand.getPersistentAuthMac());
if (authSubscription != null) {
authSubscription.unsubscribe();
}
String msg = "Cannot authorize miband, please recheck Auth code";
JoH.static_toast_long(msg);
UserError.Log.e(TAG, msg);
changeState(AUTHORIZE_FAILED);
}
}
use of com.eveningoutpost.dexdrip.Models.JoH.bytesToHex in project xDrip-plus by jamorham.
the class MiBandService method authPhase.
@SuppressLint("CheckResult")
private void authPhase() {
extendWakeLock(30000);
RxBleConnection connection = I.connection;
if (d)
UserError.Log.d(TAG, "Authorizing");
if (I.connection == null) {
if (d)
UserError.Log.d(TAG, "Cannot enable as connection is null!");
return;
}
String authKey = MiBand.getPersistentAuthKey();
if (MiBand.getMibandType() == MI_BAND4) {
if (authKey.isEmpty()) {
authKey = MiBand.getAuthKey();
if (authKey.isEmpty()) {
authKey = AuthMessages.getAuthCodeFromFilesSystem(MiBand.getMac());
}
if (!AuthMessages.isValidAuthKey(authKey)) {
JoH.static_toast_long("Wrong miband authorization key, please recheck a key and try to reconnect again");
changeState(AUTHORIZE_FAILED);
return;
} else {
MiBand.setAuthKey(authKey);
}
}
}
if (!AuthMessages.isValidAuthKey(authKey)) {
authKey = "";
}
if (d)
UserError.Log.d(TAG, "authKey: " + authKey);
authorisation = new AuthMessages(MiBand.getMibandType(), authKey);
if (d)
UserError.Log.d(TAG, "localKey: " + JoH.bytesToHex(authorisation.getLocalKey()));
authSubscription = new Subscription(connection.setupNotification(authorisation.getCharacteristicUUID()).timeout(20, // WARN
TimeUnit.SECONDS).doOnNext(notificationObservable -> {
if (d)
UserError.Log.d(TAG, "Notification for auth enabled");
if (MiBand.isAuthenticated()) {
// get random key from band
connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthKeyRequest()).subscribe(val -> {
if (d)
UserError.Log.d(TAG, "Wrote getAuthKeyRequest: " + JoH.bytesToHex(val));
}, throwable -> {
UserError.Log.e(TAG, "Could not getAuthKeyRequest: " + throwable);
});
} else {
connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthCommand()).subscribe(characteristicValue -> {
UserError.Log.d(TAG, "Wrote getAuthCommand, got: " + JoH.bytesToHex(characteristicValue));
}, throwable -> {
UserError.Log.e(TAG, "Could not write getAuthCommand: " + throwable);
});
}
}).flatMap(notificationObservable -> notificationObservable).subscribe(bytes -> {
// incoming notifications
if (d)
UserError.Log.d(TAG, "Received auth notification bytes: " + bytesToHex(bytes));
ProcessAuthCommands(connection, bytes);
// changeNextState();
}, throwable -> {
UserError.Log.d(TAG, "Throwable in Record Notification: " + throwable);
if (throwable instanceof BleCharacteristicNotFoundException) {
// maybe legacy - ignore for now but needs better handling
UserError.Log.d(TAG, "Characteristic not found for notification");
} else if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
} else if (throwable instanceof BleDisconnectedException) {
UserError.Log.d(TAG, "Disconnected while enabling notifications");
} else if (throwable instanceof TimeoutException) {
// check if it is normal timeout
if (!MiBand.isAuthenticated()) {
String errorText = "MiBand authentication failed due to authentication timeout. When your Mi Band vibrates and blinks, tap it a few times in a row.";
UserError.Log.d(TAG, errorText);
JoH.static_toast_long(errorText);
}
}
if (authSubscription != null) {
authSubscription.unsubscribe();
}
changeState(CLOSE);
}));
}
use of com.eveningoutpost.dexdrip.Models.JoH.bytesToHex in project xDrip by NightscoutFoundation.
the class BlueJayService method enableNotifications.
private void enableNotifications() {
UserError.Log.d(TAG, "enableNotifications called()");
if (I.isNotificationEnabled) {
UserError.Log.d(TAG, "Notifications already enabled");
changeNextState();
return;
}
if (notificationSubscription != null) {
notificationSubscription.unsubscribe();
}
JoH.threadSleep(500);
UserError.Log.d(TAG, "Requesting to enable notifications");
if (I.connection == null) {
UserError.Log.d(TAG, "Connection went away before we could enable notifications");
return;
}
notificationSubscription = new Subscription(I.connection.setupNotification(THINJAM_WRITE).observeOn(// needed?
Schedulers.newThread()).doOnNext(notificationObservable -> {
UserError.Log.d(TAG, "Notifications enabled");
I.connection.writeCharacteristic(THINJAM_BULK, new byte[] { 0x55 });
// Debug sleep to make sure notifications are actually enabled???
JoH.threadSleep(500);
I.isNotificationEnabled = true;
changeNextState();
}).flatMap(notificationObservable -> notificationObservable).observeOn(Schedulers.newThread()).subscribe(bytes -> {
// incoming notifications
UserError.Log.d(TAG, "Received notification bytes: " + JoH.bytesToHex(bytes));
val pushRx = PushRx.parse(bytes);
if (pushRx != null) {
UserError.Log.d(TAG, "Received PushRX: " + pushRx.toS());
getInfo().processPushRx(pushRx);
processPushRxActions(pushRx);
} else if (bytes[0] == 0x06) {
// TODO move this to parsed response
final int replyParam = ((int) bytes[1]) & 0xff;
if (replyParam == 0) {
UserError.Log.d(TAG, "Bulk up success reply marker received! - removing queue head item");
// removes first item from the queue which should be the one we just processed!
commandQueue.poll();
UserError.Log.d(TAG, "Scheduling immediate run of queue");
// remove timeout retry task
Inevitable.kill("tj-next-queue");
Inevitable.task("tj-next-queue", 0, this::processQueue);
} else {
revisedOffset = replyParam;
// race condition on display
UserError.Log.d(TAG, "Bulk up failure at: " + revisedOffset);
}
} else if (bytes[0] == (byte) 0xFE) {
audioStreamCallBack(bytes);
} else {
if (ThinJamActivity.isD()) {
notificationString.append(new String(bytes));
Inevitable.task("tj update notifi", 250, new Runnable() {
@Override
public void run() {
stringObservableField.set(notificationString.toString());
}
});
}
}
}, throwable -> {
UserError.Log.d(TAG, "Throwable in Record Notification: " + throwable);
I.isNotificationEnabled = false;
if (throwable instanceof BleCharacteristicNotFoundException) {
// maybe legacy - ignore for now but needs better handling
UserError.Log.d(TAG, "Characteristic not found for notification");
debug.processTestSuite("logcharerror");
tryGattRefresh(getI().connection);
}
if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
changeState(CLOSE);
}
if (throwable instanceof BleDisconnectedException) {
UserError.Log.d(TAG, "Disconnected while enabling notifications");
changeState(CLOSE);
}
}));
}
Aggregations