mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-07-22 14:52:25 +02:00
Bangle.js:WIP add activity tracks support
Bangle.js: WIP add supportsActivityTracks Bangle.js: testing flow of info Bangle.js:WIP receive and store csv from Bangle.js Bangle.js:store and transmit ID of last synced log bangle.js:activity tracks, act on completed fetch ... of the recorder csv file. Bangle.js: Activity tracks, now in database ... but not all data is persisted correctly I think. It's presented as 'Unknown activity'. Bangle.js:Activity tracks, try to add gps info I haven't tested with recordings where I have gps values, so far only empty values. With empty values I currently get "This activity does not contain GPX tracks" when trying to use the GPXExporter. Bangle.js: Activity tracks, now adds GPS points ... to the activity to be shown when on the "Sport Activity Detail" screen.
This commit is contained in:
parent
fc9d18100d
commit
c6cec7a0f8
|
@ -107,6 +107,11 @@ public class BangleJSCoordinator extends AbstractBLEDeviceCoordinator {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsActivityTracks() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsScreenshots() {
|
public boolean supportsScreenshots() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.banglejs;
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.banglejs;
|
||||||
|
|
||||||
|
import static java.sql.Date.valueOf;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ALLOW_HIGH_MTU;
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_ALLOW_HIGH_MTU;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BANGLEJS_TEXT_BITMAP;
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BANGLEJS_TEXT_BITMAP;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BANGLEJS_TEXT_BITMAP_SIZE;
|
import static nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst.PREF_BANGLEJS_TEXT_BITMAP_SIZE;
|
||||||
|
@ -67,8 +68,11 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
@ -76,6 +80,7 @@ import java.lang.reflect.Field;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
|
@ -84,6 +89,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.SimpleTimeZone;
|
import java.util.SimpleTimeZone;
|
||||||
|
|
||||||
import javax.xml.xpath.XPath;
|
import javax.xml.xpath.XPath;
|
||||||
|
@ -96,6 +102,7 @@ import io.wax911.emojify.EmojiManager;
|
||||||
import io.wax911.emojify.EmojiUtils;
|
import io.wax911.emojify.EmojiUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.BarcodeFormat;
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.BarcodeFormat;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.LoyaltyCard;
|
import nodomain.freeyourgadget.gadgetbridge.capabilities.loyaltycards.LoyaltyCard;
|
||||||
|
@ -108,22 +115,33 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicContr
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventNotificationControl;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventUpdatePreferences;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.banglejs.BangleJSConstants;
|
import nodomain.freeyourgadget.gadgetbridge.devices.banglejs.BangleJSConstants;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.devices.banglejs.BangleJSSampleProvider;
|
import nodomain.freeyourgadget.gadgetbridge.devices.banglejs.BangleJSSampleProvider;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.BangleJSActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.entities.BangleJSActivitySample;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.BaseActivitySummary;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.CalendarSyncState;
|
import nodomain.freeyourgadget.gadgetbridge.entities.CalendarSyncState;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.CalendarSyncStateDao;
|
import nodomain.freeyourgadget.gadgetbridge.entities.CalendarSyncStateDao;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.CalendarReceiver;
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.CalendarReceiver;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.export.ActivityTrackExporter;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.export.GPXExporter;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationManager;
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.GBLocationManager;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.LocationProviderType;
|
import nodomain.freeyourgadget.gadgetbridge.externalevents.gps.LocationProviderType;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityPoint;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
import nodomain.freeyourgadget.gadgetbridge.model.BatteryState;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.model.GPSCoordinate;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec;
|
import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec;
|
||||||
|
@ -136,6 +154,8 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEQueue;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEQueue;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.EmojiConverter;
|
import nodomain.freeyourgadget.gadgetbridge.util.EmojiConverter;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
@ -562,6 +582,206 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||||
case "act":
|
case "act":
|
||||||
handleActivity(json);
|
handleActivity(json);
|
||||||
break;
|
break;
|
||||||
|
case "trksList":
|
||||||
|
{
|
||||||
|
LOG.info("trksList says hi!");
|
||||||
|
GB.toast(getContext(), "trksList says hi!", Toast.LENGTH_LONG, GB.INFO);
|
||||||
|
JSONArray tracksList = json.getJSONArray("list");
|
||||||
|
LOG.info("New recorder logs since last fetch: " + String.valueOf(tracksList));
|
||||||
|
for (int i = 0; i < tracksList.length(); i ++) {
|
||||||
|
requestActivityTrackLog(tracksList.getString(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case "actTrk":
|
||||||
|
{
|
||||||
|
LOG.info("actTrk says hi!");
|
||||||
|
//GB.toast(getContext(), "actTrk says hi!", Toast.LENGTH_LONG, GB.INFO);
|
||||||
|
String log = json.getString("log");
|
||||||
|
String line = json.getString("line");
|
||||||
|
LOG.info(log);
|
||||||
|
LOG.info(line);
|
||||||
|
File dir;
|
||||||
|
try {
|
||||||
|
dir = FileUtils.getExternalFilesDir();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String filename = "recorder.log" + log + ".csv";
|
||||||
|
|
||||||
|
if (line.equals("end of recorder log")) { // TODO: Persist log to database here by reading the now completely transferred csv file from GB storage directory
|
||||||
|
|
||||||
|
File inputFile = new File(dir, filename);
|
||||||
|
try { // FIXME: There is maybe code inside this try-statement that should be outside of it.
|
||||||
|
|
||||||
|
// Read from the previously stored log (see the else-statement below) into a string.
|
||||||
|
BufferedReader reader = new BufferedReader(new FileReader(inputFile));
|
||||||
|
StringBuilder storedLogBuilder = new StringBuilder(reader.readLine() + "\n");
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
storedLogBuilder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
String storedLog = String.valueOf(storedLogBuilder);
|
||||||
|
storedLog = storedLog.replace(",",", "); // So all rows (internal arrays) in storedLogArray2 get the same number of entries.
|
||||||
|
LOG.info("Contents of log read from GB storage:\n" + storedLog);
|
||||||
|
|
||||||
|
// Turn the string log into a 2d array in two steps.
|
||||||
|
String[] storedLogArray = storedLog.split("\n") ;
|
||||||
|
String[][] storedLogArray2 = new String[storedLogArray.length][1];
|
||||||
|
|
||||||
|
for (int i = 0; i < storedLogArray.length; i++) {
|
||||||
|
storedLogArray2[i] = storedLogArray[i].split(",");
|
||||||
|
for (int j = 0; j < storedLogArray2[i].length;j++) {
|
||||||
|
storedLogArray2[i][j] = storedLogArray2[i][j].trim(); // Remove the extra spaces we introduced above for getting the same number of entries on all rows.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.info("Contents of storedLogArray2:\n" + Arrays.deepToString(storedLogArray2));
|
||||||
|
|
||||||
|
// Turn the 2d array into an object for easier access later on.
|
||||||
|
JSONObject storedLogObject = new JSONObject();
|
||||||
|
JSONArray valueArray = new JSONArray();
|
||||||
|
for (int i = 0; i < storedLogArray2[0].length; i++){
|
||||||
|
for (int j = 1; j < storedLogArray2.length; j++) {
|
||||||
|
valueArray.put(storedLogArray2[j][i]);
|
||||||
|
}
|
||||||
|
storedLogObject.put(storedLogArray2[0][i], valueArray);
|
||||||
|
valueArray = new JSONArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.info("storedLogObject:\n" + storedLogObject);
|
||||||
|
|
||||||
|
BaseActivitySummary summary = null;
|
||||||
|
|
||||||
|
Date startTime = new Date(Long.parseLong(storedLogArray2[1][0])*1000L);
|
||||||
|
Date endTime = new Date(Long.parseLong(storedLogArray2[storedLogArray2.length-1][0])*1000L);
|
||||||
|
summary = new BaseActivitySummary();
|
||||||
|
summary.setName(log);
|
||||||
|
summary.setStartTime(startTime);
|
||||||
|
summary.setEndTime(endTime);
|
||||||
|
summary.setActivityKind(ActivityKind.TYPE_RUNNING); // TODO: Make this depend on info from watch (currently this info isn't supplied in Bangle.js recorder logs).
|
||||||
|
summary.setRawDetailsPath(String.valueOf(inputFile));
|
||||||
|
summary.setSummaryData(storedLog);
|
||||||
|
|
||||||
|
ActivityTrack track = new ActivityTrack(); // detailsParser.parse(buffer.toByteArray());
|
||||||
|
track.startNewSegment();
|
||||||
|
track.setBaseTime(startTime);
|
||||||
|
track.setName(log);
|
||||||
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
|
DaoSession session = dbHandler.getDaoSession();
|
||||||
|
Device device = DBHelper.getDevice(getDevice(), session);
|
||||||
|
User user = DBHelper.getUser(session);
|
||||||
|
track.setDevice(device);
|
||||||
|
track.setUser(user);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
GB.toast(getContext(), "Error setting user for activity track.", Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||||
|
}
|
||||||
|
ActivityPoint point = new ActivityPoint();
|
||||||
|
Date timeOfPoint = new Date();
|
||||||
|
for (int i = 0; i < storedLogObject.getJSONArray("Time").length(); i++) {
|
||||||
|
timeOfPoint.setTime(storedLogObject.getJSONArray("Time").getLong(i)*1000L);
|
||||||
|
point.setTime(timeOfPoint);
|
||||||
|
if (storedLogObject.has("Longitude")) {
|
||||||
|
if (!Objects.equals(storedLogObject.getJSONArray("Longitude").getString(i), "")
|
||||||
|
&& !Objects.equals(storedLogObject.getJSONArray("Latitude").getString(i), "")
|
||||||
|
&& !Objects.equals(storedLogObject.getJSONArray("Altitude").getString(i), "")) {
|
||||||
|
|
||||||
|
point.setLocation(new GPSCoordinate(
|
||||||
|
storedLogObject.getJSONArray("Longitude").getDouble(i),
|
||||||
|
storedLogObject.getJSONArray("Latitude").getDouble(i),
|
||||||
|
storedLogObject.getJSONArray("Altitude").getDouble(i)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (storedLogObject.has("Heartrate") && !Objects.equals(storedLogObject.getJSONArray("Heartrate").getString(i), "")) {
|
||||||
|
point.setHeartRate(storedLogObject.getJSONArray("Heartrate").getInt(i));
|
||||||
|
}
|
||||||
|
track.addTrackPoint(point);
|
||||||
|
point = new ActivityPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
ActivityTrackExporter exporter = createExporter();
|
||||||
|
String trackType = "track";
|
||||||
|
switch (summary.getActivityKind()) {
|
||||||
|
case ActivityKind.TYPE_CYCLING:
|
||||||
|
trackType = getContext().getString(R.string.activity_type_biking);
|
||||||
|
break;
|
||||||
|
case ActivityKind.TYPE_RUNNING:
|
||||||
|
trackType = getContext().getString(R.string.activity_type_running);
|
||||||
|
break;
|
||||||
|
case ActivityKind.TYPE_WALKING:
|
||||||
|
trackType = getContext().getString(R.string.activity_type_walking);
|
||||||
|
break;
|
||||||
|
case ActivityKind.TYPE_HIKING:
|
||||||
|
trackType = getContext().getString(R.string.activity_type_hiking);
|
||||||
|
break;
|
||||||
|
case ActivityKind.TYPE_CLIMBING:
|
||||||
|
trackType = getContext().getString(R.string.activity_type_climbing);
|
||||||
|
break;
|
||||||
|
case ActivityKind.TYPE_SWIMMING:
|
||||||
|
trackType = getContext().getString(R.string.activity_type_swimming);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fileName = FileUtils.makeValidFileName("gadgetbridge-" + trackType.toLowerCase() + "-" + summary.getName() + ".gpx");
|
||||||
|
File targetFile = new File(FileUtils.getExternalFilesDir(), fileName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
exporter.performExport(track, targetFile);
|
||||||
|
|
||||||
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
|
summary.setGpxTrack(targetFile.getAbsolutePath());
|
||||||
|
//dbHandler.getDaoSession().getBaseActivitySummaryDao().update(summary);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} catch (ActivityTrackExporter.GPXTrackEmptyException ex) {
|
||||||
|
GB.toast(getContext(), "This activity does not contain GPX tracks.", Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
//summary.setSummaryData(null); // remove json before saving to database,
|
||||||
|
|
||||||
|
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||||
|
DaoSession session = dbHandler.getDaoSession();
|
||||||
|
Device device = DBHelper.getDevice(getDevice(), session);
|
||||||
|
User user = DBHelper.getUser(session);
|
||||||
|
summary.setDevice(device);
|
||||||
|
summary.setUser(user);
|
||||||
|
session.getBaseActivitySummaryDao().insertOrReplace(summary);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
GB.toast(getContext(), "Error saving activity summary", Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
} else { // We received a line of the csv, now we append it to the file in storage.
|
||||||
|
// TODO: File manipulation adapted from onFetchRecordedData() - break out to a new function to avoid code duplication?
|
||||||
|
|
||||||
|
File outputFile = new File(dir, filename);
|
||||||
|
String filenameLogID = "latestFetchedRecorderLog.txt";
|
||||||
|
File outputFileLogID = new File(dir, filenameLogID);
|
||||||
|
LOG.warn("Writing log to " + outputFile.toString());
|
||||||
|
try {
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile, true));
|
||||||
|
writer.write(line);
|
||||||
|
writer.close();
|
||||||
|
GB.toast(getContext(), "Log written to " + filename, Toast.LENGTH_LONG, GB.INFO);
|
||||||
|
|
||||||
|
BufferedWriter writerLogID = new BufferedWriter(new FileWriter(outputFileLogID));
|
||||||
|
writerLogID.write(log);
|
||||||
|
writerLogID.close();
|
||||||
|
GB.toast(getContext(), "Log ID " + log + " written to " + filenameLogID, Toast.LENGTH_LONG, GB.INFO);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.warn("Could not write to file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
case "http":
|
case "http":
|
||||||
handleHttp(json);
|
handleHttp(json);
|
||||||
break;
|
break;
|
||||||
|
@ -1375,6 +1595,28 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void requestActivityTracksList(String lastSyncedID) {
|
||||||
|
try {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
o.put("t", "listRecs");
|
||||||
|
o.put("id", lastSyncedID);
|
||||||
|
uartTxJSON("requestActivityTracksList", o);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
LOG.info("JSONException: " + e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void requestActivityTrackLog(String id) {
|
||||||
|
try {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
o.put("t", "fetchRec");
|
||||||
|
o.put("id", id);
|
||||||
|
uartTxJSON("requestActivityTrackLog", o);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
LOG.info("JSONException: " + e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnableRealtimeSteps(boolean enable) {
|
public void onEnableRealtimeSteps(boolean enable) {
|
||||||
if (enable == realtimeHRM) return;
|
if (enable == realtimeHRM) return;
|
||||||
|
@ -1388,7 +1630,30 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||||
fetchActivityData(getLastSuccessfulSyncTime());
|
fetchActivityData(getLastSuccessfulSyncTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dataTypes & RecordedDataTypes.TYPE_DEBUGLOGS) != 0) {
|
if (dataTypes == RecordedDataTypes.TYPE_GPS_TRACKS) {
|
||||||
|
GB.toast("TYPE_GPS_TRACKS says hi!", Toast.LENGTH_LONG, GB.INFO);
|
||||||
|
File dir;
|
||||||
|
try {
|
||||||
|
dir = FileUtils.getExternalFilesDir();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String filename = "latestFetchedRecorderLog.txt";
|
||||||
|
File inputFile = new File(dir, filename);
|
||||||
|
BufferedReader reader;
|
||||||
|
String lastSyncedID = "";
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new FileReader(inputFile));
|
||||||
|
lastSyncedID = String.valueOf(reader.readLine());
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
//lastSyncedID = "20230706x"; // DEBUGGING
|
||||||
|
|
||||||
|
LOG.info("Last Synced log ID: " + lastSyncedID);
|
||||||
|
requestActivityTracksList(lastSyncedID);
|
||||||
|
}
|
||||||
|
if (dataTypes == RecordedDataTypes.TYPE_DEBUGLOGS) {
|
||||||
File dir;
|
File dir;
|
||||||
try {
|
try {
|
||||||
dir = FileUtils.getExternalFilesDir();
|
dir = FileUtils.getExternalFilesDir();
|
||||||
|
@ -1816,4 +2081,11 @@ public class BangleJSDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||||
LOG.info("JSONException: " + e.getLocalizedMessage());
|
LOG.info("JSONException: " + e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ActivityTrackExporter createExporter() {
|
||||||
|
GPXExporter exporter = new GPXExporter();
|
||||||
|
exporter.setCreator(GBApplication.app().getNameAndVersion());
|
||||||
|
return exporter;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user