checkpoint

This commit is contained in:
voussoir 2023-03-12 22:09:58 -07:00
parent 8cbfa729f0
commit aca4cf20c0
7 changed files with 52 additions and 57 deletions

View file

@ -6,9 +6,8 @@ import android.util.Log
import java.io.File
import java.util.*
class Database(trackbook: Trackbook)
class Database(val trackbook: Trackbook)
{
val trackbook = trackbook
var ready: Boolean = false
lateinit var file: File
lateinit var connection: SQLiteDatabase
@ -96,8 +95,12 @@ class Database(trackbook: Trackbook)
fun update_homepoint(id: Long, name: String, radius: Double)
{
Log.i("VOUSSOIR", "Database.update_homepoint")
val values = ContentValues().apply {
put("name", name)
put("radius", radius)
}
begin_transaction()
connection.rawQuery("UPDATE homepoints SET name = ?, radius = ? WHERE id = ?", arrayOf(name, radius.toString(), id.toString()))
connection.update("homepoints", values, "id = ?", arrayOf(id.toString()))
commit()
}
@ -107,6 +110,7 @@ class Database(trackbook: Trackbook)
this.connection.execSQL("CREATE TABLE IF NOT EXISTS meta(name TEXT PRIMARY KEY, value TEXT)")
this.connection.execSQL("CREATE TABLE IF NOT EXISTS trkpt(lat REAL NOT NULL, lon REAL NOT NULL, time INTEGER NOT NULL, accuracy REAL, device_id INTEGER NOT NULL, ele INTEGER, sat INTEGER, PRIMARY KEY(lat, lon, time, device_id))")
this.connection.execSQL("CREATE TABLE IF NOT EXISTS homepoints(id INTEGER PRIMARY KEY, lat REAL NOT NULL, lon REAL NOT NULL, radius REAL NOT NULL, name TEXT)")
this.connection.execSQL("PRAGMA user_version = ${Keys.CURRENT_TRACKLIST_FORMAT_VERSION}")
this.connection.setTransactionSuccessful()
this.connection.endTransaction()
}

View file

@ -77,18 +77,9 @@ object Keys {
const val DIALOG_EMPTY_PAYLOAD_STRING: String = ""
const val DIALOG_EMPTY_PAYLOAD_INT: Int = -1
// folder names
const val FOLDER_TEMP: String = "temp"
const val FOLDER_TRACKS: String = "tracks"
const val FOLDER_GPX: String = "gpx"
// file names and extensions
const val MIME_TYPE_GPX: String = "application/gpx+xml"
const val GPX_FILE_EXTENSION: String = ".gpx"
const val TRACKBOOK_LEGACY_FILE_EXTENSION: String = ".trackbook"
const val TRACKBOOK_FILE_EXTENSION: String = ".json"
const val TEMP_FILE: String = "temp.json"
const val TRACKLIST_FILE: String = "tracklist.json"
// view types
const val VIEW_TYPE_STATISTICS: Int = 1
@ -96,13 +87,11 @@ object Keys {
// default values
val DEFAULT_DATE: Date = Date(0L)
const val DEFAULT_RFC2822_DATE: String = "Thu, 01 Jan 1970 01:00:00 +0100" // --> Date(0)
const val ONE_SECOND_IN_MILLISECONDS: Long = 1000
const val ONE_MINUTE_IN_MILLISECONDS: Long = 60 * ONE_SECOND_IN_MILLISECONDS
const val ONE_HOUR_IN_MILLISECONDS: Long = 60 * ONE_MINUTE_IN_MILLISECONDS
const val EMPTY_STRING_RESOURCE: Int = 0
const val REQUEST_CURRENT_LOCATION_INTERVAL: Long = 1 * ONE_SECOND_IN_MILLISECONDS
const val TRACKING_INTERVAL: Long = 1 * ONE_SECOND_IN_MILLISECONDS
const val SAVE_TEMP_TRACK_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS
const val SIGNIFICANT_TIME_DIFFERENCE: Long = 1 * ONE_MINUTE_IN_MILLISECONDS
const val STOP_OVER_THRESHOLD: Long = 5 * ONE_MINUTE_IN_MILLISECONDS
@ -113,7 +102,6 @@ object Keys {
const val DEFAULT_ALTITUDE: Double = 0.0
const val DEFAULT_TIME: Long = 0L
const val COMMIT_INTERVAL: Int = 30
const val DEFAULT_ALTITUDE_SMOOTHING_VALUE: Int = 13
const val DEFAULT_THRESHOLD_LOCATION_ACCURACY: Int = 30 // 30 meters
const val DEFAULT_THRESHOLD_LOCATION_AGE: Long = 5_000_000_000L // 5s in nanoseconds
const val DEFAULT_THRESHOLD_DISTANCE: Float = 15f // 15 meters

View file

@ -138,6 +138,7 @@ class MapFragment : Fragment()
// basic map setup
controller = mapView.controller
mapView.isTilesScaledToDpi = true
mapView.isVerticalMapRepetitionEnabled = false
mapView.setTileSource(TileSourceFactory.MAPNIK)
mapView.setMultiTouchControls(true)
mapView.zoomController.setVisibility(org.osmdroid.views.CustomZoomButtonsController.Visibility.NEVER)
@ -538,7 +539,8 @@ class MapFragment : Fragment()
dialog.dismiss()
}
save_button.setOnClickListener {
trackbook.database.update_homepoint(homepoint.id, name=name_input.text.toString(), radius=radius_input.text.toString().toDouble())
val radius = radius_input.text.toString().toDoubleOrNull() ?: 25.0
trackbook.database.update_homepoint(homepoint.id, name=name_input.text.toString(), radius=radius)
trackbook.load_homepoints()
create_homepoint_overlays(requireContext(), mapView, trackbook.homepoints)
dialog.dismiss()
@ -568,8 +570,8 @@ class MapFragment : Fragment()
mapView.overlays.remove(currentTrackSpecialMarkerOverlay)
}
if (trkpts.isNotEmpty()) {
createTrackOverlay(requireContext(), mapView, trkpts, trackingState)
createSpecialMakersTrackOverlay(requireContext(), mapView, trkpts, trackingState)
currentTrackOverlay = createTrackOverlay(requireContext(), mapView, trkpts, trackingState)
currentTrackSpecialMarkerOverlay = createSpecialMakersTrackOverlay(requireContext(), mapView, trkpts, trackingState)
}
}

View file

@ -85,7 +85,7 @@ data class Track (
var previous: Trkpt? = null
for (trkpt in trkpt_generator())
{
if (previous != null && (trkpt.time - previous.time) > (5 * Keys.ONE_MINUTE_IN_MILLISECONDS))
if (previous != null && (trkpt.time - previous.time) > (Keys.STOP_OVER_THRESHOLD))
{
write("\t\t</trkseg>")
write("\t\t<trkseg>")

View file

@ -57,7 +57,7 @@ class TrackerService: Service(), SensorEventListener
var recording_started: Date = GregorianCalendar.getInstance().time
var commitInterval: Int = Keys.COMMIT_INTERVAL
var currentBestLocation: Location = getDefaultLocation()
var lastCommit: Date = Keys.DEFAULT_DATE
var lastCommit: Long = 0
var location_min_time_ms: Long = 0
private val RECENT_TRKPT_COUNT = 7200
var stepCountOffset: Float = 0f
@ -150,9 +150,36 @@ class TrackerService: Service(), SensorEventListener
return object : LocationListener {
override fun onLocationChanged(location: Location)
{
if (isBetterLocation(location, currentBestLocation)) {
currentBestLocation = location
if (! isBetterLocation(location, currentBestLocation))
{
return
}
currentBestLocation = location
if (trackingState != Keys.STATE_TRACKING_ACTIVE)
{
return
}
Log.i("VOUSSOIR", "Processing point ${location.latitude}, ${location.longitude} ${location.time}.")
if (should_keep_point((location)))
{
val now: Long = location.time
// val now: Date = GregorianCalendar.getInstance().time
val trkpt = Trkpt(location=location)
trackbook.database.insert_trkpt(device_id, trkpt)
recent_trkpts.add(trkpt)
while (recent_trkpts.size > RECENT_TRKPT_COUNT)
{
recent_trkpts.removeFirst()
}
if (now - lastCommit > Keys.SAVE_TEMP_TRACK_INTERVAL)
{
trackbook.database.commit()
lastCommit = now
}
}
displayNotification()
}
override fun onProviderEnabled(provider: String)
{
@ -353,7 +380,6 @@ class TrackerService: Service(), SensorEventListener
}
PreferencesHelper.saveTrackingState(trackingState)
startStepCounter()
handler.postDelayed(periodicTrackUpdate, 0)
startForeground(Keys.TRACKER_SERVICE_NOTIFICATION_ID, displayNotification())
}
@ -365,7 +391,6 @@ class TrackerService: Service(), SensorEventListener
PreferencesHelper.saveTrackingState(trackingState)
sensorManager.unregisterListener(this)
handler.removeCallbacks(periodicTrackUpdate)
displayNotification()
stopForeground(STOP_FOREGROUND_DETACH)
@ -452,31 +477,4 @@ class TrackerService: Service(), SensorEventListener
}
return true
}
private val periodicTrackUpdate: Runnable = object : Runnable
{
override fun run() {
val now: Date = GregorianCalendar.getInstance().time
val trkpt = Trkpt(location=currentBestLocation)
Log.i("VOUSSOIR", "Processing point ${currentBestLocation.latitude}, ${currentBestLocation.longitude} ${now.time}.")
if (should_keep_point((currentBestLocation)))
{
trackbook.database.insert_trkpt(device_id, trkpt)
recent_trkpts.add(trkpt)
while (recent_trkpts.size > RECENT_TRKPT_COUNT)
{
recent_trkpts.removeFirst()
}
if (now.time - lastCommit.time > Keys.SAVE_TEMP_TRACK_INTERVAL)
{
trackbook.database.commit()
lastCommit = now
}
}
displayNotification()
handler.postDelayed(this, Keys.TRACKING_INTERVAL)
}
}
}

View file

@ -37,7 +37,7 @@ import java.text.SimpleDateFormat
import java.util.*
/* Creates icon overlay for track */
fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection<Trkpt>, trackingState: Int)
fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection<Trkpt>, trackingState: Int): SimpleFastPointOverlay
{
val color = if (trackingState == Keys.STATE_TRACKING_ACTIVE) context.getColor(R.color.default_red) else context.getColor(R.color.default_blue)
val points: MutableList<IGeoPoint> = mutableListOf()
@ -64,10 +64,11 @@ fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection<T
.setCellSize(12) // Sets the grid cell size used for indexing, in pixels. Larger cells result in faster rendering speed, but worse fidelity. Default is 10 pixels, for large datasets (>10k points), use 15.
val overlay = SimpleFastPointOverlay(pointTheme, overlayOptions)
map_view.overlays.add(overlay)
return overlay
}
/* Creates overlay containing start, stop, stopover and starred markers for track */
fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, trkpts: Collection<Trkpt>, trackingState: Int, displayStartEndMarker: Boolean = false)
fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, trkpts: Collection<Trkpt>, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay<OverlayItem>
{
val overlayItems: ArrayList<OverlayItem> = ArrayList<OverlayItem>()
val trackingActive: Boolean = trackingState == Keys.STATE_TRACKING_ACTIVE
@ -110,7 +111,9 @@ fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, trkpts:
overlayItems.add(overlayItem)
}
}
map_view.overlays.add(createOverlay(context, overlayItems))
val overlay: ItemizedIconOverlay<OverlayItem> = createOverlay(context, overlayItems)
map_view.overlays.add(overlay)
return overlay
}
fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem

View file

@ -86,7 +86,7 @@
<string name="pref_altitude_smoothing_value_title" translatable="false">Altitude Smoothing</string>
<string name="pref_auto_export_interval_summary">Automatically export GPX file after this many hours.</string>
<string name="pref_device_id_summary">A unique ID to distinguish tracks recorded across multiple devices:</string>
<string name="pref_database_folder_summary">Directory to contain your database file. You could use Syncthing to sync with your PC!</string>
<string name="pref_database_folder_summary">Directory to contain your database file. You could use Syncthing to sync with your PC.</string>
<string name="pref_auto_export_interval_title">Auto Export Interval</string>
<string name="pref_device_id">Device ID</string>
<string name="pref_database_folder">Database directory</string>
@ -96,8 +96,8 @@
<string name="pref_general_title">General</string>
<string name="pref_maintenance_title">Maintenance</string>
<string name="pref_gps_only_title">Restrict to GPS</string>
<string name="pref_gps_only_summary_gps_and_network">Currently using GPS and Network for localization.</string>
<string name="pref_gps_only_summary_gps_only">Currently using only GPS for localization.</string>
<string name="pref_gps_only_summary_gps_and_network">Currently using GPS and Network for location.</string>
<string name="pref_gps_only_summary_gps_only">Currently using only GPS for location.</string>
<string name="pref_imperial_measurement_units_summary_metric">Currently using metric units (Kilometer, Meter).</string>
<string name="pref_imperial_measurement_units_summary_imperial">Currently using imperial units (Miles, Feet).</string>
<string name="pref_imperial_measurement_units_title">Use Imperial Measurements</string>