1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-29 12:05:53 +01:00

Merge branch 'master' into notification-refactor

This commit is contained in:
Andreas Shimokawa 2017-04-29 01:27:09 +02:00
commit 15102d525b
11 changed files with 135 additions and 102 deletions

View File

@ -1,5 +1,10 @@
###Changelog
###Version 0.19.1
* Fix crash at startup
* HPlus: Improve reconnection to device
* Improve transliteration
###Version 0.19.0
* Pebble: allow calendar sync with Timeline (Title, Location, Description)
* Pebble: display calendar icon for reminders from AOSP Calendar

View File

@ -26,8 +26,8 @@ android {
targetSdkVersion 25
// note: always bump BOTH versionCode and versionName!
versionName "0.19.0"
versionCode 93
versionName "0.19.1"
versionCode 94
vectorDrawables.useSupportLibrary = true
}
buildTypes {

View File

@ -139,6 +139,13 @@ public class GBApplication extends Application {
prefs = new Prefs(sharedPrefs);
gbPrefs = new GBPrefs(prefs);
if (!GBEnvironment.isEnvironmentSetup()) {
GBEnvironment.setupEnvironment(GBEnvironment.createDeviceEnvironment());
// setup db after the environment is set up, but don't do it in test mode
// in test mode, it's done individually, see TestBase
setupDatabase();
}
// don't do anything here before we set up logging, otherwise
// slf4j may be implicitly initialized before we properly configured it.
setupLogging(isFileLoggingEnabled());
@ -149,13 +156,6 @@ public class GBApplication extends Application {
setupExceptionHandler();
if (!GBEnvironment.isEnvironmentSetup()) {
GBEnvironment.setupEnvironment(GBEnvironment.createDeviceEnvironment());
// setup db after the environment is set up, but don't do it in test mode
// in test mode, it's done individually, see TestBase
setupDatabase();
}
deviceManager = new DeviceManager(this);
deviceService = createDeviceService();

View File

@ -121,6 +121,9 @@ public final class HPlusConstants {
public static final byte DATA_DAY_SUMMARY_ALT = 0x39;
public static final byte DATA_SLEEP = 0x1A;
public static final byte DATA_VERSION = 0x18;
public static final byte DATA_VERSION1 = 0x2E;
public static final byte DATA_UNKNOWN = 0x4d;
public static final String PREF_HPLUS_SCREENTIME = "hplus_screentime";
public static final String PREF_HPLUS_ALLDAYHR = "hplus_alldayhr";
@ -130,60 +133,61 @@ public final class HPlusConstants {
public static final String PREF_HPLUS_SIT_START_TIME = "hplus_sit_start_time";
public static final String PREF_HPLUS_SIT_END_TIME = "hplus_sit_end_time";
public static final Map<Character, Byte> transliterateMap = new HashMap<Character, Byte>(){
public static final Map<Character, byte[]> transliterateMap = new HashMap<Character, byte[]>(){
{
//These are missing
put('ó', (byte) 111);
put('Ó', (byte) 79);
put('í', (byte) 105);
put('Í', (byte) 73);
put('ú', (byte) 117);
put('Ú', (byte) 85);
put('ó', new byte[]{(byte) 111});
put('Ó', new byte[]{(byte) 79});
put('í', new byte[]{(byte) 105});
put('Í', new byte[]{(byte) 73});
put('ú', new byte[]{(byte) 117});
put('Ú', new byte[]{(byte) 85});
//These mostly belong to the extended ASCII table
put('Ç', (byte) 128);
put('ü', (byte) 129);
put('é', (byte) 130);
put('â', (byte) 131);
put('ä', (byte) 132);
put('à', (byte) 133);
put('ã', (byte) 134);
put('ç', (byte) 135);
put('ê', (byte) 136);
put('ë', (byte) 137);
put('Ï', (byte) 139);
put('è', (byte) 138);
put('Î', (byte) 140);
put('Ì', (byte) 141);
put('Ã', (byte) 142);
put('Ä', (byte) 143);
put('É', (byte) 144);
put('æ', (byte) 145);
put('Æ', (byte) 146);
put('ô', (byte) 147);
put('ö', (byte) 148);
put('ò', (byte) 149);
put('û', (byte) 150);
put('ù', (byte) 151);
put('ÿ', (byte) 152);
put('Ö', (byte) 153);
put('Ü', (byte) 154);
put('¢', (byte) 155);
put('£', (byte) 156);
put('¥', (byte) 157);
put('ƒ', (byte) 159);
put('á', (byte) 160);
put('ñ', (byte) 164);
put('Ñ', (byte) 165);
put('ª', (byte) 166);
put('º', (byte) 167);
put('¿', (byte) 168);
put('¬', (byte) 170);
put('½', (byte) 171);
put('¼', (byte) 172);
put('¡', (byte) 173);
put('«', (byte) 174);
put('»', (byte) 175);
put('Ç', new byte[]{(byte) 128});
put('ü', new byte[]{(byte) 129});
put('é', new byte[]{(byte) 130});
put('â', new byte[]{(byte) 131});
put('ä', new byte[]{(byte) 132});
put('à', new byte[]{(byte) 133});
put('ã', new byte[]{(byte) 134});
put('ç', new byte[]{(byte) 135});
put('ê', new byte[]{(byte) 136});
put('ë', new byte[]{(byte) 137});
put('Ï', new byte[]{(byte) 139});
put('è', new byte[]{(byte) 138});
put('Î', new byte[]{(byte) 140});
put('Ì', new byte[]{(byte) 141});
put('Ã', new byte[]{(byte) 142});
put('Ä', new byte[]{(byte) 143});
put('É', new byte[]{(byte) 144});
put('æ', new byte[]{(byte) 145});
put('Æ', new byte[]{(byte) 146});
put('ô', new byte[]{(byte) 147});
put('ö', new byte[]{(byte) 148});
put('ò', new byte[]{(byte) 149});
put('û', new byte[]{(byte) 150});
put('ù', new byte[]{(byte) 151});
put('ÿ', new byte[]{(byte) 152});
put('Ö', new byte[]{(byte) 153});
put('Ü', new byte[]{(byte) 154});
put('¢', new byte[]{(byte) 155});
put('£', new byte[]{(byte) 156});
put('¥', new byte[]{(byte) 157});
put('ƒ', new byte[]{(byte) 159});
put('á', new byte[]{(byte) 160});
put('ñ', new byte[]{(byte) 164});
put('Ñ', new byte[]{(byte) 165});
put('ª', new byte[]{(byte) 166});
put('º', new byte[]{(byte) 167});
put('¿', new byte[]{(byte) 168});
put('¬', new byte[]{(byte) 170});
put('½', new byte[]{(byte) 171});
put('¼', new byte[]{(byte) 172});
put('¡', new byte[]{(byte) 173});
put('«', new byte[]{(byte) 174});
put('»', new byte[]{(byte) 175});
put('°', new byte[]{(byte) 0xa1, (byte) 0xe3});
}
};
}

View File

@ -198,7 +198,6 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator {
}else{
return HPlusConstants.ARG_TIMEMODE_12H;
}
}
public static byte getUnit(String address) {
@ -211,25 +210,25 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator {
}
}
public static byte getUserWeight(String address) {
public static byte getUserWeight() {
ActivityUser activityUser = new ActivityUser();
return (byte) (activityUser.getWeightKg() & 0xFF);
}
public static byte getUserHeight(String address) {
public static byte getUserHeight() {
ActivityUser activityUser = new ActivityUser();
return (byte) (activityUser.getHeightCm() & 0xFF);
}
public static byte getUserAge(String address) {
public static byte getUserAge() {
ActivityUser activityUser = new ActivityUser();
return (byte) (activityUser.getAge() & 0xFF);
}
public static byte getUserGender(String address) {
public static byte getUserGender() {
ActivityUser activityUser = new ActivityUser();
if (activityUser.getGender() == ActivityUser.GENDER_MALE)
@ -238,7 +237,7 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator {
return HPlusConstants.ARG_GENDER_FEMALE;
}
public static int getGoal(String address) {
public static int getGoal() {
ActivityUser activityUser = new ActivityUser();
return activityUser.getStepsGoal();

View File

@ -51,7 +51,13 @@ public class HPlusDataRecordDaySlot extends HPlusDataRecord {
*/
public int heartRate;
public HPlusDataRecordDaySlot(byte[] data) {
private int age = 0;
/**
* Raw intensity calculated from calories
*/
public int intensity;
public HPlusDataRecordDaySlot(byte[] data, int age) {
super(data, TYPE_DAY_SLOT);
int a = (data[4] & 0xFF) * 256 + (data[5] & 0xFF);
@ -77,6 +83,8 @@ public class HPlusDataRecordDaySlot extends HPlusDataRecord {
slotTime.set(Calendar.SECOND, 0);
timestamp = (int) (slotTime.getTimeInMillis() / 1000L);
this.age = age;
}
public String toString(){
@ -101,6 +109,9 @@ public class HPlusDataRecordDaySlot extends HPlusDataRecord {
}
secondsInactive += other.secondsInactive;
intensity = (int) ((100*heartRate)/(208-0.7*age));
}
public boolean isValid(){

View File

@ -66,7 +66,7 @@ class HPlusDataRecordRealtime extends HPlusDataRecord {
*/
public int intensity;
public HPlusDataRecordRealtime(byte[] data) {
public HPlusDataRecordRealtime(byte[] data, int age) {
super(data, TYPE_REALTIME);
if (data.length < 15) {
@ -91,7 +91,7 @@ class HPlusDataRecordRealtime extends HPlusDataRecord {
heartRate = ActivitySample.NOT_MEASURED;
}
else {
intensity = (int) (100 * Math.max(0, Math.min((heartRate - 60) / 120.0, 1))); // TODO: Calculate a proper value
intensity = (int) ((100*heartRate)/(208-0.7*age));
activityKind = ActivityKind.TYPE_UNKNOWN;
}
}

View File

@ -123,6 +123,10 @@ class HPlusHandlerThread extends GBDeviceIoThread {
break;
}
if(gbDevice.getState() == GBDevice.State.NOT_CONNECTED){
quit();
}
Calendar now = GregorianCalendar.getInstance();
if (now.compareTo(mGetDaySlotsTime) > 0) {
@ -138,7 +142,6 @@ class HPlusHandlerThread extends GBDeviceIoThread {
}
if(now.compareTo(mHelloTime) > 0){
LOG.info("Sending hello");
sendHello();
}
@ -155,10 +158,6 @@ class HPlusHandlerThread extends GBDeviceIoThread {
synchronized (waitObject) {
waitObject.notify();
}
StackTraceElement l[] = Thread.currentThread().getStackTrace();
for(StackTraceElement e: l){
LOG.warn(e.toString());
}
}
@ -221,12 +220,12 @@ class HPlusHandlerThread extends GBDeviceIoThread {
* @param data the message from the device
* @return boolean indicating success or fail
*/
public boolean processIncomingDaySlotData(byte[] data) {
public boolean processIncomingDaySlotData(byte[] data, int age) {
HPlusDataRecordDaySlot record;
try{
record = new HPlusDataRecordDaySlot(data);
record = new HPlusDataRecordDaySlot(data, age);
} catch(IllegalArgumentException e){
LOG.info((e.getMessage()));
return false;
@ -303,7 +302,7 @@ class HPlusHandlerThread extends GBDeviceIoThread {
sample.setSteps(storedRecord.steps);
sample.setHeartRate(storedRecord.heartRate);
sample.setRawKind(storedRecord.type);
sample.setRawIntensity(record.intensity);
sample.setProvider(provider);
samples.add(sample);
}
@ -384,11 +383,11 @@ class HPlusHandlerThread extends GBDeviceIoThread {
* @param data the message from the device
* @return boolean indicating success or fail
*/
public boolean processRealtimeStats(byte[] data) {
public boolean processRealtimeStats(byte[] data, int age) {
HPlusDataRecordRealtime record;
try{
record = new HPlusDataRecordRealtime(data);
record = new HPlusDataRecordRealtime(data, age);
} catch(IllegalArgumentException e){
LOG.info((e.getMessage()));
return false;
@ -497,8 +496,15 @@ class HPlusHandlerThread extends GBDeviceIoThread {
* @return boolean indicating success or fail
*/
public boolean processVersion(byte[] data) {
int major = data[2] & 0xFF;
int minor = data[1] & 0xFF;
int major, minor;
if(data.length == 11){
major = data[10] & 0xFF;
minor = data[9] & 0xFF;
}else {
major = data[2] & 0xFF;
minor = data[1] & 0xFF;
}
getDevice().setFirmwareVersion(major + "." + minor);

View File

@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
@ -59,9 +60,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.GattService;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfo;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.deviceinfo.DeviceInfoProfile;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -91,7 +90,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
public HPlusSupport(DeviceType type) {
super(LOG);
LOG.info("HPlusSupport Instance Created");
deviceType = type;
addSupportedService(HPlusConstants.UUID_SERVICE_HP);
@ -117,26 +116,26 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
protected TransactionBuilder initializeDevice(TransactionBuilder builder) {
LOG.info("Initializing");
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
gbDevice.setState(GBDevice.State.INITIALIZING);
gbDevice.sendDeviceUpdateIntent(getContext());
measureCharacteristic = getCharacteristic(HPlusConstants.UUID_CHARACTERISTIC_MEASURE);
ctrlCharacteristic = getCharacteristic(HPlusConstants.UUID_CHARACTERISTIC_CONTROL);
//Initialize device
sendUserInfo(builder); //Sync preferences
builder.notify(getCharacteristic(HPlusConstants.UUID_CHARACTERISTIC_MEASURE), true);
builder.setGattCallback(this);
builder.notify(measureCharacteristic, true);
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZED, getContext()));
//Initialize device
sendUserInfo(builder); //Sync preferences
if(syncHelper != null){
syncHelper.setHPlusSupport(this);
}else {
gbDevice.setState(GBDevice.State.INITIALIZED);
gbDevice.sendDeviceUpdateIntent(getContext());
if(syncHelper == null) {
syncHelper = new HPlusHandlerThread(getDevice(), getContext(), this);
syncHelper.start();
}
syncHelper.sync();
getDevice().setFirmwareVersion("N/A");
@ -293,7 +292,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
}
private HPlusSupport setWeight(TransactionBuilder transaction) {
byte value = HPlusCoordinator.getUserWeight(getDevice().getAddress());
byte value = HPlusCoordinator.getUserWeight();
transaction.write(ctrlCharacteristic, new byte[]{
HPlusConstants.CMD_SET_WEIGHT,
value
@ -303,7 +302,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
}
private HPlusSupport setHeight(TransactionBuilder transaction) {
byte value = HPlusCoordinator.getUserHeight(getDevice().getAddress());
byte value = HPlusCoordinator.getUserHeight();
transaction.write(ctrlCharacteristic, new byte[]{
HPlusConstants.CMD_HEIGHT,
value
@ -314,7 +313,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
private HPlusSupport setAge(TransactionBuilder transaction) {
byte value = HPlusCoordinator.getUserAge(getDevice().getAddress());
byte value = HPlusCoordinator.getUserAge();
transaction.write(ctrlCharacteristic, new byte[]{
HPlusConstants.CMD_SET_AGE,
value
@ -324,7 +323,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
}
private HPlusSupport setGender(TransactionBuilder transaction) {
byte value = HPlusCoordinator.getUserGender(getDevice().getAddress());
byte value = HPlusCoordinator.getUserGender();
transaction.write(ctrlCharacteristic, new byte[]{
HPlusConstants.CMD_SET_GENDER,
value
@ -335,7 +334,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
private HPlusSupport setGoal(TransactionBuilder transaction) {
int value = HPlusCoordinator.getGoal(getDevice().getAddress());
int value = HPlusCoordinator.getGoal();
transaction.write(ctrlCharacteristic, new byte[]{
HPlusConstants.CMD_SET_GOAL,
(byte) ((value / 256) & 0xff),
@ -806,7 +805,7 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
byte[] cs;
if (HPlusConstants.transliterateMap.containsKey(c)) {
cs = new byte[]{HPlusConstants.transliterateMap.get(c)};
cs = HPlusConstants.transliterateMap.get(c);
} else {
try {
if (HPlusCoordinator.getLanguage(this.gbDevice.getAddress()) == HPlusConstants.ARG_LANGUAGE_CN)
@ -839,10 +838,11 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
switch (data[0]) {
case HPlusConstants.DATA_VERSION:
case HPlusConstants.DATA_VERSION1:
return syncHelper.processVersion(data);
case HPlusConstants.DATA_STATS:
boolean result = syncHelper.processRealtimeStats(data);
boolean result = syncHelper.processRealtimeStats(data, HPlusCoordinator.getUserAge());
if (result) {
processExtraInfo (data);
}
@ -856,17 +856,19 @@ public class HPlusSupport extends AbstractBTLEDeviceSupport {
case HPlusConstants.DATA_DAY_SUMMARY:
case HPlusConstants.DATA_DAY_SUMMARY_ALT:
return syncHelper.processIncomingDaySlotData(data);
return syncHelper.processIncomingDaySlotData(data, HPlusCoordinator.getUserAge());
case HPlusConstants.DATA_UNKNOWN:
return true;
default:
LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + data[0]);
LOG.info("Unhandled characteristic change: " + characteristicUUID + " code: " + Arrays.toString(data));
return true;
}
}
private void processExtraInfo (byte[] data) {
try {
HPlusDataRecordRealtime record = new HPlusDataRecordRealtime(data);
HPlusDataRecordRealtime record = new HPlusDataRecordRealtime(data, HPlusCoordinator.getUserAge());
handleBatteryInfo(record.battery);

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<changelog>
<release version="0.19.1" versioncode="94">
<change>Fix crash at startup</change>
<change>Improve reconnection to device</change>
* <change>Improve transliteration</change>
</release>
<release version="0.19.0" versioncode="93">
<change>Pebble: allow calendar sync with Timeline (Title, Location, Description)</change>
<change>Pebble: display calendar icon for reminders from AOSP Calendar</change>

View File

@ -1,5 +1,6 @@
package nodomain.freeyourgadget.gadgetbridge.test;
import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;