From 33b99f5bdfccf790bd60aec32f44d81a45e6d04d Mon Sep 17 00:00:00 2001 From: Eric Bachhuber Date: Mon, 28 May 2018 14:14:21 -0500 Subject: [PATCH] Current flight latitude/longitude functional --- .../xplaneopenmap/data/FlightMapViewModel.kt | 35 -------- .../xplaneopenmap/data/UDPListener.kt | 6 +- .../data/model/FlightPathWrapper.kt | 3 + .../data/viewmodel/FlightMapViewModel.kt | 88 +++++++++++++++++++ .../xplaneopenmap/ui/FlightMapActivity.kt | 28 +++--- .../xplaneopenmap/util/AndroidHelper.kt | 2 +- 6 files changed, 113 insertions(+), 49 deletions(-) delete mode 100644 app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/FlightMapViewModel.kt create mode 100644 app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/model/FlightPathWrapper.kt create mode 100644 app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/viewmodel/FlightMapViewModel.kt diff --git a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/FlightMapViewModel.kt b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/FlightMapViewModel.kt deleted file mode 100644 index e9a8a68..0000000 --- a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/FlightMapViewModel.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.bachhuberdesign.xplaneopenmap.data - -import android.arch.lifecycle.LiveData -import android.arch.lifecycle.MutableLiveData -import android.arch.lifecycle.ViewModel -import android.location.Location -import java.net.DatagramPacket - -class FlightMapViewModel : ViewModel(), UDPCallback { - - private val flightPathLiveData: MutableLiveData = MutableLiveData() - private val messageLiveData: MutableLiveData = MutableLiveData() - private var udpListener: UDPListener? = null - - override fun onCleared() { - udpListener?.kill() - - super.onCleared() - } - - override fun onNextPacket(packet: DatagramPacket) { - val data = packet.data - - // TODO: Do something with received packet - } - - fun startUDPClient() { - udpListener = UDPListener(this) - } - - fun getFlightPathStream(): LiveData = flightPathLiveData - - fun getMessageStream(): LiveData = messageLiveData - -} \ No newline at end of file diff --git a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/UDPListener.kt b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/UDPListener.kt index c4671c6..6d6c043 100644 --- a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/UDPListener.kt +++ b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/UDPListener.kt @@ -1,5 +1,6 @@ package com.bachhuberdesign.xplaneopenmap.data +import io.milkcan.effortlessandroid.d import io.milkcan.effortlessandroid.e import java.net.DatagramPacket import java.net.DatagramSocket @@ -13,18 +14,19 @@ open class UDPListener(private val callback: UDPCallback) : Thread() { private var isKeepRunning = true override fun run() { - val packet = DatagramPacket(ByteArray(MAX_UDP_DATAGRAM_LENGTH), MAX_UDP_DATAGRAM_LENGTH) + var packet = DatagramPacket(ByteArray(64), MAX_UDP_DATAGRAM_LENGTH) var socket: DatagramSocket? = null try { socket = DatagramSocket(48001) + d("Listening for packets on port: 48001") while (isKeepRunning) { socket.receive(packet) callback.onNextPacket(packet) } - } catch (ex: Exception) { + } catch (ex: Throwable) { e("Error handling datagram: ${ex.message}", ex) } finally { socket?.close() diff --git a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/model/FlightPathWrapper.kt b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/model/FlightPathWrapper.kt new file mode 100644 index 0000000..82a7246 --- /dev/null +++ b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/model/FlightPathWrapper.kt @@ -0,0 +1,3 @@ +package com.bachhuberdesign.xplaneopenmap.data.model + +data class FlightPathWrapper(val latitude: Float, val longitude: Float) \ No newline at end of file diff --git a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/viewmodel/FlightMapViewModel.kt b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/viewmodel/FlightMapViewModel.kt new file mode 100644 index 0000000..e3772df --- /dev/null +++ b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/data/viewmodel/FlightMapViewModel.kt @@ -0,0 +1,88 @@ +package com.bachhuberdesign.xplaneopenmap.data.viewmodel + +import android.arch.lifecycle.LiveData +import android.arch.lifecycle.MutableLiveData +import android.arch.lifecycle.ViewModel +import com.bachhuberdesign.xplaneopenmap.data.UDPCallback +import com.bachhuberdesign.xplaneopenmap.data.UDPListener +import com.bachhuberdesign.xplaneopenmap.data.model.FlightPathWrapper +import io.milkcan.effortlessandroid.d +import java.net.DatagramPacket +import java.util.* +import java.nio.ByteOrder.LITTLE_ENDIAN +import java.nio.ByteBuffer + +class FlightMapViewModel : ViewModel(), UDPCallback { + + private val flightPathLiveData: MutableLiveData = MutableLiveData() + private val messageLiveData: MutableLiveData = MutableLiveData() + private var udpListener: UDPListener? = null + + override fun onCleared() { + udpListener?.kill() + + super.onCleared() + } + + override fun onNextPacket(packet: DatagramPacket) { + val data = packet.data + + d("Packet received: ${Arrays.toString(data)}") + + val dataSetIndex: Int = data[5].toInt() + val floatArray = getFloatsFromDataPacket(data) + + when (dataSetIndex) { + 20 -> handleLatitudeLongitudeAltitude(floatArray) + 21 -> handleLocationVelocityDistanceTravelled(floatArray) + 22 -> handleAllPlanesLatitude(floatArray) + 23 -> handleAllPlanesLongitude(floatArray) + } + } + + fun startUDPClient() { + udpListener = UDPListener(this) + udpListener!!.start() + } + + fun getFlightPathStream(): LiveData = flightPathLiveData + + fun getMessageStream(): LiveData = messageLiveData + + private fun handleLatitudeLongitudeAltitude(floats: FloatArray) { + floats.forEachIndexed { i, float -> d("handleLatitudeLongitudeAltitude $i: $float") } + + val latitude = floats[0] + val longitude = floats[1] + + flightPathLiveData.postValue(FlightPathWrapper(latitude, longitude)) + } + + private fun handleLocationVelocityDistanceTravelled(floats: FloatArray) { + + } + + private fun handleAllPlanesLatitude(floats: FloatArray) { + + } + + private fun handleAllPlanesLongitude(floats: FloatArray) { + + } + + private fun getFloatsFromDataPacket(data: ByteArray): FloatArray { + return arrayOf( + byteArrayOf(data[9], data[10], data[11], data[12]), + byteArrayOf(data[13], data[14], data[15], data[16]), + byteArrayOf(data[17], data[18], data[19], data[20]), + byteArrayOf(data[21], data[22], data[23], data[24]), + byteArrayOf(data[25], data[26], data[27], data[28]), + byteArrayOf(data[29], data[30], data[31], data[32]), + byteArrayOf(data[33], data[34], data[35], data[36]), + byteArrayOf(data[37], data[38], data[39], data[40]) + ) + .map { ByteBuffer.wrap(it).order(LITTLE_ENDIAN).float } + .toFloatArray() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/ui/FlightMapActivity.kt b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/ui/FlightMapActivity.kt index fd5ca6b..2b31a48 100644 --- a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/ui/FlightMapActivity.kt +++ b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/ui/FlightMapActivity.kt @@ -2,29 +2,28 @@ package com.bachhuberdesign.xplaneopenmap.ui import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders -import android.content.DialogInterface import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.support.v7.app.AlertDialog -import com.bachhuberdesign.xplaneopenmap.data.FlightMapViewModel -import com.bachhuberdesign.xplaneopenmap.data.UDPCallback -import com.bachhuberdesign.xplaneopenmap.data.UDPListener +import com.bachhuberdesign.xplaneopenmap.data.viewmodel.FlightMapViewModel import com.google.android.gms.maps.CameraUpdateFactory import com.google.android.gms.maps.GoogleMap import com.google.android.gms.maps.OnMapReadyCallback import com.google.android.gms.maps.SupportMapFragment import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.Marker import com.google.android.gms.maps.model.MarkerOptions +import io.milkcan.effortlessandroid.d import io.milkcan.effortlessandroid.toastLong import xplaneopenmap.bachhuberdesign.com.openmap.R -import java.net.DatagramPacket class FlightMapActivity : AppCompatActivity(), OnMapReadyCallback { private lateinit var map: GoogleMap private lateinit var viewModel: FlightMapViewModel + private var cameraMoved: Boolean = false private var dialog: AlertDialog? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -49,10 +48,6 @@ class FlightMapActivity : AppCompatActivity(), OnMapReadyCallback { override fun onMapReady(googleMap: GoogleMap) { map = googleMap - - val sydney = LatLng(-34.0, 151.0) - map.addMarker(MarkerOptions().position(sydney).title("Marker in Sydney")) - map.moveCamera(CameraUpdateFactory.newLatLng(sydney)) } private fun showIpAddressDialog() { @@ -60,7 +55,7 @@ class FlightMapActivity : AppCompatActivity(), OnMapReadyCallback { dialog?.dismiss() } - val ipAddress = AndroidHelper.getLocalIpAddress() + val ipAddress = AndroidHelper.getDeviceLocalIpAddress() val message = if (!ipAddress.isNullOrBlank()) { "Please set your X-Plane data export to your device's IP address: $ipAddress" @@ -83,7 +78,18 @@ class FlightMapActivity : AppCompatActivity(), OnMapReadyCallback { viewModel.getMessageStream().observe(this, Observer { toastLong("$it") }) viewModel.getFlightPathStream().observe(this, Observer { - // TODO: Handle display of flight location data + val position = LatLng(it!!.latitude.toDouble(), it.longitude.toDouble()) + d("Flight path position: $position") + val cameraUpdate = CameraUpdateFactory.newLatLngZoom(position, 12.0f) + + map.clear() + + if (!cameraMoved){ + map.moveCamera(cameraUpdate) + cameraMoved = true + } + + map.addMarker(MarkerOptions().position(position).title("Current Flight")) }) } diff --git a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/util/AndroidHelper.kt b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/util/AndroidHelper.kt index 628aa0f..d0fce02 100644 --- a/app/src/main/java/com/bachhuberdesign/xplaneopenmap/util/AndroidHelper.kt +++ b/app/src/main/java/com/bachhuberdesign/xplaneopenmap/util/AndroidHelper.kt @@ -5,7 +5,7 @@ import java.net.NetworkInterface object AndroidHelper { @JvmStatic - fun getLocalIpAddress(): String? { + fun getDeviceLocalIpAddress(): String? { try { val interfaces = NetworkInterface.getNetworkInterfaces()