Skip to content
Open
Show file tree
Hide file tree
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ All scripts located in:
- Data sync over WiFi/mobile
- Edit advanced constants

## Trajectory Files

Trajectory recordings are stored as JSON files named `trajectory_<timestamp>.txt`.
The timestamp follows `dd-MM-yy-HH-mm-ss`. Files are written and read via the
`TrajectoryIO` helper which converts between the protobuf `Traj.Trajectory`
and its JSON representation.

## 🧩 Common Issues & Fixes

| Issue | Fix |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.openpositioning.PositionMe.data.local;

import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import com.openpositioning.PositionMe.Traj;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* Simple repository for persisting {@link Traj.Trajectory} objects to the app's
* private storage. The data is written using {@link TrajectoryIO}.
*/
public class FileRepository {
private static final String TAG = "FileRepository";
private final Context context;

public FileRepository(Context context) {
this.context = context.getApplicationContext();
}

/**
* Save the trajectory to the app-specific documents directory.
*
* @param trajectory trajectory to persist
* @return resulting file or {@code null} if failed
*/
public File saveTrajectory(Traj.Trajectory trajectory) {
File dir;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
dir = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
if (dir == null) {
dir = context.getFilesDir();
}
} else {
dir = context.getFilesDir();
}
if (dir != null && !dir.exists()) {
dir.mkdirs();
}
String time = new SimpleDateFormat("dd-MM-yy-HH-mm-ss").format(new Date());
File file = new File(dir, "trajectory_" + time + ".txt");
try {
TrajectoryIO.writeTrajectory(file, trajectory);
Log.i(TAG, "Trajectory written to: " + file.getAbsolutePath());
return file;
} catch (Exception e) {
Log.e(TAG, "Failed to save trajectory", e);
return null;
}
}

/**
* Load a trajectory from a file.
*/
public Traj.Trajectory readTrajectory(File file) throws Exception {
return TrajectoryIO.readTrajectory(file);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.openpositioning.PositionMe.data.local;

import com.google.protobuf.util.JsonFormat;
import com.openpositioning.PositionMe.Traj;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;

/**
* Utility class for reading and writing {@link Traj.Trajectory} files.
* <p>
* The trajectories are stored as JSON text files. Use
* {@link #writeTrajectory(File, Traj.Trajectory)} to persist a trajectory and
* {@link #readTrajectory(File)} to load it back.
*/
public class TrajectoryIO {

/**
* Writes the given trajectory to a file in JSON format.
*
* @param file destination file
* @param traj trajectory to write
* @throws IOException if writing fails
*/
public static void writeTrajectory(File file, Traj.Trajectory traj) throws IOException {
try (FileWriter writer = new FileWriter(file)) {
writer.write(JsonFormat.printer().print(traj));
writer.flush();
}
}

/**
* Reads a trajectory from a JSON file.
*
* @param file source file
* @return parsed trajectory
* @throws IOException if reading fails
*/
public static Traj.Trajectory readTrajectory(File file) throws IOException {
String json = new String(Files.readAllBytes(file.toPath()));
Traj.Trajectory.Builder builder = Traj.Trajectory.newBuilder();
JsonFormat.parser().merge(json, builder);
return builder.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.google.protobuf.util.JsonFormat;
import com.openpositioning.PositionMe.BuildConfig;
import com.openpositioning.PositionMe.Traj;
import com.openpositioning.PositionMe.data.local.TrajectoryIO;
import com.openpositioning.PositionMe.presentation.fragment.FilesFragment;
import com.openpositioning.PositionMe.presentation.activity.MainActivity;
import com.openpositioning.PositionMe.sensors.Observable;
Expand Down Expand Up @@ -539,10 +540,8 @@ public void onResponse(Call call, Response response) throws IOException {
}

File file = new File(appSpecificDownloads, fileName);
try (FileWriter fileWriter = new FileWriter(file)) {
String receivedTrajectoryString = JsonFormat.printer().print(receivedTrajectory);
fileWriter.write(receivedTrajectoryString);
fileWriter.flush();
try {
TrajectoryIO.writeTrajectory(file, receivedTrajectory);
System.err.println("Received trajectory stored in: " + file.getAbsolutePath());
} catch (IOException ee) {
System.err.println("Trajectory download failed");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.openpositioning.PositionMe.utils.PdrProcessing;
import com.openpositioning.PositionMe.data.remote.ServerCommunications;
import com.openpositioning.PositionMe.Traj;
import com.openpositioning.PositionMe.data.local.FileRepository;
import com.openpositioning.PositionMe.presentation.fragment.SettingsFragment;
import com.openpositioning.PositionMe.domain.EKF;

Expand Down Expand Up @@ -1322,6 +1323,9 @@ public void setTrajectoryMapFragment(com.openpositioning.PositionMe.presentation
public void sendTrajectoryToCloud() {
// Build object
Traj.Trajectory sentTrajectory = trajectory.build();
// Persist locally
FileRepository repo = new FileRepository(appContext);
repo.saveTrajectory(sentTrajectory);
// Pass object to communications object
this.serverCommunications.sendTrajectory(sentTrajectory);
}
Expand Down