Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds compatibility with Renpho (QN Scale) scales that use the 2nd set of characteristics #1083

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ public class BluetoothQNScale extends BluetoothCommunication {
private final UUID CUSTOM5_MEASUREMENT_CHARACTERISTIC = UUID.fromString("0000ffe5-0000-1000-8000-00805f9b34fb"); // write-only
/////////////

// 2nd Type Service and Characteristics (2nd Type doesn't need to indicate, and 4th characteristic is shared with 3rd.)
private final UUID WEIGHT_MEASUREMENT_SERVICE_ALTERNATIVE = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");
private final UUID CUSTOM1_MEASUREMENT_CHARACTERISTIC_ALTERNATIVE = UUID.fromString("0000fff1-0000-1000-8000-00805f9b34fb"); // notify, read-only
private final UUID CUSTOM3_MEASUREMENT_CHARACTERISTIC_ALTERNATIVE = UUID.fromString("0000fff2-0000-1000-8000-00805f9b34fb"); // write-only

private boolean useFirstType = true;


/** API
connectDevice(device, "userId", 170, 1, birthday, new new QNBleCallback(){
void onConnectStart(QNBleDevice bleDevice);
Expand Down Expand Up @@ -87,12 +95,29 @@ public String driverName() {
protected boolean onNextStep(int stepNr) {
switch (stepNr) {
case 0:
// Try writing bytes to 0xffe4 to check whether to use 1st or 2nd type
try {
long timestamp = new Date().getTime() / 1000;
timestamp -= SCALE_UNIX_TIMESTAMP_OFFSET;
byte[] date = new byte[4];
Converters.toInt32Le(date, 0, timestamp);
writeBytes(WEIGHT_MEASUREMENT_SERVICE, CUSTOM4_MEASUREMENT_CHARACTERISTIC, new byte[]{(byte) 0x02, date[0], date[1], date[2], date[3]});
} catch (NullPointerException e) {
useFirstType = false;
}

// set notification on for custom characteristic 1 (weight, time, and others)
setNotificationOn(WEIGHT_MEASUREMENT_SERVICE, CUSTOM1_MEASUREMENT_CHARACTERISTIC);
if (useFirstType) {
setNotificationOn(WEIGHT_MEASUREMENT_SERVICE, CUSTOM1_MEASUREMENT_CHARACTERISTIC);
} else {
setNotificationOn(WEIGHT_MEASUREMENT_SERVICE_ALTERNATIVE, CUSTOM1_MEASUREMENT_CHARACTERISTIC_ALTERNATIVE);
}
break;
case 1:
// set indication on for weight measurement
setIndicationOn(WEIGHT_MEASUREMENT_SERVICE, CUSTOM2_MEASUREMENT_CHARACTERISTIC);
if (useFirstType) {
setIndicationOn(WEIGHT_MEASUREMENT_SERVICE, CUSTOM2_MEASUREMENT_CHARACTERISTIC);
}
break;
case 2:
final ScaleUser scaleUser = OpenScale.getInstance().getSelectedScaleUser();
Expand All @@ -108,7 +133,12 @@ protected boolean onNextStep(int stepNr) {
byte[] ffe3magicBytes = new byte[]{(byte) 0x13, (byte) 0x09, (byte) 0x15, weightUnitByte, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
// Set last byte to be checksum
ffe3magicBytes[ffe3magicBytes.length -1] = sumChecksum(ffe3magicBytes, 0, ffe3magicBytes.length - 1);
writeBytes(WEIGHT_MEASUREMENT_SERVICE, CUSTOM3_MEASUREMENT_CHARACTERISTIC, ffe3magicBytes);

if (useFirstType) {
writeBytes(WEIGHT_MEASUREMENT_SERVICE, CUSTOM3_MEASUREMENT_CHARACTERISTIC, ffe3magicBytes);
} else {
writeBytes(WEIGHT_MEASUREMENT_SERVICE_ALTERNATIVE, CUSTOM3_MEASUREMENT_CHARACTERISTIC_ALTERNATIVE, ffe3magicBytes);
}
break;
case 3:
// send time magic number to receive weight data
Expand All @@ -117,7 +147,12 @@ protected boolean onNextStep(int stepNr) {
byte[] date = new byte[4];
Converters.toInt32Le(date, 0, timestamp);
byte[] timeMagicBytes = new byte[]{(byte) 0x02, date[0], date[1], date[2], date[3]};
writeBytes(WEIGHT_MEASUREMENT_SERVICE, CUSTOM4_MEASUREMENT_CHARACTERISTIC, timeMagicBytes);

if (useFirstType) {
writeBytes(WEIGHT_MEASUREMENT_SERVICE, CUSTOM4_MEASUREMENT_CHARACTERISTIC, timeMagicBytes);
} else {
writeBytes(WEIGHT_MEASUREMENT_SERVICE_ALTERNATIVE, CUSTOM3_MEASUREMENT_CHARACTERISTIC_ALTERNATIVE, timeMagicBytes);
}
break;
case 4:
sendMessage(R.string.info_step_on_scale, 0);
Expand All @@ -137,7 +172,7 @@ protected boolean onNextStep(int stepNr) {
public void onBluetoothNotify(UUID characteristic, byte[] value) {
final byte[] data = value;

if (characteristic.equals(CUSTOM1_MEASUREMENT_CHARACTERISTIC)) {
if (characteristic.equals(CUSTOM1_MEASUREMENT_CHARACTERISTIC) || characteristic.equals(CUSTOM1_MEASUREMENT_CHARACTERISTIC_ALTERNATIVE)) {
parseCustom1Data(data);
}
}
Expand All @@ -162,6 +197,12 @@ private void parseCustom1Data(byte[] data){
if (!this.hasReceived) {
this.hasReceived = true;
weightKg = decodeWeight(data[3], data[4]);

// Weight needs to be divided by 10 if 2nd type
if (!useFirstType) {
weightKg /= 10;
}

int weightByteOne = data[3] & 0xFF;
int weightByteTwo = data[4] & 0xFF;

Expand Down