use of nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySample in project Gadgetbridge by Freeyourgadget.
the class CasioGBX100DeviceSupport method getSumWithinRange.
public CasioGBX100ActivitySample getSumWithinRange(int timestamp_from, int timestamp_to) {
int steps = 0;
int calories = 0;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
User user = DBHelper.getUser(dbHandler.getDaoSession());
Device device = DBHelper.getDevice(this.getDevice(), dbHandler.getDaoSession());
CasioGBX100SampleProvider provider = new CasioGBX100SampleProvider(this.getDevice(), dbHandler.getDaoSession());
List<CasioGBX100ActivitySample> samples = provider.getActivitySamples(timestamp_from, timestamp_to);
for (CasioGBX100ActivitySample sample : samples) {
if (sample.getDevice().equals(device) && sample.getUser().equals(user)) {
steps += sample.getSteps();
calories += sample.getCalories();
}
}
} catch (Exception e) {
LOG.error("Error fetching activity data.");
}
CasioGBX100ActivitySample ret = new CasioGBX100ActivitySample();
ret.setCalories(calories);
ret.setSteps(steps);
LOG.debug("Fetched for today: " + calories + " cals and " + steps + " steps.");
return ret;
}
use of nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySample in project Gadgetbridge by Freeyourgadget.
the class CasioGBX100DeviceSupport method addGBActivitySamples.
private void addGBActivitySamples(ArrayList<CasioGBX100ActivitySample> samples) {
try (DBHandler dbHandler = GBApplication.acquireDB()) {
User user = DBHelper.getUser(dbHandler.getDaoSession());
Device device = DBHelper.getDevice(this.getDevice(), dbHandler.getDaoSession());
CasioGBX100SampleProvider provider = new CasioGBX100SampleProvider(this.getDevice(), dbHandler.getDaoSession());
for (CasioGBX100ActivitySample sample : samples) {
sample.setDevice(device);
sample.setUser(user);
sample.setProvider(provider);
provider.addGBActivitySample(sample);
}
} catch (Exception ex) {
// Why is this a toast? The user doesn't care about the error.
GB.toast(getContext(), "Error saving samples: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
GB.updateTransferNotification(null, "Data transfer failed", false, 0, getContext());
LOG.error(ex.getMessage());
}
}
use of nodomain.freeyourgadget.gadgetbridge.entities.CasioGBX100ActivitySample in project Gadgetbridge by Freeyourgadget.
the class FetchStepCountDataOperation method onCharacteristicChanged.
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
UUID characteristicUUID = characteristic.getUuid();
byte[] data = characteristic.getValue();
if (data.length == 0)
return true;
if (characteristicUUID.equals(CasioConstants.CASIO_DATA_REQUEST_SP_CHARACTERISTIC_UUID)) {
int length = 0;
if (data.length > 3) {
length = (data[2] & 0xff) | ((data[3] & 0xff) << 8);
}
LOG.debug("Response is going to be " + length + " bytes long");
GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, 10, getContext());
return true;
} else if (characteristicUUID.equals(CasioConstants.CASIO_CONVOY_CHARACTERISTIC_UUID)) {
if (data.length < 18) {
LOG.info("Data length too short.");
} else {
for (int i = 0; i < data.length; i++) data[i] = (byte) (~data[i]);
int payloadLength = ((data[0] & 0xff) | ((data[1] & 0xff) << 8));
if (data.length == (payloadLength + 2)) {
LOG.debug("Payload length and data length match.");
} else {
LOG.debug("Payload length and data length do not match: " + payloadLength + " vs. " + data.length);
}
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
ArrayList<CasioGBX100ActivitySample> stepCountData = new ArrayList<>();
int year = data[2];
// Zero-based
int month = data[3] - 1;
int day = data[4];
int hour = data[5];
int minute = data[6];
int stepCount = ((data[7] & 0xff) | ((data[8] & 0xff) << 8) | ((data[9] & 0xff) << 16) | ((data[10] & 0xff) << 24));
// it reports 0xfffffffe if no steps have been recorded
if (stepCount == 0xfffffffe)
stepCount = 0;
int calories = ((data[11] & 0xff) | ((data[12] & 0xff) << 8));
if (calories == 0xfffe)
calories = 0;
int yearOfBirth = ((data[13] & 0xff) | ((data[14] & 0xff) << 8));
int monthOfBirth = data[15];
int dayOfBirth = data[16];
LOG.debug("Current step count value: " + stepCount);
LOG.debug("Current calories: " + calories);
// data[17]:
// 0x01 probably means finished.
// 0x00 probably means more data.
// Set timestamps for retrieving recorded data for the current day
cal.set(year + 2000, month, day, hour, 30, 0);
int ts_to = (int) (cal.getTimeInMillis() / 1000);
cal.set(year + 2000, month, day, 0, 0, 0);
int ts_from = (int) (cal.getTimeInMillis() / 1000);
CasioGBX100ActivitySample sum = support.getSumWithinRange(ts_from, ts_to);
int caloriesToday = sum.getCalories();
int stepsToday = sum.getSteps();
// Set timestamp to currently fetched data for fetching historic data
cal.set(year + 2000, month, day, hour, 30, 0);
if (data[17] == 0x00 && data.length > 18) {
LOG.info("We got historic step count data.");
int index = 18;
boolean inPacket = false;
int packetIndex = 0;
int packetLength = 0;
int type = 0;
while (index < data.length) {
if (!inPacket) {
type = data[index];
packetLength = ((data[index + 1] & 0xff) | ((data[index + 2] & 0xff) << 8));
packetIndex = 0;
inPacket = true;
index = index + 3;
LOG.debug("Decoding packet with type: " + type + " and length: " + packetLength);
}
int count = ((data[index] & 0xff) | ((data[index + 1] & 0xff) << 8));
if (count == 0xfffe)
count = 0;
LOG.debug("Got count " + count);
index = index + 2;
if (index >= data.length) {
LOG.debug("End of packet.");
}
if (type == CasioConstants.CASIO_CONVOY_DATATYPE_STEPS) {
cal.add(Calendar.HOUR, -1);
int ts = (int) (cal.getTimeInMillis() / 1000);
stepCountData.add(new CasioGBX100ActivitySample());
stepCountData.get(packetIndex / 2).setSteps(count);
stepCountData.get(packetIndex / 2).setTimestamp(ts);
if (count > 0) {
stepCountData.get(packetIndex / 2).setRawKind(ActivityKind.TYPE_ACTIVITY);
} else {
stepCountData.get(packetIndex / 2).setRawKind(ActivityKind.TYPE_NOT_MEASURED);
}
if (ts > ts_from && ts < ts_to) {
stepsToday += count;
}
} else if (type == CasioConstants.CASIO_CONVOY_DATATYPE_CALORIES) {
if (stepCountData.get(packetIndex / 2).getSteps() > 0) {
// The last packet might contain an invalid calory count
// of 255, but only if the steps are also invalid.
stepCountData.get(packetIndex / 2).setCalories(count);
int ts = stepCountData.get(packetIndex / 2).getTimestamp();
if (ts > ts_from && ts < ts_to) {
caloriesToday += count;
}
}
}
packetIndex = packetIndex + 2;
if (packetIndex >= packetLength)
inPacket = false;
}
}
// This generates an artificial "now" timestamp for the current
// activity based on the existing data. This timestamp will be overwritten
// by the next fetch operation with the actual value.
int steps = stepCount - stepsToday;
int cals = calories - caloriesToday;
if (steps > 0 && cals > 0) {
cal.set(year + 2000, month, day, hour, 30, 0);
int ts = (int) (cal.getTimeInMillis() / 1000);
LOG.debug("Artificial timestamp: " + cals + " calories and " + steps + " steps");
CasioGBX100ActivitySample sample = new CasioGBX100ActivitySample();
sample.setSteps(steps);
sample.setCalories(cals);
sample.setTimestamp(ts);
if (steps > 0)
sample.setRawKind(ActivityKind.TYPE_ACTIVITY);
else
sample.setRawKind(ActivityKind.TYPE_NOT_MEASURED);
stepCountData.add(0, sample);
}
support.stepCountDataFetched(stepCount, calories, stepCountData);
}
GB.updateTransferNotification(null, getContext().getString(R.string.busy_task_fetch_activity_data), true, 80, getContext());
writeStepCountAck();
return true;
} else {
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
return super.onCharacteristicChanged(gatt, characteristic);
}
}
Aggregations