138 lines
4.9 KiB
Kotlin
138 lines
4.9 KiB
Kotlin
package org.pupes.mhdrunpathfinder
|
|
|
|
import android.app.Activity
|
|
import android.os.Handler
|
|
import android.os.Looper
|
|
import android.widget.Toast
|
|
import androidx.compose.ui.graphics.Color
|
|
import androidx.compose.ui.unit.dp
|
|
import kotlinx.serialization.Serializable
|
|
import kotlinx.serialization.json.Json
|
|
import okhttp3.OkHttpClient
|
|
import ovh.plrapps.mapcompose.api.addPath
|
|
import ovh.plrapps.mapcompose.api.moveMarker
|
|
import ovh.plrapps.mapcompose.api.removePath
|
|
import ovh.plrapps.mapcompose.api.updatePath
|
|
import java.net.URL
|
|
|
|
@Serializable
|
|
data class HaukResponse(
|
|
val type: Int,
|
|
val expire: Long,
|
|
val serverTime: Double,
|
|
val interval: Int,
|
|
val points: List<List<Double?>>,
|
|
val encrypted: Boolean,
|
|
val salt: String? = null
|
|
)
|
|
|
|
|
|
// OkHttpClient for making HTTP requests
|
|
val haukhttpClient = OkHttpClient.Builder()
|
|
.build()
|
|
|
|
private val HaukMainHandler = Handler(Looper.getMainLooper())
|
|
private var HaukTrackingThread: Thread? = null
|
|
var HaukIsTracking = false
|
|
|
|
private var PathCreated = false
|
|
private fun fetchHaukPosition(haukUrl: String, callee: Activity) {
|
|
try {
|
|
val url = URL(haukUrl)
|
|
val targetId = url.toString().substringAfter("?")
|
|
|
|
val request = okhttp3.Request.Builder()
|
|
.url("${url.protocol}://${url.host}/api/fetch.php?id=$targetId")
|
|
.header("User-Agent", "${BuildConfig.APPLICATION_ID}/${BuildConfig.VERSION_NAME} (Android)")
|
|
.build()
|
|
|
|
haukhttpClient.newCall(request).execute().use { response ->
|
|
var message = if (response.isSuccessful) {
|
|
response.body?.string() ?: "Empty response"
|
|
} else {
|
|
"Error: ${response.code} ${response.message}"
|
|
}
|
|
|
|
message = "{" + message.substringAfter("{");
|
|
val hauk_response = json.decodeFromString<HaukResponse>(message)
|
|
val lat = hauk_response.points.last().getOrNull(0)
|
|
val lon = hauk_response.points.last().getOrNull(1)
|
|
if (lat != null && lon != null) {
|
|
|
|
val lastlat = hauk_response.points.getOrNull(hauk_response.points.size - 2)?.getOrNull(0)
|
|
val lastlon = hauk_response.points.getOrNull(hauk_response.points.size - 2)?.getOrNull(1)
|
|
val newspeed =
|
|
if (lastlat != null && lastlon != null) {
|
|
var fulldistance: Double = 0.0
|
|
for (i in 1 until hauk_response.points.size -1) {
|
|
try{
|
|
fulldistance += haversineDistance(hauk_response.points[i-1][0]!!, hauk_response.points[i-1][1]!!, hauk_response.points[i][0]!!, hauk_response.points[i][1]!!)
|
|
} catch (e: Exception) {
|
|
// Ignore
|
|
}
|
|
}
|
|
(fulldistance / (hauk_response.interval * hauk_response.points.size)*3600)
|
|
} else {
|
|
0.0
|
|
}
|
|
HaukMainHandler.post {
|
|
try {
|
|
mapState.moveMarker("target_position", x = longitudeToXNormalized(lon), y = latitudeToYNormalized(lat))
|
|
target_speed = "${"%.1f".format(newspeed)}km/h"
|
|
} catch (e: Exception) {
|
|
// Marker might not exist yet, ignore
|
|
}
|
|
|
|
pathDataBuilder.addPoint(longitudeToXNormalized(lon), latitudeToYNormalized(lat));
|
|
if (!PathCreated) {
|
|
mapState.addPath(
|
|
"target_path", color = Color(0xFF0000FF),
|
|
pathData = pathDataBuilder.build()?: return@post,
|
|
width = 1.dp
|
|
);
|
|
PathCreated = true
|
|
}
|
|
mapState.updatePath("target_path", pathData = pathDataBuilder.build())
|
|
|
|
}
|
|
} else {
|
|
HaukMainHandler.post {
|
|
Toast.makeText(callee, "TARGET LOCATION NOT AVAILABLE", Toast.LENGTH_SHORT).show()
|
|
}
|
|
}}
|
|
} catch (e: Exception) {
|
|
// Post UI update to main thread
|
|
HaukMainHandler.post {
|
|
Toast.makeText(callee, e.message ?: "Unknown error", Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
}
|
|
|
|
// Start the timer with a URL:
|
|
fun startHaukTracking(url: String, callee: Activity) {
|
|
if (HaukIsTracking) return
|
|
|
|
HaukIsTracking = true
|
|
|
|
|
|
|
|
|
|
HaukTrackingThread = Thread {
|
|
while (HaukIsTracking) {
|
|
fetchHaukPosition(url, callee)
|
|
try {
|
|
Thread.sleep(1000) // Wait 1 second between requests
|
|
} catch (e: InterruptedException) {
|
|
break
|
|
}
|
|
}
|
|
}.apply { start() }
|
|
}
|
|
|
|
fun stopHaukTracking() {
|
|
HaukIsTracking = false
|
|
HaukTrackingThread?.interrupt()
|
|
HaukTrackingThread = null
|
|
mapState.removePath("target_path");
|
|
PathCreated = false;
|
|
} |