diff --git a/app/build.gradle b/app/build.gradle index 476dd35c..5106f8ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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") diff --git a/app/src/main/java/com/rtbishop/look4sat/data/model/SatTrans.kt b/app/src/main/java/com/rtbishop/look4sat/data/model/SatTrans.kt index 9af320c7..2d1b42c6 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/model/SatTrans.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/model/SatTrans.kt @@ -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 diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt index 77c1deaf..f558b8b3 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarFragment.kt @@ -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) diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt index 44e9dfbb..20f5859d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarViewModel.kt @@ -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>() private val _azimuth = MutableLiveData() + val transmitters: LiveData> = _transmitters val azimuth: LiveData = _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) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt index 54123ad7..5261de81 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/TransAdapter.kt @@ -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() { +class TransAdapter : RecyclerView.Adapter() { - private var transmittersList = emptyList() + private val diffCallback = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: SatTrans, newItem: SatTrans): Boolean { + return oldItem.uuid == newItem.uuid + } - fun setData(list: List) { - 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) { + 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 + 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