Added SatPass class to get the full info of a pass for the recycler items. Still trying to figure out what the final app is going to look like. Sitting at home with a cold.

This commit is contained in:
Arty Bishop committed 2019-11-08 13:50:44 +01:00
1 parent b7291db0f9
commit a0f723e233
6 files changed
+100 -28

No files matched your search

+1
View File
@@ -46,6 +46,7 @@ dependencies {
implementation "androidx.navigation:navigation-ui-ktx:$navigation" implementation "androidx.navigation:navigation-ui-ktx:$navigation"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle" implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle"
implementation "androidx.work:work-runtime-ktx:$work" implementation "androidx.work:work-runtime-ktx:$work"
implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-runtime:$room"
implementation "androidx.room:room-ktx:$room" implementation "androidx.room:room-ktx:$room"
@@ -0,0 +1,5 @@
package com.rtbishop.lookingsat.repo
import com.github.amsacode.predict4java.SatPassTime
data class SatPass(val satName: String, val catNum: Int, val pass: SatPassTime)
@@ -5,12 +5,12 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.amsacode.predict4java.SatPassTime
import com.rtbishop.lookingsat.R import com.rtbishop.lookingsat.R
import com.rtbishop.lookingsat.repo.SatPass
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
class SatPassAdapter(private val satPassList: MutableList<SatPassTime>) : class SatPassAdapter(private val satPassList: List<SatPass>) :
RecyclerView.Adapter<SatPassAdapter.ViewHolder>() { RecyclerView.Adapter<SatPassAdapter.ViewHolder>() {
override fun getItemCount(): Int { override fun getItemCount(): Int {
@@ -27,16 +27,19 @@ class SatPassAdapter(private val satPassList: MutableList<SatPassTime>) :
val satPass = satPassList[position] val satPass = satPassList[position]
val satName = holder.itemView.findViewById<TextView>(R.id.card_sat_name) val satName = holder.itemView.findViewById<TextView>(R.id.card_sat_name)
val passVector = holder.itemView.findViewById<TextView>(R.id.card_pass_vector)
val maxEl = holder.itemView.findViewById<TextView>(R.id.card_max_el) val maxEl = holder.itemView.findViewById<TextView>(R.id.card_max_el)
val passVector = holder.itemView.findViewById<TextView>(R.id.card_pass_vector)
val passStart = holder.itemView.findViewById<TextView>(R.id.card_pass_start) val passStart = holder.itemView.findViewById<TextView>(R.id.card_pass_start)
val passEnd = holder.itemView.findViewById<TextView>(R.id.card_pass_end) val passEnd = holder.itemView.findViewById<TextView>(R.id.card_pass_end)
satName.text = String.format("%s", "Meteor M2-2") satName.text = String.format("%s", satPass.satName)
passVector.text = String.format("V: %02d° -> %02d°", satPass.aosAzimuth, satPass.losAzimuth) maxEl.text = String.format("%.1f°", satPass.pass.maxEl)
maxEl.text = String.format("%.1f°", satPass.maxEl) passVector.text =
passStart.text = SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(satPass.startTime) String.format("V: %02d° -> %02d°", satPass.pass.aosAzimuth, satPass.pass.losAzimuth)
passEnd.text = SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(satPass.endTime) passStart.text =
SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(satPass.pass.startTime)
passEnd.text =
SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(satPass.pass.endTime)
} }
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
@@ -5,20 +5,31 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.ProgressBar
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.amsacode.predict4java.TLE
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.rtbishop.lookingsat.R import com.rtbishop.lookingsat.R
import com.rtbishop.lookingsat.repo.SatPass
import com.rtbishop.lookingsat.vm.MainViewModel import com.rtbishop.lookingsat.vm.MainViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class SkyFragment : Fragment() { class SkyFragment : Fragment() {
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
private lateinit var recView: RecyclerView private lateinit var recView: RecyclerView
private lateinit var recAdapter: RecyclerView.Adapter<*> private lateinit var recAdapter: RecyclerView.Adapter<*>
private lateinit var recLayoutManager: RecyclerView.LayoutManager
private lateinit var btnRefresh: ImageButton private lateinit var btnRefresh: ImageButton
private lateinit var progressBar: ProgressBar
private lateinit var fab: FloatingActionButton
private var satPassList: List<SatPass> = emptyList()
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
@@ -32,17 +43,25 @@ class SkyFragment : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java) viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
btnRefresh = (activity as MainActivity).findViewById(R.id.toolbar_btn_refresh) btnRefresh = (activity as MainActivity).findViewById(R.id.toolbar_btn_refresh)
progressBar = view.findViewById(R.id.sky_progressbar)
recView = view.findViewById(R.id.sky_recycler)
fab = view.findViewById(R.id.sky_fab)
recView.layoutManager = LinearLayoutManager(activity)
recView.setHasFixedSize(true)
btnRefresh.setOnClickListener { btnRefresh.setOnClickListener {
val satPassList = viewModel.updateRecycler() lifecycleScope.launch(Dispatchers.Main) {
recView.visibility = View.INVISIBLE
recLayoutManager = LinearLayoutManager(activity) progressBar.visibility = View.VISIBLE
recAdapter = SatPassAdapter(satPassList) progressBar.isIndeterminate = true
recView = view.findViewById(R.id.recycler_sky) satPassList = viewModel.updateRecycler()
recAdapter = SatPassAdapter(satPassList)
recView.setHasFixedSize(true) recView.adapter = recAdapter
recView.layoutManager = recLayoutManager progressBar.isIndeterminate = false
recView.adapter = recAdapter progressBar.visibility = View.INVISIBLE
recView.visibility = View.VISIBLE
}
} }
} }
} }
@@ -4,6 +4,7 @@ import android.app.Application
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.location.Location import android.location.Location
import android.util.Log
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
@@ -12,13 +13,15 @@ import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.github.amsacode.predict4java.GroundStationPosition import com.github.amsacode.predict4java.GroundStationPosition
import com.github.amsacode.predict4java.PassPredictor import com.github.amsacode.predict4java.PassPredictor
import com.github.amsacode.predict4java.SatPassTime import com.github.amsacode.predict4java.SatNotFoundException
import com.github.amsacode.predict4java.TLE import com.github.amsacode.predict4java.TLE
import com.google.android.gms.location.LocationServices import com.google.android.gms.location.LocationServices
import com.rtbishop.lookingsat.Injector import com.rtbishop.lookingsat.Injector
import com.rtbishop.lookingsat.repo.Repository import com.rtbishop.lookingsat.repo.Repository
import com.rtbishop.lookingsat.repo.SatPass
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.IOException import java.io.IOException
import java.util.* import java.util.*
@@ -29,12 +32,15 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
private val keyLon = "LONGITUDE" private val keyLon = "LONGITUDE"
private val keyHeight = "HEIGHT" private val keyHeight = "HEIGHT"
private val tleFile = "tles.txt" private val tleFile = "tles.txt"
private val tag = "myTag"
private val repository: Repository = Injector.provideRepository(application) private val repository: Repository = Injector.provideRepository(application)
private val preferences = PreferenceManager.getDefaultSharedPreferences(application) private val preferences = PreferenceManager.getDefaultSharedPreferences(application)
private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(application) private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(application)
private val _debugMessage = MutableLiveData("") private val _debugMessage = MutableLiveData("")
val debugMessage: LiveData<String> = _debugMessage val debugMessage: LiveData<String> = _debugMessage
private val _gsp = MutableLiveData<GroundStationPosition>( private val _gsp = MutableLiveData<GroundStationPosition>(
GroundStationPosition( GroundStationPosition(
preferences.getDouble(keyLat, 0.0), preferences.getDouble(keyLat, 0.0),
@@ -44,17 +50,41 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
) )
val gsp: LiveData<GroundStationPosition> = _gsp val gsp: LiveData<GroundStationPosition> = _gsp
fun updateRecycler(): MutableList<SatPassTime> { var tleList: List<TLE> = loadTwoLineElementFile().sortedWith(compareBy { it.name })
var satPassList = mutableListOf<SatPassTime>()
try {
val tles = TLE.importSat(getApplication<Application>().openFileInput(tleFile))
val passPredictor = PassPredictor(tles[0], _gsp.value) private fun loadTwoLineElementFile(): List<TLE> {
satPassList = passPredictor.getPasses(Date(), 6, false) return try {
TLE.importSat(getApplication<Application>().openFileInput(tleFile))
} catch (exception: FileNotFoundException) { } catch (exception: FileNotFoundException) {
_debugMessage.postValue("TLE file wasn't found") _debugMessage.postValue("TLE file wasn't found")
emptyList()
} }
return satPassList }
suspend fun updateRecycler(): List<SatPass> {
val satPassList = mutableListOf<SatPass>()
var sortedList = listOf<SatPass>()
withContext(Dispatchers.Default) {
for (tle in tleList.subList(0, 1)) {
try {
Log.d(tag, "Trying ${tle.name}")
val passPredictor = PassPredictor(tle, gsp.value)
val passes = passPredictor.getPasses(Date(), 6, false)
for (pass in passes) {
Log.d(tag, "Trying ${pass.maxEl}")
satPassList.add(SatPass(tle.name, tle.catnum, pass))
}
} catch (exception: IllegalArgumentException) {
val tleProblem = "There was a problem with TLE"
Log.d(tag, tleProblem)
_debugMessage.postValue(tleProblem)
} catch (exception: SatNotFoundException) {
Log.d(tag, "Certain satellites shall not pass")
}
}
sortedList = satPassList.sortedWith(compareBy { it.pass.startTime })
}
return sortedList
} }
fun updateLocation() { fun updateLocation() {
@@ -77,9 +107,11 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
fun updateTwoLineElementFile() { fun updateTwoLineElementFile() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
val stream = repository.fetchTleStream()
getApplication<Application>().openFileOutput(tleFile, Context.MODE_PRIVATE).use { getApplication<Application>().openFileOutput(tleFile, Context.MODE_PRIVATE).use {
it.write(repository.fetchTleStream().readBytes()) it.write(stream.readBytes())
} }
tleList = TLE.importSat(stream)
_debugMessage.postValue("TLE file was updated") _debugMessage.postValue("TLE file was updated")
} catch (exception: IOException) { } catch (exception: IOException) {
_debugMessage.postValue("Couldn't update TLE file") _debugMessage.postValue("Couldn't update TLE file")
+13 -1
View File
@@ -6,10 +6,22 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".ui.SkyFragment"> tools:context=".ui.SkyFragment">
<ProgressBar
android:id="@+id/sky_progressbar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="@+id/sky_recycler"
app:layout_constraintEnd_toEndOf="@+id/sky_recycler"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_sky" android:id="@+id/sky_recycler"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"