diff --git a/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt b/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt index 91bc8c6d..051a2c06 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/model/SatPass.kt @@ -17,7 +17,6 @@ */ package com.rtbishop.look4sat.data.model -import com.github.amsacode.predict4java.SatPassTime import com.github.amsacode.predict4java.Satellite import com.rtbishop.look4sat.utility.PassPredictor diff --git a/app/src/main/java/com/rtbishop/look4sat/data/model/SatPassTime.kt b/app/src/main/java/com/rtbishop/look4sat/data/model/SatPassTime.kt new file mode 100644 index 00000000..6f9b5062 --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/data/model/SatPassTime.kt @@ -0,0 +1,37 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.rtbishop.look4sat.data.model + +import java.util.* + +class SatPassTime( + private val startTime: Date, + private val endTime: Date, + val aosAzimuth: Int, + val losAzimuth: Int, + val maxEl: Double +) { + + fun getStartTime(): Date { + return Date(startTime.time) + } + + fun getEndTime(): Date { + return Date(endTime.time) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt b/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt index 80d9df32..98fe2eed 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/repository/PassesRepo.kt @@ -72,10 +72,10 @@ class PassesRepo @Inject constructor( this.time = refDate this.add(Calendar.HOUR, hoursAhead) }.time - passes.removeAll { it.pass.startTime.after(dateFuture) } - passes.removeAll { it.pass.endTime.before(refDate) } + passes.removeAll { it.pass.getStartTime().after(dateFuture) } + passes.removeAll { it.pass.getEndTime().before(refDate) } passes.removeAll { it.pass.maxEl < prefsRepo.getMinElevation() } - passes.sortBy { it.pass.startTime } + passes.sortBy { it.pass.getStartTime() } return passes } } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt index fbfdefbf..839d2281 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesAdapter.kt @@ -46,9 +46,9 @@ class PassesAdapter(private val shouldUseUTC: Boolean = false) : val satPass = iterator.next() if (!satPass.satellite.tle.isDeepspace) { if (satPass.progress < 100) { - val timeStart = satPass.pass.startTime.time + val timeStart = satPass.pass.getStartTime().time if (timeNow > timeStart) { - val timeEnd = satPass.pass.endTime.time + val timeEnd = satPass.pass.getEndTime().time val index = satPassList.indexOf(satPass) val deltaNow = timeNow.minus(timeStart).toFloat() val deltaTotal = timeEnd.minus(timeStart).toFloat() @@ -115,9 +115,9 @@ class PassesAdapter(private val shouldUseUTC: Boolean = false) : passLeoAosAz.text = String.format(aosAzFormat, satPass.pass.aosAzimuth) passLeoMaxEl.text = String.format(maxElFormat, satPass.pass.maxEl) passLeoLosAz.text = String.format(losAzFormat, satPass.pass.losAzimuth) - passLeoStart.text = startFormat.format(satPass.pass.startTime) + passLeoStart.text = startFormat.format(satPass.pass.getStartTime()) passLeoAlt.text = String.format(altFormat, satPos.altitude) - passLeoEnd.text = endFormat.format(satPass.pass.endTime) + passLeoEnd.text = endFormat.format(satPass.pass.getEndTime()) passLeoProgress.progress = satPass.progress } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt index 54467456..cc34d519 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/passesScreen/PassesFragment.kt @@ -100,12 +100,12 @@ class PassesFragment : Fragment(R.layout.fragment_passes) { private fun tickMainTimer(timeNow: Long) { if (passes.isNotEmpty()) { try { - val nextPass = passes.first { it.pass.startTime.time.minus(timeNow) > 0 } - val millisBeforeStart = nextPass.pass.startTime.time.minus(timeNow) + val nextPass = passes.first { it.pass.getStartTime().time.minus(timeNow) > 0 } + val millisBeforeStart = nextPass.pass.getStartTime().time.minus(timeNow) binding?.passesTimer?.text = millisBeforeStart.formatForTimer() } catch (e: NoSuchElementException) { val lastPass = passes.last() - val millisBeforeEnd = lastPass.pass.endTime.time.minus(timeNow) + val millisBeforeEnd = lastPass.pass.getEndTime().time.minus(timeNow) binding?.passesTimer?.text = millisBeforeEnd.formatForTimer() } } else { 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 66178746..340a8cd3 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 @@ -30,7 +30,6 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.SimpleItemAnimator import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.data.model.Result import com.rtbishop.look4sat.data.model.SatPass import com.rtbishop.look4sat.databinding.FragmentPolarBinding import com.rtbishop.look4sat.utility.RecyclerDivider @@ -57,7 +56,7 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener { binding = FragmentPolarBinding.bind(view) sensorManager = requireContext().getSystemService(Context.SENSOR_SERVICE) as SensorManager magneticDeclination = viewModel.getMagDeclination() - observePasses() + observePass() } override fun onResume() { @@ -92,15 +91,23 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener { polarView?.rotation = -(roundedAzimuth + magneticDeclination) } - private fun observePasses() { - viewModel.getPasses().observe(viewLifecycleOwner, { result -> - if (result is Result.Success) { - satPass = result.data[requireArguments().getInt("index")] - polarView = PolarView(requireContext()).apply { setPass(satPass) } - binding.frame.addView(polarView) - observeTransmitters() - } + private fun observePass() { + val passId = requireArguments().getInt("index") + viewModel.getPass(passId).observe(viewLifecycleOwner, { pass -> + satPass = pass + polarView = PolarView(requireContext()).apply { setPass(pass) } + binding.frame.addView(polarView) + observeTransmitters() }) + +// viewModel.getPasses().observe(viewLifecycleOwner, { result -> +// if (result is Result.Success) { +// satPass = result.data[requireArguments().getInt("index")] +// polarView = PolarView(requireContext()).apply { setPass(satPass) } +// binding.frame.addView(polarView) +// observeTransmitters() +// } +// }) } private fun observeTransmitters() { @@ -148,13 +155,13 @@ class PolarFragment : Fragment(R.layout.fragment_polar), SensorEventListener { binding.altitude.text = String.format(polarAlt, satPos.altitude) if (!satPass.satellite.tle.isDeepspace) { - if (dateNow.before(satPass.pass.startTime)) { - val millisBeforeStart = satPass.pass.startTime.time.minus(timeNow) + if (dateNow.before(satPass.pass.getStartTime())) { + val millisBeforeStart = satPass.pass.getStartTime().time.minus(timeNow) binding.polarTimer.text = millisBeforeStart.formatForTimer() } else { - val millisBeforeEnd = satPass.pass.endTime.time.minus(timeNow) + val millisBeforeEnd = satPass.pass.getEndTime().time.minus(timeNow) binding.polarTimer.text = millisBeforeEnd.formatForTimer() - if (dateNow.after(satPass.pass.endTime)) { + if (dateNow.after(satPass.pass.getEndTime())) { binding.polarTimer.text = 0L.formatForTimer() findNavController().popBackStack() } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt index a9ad7889..925e9f28 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/polarScreen/PolarView.kt @@ -92,13 +92,13 @@ class PolarView(context: Context) : View(context) { } private fun drawPassTrajectory(cvs: Canvas, satPass: SatPass) { - val startTime = satPass.pass.startTime - val endTime = satPass.pass.endTime + val startTime = satPass.pass.getStartTime() + val endTime = satPass.pass.getEndTime() while (startTime.before(endTime)) { val satPos = satPass.predictor.getSatPos(startTime) val x = sph2CartX(satPos.azimuth, satPos.elevation, radius.toDouble()) val y = sph2CartY(satPos.azimuth, satPos.elevation, radius.toDouble()) - if (startTime.compareTo(satPass.pass.startTime) == 0) { + if (startTime.compareTo(satPass.pass.getStartTime()) == 0) { path.moveTo(x, -y) } else { path.lineTo(x, -y) 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 5de0141f..04c42fd4 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 @@ -20,11 +20,14 @@ package com.rtbishop.look4sat.ui.polarScreen import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData import androidx.lifecycle.liveData +import com.rtbishop.look4sat.data.model.Result +import com.rtbishop.look4sat.data.model.SatPass import com.rtbishop.look4sat.data.repository.PassesRepo import com.rtbishop.look4sat.data.repository.PrefsRepo import com.rtbishop.look4sat.data.repository.SatelliteRepo import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collect import javax.inject.Inject @HiltViewModel @@ -41,6 +44,14 @@ class PolarViewModel @Inject constructor( } } + fun getPass(passId: Int) = liveData { + passesRepo.passes.collect { passes -> + if (passes is Result.Success) { + emit(passes.data[passId]) + } + } + } + fun getPasses() = passesRepo.passes.asLiveData() fun shouldUseCompass(): Boolean { diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt b/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt index f8806904..36d997c9 100644 --- a/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt +++ b/app/src/main/java/com/rtbishop/look4sat/utility/PassPredictor.kt @@ -18,19 +18,30 @@ package com.rtbishop.look4sat.utility import com.github.amsacode.predict4java.GroundStationPosition -import com.github.amsacode.predict4java.SatPassTime import com.github.amsacode.predict4java.SatPos import com.github.amsacode.predict4java.Satellite +import com.rtbishop.look4sat.data.model.SatPassTime import java.util.* class PassPredictor(private val satellite: Satellite, private val qth: GroundStationPosition) { private val oneQuarterOrbitMin = (24.0 * 60.0 / satellite.tle.meanmo / 4.0).toInt() + private val speedOfLight = 2.99792458E8 + + fun getDownlinkFreq(freq: Long, date: Date): Long { + val rangeRate = getSatPos(date).rangeRate + return (freq.toDouble() * (speedOfLight - rangeRate * 1000.0) / speedOfLight).toLong() + } + + fun getUplinkFreq(freq: Long, date: Date): Long { + val rangeRate = getSatPos(date).rangeRate + return (freq.toDouble() * (speedOfLight + rangeRate * 1000.0) / speedOfLight).toLong() + } fun getSatPos(date: Date): SatPos { return satellite.getPosition(qth, date) } - + fun getPositions(refDate: Date, stepSeconds: Int, minBefore: Int, minAfter: Int): List { val positions = mutableListOf() val endDate = Date(refDate.time + minAfter * 60L * 1000L) @@ -57,9 +68,10 @@ class PassPredictor(private val satellite: Satellite, private val qth: GroundSta do { if (count > 0) shouldWindBack = false val pass = nextNearEarthPass(startDate, shouldWindBack) - lastAosDate = pass.startTime + lastAosDate = pass.getStartTime() passes.add(pass) - startDate = Date(pass.endTime.time + (oneQuarterOrbitMin * 3) * 60L * 1000L) + startDate = + Date(pass.getEndTime().time + (oneQuarterOrbitMin * 3) * 60L * 1000L) count++ } while (lastAosDate < endDate) } @@ -73,7 +85,7 @@ class PassPredictor(private val satellite: Satellite, private val qth: GroundSta val endDate = Date(refDate.time + 24 * 60L * 60L * 1000L) val azimuth = Math.toDegrees(satPos.azimuth).toInt() val maxEl = Math.toDegrees(satPos.elevation) - return SatPassTime(startDate, endDate, "pole", azimuth, azimuth, maxEl) + return SatPassTime(startDate, endDate, azimuth, azimuth, maxEl) } private fun nextNearEarthPass(refDate: Date, windBack: Boolean = false): SatPassTime { @@ -138,6 +150,6 @@ class PassPredictor(private val satellite: Satellite, private val qth: GroundSta val endDate = satPos.time val losAzimuth = Math.toDegrees(satPos.azimuth).toInt() val maxEl = Math.toDegrees(maxElevation) - return SatPassTime(startDate, endDate, "pole", aosAzimuth, losAzimuth, maxEl) + return SatPassTime(startDate, endDate, aosAzimuth, losAzimuth, maxEl) } } diff --git a/build.gradle b/build.gradle index a784437d..fe6a072e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - gradle_version = '4.1.2' + gradle_version = '4.1.3' gradle_plugin_version = '1.4.31' material_version = '1.3.0' constraint_layout_version = '2.0.4'