Skip to content

Commit

Permalink
Merge pull request #32 from CrazyDude1994/uav-radar
Browse files Browse the repository at this point in the history
Uav radar
  • Loading branch information
Sergey Kartavtsev authored Jun 5, 2019
2 parents 2bd73d5 + 56b6bec commit 24979ea
Show file tree
Hide file tree
Showing 13 changed files with 250 additions and 8 deletions.
6 changes: 4 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ android {
applicationId "crazydude.com.telemetry"
minSdkVersion 16
targetSdkVersion 28
versionCode 13
versionName "1.4"
versionCode 15
versionName "1.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
Expand All @@ -47,6 +47,8 @@ dependencies {
implementation 'androidx.preference:preference:1.0.0'
implementation 'com.google.firebase:firebase-core:16.0.9'
implementation 'com.jaredrummler:colorpicker:1.1.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.google.maps.android:android-maps-utils:0.5+'
releaseImplementation 'com.crashlytics.sdk.android:crashlytics:2.10.0'
}
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>

<application
android:usesCleartextTraffic="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
12 changes: 12 additions & 0 deletions app/src/main/java/crazydude/com/telemetry/api/AddLogRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package crazydude.com.telemetry.api

import com.google.gson.annotations.SerializedName

data class AddLogRequest(
@SerializedName("session_id") val sessionId: String,
@SerializedName("latitude") val latitude: Double,
@SerializedName("longitude") val longitude: Double,
@SerializedName("altitude") val altitude: Float,
@SerializedName("heading") val heading: Float,
@SerializedName("speed") val speed: Float
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package crazydude.com.telemetry.api

import com.google.gson.annotations.SerializedName

data class AddLogResponse(@SerializedName("status") val status: String)
21 changes: 21 additions & 0 deletions app/src/main/java/crazydude/com/telemetry/api/ApiManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package crazydude.com.telemetry.api

import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.Retrofit



class ApiManager {

companion object {

const val API_URL = "https://uavradar.org/"

private val retrofit = Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()

val apiService = retrofit.create(ApiService::class.java)
}
}
14 changes: 14 additions & 0 deletions app/src/main/java/crazydude/com/telemetry/api/ApiService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package crazydude.com.telemetry.api

import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.POST

interface ApiService {

@POST("api/session/create")
fun createSession(@Body sessionCreateRequest: SessionCreateRequest): Call<SessionCreateResponse>

@POST("api/data/add")
fun sendData(@Body addLogRequest: AddLogRequest): Call<AddLogResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package crazydude.com.telemetry.api

import com.google.gson.annotations.SerializedName

data class SessionCreateRequest(
@SerializedName("callsign") val callsign: String,
@SerializedName("model") val model: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package crazydude.com.telemetry.api

import com.google.gson.annotations.SerializedName

data class SessionCreateResponse(
@SerializedName("status") val status: String,
@SerializedName("session_id") val sessionId: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,24 @@ class PreferenceManager(context: Context) {
fun setMapType(mapType: Int) {
sharedPreferences.edit().putInt("map_type", mapType).apply()
}

fun isSendDataEnabled(): Boolean {
return sharedPreferences.getBoolean("send_telemetry_data", false)
}

fun isSendDataDialogShown(): Boolean {
return sharedPreferences.contains("send_telemetry_data")
}

fun getModel(): String {
return sharedPreferences.getString("model", "") ?: ""
}

fun getCallsign(): String {
return sharedPreferences.getString("callsign", "") ?: ""
}

fun setTelemetrySendingEnabled(enabled: Boolean) {
sharedPreferences.edit().putBoolean("send_telemetry_data", enabled).apply()
}
}
86 changes: 80 additions & 6 deletions app/src/main/java/crazydude/com/telemetry/service/DataService.kt
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
package crazydude.com.telemetry.service

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.bluetooth.*
import android.bluetooth.BluetoothDevice
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.*
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import android.widget.Toast
import com.google.android.gms.maps.model.LatLng
import crazydude.com.telemetry.R
import crazydude.com.telemetry.api.*
import crazydude.com.telemetry.manager.PreferenceManager
import crazydude.com.telemetry.protocol.*
import crazydude.com.telemetry.protocol.BluetoothDataPoller
import crazydude.com.telemetry.protocol.BluetoothLeDataPoller
import crazydude.com.telemetry.protocol.DataDecoder
import crazydude.com.telemetry.protocol.DataPoller
import crazydude.com.telemetry.ui.MapsActivity
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
Expand All @@ -32,7 +38,14 @@ class DataService : Service(), DataDecoder.Listener {
private var dataListener: DataDecoder.Listener? = null
private val dataBinder = DataBinder()
private var hasGPSFix = false
private var isArmed = false
private var satellites = 0
private var lastLatitude: Double = 0.0
private var lastLongitude: Double = 0.0
private var lastAltitude: Float = 0.0f
private var lastSpeed: Float = 0.0f
private var lastHeading: Float = 0.0f
private val apiHandler = Handler()
private lateinit var preferenceManager: PreferenceManager
val points: ArrayList<LatLng> = ArrayList()

Expand Down Expand Up @@ -98,7 +111,8 @@ class DataService : Service(), DataDecoder.Listener {
}

if (!isBle) {
val socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"))
val socket =
device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"))
dataPoller = BluetoothDataPoller(socket, this, fileOutputStream, csvFileOutputStream)
} else {
dataPoller = BluetoothLeDataPoller(this, device, this, fileOutputStream, csvFileOutputStream)
Expand Down Expand Up @@ -152,12 +166,64 @@ class DataService : Service(), DataDecoder.Listener {
runOnMainThread(Runnable {
dataListener?.onConnected()
})

if (preferenceManager.isSendDataEnabled()) {
createSession()
}
}

fun createSession() {
if (!isConnected()) {
return
}
ApiManager.apiService.createSession(
SessionCreateRequest(preferenceManager.getCallsign(), preferenceManager.getModel())
).enqueue(object : Callback<SessionCreateResponse?> {
override fun onFailure(call: Call<SessionCreateResponse?>, t: Throwable) {
Handler()
.postDelayed({ createSession() }, 5000)
}

override fun onResponse(
call: Call<SessionCreateResponse?>,
response: Response<SessionCreateResponse?>
) {
response.body()?.let {
sendTelemetryData(it.sessionId)
}
}
})
}

fun sendTelemetryData(sessionId: String) {
if (!isConnected()) {
return
}
apiHandler.postDelayed({
if (hasGPSFix && isArmed) {
ApiManager.apiService.sendData(
AddLogRequest(sessionId, lastLatitude, lastLongitude, lastAltitude, lastHeading, lastSpeed)
).enqueue(object : Callback<AddLogResponse?> {
override fun onFailure(call: Call<AddLogResponse?>, t: Throwable) {
sendTelemetryData(sessionId)
}

override fun onResponse(call: Call<AddLogResponse?>, response: Response<AddLogResponse?>) {
sendTelemetryData(sessionId)
}
})
} else {
sendTelemetryData(sessionId)
}
}, 5000)
}

override fun onGPSData(latitude: Double, longitude: Double) {
if (hasGPSFix) {
points.add(LatLng(latitude, longitude))
}
lastLatitude = latitude
lastLongitude = longitude
runOnMainThread(Runnable {
dataListener?.onGPSData(latitude, longitude)
})
Expand Down Expand Up @@ -186,12 +252,16 @@ class DataService : Service(), DataDecoder.Listener {
}

override fun onHeadingData(heading: Float) {
lastHeading = heading
runOnMainThread(Runnable {
dataListener?.onHeadingData(heading)
})
}

override fun onAirSpeed(speed: Float) {
if (preferenceManager.usePitotTube()) {
lastSpeed = speed
}
runOnMainThread(Runnable {
dataListener?.onAirSpeed(speed)
})
Expand Down Expand Up @@ -227,6 +297,7 @@ class DataService : Service(), DataDecoder.Listener {
}

override fun onAltitudeData(altitude: Float) {
lastAltitude = altitude
runOnMainThread(Runnable {
dataListener?.onAltitudeData(altitude)
})
Expand Down Expand Up @@ -257,6 +328,9 @@ class DataService : Service(), DataDecoder.Listener {
}

override fun onGSpeedData(speed: Float) {
if (!preferenceManager.usePitotTube()) {
lastSpeed = speed
}
runOnMainThread(Runnable { dataListener?.onGSpeedData(speed) })
}

Expand All @@ -266,10 +340,10 @@ class DataService : Service(), DataDecoder.Listener {
firstFlightMode: DataDecoder.Companion.FlyMode,
secondFlightMode: DataDecoder.Companion.FlyMode?
) {
isArmed = armed
runOnMainThread(Runnable {
dataListener?.onFlyModeData(armed, heading, firstFlightMode, secondFlightMode)
})

}

private fun runOnMainThread(runnable: Runnable) {
Expand Down
30 changes: 30 additions & 0 deletions app/src/main/java/crazydude/com/telemetry/ui/MapsActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.IBinder
import android.text.Html
import android.text.method.LinkMovementMethod
import android.view.View
import android.widget.*
import androidx.annotation.DrawableRes
Expand All @@ -32,10 +34,16 @@ import com.google.android.gms.maps.model.*
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.maps.android.SphericalUtil
import crazydude.com.telemetry.R
import crazydude.com.telemetry.api.ApiManager
import crazydude.com.telemetry.api.SessionCreateRequest
import crazydude.com.telemetry.api.SessionCreateResponse
import crazydude.com.telemetry.manager.PreferenceManager
import crazydude.com.telemetry.protocol.DataDecoder
import crazydude.com.telemetry.protocol.LogPlayer
import crazydude.com.telemetry.service.DataService
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.io.File
import kotlin.math.roundToInt

Expand Down Expand Up @@ -473,9 +481,11 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, DataDecoder.Listen
if (requestCode == REQUEST_LOCATION_PERMISSION) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
map?.isMyLocationEnabled = true
checkSendDataDialogShown()
} else {
AlertDialog.Builder(this)
.setMessage("Location permission is needed in order to discover BLE devices and show your location on map")
.setOnDismissListener { checkSendDataDialogShown() }
.setPositiveButton("OK", null)
.show()
}
Expand Down Expand Up @@ -577,6 +587,7 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, DataDecoder.Listen
map?.mapType = mapType
if (checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
map?.isMyLocationEnabled = true
checkSendDataDialogShown()
} else {
ActivityCompat.requestPermissions(
this,
Expand All @@ -597,6 +608,25 @@ class MapsActivity : AppCompatActivity(), OnMapReadyCallback, DataDecoder.Listen
}
}

private fun checkSendDataDialogShown() {
if (!preferenceManager.isSendDataDialogShown()) {
val dialog = AlertDialog.Builder(this)
.setMessage(
Html.fromHtml(
"You can enable telemetry data sharing. Telemetry data sharing sends data to <a href='https://uavradar.org'>https://uavradar.org</a> at which" +
"you can watch for other aicraft flights (just like flightradar24, but for UAV). You can assign" +
" your callsign and your UAV model in the settings which will be used as your aircraft info. " +
"Data sent when you arm your UAV and have valid 3D GPS Fix"
)
)
.setPositiveButton("Enable") { _, i -> preferenceManager.setTelemetrySendingEnabled(true) }
.setNegativeButton("Disable") { _, i -> preferenceManager.setTelemetrySendingEnabled(false) }
.setCancelable(false)
.show()
dialog.findViewById<TextView>(android.R.id.message)?.movementMethod = LinkMovementMethod.getInstance()
}
}

private fun showMapTypeSelectorDialog() {
val fDialogTitle = "Select Map Type"
val builder = AlertDialog.Builder(this)
Expand Down
Loading

0 comments on commit 24979ea

Please sign in to comment.