kopia lustrzana https://github.com/rt-bishop/Look4Sat
Fixed transmitters doppler frequency update logic
rodzic
555c2fe626
commit
db710c55c4
app
src/main/java/com/rtbishop/look4sat
data/model
ui/polarScreen
fastlane/metadata/android/en-US
changelogs
whatsnew
|
@ -13,8 +13,8 @@ android {
|
|||
applicationId "com.rtbishop.look4sat"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 231
|
||||
versionName "2.3.1"
|
||||
versionCode 232
|
||||
versionName "2.3.2"
|
||||
kapt {
|
||||
arguments {
|
||||
arg("room.schemaLocation", "$projectDir/schemas")
|
||||
|
|
|
@ -26,8 +26,8 @@ data class SatTrans(
|
|||
@PrimaryKey @field:Json(name = "uuid") val uuid: String,
|
||||
@field:Json(name = "description") val info: String,
|
||||
@field:Json(name = "alive") val isAlive: Boolean,
|
||||
@field:Json(name = "downlink_low") val downlink: Long?,
|
||||
@field:Json(name = "uplink_low") val uplink: Long?,
|
||||
@field:Json(name = "downlink_low") var downlink: Long?,
|
||||
@field:Json(name = "uplink_low") var uplink: Long?,
|
||||
@field:Json(name = "mode") val mode: String?,
|
||||
@field:Json(name = "invert") val isInverted: Boolean,
|
||||
@field:Json(name = "norad_cat_id") val catNum: Int
|
||||
|
|
|
@ -40,17 +40,18 @@ class PolarFragment : Fragment(R.layout.fragment_polar) {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val binding = FragmentPolarBinding.bind(view)
|
||||
val catNum = requireArguments().getInt("catNum")
|
||||
val aosTime = requireArguments().getLong("aosTime")
|
||||
viewModel.getPass(catNum, aosTime).observe(viewLifecycleOwner) { pass ->
|
||||
polarView = PolarView(requireContext()).apply { setPass(pass) }
|
||||
binding.frame.addView(polarView)
|
||||
observeTransmitters(pass, binding)
|
||||
FragmentPolarBinding.bind(view).apply {
|
||||
val transAdapter = TransAdapter()
|
||||
recycler.apply {
|
||||
setHasFixedSize(true)
|
||||
adapter = transAdapter
|
||||
isVerticalScrollBarEnabled = false
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
||||
addItemDecoration(RecyclerDivider(R.drawable.rec_divider_dark))
|
||||
}
|
||||
setupObservers(transAdapter, this)
|
||||
}
|
||||
viewModel.azimuth.observe(viewLifecycleOwner, { trueNorthAzimuth ->
|
||||
polarView?.rotation = -trueNorthAzimuth
|
||||
})
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -63,35 +64,41 @@ class PolarFragment : Fragment(R.layout.fragment_polar) {
|
|||
viewModel.disableSensor()
|
||||
}
|
||||
|
||||
private fun observeTransmitters(satPass: SatPass, binding: FragmentPolarBinding) {
|
||||
viewModel.getSatTransmitters(satPass.catNum).observe(viewLifecycleOwner, { list ->
|
||||
val transmitterAdapter = TransAdapter(satPass)
|
||||
private fun setupObservers(transAdapter: TransAdapter, binding: FragmentPolarBinding) {
|
||||
val catNum = requireArguments().getInt("catNum")
|
||||
val aosTime = requireArguments().getLong("aosTime")
|
||||
viewModel.getPass(catNum, aosTime).observe(viewLifecycleOwner) { pass ->
|
||||
polarView = PolarView(requireContext()).apply { setPass(pass) }
|
||||
binding.frame.addView(polarView)
|
||||
observeTransmitters(pass, transAdapter, binding)
|
||||
}
|
||||
viewModel.azimuth.observe(viewLifecycleOwner, { trueNorthAzimuth ->
|
||||
polarView?.rotation = -trueNorthAzimuth
|
||||
})
|
||||
}
|
||||
|
||||
private fun observeTransmitters(
|
||||
satPass: SatPass,
|
||||
transAdapter: TransAdapter,
|
||||
binding: FragmentPolarBinding
|
||||
) {
|
||||
viewModel.transmitters.observe(viewLifecycleOwner, { list ->
|
||||
if (list.isNotEmpty()) {
|
||||
transmitterAdapter.setData(list)
|
||||
binding.recycler.apply {
|
||||
setHasFixedSize(true)
|
||||
adapter = transmitterAdapter
|
||||
isVerticalScrollBarEnabled = false
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
|
||||
addItemDecoration(RecyclerDivider(R.drawable.rec_divider_dark))
|
||||
visibility = View.VISIBLE
|
||||
}
|
||||
transAdapter.submitList(list)
|
||||
binding.recycler.visibility = View.VISIBLE
|
||||
binding.noTransMsg.visibility = View.INVISIBLE
|
||||
} else {
|
||||
binding.recycler.visibility = View.INVISIBLE
|
||||
binding.noTransMsg.visibility = View.VISIBLE
|
||||
}
|
||||
viewModel.getAppTimer().observe(viewLifecycleOwner, {
|
||||
setPassText(it, satPass, binding)
|
||||
polarView?.invalidate()
|
||||
transmitterAdapter.tickTransmitters()
|
||||
})
|
||||
setPassText(satPass, binding)
|
||||
polarView?.invalidate()
|
||||
})
|
||||
}
|
||||
|
||||
private fun setPassText(timeNow: Long, satPass: SatPass, binding: FragmentPolarBinding) {
|
||||
val dateNow = Date(timeNow)
|
||||
private fun setPassText(satPass: SatPass, binding: FragmentPolarBinding) {
|
||||
val dateNow = Date()
|
||||
val timeNow = System.currentTimeMillis()
|
||||
val satPos = satPass.predictor.getSatPos(dateNow)
|
||||
val polarAz = getString(R.string.pat_azimuth)
|
||||
val polarEl = getString(R.string.pat_elevation)
|
||||
|
|
|
@ -18,12 +18,18 @@
|
|||
package com.rtbishop.look4sat.ui.polarScreen
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import com.rtbishop.look4sat.data.repository.PassesRepo
|
||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||
import com.rtbishop.look4sat.utility.PrefsManager
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
|
@ -35,20 +41,18 @@ class PolarViewModel @Inject constructor(
|
|||
) : ViewModel(), Orientation.OrientationListener {
|
||||
|
||||
private val magDeclination = prefsManager.getMagDeclination()
|
||||
private val _transmitters = MutableLiveData<List<SatTrans>>()
|
||||
private val _azimuth = MutableLiveData<Float>()
|
||||
val transmitters: LiveData<List<SatTrans>> = _transmitters
|
||||
val azimuth: LiveData<Float> = _azimuth
|
||||
|
||||
fun getAppTimer() = liveData {
|
||||
while (true) {
|
||||
emit(System.currentTimeMillis())
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
|
||||
fun getPass(catNum: Int, aosTime: Long) = liveData {
|
||||
passesRepo.passes.collect { passes ->
|
||||
val pass = passes.find { it.catNum == catNum && it.aosDate.time == aosTime }
|
||||
pass?.let { emit(it) }
|
||||
pass?.let { satPass ->
|
||||
processTransmitters(satPass)
|
||||
emit(satPass)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,10 +64,28 @@ class PolarViewModel @Inject constructor(
|
|||
if (prefsManager.shouldUseCompass()) orientation.stopListening()
|
||||
}
|
||||
|
||||
fun getSatTransmitters(satId: Int) =
|
||||
satelliteRepo.getSatTransmitters(satId).asLiveData(viewModelScope.coroutineContext)
|
||||
|
||||
override fun onOrientationChanged(azimuth: Float, pitch: Float, roll: Float) {
|
||||
_azimuth.value = azimuth + magDeclination
|
||||
}
|
||||
|
||||
private fun processTransmitters(satPass: SatPass) {
|
||||
viewModelScope.launch {
|
||||
satelliteRepo.getSatTransmitters(satPass.catNum).collect { transList ->
|
||||
while (isActive) {
|
||||
val timeNow = Date()
|
||||
val copiedList = transList.map { it.copy() }
|
||||
copiedList.forEach { transmitter ->
|
||||
transmitter.downlink?.let {
|
||||
transmitter.downlink = satPass.predictor.getDownlinkFreq(it, timeNow)
|
||||
}
|
||||
transmitter.uplink?.let {
|
||||
transmitter.uplink = satPass.predictor.getUplinkFreq(it, timeNow)
|
||||
}
|
||||
}
|
||||
_transmitters.postValue(copiedList.map { it.copy() })
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,45 +19,44 @@ package com.rtbishop.look4sat.ui.polarScreen
|
|||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.AsyncListDiffer
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import com.rtbishop.look4sat.databinding.ItemTransBinding
|
||||
import com.rtbishop.look4sat.utility.PassPredictor
|
||||
import java.util.*
|
||||
|
||||
class TransAdapter(private val pass: SatPass) : RecyclerView.Adapter<TransAdapter.TransHolder>() {
|
||||
class TransAdapter : RecyclerView.Adapter<TransAdapter.TransHolder>() {
|
||||
|
||||
private var transmittersList = emptyList<SatTrans>()
|
||||
private val diffCallback = object : DiffUtil.ItemCallback<SatTrans>() {
|
||||
override fun areItemsTheSame(oldItem: SatTrans, newItem: SatTrans): Boolean {
|
||||
return oldItem.uuid == newItem.uuid
|
||||
}
|
||||
|
||||
fun setData(list: List<SatTrans>) {
|
||||
transmittersList = list
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun tickTransmitters() {
|
||||
if (!pass.isDeepSpace) {
|
||||
notifyDataSetChanged()
|
||||
override fun areContentsTheSame(oldItem: SatTrans, newItem: SatTrans): Boolean {
|
||||
return oldItem.downlink == newItem.downlink
|
||||
}
|
||||
}
|
||||
private val differ = AsyncListDiffer(this, diffCallback)
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return transmittersList.size
|
||||
fun submitList(transmitters: List<SatTrans>) {
|
||||
differ.submitList(transmitters)
|
||||
}
|
||||
|
||||
override fun getItemCount() = differ.currentList.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransHolder {
|
||||
return TransHolder.from(parent)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: TransHolder, position: Int) {
|
||||
holder.bind(transmittersList[position], pass)
|
||||
holder.bind(differ.currentList[position])
|
||||
}
|
||||
|
||||
class TransHolder private constructor(private val binding: ItemTransBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
|
||||
private val dateNow = Date()
|
||||
private val divider = 1000000f
|
||||
private val strNo = itemView.context.getString(R.string.btn_no)
|
||||
private val strYes = itemView.context.getString(R.string.btn_yes)
|
||||
|
@ -66,11 +65,22 @@ class TransAdapter(private val pass: SatPass) : RecyclerView.Adapter<TransAdapte
|
|||
private val formatLinkNull = itemView.context.getString(R.string.trans_no_link)
|
||||
private val isInverted = itemView.context.getString(R.string.trans_inverted)
|
||||
|
||||
fun bind(satTrans: SatTrans, satPass: SatPass) {
|
||||
fun bind(satTrans: SatTrans) {
|
||||
binding.description.text = satTrans.info
|
||||
|
||||
if (satPass.isDeepSpace) setRegularFreq(satTrans)
|
||||
else setDopplerFreq(satTrans, satPass.predictor)
|
||||
satTrans.downlink.let { downlink ->
|
||||
if (downlink != null) {
|
||||
val downlinkFreq = downlink / divider
|
||||
binding.downlink.text = String.format(Locale.ENGLISH, formatLink, downlinkFreq)
|
||||
} else binding.downlink.text = formatLinkNull
|
||||
}
|
||||
|
||||
satTrans.uplink.let { uplink ->
|
||||
if (uplink != null) {
|
||||
val uplinkFreq = uplink / divider
|
||||
binding.uplink.text = String.format(Locale.ENGLISH, formatLink, uplinkFreq)
|
||||
} else binding.uplink.text = formatLinkNull
|
||||
}
|
||||
|
||||
if (satTrans.mode != null) binding.mode.text = String.format(mode, satTrans.mode)
|
||||
else binding.mode.text = String.format(mode, strNo)
|
||||
|
@ -79,30 +89,6 @@ class TransAdapter(private val pass: SatPass) : RecyclerView.Adapter<TransAdapte
|
|||
else binding.isInverted.text = String.format(isInverted, strNo)
|
||||
}
|
||||
|
||||
private fun setRegularFreq(satTrans: SatTrans) {
|
||||
if (satTrans.downlink != null) {
|
||||
val downFreq = satTrans.downlink / divider
|
||||
binding.downlink.text = String.format(Locale.ENGLISH, formatLink, downFreq)
|
||||
} else binding.downlink.text = formatLinkNull
|
||||
|
||||
if (satTrans.uplink != null) {
|
||||
val upFreq = satTrans.uplink / divider
|
||||
binding.uplink.text = String.format(Locale.ENGLISH, formatLink, upFreq)
|
||||
} else binding.uplink.text = formatLinkNull
|
||||
}
|
||||
|
||||
private fun setDopplerFreq(satTrans: SatTrans, predictor: PassPredictor) {
|
||||
if (satTrans.downlink != null) {
|
||||
val downlink = predictor.getDownlinkFreq(satTrans.downlink, dateNow) / divider
|
||||
binding.downlink.text = String.format(Locale.ENGLISH, formatLink, downlink)
|
||||
} else binding.downlink.text = formatLinkNull
|
||||
|
||||
if (satTrans.uplink != null) {
|
||||
val uplink = predictor.getUplinkFreq(satTrans.uplink, dateNow) / divider
|
||||
binding.uplink.text = String.format(Locale.ENGLISH, formatLink, uplink)
|
||||
} else binding.uplink.text = formatLinkNull
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun from(parent: ViewGroup): TransHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
|
|
|
@ -3,4 +3,6 @@ Now updating recyclers views asyncronously
|
|||
Switched to concurrent satellite data update
|
||||
Minor visual changes to map info
|
||||
Separated application screens logic
|
||||
Bug fixes, huge code cleanup
|
||||
Bug fixes, huge code cleanup
|
||||
Fixed recent InflatingException
|
||||
Fixed transmitters doppler frequency update logic
|
|
@ -4,4 +4,5 @@ Switched to concurrent satellite data update
|
|||
Minor visual changes to map info
|
||||
Separated application screens logic
|
||||
Bug fixes, huge code cleanup
|
||||
Fixed recent InflatingException
|
||||
Fixed recent InflatingException
|
||||
Fixed transmitters doppler frequency update logic
|
Ładowanie…
Reference in New Issue