1
0
mirror of https://github.com/oliexdev/openScale.git synced 2025-08-28 18:49:56 +02:00

Add support for OKOK 1.1 scales (weight only) (#738)

This commit is contained in:
Santtu Lakkala
2021-10-10 12:08:16 +03:00
committed by GitHub
parent 4ec9b4bd0c
commit 36eb1a8b40
2 changed files with 99 additions and 33 deletions

View File

@@ -111,7 +111,7 @@ public class BluetoothFactory {
if (deviceName.equals("Hoffen BS-8107")) {
return new BluetoothHoffenBBS8107(context);
}
if (deviceName.equals("ADV")) {
if (deviceName.equals("ADV") || deviceName.equals("Chipsea-BLE")) {
return new BluetoothOKOK(context);
}
if (deviceName.equals("BF105")) {

View File

@@ -20,43 +20,102 @@ import java.util.List;
import timber.log.Timber;
public class BluetoothOKOK extends BluetoothCommunication {
private static final int MANUFACTURER_DATA_ID = 0x20ca; // 16-bit little endian "header" 0xca 0x20
private static final int IDX_FINAL = 6;
private static final int IDX_WEIGHT_MSB = 8;
private static final int IDX_WEIGHT_LSB = 9;
private static final int IDX_IMPEDANCE_MSB = 10;
private static final int IDX_IMPEDANCE_LSB = 11;
private static final int IDX_CHECKSUM = 12;
private static final int MANUFACTURER_DATA_ID_V20 = 0x20ca; // 16-bit little endian "header" 0xca 0x20
private static final int MANUFACTURER_DATA_ID_V11 = 0x11ca; // 16-bit little endian "header" 0xca 0x11
private static final int IDX_V20_FINAL = 6;
private static final int IDX_V20_WEIGHT_MSB = 8;
private static final int IDX_V20_WEIGHT_LSB = 9;
private static final int IDX_V20_IMPEDANCE_MSB = 10;
private static final int IDX_V20_IMPEDANCE_LSB = 11;
private static final int IDX_V20_CHECKSUM = 12;
private static final int IDX_V11_WEIGHT_MSB = 3;
private static final int IDX_V11_WEIGHT_LSB = 4;
private static final int IDX_V11_BODY_PROPERTIES = 9;
private static final int IDX_V11_CHECKSUM = 16;
private BluetoothCentralManager central;
private final BluetoothCentralManagerCallback btCallback = new BluetoothCentralManagerCallback() {
@Override
public void onDiscoveredPeripheral(@NotNull BluetoothPeripheral peripheral, @NotNull ScanResult scanResult) {
SparseArray<byte[]> manufacturerSpecificData = scanResult.getScanRecord().getManufacturerSpecificData();
byte[] data = scanResult.getScanRecord().getManufacturerSpecificData(MANUFACTURER_DATA_ID);
if (manufacturerSpecificData.indexOfKey(MANUFACTURER_DATA_ID_V20) > -1) {
byte[] data = manufacturerSpecificData.get(MANUFACTURER_DATA_ID_V20);
float divider = 10.0f;
byte checksum = 0x20; // Version field is part of the checksum, but not in array
if (data == null || data.length != 19)
return;
if ((data[IDX_FINAL] & 1) == 0)
if ((data[IDX_V20_FINAL] & 1) == 0)
return;
for (int i = 0; i < IDX_CHECKSUM; i++)
for (int i = 0; i < IDX_V20_CHECKSUM; i++)
checksum ^= data[i];
if (data[IDX_CHECKSUM] != checksum) {
Timber.d("Checksum error, got %x, expected %x", data[12] & 0xff, checksum & 0xff);
if (data[IDX_V20_CHECKSUM] != checksum) {
Timber.d("Checksum error, got %x, expected %x", data[IDX_V20_CHECKSUM] & 0xff, checksum & 0xff);
return;
}
if ((data[IDX_FINAL] & 4) == 4)
if ((data[IDX_V20_FINAL] & 4) == 4)
divider = 100.0f;
int weight = data[IDX_WEIGHT_MSB] & 0xff;
weight = weight << 8 | (data[IDX_WEIGHT_LSB] & 0xff);
int impedance = data[IDX_IMPEDANCE_MSB] & 0xff;
impedance = impedance << 8 | (data[IDX_IMPEDANCE_LSB] & 0xff);
int weight = data[IDX_V20_WEIGHT_MSB] & 0xff;
weight = weight << 8 | (data[IDX_V20_WEIGHT_LSB] & 0xff);
int impedance = data[IDX_V20_IMPEDANCE_MSB] & 0xff;
impedance = impedance << 8 | (data[IDX_V20_IMPEDANCE_LSB] & 0xff);
Timber.d("Got weight: %f and impedance %f", weight / divider, impedance / 10f);
ScaleMeasurement entry = new ScaleMeasurement();
entry.setWeight(weight / divider);
addScaleMeasurement(entry);
disconnect();
} else if (manufacturerSpecificData.indexOfKey(MANUFACTURER_DATA_ID_V11) > -1) {
byte[] data = manufacturerSpecificData.get(MANUFACTURER_DATA_ID_V11);
float divider = 10.0f;
float extraWeight = 0;
byte checksum = 0xca ^ 0x11; // Version and magic fields are part of the checksum, but not in array
if (data == null || data.length != IDX_V11_CHECKSUM + 6 + 1)
return;
for (int i = 0; i < IDX_V11_CHECKSUM; i++)
checksum ^= data[i];
if (data[IDX_V11_CHECKSUM] != checksum) {
Timber.d("Checksum error, got %x, expected %x", data[IDX_V11_CHECKSUM] & 0xff, checksum & 0xff);
return;
}
int weight = data[IDX_V11_WEIGHT_MSB] & 0xff;
weight = weight << 8 | (data[IDX_V11_WEIGHT_LSB] & 0xff);
switch ((data[IDX_V11_BODY_PROPERTIES] >> 1) & 3) {
default:
Timber.w("Invalid weight scale received, assuming 1 decimal");
/* fall-through */
case 0:
divider = 10.0f;
break;
case 1:
divider = 1.0f;
break;
case 2:
divider = 100.0f;
break;
}
switch ((data[IDX_V11_BODY_PROPERTIES] >> 3) & 3) {
case 0: // kg
break;
case 1: // Jin
divider *= 2;
break;
case 3: // st & lb
extraWeight = (weight >> 8) * 6.350293f;
weight &= 0xff;
/* fall-through */
case 2: // lb
divider *= 2.204623;
break;
}
Timber.d("Got weight: %f", weight / divider);
ScaleMeasurement entry = new ScaleMeasurement();
entry.setWeight(extraWeight + weight / divider);
addScaleMeasurement(entry);
disconnect();
}
}
};
@@ -75,11 +134,18 @@ public class BluetoothOKOK extends BluetoothCommunication {
public void connect(String macAddress) {
Timber.d("Mac address: %s", macAddress);
List<ScanFilter> filters = new LinkedList<ScanFilter>();
ScanFilter.Builder b = new ScanFilter.Builder();
b.setDeviceAddress(macAddress);
b.setDeviceName("ADV");
b.setManufacturerData(MANUFACTURER_DATA_ID, null, null);
b.setManufacturerData(MANUFACTURER_DATA_ID_V20, null, null);
filters.add(b.build());
b.setDeviceName("Chipsea-BLE");
b.setManufacturerData(MANUFACTURER_DATA_ID_V11, null, null);
filters.add(b.build());
central.scanForPeripheralsUsingFilters(filters);
}