From bceeb0119495cb22c4c45394ff0a8dac73de8e35 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Wed, 15 Sep 2021 09:20:47 +0100 Subject: [PATCH] Further refactoring of Look4Sat core module classes --- .../look4sat/framework/PreferencesProvider.kt | 9 +- .../api/{SatDataRemote.kt => RemoteSource.kt} | 6 +- ...{SatDataService.kt => SatelliteService.kt} | 2 +- .../db/{RoomConverters.kt => Converters.kt} | 16 +- .../db/{SatDataLocal.kt => LocalSource.kt} | 24 +- .../db/{SatDataDao.kt => SatelliteDao.kt} | 4 +- .../db/{SatDataDb.kt => SatelliteDb.kt} | 6 +- .../look4sat/framework/model/SatEntry.kt | 2 +- ...atDataModule.kt => SatelliteDataModule.kt} | 60 ++- .../satItemScreen/SatItemAdapter.kt | 2 +- .../satItemScreen/SatItemFragment.kt | 2 +- .../satItemScreen/SatItemViewModel.kt | 20 +- .../satMapScreen/SatMapFragment.kt | 8 +- .../satMapScreen/SatMapViewModel.kt | 47 +-- .../satPassInfoScreen/PassInfoFragment.kt | 11 +- .../satPassInfoScreen/PassInfoView.kt | 12 +- .../satPassInfoScreen/PassInfoViewModel.kt | 37 +- .../satPassInfoScreen/SatTransAdapter.kt | 2 +- .../satPassScreen/SatPassAdapter.kt | 2 +- .../satPassScreen/SatPassFragment.kt | 2 +- .../satPassScreen/SatPassViewModel.kt | 25 +- .../rtbishop/look4sat/utility/DataMapper.kt | 6 +- ...tDataLocalSource.kt => LocalDataSource.kt} | 10 +- .../rtbishop/look4sat/data/PassPredictor.kt | 388 ++++++++++++++++++ .../look4sat/data/PreferencesSource.kt | 2 +- ...ataRemoteSource.kt => RemoteDataSource.kt} | 4 +- .../look4sat/data/SatPassRepository.kt | 71 ---- .../rtbishop/look4sat/data/SatPredictor.kt | 86 ---- ...{SatDataRepository.kt => SatelliteRepo.kt} | 34 +- .../{predict4kotlin => }/DeepSpaceSat.kt | 2 +- .../domain/{predict4kotlin => }/GeoPos.kt | 2 +- .../{predict4kotlin => }/NearEarthSat.kt | 2 +- .../{predict4kotlin => }/QthConverter.kt | 4 +- .../com/rtbishop/look4sat/domain}/SatData.kt | 5 +- .../look4sat/domain/{model => }/SatEntry.kt | 4 +- .../look4sat/domain/{model => }/SatItem.kt | 2 +- .../domain/{predict4kotlin => }/SatPass.kt | 5 +- .../domain/{predict4kotlin => }/SatPos.kt | 5 +- .../look4sat/domain/{model => }/SatTrans.kt | 2 +- .../domain/{predict4kotlin => }/Satellite.kt | 15 +- .../domain/{predict4kotlin => }/StationPos.kt | 2 +- .../domain/{predict4kotlin => }/TLE.kt | 2 +- .../domain/predict4kotlin/PassPredictor.kt | 173 -------- .../look4sat/domain/predict4kotlin/SkyPos.kt | 20 - .../com/rtbishop/look4sat/Look4SatTest.kt | 2 +- .../com/rtbishop/look4sat/QthConverterTest.kt | 28 +- 46 files changed, 603 insertions(+), 572 deletions(-) rename app/src/main/java/com/rtbishop/look4sat/framework/api/{SatDataRemote.kt => RemoteSource.kt} (86%) rename app/src/main/java/com/rtbishop/look4sat/framework/api/{SatDataService.kt => SatelliteService.kt} (97%) rename app/src/main/java/com/rtbishop/look4sat/framework/db/{RoomConverters.kt => Converters.kt} (76%) rename app/src/main/java/com/rtbishop/look4sat/framework/db/{SatDataLocal.kt => LocalSource.kt} (73%) rename app/src/main/java/com/rtbishop/look4sat/framework/db/{SatDataDao.kt => SatelliteDao.kt} (97%) rename app/src/main/java/com/rtbishop/look4sat/framework/db/{SatDataDb.kt => SatelliteDb.kt} (89%) rename app/src/main/java/com/rtbishop/look4sat/injection/{SatDataModule.kt => SatelliteDataModule.kt} (59%) rename core/src/main/java/com/rtbishop/look4sat/data/{SatDataLocalSource.kt => LocalDataSource.kt} (83%) create mode 100644 core/src/main/java/com/rtbishop/look4sat/data/PassPredictor.kt rename core/src/main/java/com/rtbishop/look4sat/data/{SatDataRemoteSource.kt => RemoteDataSource.kt} (92%) delete mode 100644 core/src/main/java/com/rtbishop/look4sat/data/SatPassRepository.kt delete mode 100644 core/src/main/java/com/rtbishop/look4sat/data/SatPredictor.kt rename core/src/main/java/com/rtbishop/look4sat/data/{SatDataRepository.kt => SatelliteRepo.kt} (73%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/DeepSpaceSat.kt (99%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/GeoPos.kt (94%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/NearEarthSat.kt (99%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/QthConverter.kt (97%) rename {app/src/main/java/com/rtbishop/look4sat/framework/model => core/src/main/java/com/rtbishop/look4sat/domain}/SatData.kt (85%) rename core/src/main/java/com/rtbishop/look4sat/domain/{model => }/SatEntry.kt (90%) rename core/src/main/java/com/rtbishop/look4sat/domain/{model => }/SatItem.kt (95%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/SatPass.kt (91%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/SatPos.kt (96%) rename core/src/main/java/com/rtbishop/look4sat/domain/{model => }/SatTrans.kt (95%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/Satellite.kt (97%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/StationPos.kt (94%) rename core/src/main/java/com/rtbishop/look4sat/domain/{predict4kotlin => }/TLE.kt (98%) delete mode 100644 core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/PassPredictor.kt delete mode 100644 core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SkyPos.kt diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/PreferencesProvider.kt b/app/src/main/java/com/rtbishop/look4sat/framework/PreferencesProvider.kt index 32dbf55a..e9efded1 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/PreferencesProvider.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/PreferencesProvider.kt @@ -22,8 +22,8 @@ import android.hardware.GeomagneticField import android.location.LocationManager import androidx.core.content.edit import com.rtbishop.look4sat.data.PreferencesSource -import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter -import com.rtbishop.look4sat.domain.predict4kotlin.StationPos +import com.rtbishop.look4sat.domain.QthConverter +import com.rtbishop.look4sat.domain.StationPos import com.rtbishop.look4sat.utility.round import com.squareup.moshi.Moshi import com.squareup.moshi.Types @@ -31,7 +31,6 @@ import javax.inject.Inject class PreferencesProvider @Inject constructor( moshi: Moshi, - private val qthConverter: QthConverter, private val locationManager: LocationManager, private val preferences: SharedPreferences ) : PreferencesSource { @@ -86,7 +85,7 @@ class PreferencesProvider @Inject constructor( } override fun positionToQTH(lat: Double, lon: Double): String? { - return qthConverter.positionToQTH(lat, lon) + return QthConverter.positionToQTH(lat, lon) } override fun loadStationPosition(): StationPos { @@ -123,7 +122,7 @@ class PreferencesProvider @Inject constructor( } override fun updatePositionFromQTH(qthString: String): Boolean { - val position = qthConverter.qthToPosition(qthString) ?: return false + val position = QthConverter.qthToPosition(qthString) ?: return false val stationPosition = StationPos(position.latitude, position.longitude, 0.0) saveStationPosition(stationPosition) return true diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/api/SatDataRemote.kt b/app/src/main/java/com/rtbishop/look4sat/framework/api/RemoteSource.kt similarity index 86% rename from app/src/main/java/com/rtbishop/look4sat/framework/api/SatDataRemote.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/api/RemoteSource.kt index efc6b70b..e1270576 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/api/SatDataRemote.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/api/RemoteSource.kt @@ -17,12 +17,12 @@ */ package com.rtbishop.look4sat.framework.api -import com.rtbishop.look4sat.data.SatDataRemoteSource -import com.rtbishop.look4sat.domain.model.SatTrans +import com.rtbishop.look4sat.data.RemoteDataSource +import com.rtbishop.look4sat.domain.SatTrans import com.rtbishop.look4sat.utility.DataMapper import java.io.InputStream -class SatDataRemote(private val api: SatDataService) : SatDataRemoteSource { +class RemoteSource(private val api: SatelliteService) : RemoteDataSource { override suspend fun fetchDataStream(url: String): InputStream? { return api.fetchFileByUrl(url).body()?.byteStream() diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/api/SatDataService.kt b/app/src/main/java/com/rtbishop/look4sat/framework/api/SatelliteService.kt similarity index 97% rename from app/src/main/java/com/rtbishop/look4sat/framework/api/SatDataService.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/api/SatelliteService.kt index 3d341688..2034d482 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/api/SatDataService.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/api/SatelliteService.kt @@ -24,7 +24,7 @@ import retrofit2.http.GET import retrofit2.http.Streaming import retrofit2.http.Url -interface SatDataService { +interface SatelliteService { @Streaming @GET diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/db/RoomConverters.kt b/app/src/main/java/com/rtbishop/look4sat/framework/db/Converters.kt similarity index 76% rename from app/src/main/java/com/rtbishop/look4sat/framework/db/RoomConverters.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/db/Converters.kt index 2411c223..b7c96f46 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/db/RoomConverters.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/db/Converters.kt @@ -18,34 +18,34 @@ package com.rtbishop.look4sat.framework.db import androidx.room.TypeConverter -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite -import com.rtbishop.look4sat.domain.predict4kotlin.TLE +import com.rtbishop.look4sat.domain.Satellite +import com.rtbishop.look4sat.domain.TLE import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi -object RoomConverters { +object Converters { - private lateinit var tleAdapter: JsonAdapter + private lateinit var paramsAdapter: JsonAdapter fun initialize(moshi: Moshi) { - tleAdapter = moshi.adapter(TLE::class.java) + paramsAdapter = moshi.adapter(TLE::class.java) } @JvmStatic @TypeConverter fun tleToString(tle: TLE): String { - return tleAdapter.toJson(tle) + return paramsAdapter.toJson(tle) } @JvmStatic @TypeConverter fun tleFromString(string: String): TLE? { - return tleAdapter.fromJson(string) + return paramsAdapter.fromJson(string) } @JvmStatic @TypeConverter fun satFromString(string: String): Satellite? { - return tleAdapter.fromJson(string)?.createSat() + return paramsAdapter.fromJson(string)?.createSat() } } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataLocal.kt b/app/src/main/java/com/rtbishop/look4sat/framework/db/LocalSource.kt similarity index 73% rename from app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataLocal.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/db/LocalSource.kt index 93410fd1..8a5e9c1c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataLocal.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/db/LocalSource.kt @@ -17,42 +17,42 @@ */ package com.rtbishop.look4sat.framework.db -import com.rtbishop.look4sat.data.SatDataLocalSource -import com.rtbishop.look4sat.domain.model.SatEntry -import com.rtbishop.look4sat.domain.model.SatItem -import com.rtbishop.look4sat.domain.model.SatTrans -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite +import com.rtbishop.look4sat.data.LocalDataSource +import com.rtbishop.look4sat.domain.SatEntry +import com.rtbishop.look4sat.domain.SatItem +import com.rtbishop.look4sat.domain.SatTrans +import com.rtbishop.look4sat.domain.Satellite import com.rtbishop.look4sat.utility.DataMapper import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -class SatDataLocal(private val satDataDao: SatDataDao) : SatDataLocalSource { +class LocalSource(private val satelliteDao: SatelliteDao) : LocalDataSource { override fun getSatItems(): Flow> { - return satDataDao.getSatItems() + return satelliteDao.getSatItems() .map { satItems -> DataMapper.satItemsToDomainItems(satItems) } } override suspend fun getSelectedSatellites(): List { - return satDataDao.getSelectedSatellites() + return satelliteDao.getSelectedSatellites() } override suspend fun updateEntries(entries: List) { val satEntries = entries.map { entry -> DataMapper.domainEntryToSatEntry(entry) } - satDataDao.updateEntries(satEntries) + satelliteDao.updateEntries(satEntries) } override suspend fun updateEntriesSelection(catNums: List, isSelected: Boolean) { - satDataDao.updateEntriesSelection(catNums, isSelected) + satelliteDao.updateEntriesSelection(catNums, isSelected) } override fun getSatTransmitters(catNum: Int): Flow> { - return satDataDao.getSatTransmitters(catNum) + return satelliteDao.getSatTransmitters(catNum) .map { satTransList -> DataMapper.satTransListToDomainTransList(satTransList) } } override suspend fun updateTransmitters(satelliteTrans: List) { val satTransList = DataMapper.domainTransListToSatTransList(satelliteTrans) - satDataDao.updateTransmitters(satTransList) + satelliteDao.updateTransmitters(satTransList) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataDao.kt b/app/src/main/java/com/rtbishop/look4sat/framework/db/SatelliteDao.kt similarity index 97% rename from app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataDao.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/db/SatelliteDao.kt index 4d0c8b34..c0304911 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataDao.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/db/SatelliteDao.kt @@ -21,11 +21,11 @@ import androidx.room.* import com.rtbishop.look4sat.framework.model.SatEntry import com.rtbishop.look4sat.framework.model.SatItem import com.rtbishop.look4sat.framework.model.SatTrans -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite +import com.rtbishop.look4sat.domain.Satellite import kotlinx.coroutines.flow.Flow @Dao -interface SatDataDao { +interface SatelliteDao { @Transaction @Query("SELECT catNum, name, isSelected FROM entries ORDER BY name ASC") diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataDb.kt b/app/src/main/java/com/rtbishop/look4sat/framework/db/SatelliteDb.kt similarity index 89% rename from app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataDb.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/db/SatelliteDb.kt index 3246a4ff..bf05ed11 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/db/SatDataDb.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/db/SatelliteDb.kt @@ -24,8 +24,8 @@ import com.rtbishop.look4sat.framework.model.SatEntry import com.rtbishop.look4sat.framework.model.SatTrans @Database(entities = [SatEntry::class, SatTrans::class], version = 1, exportSchema = false) -@TypeConverters(RoomConverters::class) -abstract class SatDataDb : RoomDatabase() { +@TypeConverters(Converters::class) +abstract class SatelliteDb : RoomDatabase() { - abstract fun satelliteDao(): SatDataDao + abstract fun satelliteDao(): SatelliteDao } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt b/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt index 04ecf80e..272c8048 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt @@ -19,7 +19,7 @@ package com.rtbishop.look4sat.framework.model import androidx.room.Entity import androidx.room.PrimaryKey -import com.rtbishop.look4sat.domain.predict4kotlin.TLE +import com.rtbishop.look4sat.domain.TLE @Entity(tableName = "entries") data class SatEntry( diff --git a/app/src/main/java/com/rtbishop/look4sat/injection/SatDataModule.kt b/app/src/main/java/com/rtbishop/look4sat/injection/SatelliteDataModule.kt similarity index 59% rename from app/src/main/java/com/rtbishop/look4sat/injection/SatDataModule.kt rename to app/src/main/java/com/rtbishop/look4sat/injection/SatelliteDataModule.kt index a9da2788..c7ddaaf6 100644 --- a/app/src/main/java/com/rtbishop/look4sat/injection/SatDataModule.kt +++ b/app/src/main/java/com/rtbishop/look4sat/injection/SatelliteDataModule.kt @@ -22,14 +22,13 @@ import android.content.SharedPreferences import android.location.LocationManager import androidx.room.Room import com.rtbishop.look4sat.data.* -import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter import com.rtbishop.look4sat.framework.PreferencesProvider -import com.rtbishop.look4sat.framework.api.SatDataRemote -import com.rtbishop.look4sat.framework.api.SatDataService -import com.rtbishop.look4sat.framework.db.RoomConverters -import com.rtbishop.look4sat.framework.db.SatDataDao -import com.rtbishop.look4sat.framework.db.SatDataDb -import com.rtbishop.look4sat.framework.db.SatDataLocal +import com.rtbishop.look4sat.framework.api.RemoteSource +import com.rtbishop.look4sat.framework.api.SatelliteService +import com.rtbishop.look4sat.framework.db.Converters +import com.rtbishop.look4sat.framework.db.LocalSource +import com.rtbishop.look4sat.framework.db.SatelliteDao +import com.rtbishop.look4sat.framework.db.SatelliteDb import com.squareup.moshi.Moshi import dagger.Module import dagger.Provides @@ -45,12 +44,7 @@ import javax.net.ssl.HostnameVerifier @Module @InstallIn(SingletonComponent::class) -object SatDataModule { - - @Provides - fun provideQthConverter(): QthConverter { - return QthConverter() - } +object SatelliteDataModule { @Provides fun provideMoshi(): Moshi { @@ -61,56 +55,52 @@ object SatDataModule { @Singleton fun providePreferenceSource( moshi: Moshi, - qthConverter: QthConverter, locationManager: LocationManager, preferences: SharedPreferences ): PreferencesSource { - return PreferencesProvider(moshi, qthConverter, locationManager, preferences) + return PreferencesProvider(moshi, locationManager, preferences) } @Provides @Singleton - fun providePassesRepo( - preferencesSource: PreferencesSource, - @DefaultDispatcher defaultDispatcher: CoroutineDispatcher - ): SatPassRepository { - return SatPassRepository(preferencesSource, defaultDispatcher) + fun providePassPredictor(@DefaultDispatcher dispatcher: CoroutineDispatcher): PassPredictor { + return PassPredictor(dispatcher) } @Provides @Singleton fun provideSatelliteRepo( preferencesSource: PreferencesSource, - satLocalSource: SatDataLocalSource, - satRemoteSource: SatDataRemoteSource, - @IoDispatcher ioDispatcher: CoroutineDispatcher - ): SatDataRepository { - return SatDataRepository(preferencesSource, satLocalSource, satRemoteSource, ioDispatcher) + localDataSource: LocalDataSource, + remoteDataSource: RemoteDataSource, + @IoDispatcher dispatcher: CoroutineDispatcher + ): SatelliteRepo { + return SatelliteRepo(preferencesSource, localDataSource, remoteDataSource, dispatcher) } @Provides - fun provideLocalDataSource(satDataDao: SatDataDao): SatDataLocalSource { - return SatDataLocal(satDataDao) + fun provideLocalDataSource(satelliteDao: SatelliteDao): LocalDataSource { + return LocalSource(satelliteDao) } @Provides - fun provideSatDataDao(db: SatDataDb): SatDataDao { + fun provideSatelliteDao(db: SatelliteDb): SatelliteDao { return db.satelliteDao() } @Provides - fun provideSatelliteDb(@ApplicationContext context: Context, moshi: Moshi): SatDataDb { - RoomConverters.initialize(moshi) - return Room.databaseBuilder(context, SatDataDb::class.java, "SatelliteDb").build() + fun provideSatelliteDb(@ApplicationContext context: Context, moshi: Moshi): SatelliteDb { + Converters.initialize(moshi) + return Room.databaseBuilder(context, SatelliteDb::class.java, "SatelliteDb").build() } @Provides - fun provideRemoteDataSource(satDataService: SatDataService): SatDataRemoteSource { - return SatDataRemote(satDataService) + fun provideRemoteDataSource(satelliteService: SatelliteService): RemoteDataSource { + return RemoteSource(satelliteService) } @Provides - fun provideSatDataService(): SatDataService { + fun provideSatelliteService(): SatelliteService { val verifier = HostnameVerifier { _, _ -> true } val httpClient = OkHttpClient.Builder().hostnameVerifier(verifier).build() return Retrofit.Builder() @@ -118,6 +108,6 @@ object SatDataModule { .client(httpClient) .addConverterFactory(MoshiConverterFactory.create()) .build() - .create(SatDataService::class.java) + .create(SatelliteService::class.java) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemAdapter.kt index 3b3ca1a7..49a6a6d9 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemAdapter.kt @@ -23,7 +23,7 @@ import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.rtbishop.look4sat.databinding.SatItemBinding -import com.rtbishop.look4sat.domain.model.SatItem +import com.rtbishop.look4sat.domain.SatItem class SatItemAdapter : RecyclerView.Adapter() { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemFragment.kt index ab28acdd..48b58810 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemFragment.kt @@ -28,7 +28,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.FragmentEntriesBinding -import com.rtbishop.look4sat.domain.model.SatItem +import com.rtbishop.look4sat.domain.SatItem import com.rtbishop.look4sat.framework.model.Result import com.rtbishop.look4sat.utility.RecyclerDivider import com.rtbishop.look4sat.utility.getNavResult diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemViewModel.kt index daa38f67..9e36dcb1 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satItemScreen/SatItemViewModel.kt @@ -22,8 +22,8 @@ import android.net.Uri import android.widget.SearchView import androidx.lifecycle.* import com.rtbishop.look4sat.data.PreferencesSource -import com.rtbishop.look4sat.data.SatDataRepository -import com.rtbishop.look4sat.domain.model.SatItem +import com.rtbishop.look4sat.data.SatelliteRepo +import com.rtbishop.look4sat.domain.SatItem import com.rtbishop.look4sat.framework.model.Result import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.collect @@ -35,13 +35,13 @@ import javax.inject.Inject class SatItemViewModel @Inject constructor( private val preferencesSource: PreferencesSource, private val resolver: ContentResolver, - private val satDataRepository: SatDataRepository, + private val satelliteRepo: SatelliteRepo, ) : ViewModel(), SatItemAdapter.EntriesClickListener, SearchView.OnQueryTextListener { - private val transModes = MutableLiveData(satDataRepository.loadSelectedModes()) + private val transModes = MutableLiveData(satelliteRepo.loadSelectedModes()) private val currentQuery = MutableLiveData(String()) private val itemsWithModes = transModes.switchMap { modes -> - liveData { satDataRepository.getSatItems().collect { emit(filterByModes(it, modes)) } } + liveData { satelliteRepo.getSatItems().collect { emit(filterByModes(it, modes)) } } } private val itemsWithQuery = currentQuery.switchMap { query -> itemsWithModes.map { items -> Result.Success(filterByQuery(items, query)) } @@ -57,7 +57,7 @@ class SatItemViewModel @Inject constructor( _satData.value = Result.InProgress runCatching { resolver.openInputStream(uri)?.use { stream -> - satDataRepository.updateEntriesFromFile(stream) + satelliteRepo.updateEntriesFromFile(stream) } }.onFailure { _satData.value = Result.Error(it) } } @@ -68,7 +68,7 @@ class SatItemViewModel @Inject constructor( _satData.value = Result.InProgress try { preferencesSource.saveTleSources(sources) - satDataRepository.updateEntriesFromWeb(sources) + satelliteRepo.updateEntriesFromWeb(sources) } catch (exception: Exception) { _satData.value = Result.Error(exception) } @@ -84,12 +84,12 @@ class SatItemViewModel @Inject constructor( } fun loadSelectedModes(): List { - return satDataRepository.loadSelectedModes() + return satelliteRepo.loadSelectedModes() } fun saveSelectedModes(modes: List) { transModes.value = modes - satDataRepository.saveSelectedModes(modes) + satelliteRepo.saveSelectedModes(modes) } override fun onQueryTextSubmit(query: String): Boolean { @@ -102,7 +102,7 @@ class SatItemViewModel @Inject constructor( } override fun updateSelection(catNums: List, isSelected: Boolean) { - viewModelScope.launch { satDataRepository.updateEntriesSelection(catNums, isSelected) } + viewModelScope.launch { satelliteRepo.updateEntriesSelection(catNums, isSelected) } } private fun filterByModes(items: List, modes: List): List { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapFragment.kt index 77a4d7a6..b8483150 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapFragment.kt @@ -29,9 +29,9 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.FragmentMapBinding -import com.rtbishop.look4sat.domain.predict4kotlin.GeoPos -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite -import com.rtbishop.look4sat.framework.model.SatData +import com.rtbishop.look4sat.domain.GeoPos +import com.rtbishop.look4sat.domain.Satellite +import com.rtbishop.look4sat.domain.SatData import dagger.hilt.android.AndroidEntryPoint import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.TileSourceFactory @@ -89,7 +89,7 @@ class SatMapFragment : Fragment(R.layout.fragment_map) { } private fun setupObservers(binding: FragmentMapBinding) { - viewModel.stationPos.observe(viewLifecycleOwner, { renderStationPos(it, binding) }) + viewModel.stationPosLiveData.observe(viewLifecycleOwner, { renderStationPos(it, binding) }) viewModel.satPositions.observe(viewLifecycleOwner, { renderSatPositions(it, binding) }) viewModel.satTrack.observe(viewLifecycleOwner, { renderSatTrack(it, binding) }) viewModel.satFootprint.observe(viewLifecycleOwner, { renderSatFootprint(it, binding) }) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapViewModel.kt index 3b072925..4b049e57 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satMapScreen/SatMapViewModel.kt @@ -19,11 +19,12 @@ package com.rtbishop.look4sat.presentation.satMapScreen import androidx.lifecycle.* import com.rtbishop.look4sat.data.PreferencesSource -import com.rtbishop.look4sat.data.SatDataRepository -import com.rtbishop.look4sat.domain.predict4kotlin.GeoPos -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite -import com.rtbishop.look4sat.domain.predict4kotlin.StationPos -import com.rtbishop.look4sat.framework.model.SatData +import com.rtbishop.look4sat.data.SatelliteRepo +import com.rtbishop.look4sat.data.PassPredictor +import com.rtbishop.look4sat.domain.GeoPos +import com.rtbishop.look4sat.domain.Satellite +import com.rtbishop.look4sat.domain.StationPos +import com.rtbishop.look4sat.domain.SatData import com.rtbishop.look4sat.injection.DefaultDispatcher import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.* @@ -35,19 +36,20 @@ import kotlin.math.sqrt @HiltViewModel class SatMapViewModel @Inject constructor( - private val satDataRepository: SatDataRepository, - private val preferencesSource: PreferencesSource, + private val satelliteRepo: SatelliteRepo, + private val passPredictor: PassPredictor, + private val preferences: PreferencesSource, @DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher ) : ViewModel() { - private val gsp = preferencesSource.loadStationPosition() + private val stationPos = preferences.loadStationPosition() private var dataUpdateJob: Job? = null private var allSatList = listOf() private lateinit var selectedSat: Satellite - val stationPos = liveData { - val osmLat = clipLat(gsp.latitude) - val osmLon = clipLon(gsp.longitude) + val stationPosLiveData = liveData { + val osmLat = clipLat(stationPos.latitude) + val osmLon = clipLon(stationPos.longitude) emit(GeoPos(osmLat, osmLon)) } @@ -65,7 +67,7 @@ class SatMapViewModel @Inject constructor( init { viewModelScope.launch { - satDataRepository.getSelectedSatellites().also { selectedSatellites -> + satelliteRepo.getSelectedSatellites().also { selectedSatellites -> if (selectedSatellites.isNotEmpty()) { allSatList = selectedSatellites selectSatellite(selectedSatellites.first()) @@ -75,7 +77,7 @@ class SatMapViewModel @Inject constructor( } fun shouldUseTextLabels(): Boolean { - return preferencesSource.shouldUseTextLabels() + return preferences.shouldUseTextLabels() } fun scrollSelection(decrement: Boolean) { @@ -97,12 +99,12 @@ class SatMapViewModel @Inject constructor( dataUpdateJob?.cancelAndJoin() dataUpdateJob = launch { val dateNow = Date() - setSelectedSatTrack(selectedSat, gsp, dateNow) + setSelectedSatTrack(selectedSat, stationPos, dateNow) while (isActive) { dateNow.time = System.currentTimeMillis() - setSatPositions(allSatList, gsp, dateNow) - setSelectedSatFootprint(selectedSat, gsp, dateNow) - setSelectedSatData(selectedSat, gsp, dateNow) + setSatPositions(allSatList, stationPos, dateNow) + setSelectedSatFootprint(selectedSat, stationPos, dateNow) + setSelectedSatData(selectedSat, stationPos, dateNow) delay(updateFreq) } } @@ -113,7 +115,7 @@ class SatMapViewModel @Inject constructor( withContext(defaultDispatcher) { val satPositions = mutableMapOf() list.forEach { satellite -> - val satPos = satellite.getPredictor(gsp).getSatPos(date) + val satPos = satellite.getPosition(gsp, date.time) val osmLat = clipLat(Math.toDegrees(satPos.latitude)) val osmLon = clipLon(Math.toDegrees(satPos.longitude)) satPositions[satellite] = GeoPos(osmLat, osmLon) @@ -127,7 +129,7 @@ class SatMapViewModel @Inject constructor( val satTracks = mutableListOf>() val currentTrack = mutableListOf() var oldLongitude = 0.0 - sat.getPredictor(gsp).getPositions(date, 15, 0, 2.4).forEach { satPos -> + passPredictor.getPositions(sat, gsp, date, 15, 0, 2.4).forEach { satPos -> val osmLat = clipLat(Math.toDegrees(satPos.latitude)) val osmLon = clipLon(Math.toDegrees(satPos.longitude)) val currentPosition = GeoPos(osmLat, osmLon) @@ -154,7 +156,7 @@ class SatMapViewModel @Inject constructor( private suspend fun setSelectedSatFootprint(sat: Satellite, gsp: StationPos, date: Date) { withContext(defaultDispatcher) { - val satFootprint = sat.getPosition(gsp, date).getRangeCircle().map { rangePos -> + val satFootprint = sat.getPosition(gsp, date.time).getRangeCircle().map { rangePos -> val osmLat = clipLat(rangePos.latitude) val osmLon = clipLon(rangePos.longitude) GeoPos(osmLat, osmLon) @@ -165,12 +167,11 @@ class SatMapViewModel @Inject constructor( private suspend fun setSelectedSatData(sat: Satellite, gsp: StationPos, date: Date) { withContext(defaultDispatcher) { - val satPos = sat.getPredictor(gsp).getSatPos(date) + val satPos = sat.getPosition(gsp, date.time) val osmLat = clipLat(Math.toDegrees(satPos.latitude)) val osmLon = clipLon(Math.toDegrees(satPos.longitude)) val osmPos = GeoPos(osmLat, osmLon) - val qthLoc = - preferencesSource.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --" + val qthLoc = preferences.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --" val velocity = getOrbitalVelocity(satPos.altitude) val satData = SatData( sat, sat.params.catnum, sat.params.name, satPos.range, diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoFragment.kt index 6b6e5c33..dcce78c9 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoFragment.kt @@ -27,7 +27,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator import com.rtbishop.look4sat.R import com.rtbishop.look4sat.data.PreferencesSource import com.rtbishop.look4sat.databinding.FragmentPolarBinding -import com.rtbishop.look4sat.domain.predict4kotlin.SatPass +import com.rtbishop.look4sat.domain.SatPass import com.rtbishop.look4sat.utility.RecyclerDivider import com.rtbishop.look4sat.utility.navigateSafe import com.rtbishop.look4sat.utility.toTimerString @@ -39,7 +39,7 @@ import javax.inject.Inject class PassInfoFragment : Fragment(R.layout.fragment_polar) { @Inject - lateinit var preferencesSource: PreferencesSource + lateinit var preferences: PreferencesSource private val viewModel: PassInfoViewModel by viewModels() private var passInfoView: PassInfoView? = null @@ -72,10 +72,12 @@ class PassInfoFragment : Fragment(R.layout.fragment_polar) { private fun setupObservers(satTransAdapter: SatTransAdapter, binding: FragmentPolarBinding) { val catNum = requireArguments().getInt("catNum") val aosTime = requireArguments().getLong("aosTime") + val stationPos = preferences.loadStationPosition() viewModel.getPass(catNum, aosTime).observe(viewLifecycleOwner) { pass -> passInfoView = PassInfoView(requireContext()).apply { - setShowAim(preferencesSource.shouldUseCompass()) + setShowAim(preferences.shouldUseCompass()) setPass(pass) + setStationPos(stationPos) } binding.frame.addView(passInfoView) observeTransmitters(pass, satTransAdapter, binding) @@ -107,7 +109,8 @@ class PassInfoFragment : Fragment(R.layout.fragment_polar) { private fun setPassText(satPass: SatPass, binding: FragmentPolarBinding) { val dateNow = Date() val timeNow = System.currentTimeMillis() - val satPos = satPass.predictor.getSatPos(dateNow) + val stationPos = preferences.loadStationPosition() + val satPos = satPass.satellite.getPosition(stationPos, dateNow.time) val polarAz = getString(R.string.pat_azimuth) val polarEl = getString(R.string.pat_elevation) val polarRng = getString(R.string.pat_distance) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoView.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoView.kt index a8d38880..eaab3bb3 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoView.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoView.kt @@ -22,7 +22,8 @@ import android.graphics.* import android.view.View import androidx.core.content.ContextCompat import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.domain.predict4kotlin.SatPass +import com.rtbishop.look4sat.domain.SatPass +import com.rtbishop.look4sat.domain.StationPos import java.util.* import kotlin.math.cos import kotlin.math.min @@ -37,6 +38,7 @@ class PassInfoView(context: Context) : View(context) { private val radarRadius = radarWidth * 0.48f private val piDiv2 = Math.PI / 2.0 private val strokeSize = scale * 2f + private var stationPos: StationPos = StationPos(0.0, 0.0, 0.0) private var radarColor = ContextCompat.getColor(context, R.color.greyLight) private var radarCircleNum = 3 @@ -101,6 +103,10 @@ class PassInfoView(context: Context) : View(context) { this.satPass = satPass } + fun setStationPos(stationPos: StationPos) { + this.stationPos = stationPos + } + fun setShowAim(showAim: Boolean) { shouldShowAim = showAim } @@ -170,7 +176,7 @@ class PassInfoView(context: Context) : View(context) { } private fun drawSatellite(canvas: Canvas, satPass: SatPass) { - val satPos = satPass.predictor.getSatPos(Date()) + val satPos = satPass.satellite.getPosition(stationPos, Date().time) if (satPos.elevation > 0) { val satX = sph2CartX(satPos.azimuth, satPos.elevation, radarRadius.toDouble()) val satY = sph2CartY(satPos.azimuth, satPos.elevation, radarRadius.toDouble()) @@ -202,7 +208,7 @@ class PassInfoView(context: Context) : View(context) { private fun createPassTrajectory(satPass: SatPass) { var currentTime = satPass.aosTime while (currentTime < satPass.losTime) { - val satPos = satPass.predictor.getSatPos(Date(currentTime)) + val satPos = satPass.satellite.getPosition(stationPos, currentTime) val passX = sph2CartX(satPos.azimuth, satPos.elevation, radarRadius.toDouble()) val passY = sph2CartY(satPos.azimuth, satPos.elevation, radarRadius.toDouble()) if (currentTime == satPass.aosTime) { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoViewModel.kt index 2fe3729e..a94b7307 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/PassInfoViewModel.kt @@ -18,12 +18,12 @@ package com.rtbishop.look4sat.presentation.satPassInfoScreen import androidx.lifecycle.* -import com.rtbishop.look4sat.data.SatPassRepository +import com.rtbishop.look4sat.data.PassPredictor import com.rtbishop.look4sat.data.PreferencesSource -import com.rtbishop.look4sat.data.SatDataRepository +import com.rtbishop.look4sat.data.SatelliteRepo import com.rtbishop.look4sat.injection.IoDispatcher -import com.rtbishop.look4sat.domain.model.SatTrans -import com.rtbishop.look4sat.domain.predict4kotlin.SatPass +import com.rtbishop.look4sat.domain.SatTrans +import com.rtbishop.look4sat.domain.SatPass import com.rtbishop.look4sat.framework.OrientationProvider import com.rtbishop.look4sat.utility.round import dagger.hilt.android.lifecycle.HiltViewModel @@ -37,19 +37,20 @@ import javax.inject.Inject @HiltViewModel class PassInfoViewModel @Inject constructor( private val orientationProvider: OrientationProvider, - private val preferencesSource: PreferencesSource, - private val satPassRepository: SatPassRepository, - private val satDataRepository: SatDataRepository, + private val preferences: PreferencesSource, + private val passPredictor: PassPredictor, + private val satelliteRepo: SatelliteRepo, @IoDispatcher private val ioDispatcher: CoroutineDispatcher ) : ViewModel(), OrientationProvider.OrientationListener { + private val stationPos = preferences.loadStationPosition() private val _transmitters = MutableLiveData>() private val _orientation = MutableLiveData>() val transmitters: LiveData> = _transmitters val orientation: LiveData> = _orientation fun getPass(catNum: Int, aosTime: Long) = liveData { - satPassRepository.passes.collect { passes -> + passPredictor.passes.collect { passes -> val pass = passes.find { it.catNum == catNum && it.aosTime == aosTime } pass?.let { satPass -> processTransmitters(satPass) @@ -60,27 +61,27 @@ class PassInfoViewModel @Inject constructor( } fun enableSensor() { - if (preferencesSource.shouldUseCompass()) orientationProvider.startListening(this) + if (preferences.shouldUseCompass()) orientationProvider.startListening(this) } fun disableSensor() { - if (preferencesSource.shouldUseCompass()) orientationProvider.stopListening() + if (preferences.shouldUseCompass()) orientationProvider.stopListening() } override fun onOrientationChanged(azimuth: Float, pitch: Float, roll: Float) { - _orientation.value = Triple(azimuth + preferencesSource.getMagDeclination(), pitch, roll) + _orientation.value = Triple(azimuth + preferences.getMagDeclination(), pitch, roll) } private fun initRotatorControl(satPass: SatPass) { viewModelScope.launch { - val rotatorPrefs = preferencesSource.getRotatorServer() + val rotatorPrefs = preferences.getRotatorServer() if (rotatorPrefs != null) { runCatching { withContext(ioDispatcher) { val socket = Socket(rotatorPrefs.first, rotatorPrefs.second) val writer = socket.getOutputStream().bufferedWriter() while (isActive) { - val satPos = satPass.predictor.getSatPos(Date()) + val satPos = satPass.satellite.getPosition(stationPos, Date().time) val azimuth = Math.toDegrees(satPos.azimuth).round(1) val elevation = Math.toDegrees(satPos.elevation).round(1) writer.write("\\set_pos $azimuth $elevation") @@ -97,16 +98,16 @@ class PassInfoViewModel @Inject constructor( private fun processTransmitters(satPass: SatPass) { viewModelScope.launch { - satDataRepository.getSatTransmitters(satPass.catNum).collect { transList -> + satelliteRepo.getSatTransmitters(satPass.catNum).collect { transList -> while (isActive) { - val timeNow = Date() + val satPos = satPass.satellite.getPosition(stationPos, Date().time) val copiedList = transList.map { it.copy() } copiedList.forEach { transmitter -> transmitter.downlink?.let { - transmitter.downlink = satPass.predictor.getDownlinkFreq(it, timeNow) + transmitter.downlink = satPos.getDownlinkFreq(it) } transmitter.uplink?.let { - transmitter.uplink = satPass.predictor.getUplinkFreq(it, timeNow) + transmitter.uplink = satPos.getUplinkFreq(it) } } _transmitters.postValue(copiedList.map { it.copy() }) @@ -115,4 +116,4 @@ class PassInfoViewModel @Inject constructor( } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/SatTransAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/SatTransAdapter.kt index 506e5ec7..d15c09e5 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/SatTransAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassInfoScreen/SatTransAdapter.kt @@ -24,7 +24,7 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.ItemTransBinding -import com.rtbishop.look4sat.domain.model.SatTrans +import com.rtbishop.look4sat.domain.SatTrans import java.util.* class SatTransAdapter : RecyclerView.Adapter() { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassAdapter.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassAdapter.kt index fa0ccee1..707d21e5 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassAdapter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassAdapter.kt @@ -25,7 +25,7 @@ import androidx.recyclerview.widget.RecyclerView import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.ItemPassGeoBinding import com.rtbishop.look4sat.databinding.ItemPassLeoBinding -import com.rtbishop.look4sat.domain.predict4kotlin.SatPass +import com.rtbishop.look4sat.domain.SatPass import java.text.SimpleDateFormat import java.util.* diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassFragment.kt index 7a8b58ec..af7e6551 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassFragment.kt @@ -29,7 +29,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.SimpleItemAnimator import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.FragmentPassesBinding -import com.rtbishop.look4sat.domain.predict4kotlin.SatPass +import com.rtbishop.look4sat.domain.SatPass import com.rtbishop.look4sat.framework.model.Result import com.rtbishop.look4sat.utility.RecyclerDivider import com.rtbishop.look4sat.utility.navigateSafe diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassViewModel.kt index 1f345e44..b81ebb7e 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/satPassScreen/SatPassViewModel.kt @@ -22,9 +22,9 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.rtbishop.look4sat.data.PreferencesSource -import com.rtbishop.look4sat.data.SatDataRepository -import com.rtbishop.look4sat.data.SatPassRepository -import com.rtbishop.look4sat.domain.predict4kotlin.SatPass +import com.rtbishop.look4sat.data.SatelliteRepo +import com.rtbishop.look4sat.data.PassPredictor +import com.rtbishop.look4sat.domain.SatPass import com.rtbishop.look4sat.framework.model.Result import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.* @@ -33,8 +33,8 @@ import javax.inject.Inject @HiltViewModel class SatPassViewModel @Inject constructor( - private val satDataRepository: SatDataRepository, - private val satPassRepository: SatPassRepository, + private val satelliteRepo: SatelliteRepo, + private val passPredictor: PassPredictor, private val preferencesSource: PreferencesSource ) : ViewModel() { @@ -48,13 +48,14 @@ class SatPassViewModel @Inject constructor( if (preferencesSource.isSetupDone()) { viewModelScope.launch { _passes.postValue(Result.InProgress) - satPassRepository.triggerCalculation(satDataRepository.getSelectedSatellites()) + val stationPos = preferencesSource.loadStationPosition() + passPredictor.triggerCalculation(satelliteRepo.getSelectedSatellites(), stationPos) } } else { _isFirstLaunchDone.value = false } viewModelScope.launch { - satPassRepository.passes.collect { passes -> + passPredictor.passes.collect { passes -> passesProcessing?.cancelAndJoin() passesProcessing = viewModelScope.launch { tickPasses(passes) } } @@ -66,9 +67,10 @@ class SatPassViewModel @Inject constructor( viewModelScope.launch { _passes.postValue(Result.InProgress) val defaultCatNums = listOf(43700, 25544, 25338, 28654, 33591, 40069, 27607, 24278) - satDataRepository.updateEntriesFromWeb(preferencesSource.loadDefaultSources()) - satDataRepository.updateEntriesSelection(defaultCatNums, true) - satPassRepository.forceCalculation(satDataRepository.getSelectedSatellites()) + val stationPos = preferencesSource.loadStationPosition() + satelliteRepo.updateEntriesFromWeb(preferencesSource.loadDefaultSources()) + satelliteRepo.updateEntriesSelection(defaultCatNums, true) + passPredictor.forceCalculation(satelliteRepo.getSelectedSatellites(), stationPos) preferencesSource.setSetupDone() _isFirstLaunchDone.value = true } @@ -78,7 +80,8 @@ class SatPassViewModel @Inject constructor( viewModelScope.launch { _passes.postValue(Result.InProgress) passesProcessing?.cancelAndJoin() - satPassRepository.forceCalculation(satDataRepository.getSelectedSatellites()) + val stationPos = preferencesSource.loadStationPosition() + passPredictor.forceCalculation(satelliteRepo.getSelectedSatellites(), stationPos) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/utility/DataMapper.kt b/app/src/main/java/com/rtbishop/look4sat/utility/DataMapper.kt index 9f2b1bbf..38ff789b 100644 --- a/app/src/main/java/com/rtbishop/look4sat/utility/DataMapper.kt +++ b/app/src/main/java/com/rtbishop/look4sat/utility/DataMapper.kt @@ -20,9 +20,9 @@ package com.rtbishop.look4sat.utility import com.rtbishop.look4sat.framework.model.SatEntry import com.rtbishop.look4sat.framework.model.SatItem import com.rtbishop.look4sat.framework.model.SatTrans -import com.rtbishop.look4sat.domain.model.SatEntry as DomainEntry -import com.rtbishop.look4sat.domain.model.SatItem as DomainItem -import com.rtbishop.look4sat.domain.model.SatTrans as DomainTrans +import com.rtbishop.look4sat.domain.SatEntry as DomainEntry +import com.rtbishop.look4sat.domain.SatItem as DomainItem +import com.rtbishop.look4sat.domain.SatTrans as DomainTrans object DataMapper { diff --git a/core/src/main/java/com/rtbishop/look4sat/data/SatDataLocalSource.kt b/core/src/main/java/com/rtbishop/look4sat/data/LocalDataSource.kt similarity index 83% rename from core/src/main/java/com/rtbishop/look4sat/data/SatDataLocalSource.kt rename to core/src/main/java/com/rtbishop/look4sat/data/LocalDataSource.kt index 2c5d29f7..d2c654bc 100644 --- a/core/src/main/java/com/rtbishop/look4sat/data/SatDataLocalSource.kt +++ b/core/src/main/java/com/rtbishop/look4sat/data/LocalDataSource.kt @@ -17,13 +17,13 @@ */ package com.rtbishop.look4sat.data -import com.rtbishop.look4sat.domain.model.SatEntry -import com.rtbishop.look4sat.domain.model.SatItem -import com.rtbishop.look4sat.domain.model.SatTrans -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite +import com.rtbishop.look4sat.domain.SatEntry +import com.rtbishop.look4sat.domain.SatItem +import com.rtbishop.look4sat.domain.SatTrans +import com.rtbishop.look4sat.domain.Satellite import kotlinx.coroutines.flow.Flow -interface SatDataLocalSource { +interface LocalDataSource { fun getSatItems(): Flow> diff --git a/core/src/main/java/com/rtbishop/look4sat/data/PassPredictor.kt b/core/src/main/java/com/rtbishop/look4sat/data/PassPredictor.kt new file mode 100644 index 00000000..5e2b1b06 --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/data/PassPredictor.kt @@ -0,0 +1,388 @@ +/* + * 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 + +import com.rtbishop.look4sat.domain.* +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.withContext +import java.util.* +import kotlin.math.max +import kotlin.math.min +import kotlin.math.pow +import kotlin.math.sqrt + +class PassPredictor(private val defaultDispatcher: CoroutineDispatcher) { + + // Radar view - beacon + private val _skyPosition = MutableSharedFlow(replay = 1) + val skyPosition: SharedFlow = _skyPosition + + suspend fun getSkyPosition(pass: SatPass, stationPos: StationPos, date: Date) { + withContext(defaultDispatcher) { + _skyPosition.emit(pass.satellite.getPosition(stationPos, date.time)) + } + } + + // Radar view - track + private val _skyTrack = MutableSharedFlow>(replay = 1) + val skyTrack: SharedFlow> = _skyTrack + + suspend fun getSkyTrack(pass: SatPass, stationPos: StationPos) { + withContext(defaultDispatcher) { + val positions = mutableListOf() + var currentTime = pass.aosTime + while (currentTime < pass.losTime) { + positions.add(pass.satellite.getPosition(stationPos, currentTime)) + currentTime += 15000 + } + _skyTrack.emit(positions) + } + } + + // Map view - beacons + private val _mapPositions = MutableSharedFlow>(replay = 1) + val mapPositions: SharedFlow> = _mapPositions + + suspend fun getMapPositions(satellites: List, stationPos: StationPos, date: Date) { + withContext(defaultDispatcher) { + val positions = mutableMapOf() + satellites.forEach { satellite -> + val satPos = satellite.getPosition(stationPos, date.time) + val osmLat = clipLat(Math.toDegrees(satPos.latitude)) + val osmLon = clipLon(Math.toDegrees(satPos.longitude)) + positions[satellite] = GeoPos(osmLat, osmLon) + } + _mapPositions.emit(positions) + } + } + + // Map view - track + private val _mapTrack = MutableSharedFlow>>(replay = 1) + val mapTrack: SharedFlow>> = _mapTrack + + suspend fun getMapTrack(satellite: Satellite, stationPos: StationPos, date: Date) { + withContext(defaultDispatcher) { + val positions = mutableListOf() + val orbitalPeriod = satellite.getQuarterOrbitMin() * 4 + val endTime = date.time + (orbitalPeriod * 2.4 * 60L * 1000L).toLong() + var currentTime = date.time + while (currentTime < endTime) { + positions.add(satellite.getPosition(stationPos, currentTime)) + currentTime += 15000 + } + + val satTracks = mutableListOf>() + val currentTrack = mutableListOf() + var oldLongitude = 0.0 + positions.forEach { satPos -> + val osmLat = clipLat(Math.toDegrees(satPos.latitude)) + val osmLon = clipLon(Math.toDegrees(satPos.longitude)) + val currentPos = GeoPos(osmLat, osmLon) + if (oldLongitude < -170.0 && currentPos.longitude > 170.0) { + // adding left terminal position + currentTrack.add(GeoPos(osmLat, -180.0)) + satTracks.add(mutableListOf().apply { addAll(currentTrack) }) + currentTrack.clear() + } else if (oldLongitude > 170.0 && currentPos.longitude < -170.0) { + // adding right terminal position + currentTrack.add(GeoPos(osmLat, 180.0)) + satTracks.add(mutableListOf().apply { addAll(currentTrack) }) + currentTrack.clear() + } + oldLongitude = currentPos.longitude + currentTrack.add(currentPos) + } + satTracks.add(currentTrack) + _mapTrack.emit(satTracks) + } + } + + private val _mapFootprint = MutableSharedFlow>(replay = 1) + val mapFootprint: SharedFlow> = _mapFootprint + + suspend fun setSelectedSatFootprint(satellite: Satellite, stationPos: StationPos, date: Date) { + withContext(defaultDispatcher) { + val satPos = satellite.getPosition(stationPos, date.time) + val satFootprint = satPos.getRangeCircle().map { groundPos -> + val osmLat = clipLat(groundPos.latitude) + val osmLon = clipLon(groundPos.longitude) + GeoPos(osmLat, osmLon) + } + _mapFootprint.emit(satFootprint) + } + } + + private val _satData = MutableSharedFlow(replay = 1) + val satData: SharedFlow = _satData + + suspend fun setSelectedSatData(satellite: Satellite, stationPos: StationPos, date: Date) { + withContext(defaultDispatcher) { + val satPos = satellite.getPosition(stationPos, date.time) + val osmLat = clipLat(Math.toDegrees(satPos.latitude)) + val osmLon = clipLon(Math.toDegrees(satPos.longitude)) + val osmPos = GeoPos(osmLat, osmLon) + val qthLoc = QthConverter.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --" + val velocity = getOrbitalVelocity(satPos.altitude) + val satData = SatData( + satellite, satellite.params.catnum, satellite.params.name, satPos.range, + satPos.altitude, velocity, qthLoc, osmPos + ) + _satData.emit(satData) + } + } + + private fun getOrbitalVelocity(altitude: Double): Double { + val earthG = 6.674 * 10.0.pow(-11) + val earthM = 5.98 * 10.0.pow(24) + val radius = 6.37 * 10.0.pow(6) + altitude * 10.0.pow(3) + return sqrt(earthG * earthM / radius) / 1000 + } + + private fun clipLat(pLatitude: Double): Double { + return clip(pLatitude, -85.05, 85.05) + } + + private fun clipLon(pLongitude: Double): Double { + var result = pLongitude + while (result < -180.0) result += 360.0 + while (result > 180.0) result -= 360.0 + return clip(result, -180.0, 180.0) + } + + private fun clip(currentValue: Double, minValue: Double, maxValue: Double): Double { + return min(max(currentValue, minValue), maxValue) + } + + fun getPositions( + satellite: Satellite, + stationPos: StationPos, + refDate: Date, + stepSec: Int, + minBefore: Int, + orbits: Double + ): List { + val positions = mutableListOf() + val orbitalPeriod = 24 * 60 / satellite.params.meanmo + val endDate = Date(refDate.time + (orbitalPeriod * orbits * 60L * 1000L).toLong()) + val startDate = Date(refDate.time - minBefore * 60L * 1000L) + var currentDate = startDate + while (currentDate.before(endDate)) { + val satPos = satellite.getPosition(stationPos, currentDate.time) + positions.add(satPos) + currentDate = Date(currentDate.time + stepSec * 1000) + } + return positions + } + + // List view - passes + private val _passes = MutableSharedFlow>(replay = 1) + private var selectedSatellites = emptyList() + val passes: SharedFlow> = _passes + + suspend fun triggerCalculation( + satellites: List, + stationPos: StationPos, + refDate: Date = Date(), + hoursAhead: Int = 8 + ) { + if (satellites.isEmpty()) { + _passes.emit(emptyList()) + } else { + val oldCatNums = selectedSatellites.map { it.params.catnum } + val newCatNums = satellites.map { it.params.catnum } + if (oldCatNums != newCatNums) forceCalculation( + satellites, + stationPos, + refDate, + hoursAhead + ) + } + } + + suspend fun forceCalculation( + satellites: List, + stationPos: StationPos, + refDate: Date = Date(), + hoursAhead: Int = 8 + ) { + if (satellites.isEmpty()) { + _passes.emit(emptyList()) + } else { + withContext(defaultDispatcher) { + val allPasses = mutableListOf() + selectedSatellites = satellites + satellites.forEach { satellite -> + val passes = getPasses(satellite, stationPos, refDate, hoursAhead) + allPasses.addAll(passes) + } + _passes.emit(filterPasses(allPasses, refDate)) + } + } + } + + private fun getPasses( + satellite: Satellite, + stationPos: StationPos, + date: Date, + hoursAhead: Int + ): List { + val passes = mutableListOf() + val endDate = Date(date.time + hoursAhead * 60L * 60L * 1000L) + val quarterOrbitMin = satellite.getQuarterOrbitMin() + var startDate = date + var shouldWindBack = true + var lastAosDate: Date + var count = 0 + if (satellite.willBeSeen(stationPos)) { + if (satellite.params.isDeepspace) { + passes.add(nextDeepSpacePass(satellite, stationPos, date)) + } else { + do { + if (count > 0) shouldWindBack = false + val pass = nextNearEarthPass(satellite, stationPos, startDate, shouldWindBack) + lastAosDate = Date(pass.aosTime) + passes.add(pass) + startDate = Date(pass.losTime + (quarterOrbitMin * 3) * 60L * 1000L) + count++ + } while (lastAosDate < endDate) + } + } + return passes + } + + private fun filterPasses( + passes: List, + refDate: Date, + hoursAhead: Int = 8, + minElevation: Double = 16.0 + ): List { + val timeFuture = refDate.time + (hoursAhead * 3600 * 1000) + return passes.filter { it.losTime > refDate.time } + .filter { it.aosTime < timeFuture } + .filter { it.maxElevation > minElevation } + .sortedBy { it.aosTime } + } + + private fun nextDeepSpacePass( + satellite: Satellite, + stationPos: StationPos, + refDate: Date + ): SatPass { + val satPos = satellite.getPosition(stationPos, refDate.time) + val aos = Date(refDate.time - 24 * 60L * 60L * 1000L).time + val los = Date(refDate.time + 24 * 60L * 60L * 1000L).time + val tca = Date((aos + los) / 2).time + val az = Math.toDegrees(satPos.azimuth) + val elev = Math.toDegrees(satPos.elevation) + val alt = satPos.altitude + return SatPass(aos, az, los, az, tca, az, alt, elev, satellite) + } + + private fun nextNearEarthPass( + satellite: Satellite, + stationPos: StationPos, + refDate: Date, + windBack: Boolean = false + ): SatPass { + val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply { + clear() + timeInMillis = refDate.time + } + val quarterOrbitMin = satellite.getQuarterOrbitMin() + + var elevation: Double + var maxElevation = 0.0 + var alt = 0.0 + var tcaAz = 0.0 + + // wind back time 1/4 of an orbit + if (windBack) calendar.add(Calendar.MINUTE, -quarterOrbitMin) + var satPos = satellite.getPosition(stationPos, calendar.time.time) + + if (satPos.elevation > 0.0) { + // move forward in 30 second intervals until the sat goes below the horizon + do { + calendar.add(Calendar.SECOND, 30) + satPos = satellite.getPosition(stationPos, calendar.time.time) + } while (satPos.elevation > 0.0) + // move forward 3/4 of an orbit + calendar.add(Calendar.MINUTE, quarterOrbitMin * 3) + } + + // find the next time sat comes above the horizon + do { + calendar.add(Calendar.SECOND, 60) + satPos = satellite.getPosition(stationPos, calendar.time.time) + elevation = satPos.elevation + if (elevation > maxElevation) { + maxElevation = elevation + alt = satPos.altitude + tcaAz = Math.toDegrees(satPos.azimuth) + } + } while (satPos.elevation < 0.0) + + // refine to 3 seconds + calendar.add(Calendar.SECOND, -60) + do { + calendar.add(Calendar.SECOND, 3) + satPos = satellite.getPosition(stationPos, calendar.time.time) + elevation = satPos.elevation + if (elevation > maxElevation) { + maxElevation = elevation + alt = satPos.altitude + tcaAz = Math.toDegrees(satPos.azimuth) + } + } while (satPos.elevation < 0.0) + + val aos = satPos.time + val aosAz = Math.toDegrees(satPos.azimuth) + + // find when sat goes below + do { + calendar.add(Calendar.SECOND, 30) + satPos = satellite.getPosition(stationPos, calendar.time.time) + elevation = satPos.elevation + if (elevation > maxElevation) { + maxElevation = elevation + alt = satPos.altitude + tcaAz = Math.toDegrees(satPos.azimuth) + } + } while (satPos.elevation > 0.0) + + // refine to 3 seconds + calendar.add(Calendar.SECOND, -30) + do { + calendar.add(Calendar.SECOND, 3) + satPos = satellite.getPosition(stationPos, calendar.time.time) + elevation = satPos.elevation + if (elevation > maxElevation) { + maxElevation = elevation + alt = satPos.altitude + tcaAz = Math.toDegrees(satPos.azimuth) + } + } while (satPos.elevation > 0.0) + + val los = satPos.time + val losAz = Math.toDegrees(satPos.azimuth) + val tca = Date((aos + los) / 2).time + val elev = Math.toDegrees(maxElevation) + return SatPass(aos, aosAz, los, losAz, tca, tcaAz, alt, elev, satellite) + } +} diff --git a/core/src/main/java/com/rtbishop/look4sat/data/PreferencesSource.kt b/core/src/main/java/com/rtbishop/look4sat/data/PreferencesSource.kt index 3215bed8..d4360a6e 100644 --- a/core/src/main/java/com/rtbishop/look4sat/data/PreferencesSource.kt +++ b/core/src/main/java/com/rtbishop/look4sat/data/PreferencesSource.kt @@ -17,7 +17,7 @@ */ package com.rtbishop.look4sat.data -import com.rtbishop.look4sat.domain.predict4kotlin.StationPos +import com.rtbishop.look4sat.domain.StationPos interface PreferencesSource { diff --git a/core/src/main/java/com/rtbishop/look4sat/data/SatDataRemoteSource.kt b/core/src/main/java/com/rtbishop/look4sat/data/RemoteDataSource.kt similarity index 92% rename from core/src/main/java/com/rtbishop/look4sat/data/SatDataRemoteSource.kt rename to core/src/main/java/com/rtbishop/look4sat/data/RemoteDataSource.kt index c015aa15..a1a2164f 100644 --- a/core/src/main/java/com/rtbishop/look4sat/data/SatDataRemoteSource.kt +++ b/core/src/main/java/com/rtbishop/look4sat/data/RemoteDataSource.kt @@ -17,10 +17,10 @@ */ package com.rtbishop.look4sat.data -import com.rtbishop.look4sat.domain.model.SatTrans +import com.rtbishop.look4sat.domain.SatTrans import java.io.InputStream -interface SatDataRemoteSource { +interface RemoteDataSource { suspend fun fetchDataStream(url: String): InputStream? diff --git a/core/src/main/java/com/rtbishop/look4sat/data/SatPassRepository.kt b/core/src/main/java/com/rtbishop/look4sat/data/SatPassRepository.kt deleted file mode 100644 index 8f25f6f2..00000000 --- a/core/src/main/java/com/rtbishop/look4sat/data/SatPassRepository.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 - -import com.rtbishop.look4sat.domain.predict4kotlin.SatPass -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.withContext -import java.util.* - -class SatPassRepository( - private val preferencesSource: PreferencesSource, - private val defaultDispatcher: CoroutineDispatcher -) { - private val _passes = MutableSharedFlow>(replay = 1) - private var selectedSatellites = emptyList() - val passes: SharedFlow> = _passes - - suspend fun triggerCalculation(satellites: List, refDate: Date = Date()) { - if (satellites.isEmpty()) { - _passes.emit(emptyList()) - } else { - val oldCatNums = selectedSatellites.map { it.params.catnum } - val newCatNums = satellites.map { it.params.catnum } - if (oldCatNums != newCatNums) forceCalculation(satellites, refDate) - } - } - - suspend fun forceCalculation(satellites: List, refDate: Date = Date()) { - if (satellites.isEmpty()) { - _passes.emit(emptyList()) - } else { - withContext(defaultDispatcher) { - val allPasses = mutableListOf() - selectedSatellites = satellites - satellites.forEach { satellite -> allPasses.addAll(getPasses(satellite, refDate)) } - _passes.emit(filterPasses(allPasses, refDate)) - } - } - } - - private fun getPasses(satellite: Satellite, refDate: Date): List { - val predictor = satellite.getPredictor(preferencesSource.loadStationPosition()) - return predictor.getPasses(refDate, preferencesSource.getHoursAhead(), true) - } - - private fun filterPasses(passes: List, refDate: Date): List { - val timeFuture = refDate.time + (preferencesSource.getHoursAhead() * 3600 * 1000) - return passes.filter { it.losTime > refDate.time } - .filter { it.aosTime < timeFuture } - .filter { it.maxElevation > preferencesSource.getMinElevation() } - .sortedBy { it.aosTime } - } -} diff --git a/core/src/main/java/com/rtbishop/look4sat/data/SatPredictor.kt b/core/src/main/java/com/rtbishop/look4sat/data/SatPredictor.kt deleted file mode 100644 index 7e945894..00000000 --- a/core/src/main/java/com/rtbishop/look4sat/data/SatPredictor.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.rtbishop.look4sat.data - -import com.rtbishop.look4sat.domain.predict4kotlin.* -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.withContext -import java.util.* - -class SatPredictor( - private val preferencesSource: PreferencesSource, - private val defaultDispatcher: CoroutineDispatcher -) { - // Multi Sat passes - private val _passes = MutableSharedFlow>(replay = 1) - private var selectedSatellites = emptyList() - val passes: SharedFlow> = _passes - - suspend fun triggerCalculation(satellites: List, refDate: Date = Date()) { - if (satellites.isEmpty()) { - _passes.emit(emptyList()) - } else { - val oldCatNums = selectedSatellites.map { it.params.catnum } - val newCatNums = satellites.map { it.params.catnum } - if (oldCatNums != newCatNums) forceCalculation(satellites, refDate) - } - } - - suspend fun forceCalculation(satellites: List, refDate: Date = Date()) { - if (satellites.isEmpty()) { - _passes.emit(emptyList()) - } else { - withContext(defaultDispatcher) { - val allPasses = mutableListOf() - selectedSatellites = satellites - satellites.forEach { satellite -> allPasses.addAll(getPasses(satellite, refDate)) } - _passes.emit(filterPasses(allPasses, refDate)) - } - } - } - - private fun getPasses(satellite: Satellite, refDate: Date): List { - val predictor = satellite.getPredictor(preferencesSource.loadStationPosition()) - return predictor.getPasses(refDate, preferencesSource.getHoursAhead(), true) - } - - private fun filterPasses(passes: List, refDate: Date): List { - val timeFuture = refDate.time + (preferencesSource.getHoursAhead() * 3600 * 1000) - return passes.filter { it.losTime > refDate.time } - .filter { it.aosTime < timeFuture } - .filter { it.maxElevation > preferencesSource.getMinElevation() } - .sortedBy { it.aosTime } - } - - // Single Sat radar - - // Constant calculation of beacon Az/El point - private val _beaconPoint = MutableSharedFlow(replay = 1) - val beaconPoint: SharedFlow = _beaconPoint - - suspend fun calculateSatBeacon(satPass: SatPass, stationPos: StationPos, date: Date) { - withContext(defaultDispatcher) { - val satPos = satPass.satellite.getPosition(stationPos, date) - _beaconPoint.emit(SkyPos(satPos.azimuth, satPos.elevation)) - } - } - - // Single calculation of beacon Az/El points list - private val _trajectoryPoints = MutableSharedFlow>(replay = 1) - val trajectoryPoints: SharedFlow> = _trajectoryPoints - - suspend fun calculateSatTrajectory(satPass: SatPass, stationPos: StationPos) { - withContext(defaultDispatcher) { - val trajectoryPoints = mutableListOf() - var currentTime = satPass.aosTime - while (currentTime < satPass.losTime) { - val satPos = satPass.satellite.getPosition(stationPos, Date(currentTime)) - trajectoryPoints.add(SkyPos(satPos.azimuth, satPos.elevation)) - currentTime += 15000 - } - _trajectoryPoints.emit(trajectoryPoints) - } - } - - // Multi Sat map -} \ No newline at end of file diff --git a/core/src/main/java/com/rtbishop/look4sat/data/SatDataRepository.kt b/core/src/main/java/com/rtbishop/look4sat/data/SatelliteRepo.kt similarity index 73% rename from core/src/main/java/com/rtbishop/look4sat/data/SatDataRepository.kt rename to core/src/main/java/com/rtbishop/look4sat/data/SatelliteRepo.kt index 6bebe70e..2f4c35a8 100644 --- a/core/src/main/java/com/rtbishop/look4sat/data/SatDataRepository.kt +++ b/core/src/main/java/com/rtbishop/look4sat/data/SatelliteRepo.kt @@ -17,11 +17,11 @@ */ package com.rtbishop.look4sat.data -import com.rtbishop.look4sat.domain.model.SatEntry -import com.rtbishop.look4sat.domain.model.SatItem -import com.rtbishop.look4sat.domain.model.SatTrans -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite -import com.rtbishop.look4sat.domain.predict4kotlin.TLE +import com.rtbishop.look4sat.domain.SatEntry +import com.rtbishop.look4sat.domain.SatItem +import com.rtbishop.look4sat.domain.SatTrans +import com.rtbishop.look4sat.domain.Satellite +import com.rtbishop.look4sat.domain.TLE import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow @@ -30,10 +30,10 @@ import kotlinx.coroutines.withContext import java.io.InputStream import java.util.zip.ZipInputStream -class SatDataRepository( +class SatelliteRepo( private val preferencesSource: PreferencesSource, - private val satLocalSource: SatDataLocalSource, - private val satRemoteSource: SatDataRemoteSource, + private val localDataSource: LocalDataSource, + private val remoteDataSource: RemoteDataSource, private val ioDispatcher: CoroutineDispatcher ) { @@ -46,19 +46,19 @@ class SatDataRepository( } fun getSatItems(): Flow> { - return satLocalSource.getSatItems() + return localDataSource.getSatItems() } fun getSatTransmitters(catNum: Int): Flow> { - return satLocalSource.getSatTransmitters(catNum) + return localDataSource.getSatTransmitters(catNum) } suspend fun getSelectedSatellites(): List { - return satLocalSource.getSelectedSatellites() + return localDataSource.getSelectedSatellites() } suspend fun updateEntriesFromFile(stream: InputStream) = withContext(ioDispatcher) { - satLocalSource.updateEntries(importSatEntries(stream)) + localDataSource.updateEntries(importSatEntries(stream)) } suspend fun updateEntriesFromWeb(sources: List) { @@ -67,7 +67,7 @@ class SatDataRepository( val streams = mutableListOf() val entries = mutableListOf() sources.forEach { source -> - satRemoteSource.fetchDataStream(source)?.let { stream -> + remoteDataSource.fetchDataStream(source)?.let { stream -> if (source.contains(".zip", true)) { val zipStream = ZipInputStream(stream).apply { nextEntry } streams.add(zipStream) @@ -77,17 +77,17 @@ class SatDataRepository( } } streams.forEach { stream -> entries.addAll(importSatEntries(stream)) } - satLocalSource.updateEntries(entries) + localDataSource.updateEntries(entries) } launch(ioDispatcher) { - val transmitters = satRemoteSource.fetchTransmitters().filter { it.isAlive } - satLocalSource.updateTransmitters(transmitters) + val transmitters = remoteDataSource.fetchTransmitters().filter { it.isAlive } + localDataSource.updateTransmitters(transmitters) } } } suspend fun updateEntriesSelection(catNums: List, isSelected: Boolean) { - satLocalSource.updateEntriesSelection(catNums, isSelected) + localDataSource.updateEntriesSelection(catNums, isSelected) } private fun importSatEntries(stream: InputStream): List { diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/DeepSpaceSat.kt b/core/src/main/java/com/rtbishop/look4sat/domain/DeepSpaceSat.kt similarity index 99% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/DeepSpaceSat.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/DeepSpaceSat.kt index 820d67c0..87431a8b 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/DeepSpaceSat.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/DeepSpaceSat.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain import kotlin.math.* diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/GeoPos.kt b/core/src/main/java/com/rtbishop/look4sat/domain/GeoPos.kt similarity index 94% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/GeoPos.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/GeoPos.kt index 24d4bf13..63d95bdb 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/GeoPos.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/GeoPos.kt @@ -15,6 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain data class GeoPos(val latitude: Double, val longitude: Double) diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/NearEarthSat.kt b/core/src/main/java/com/rtbishop/look4sat/domain/NearEarthSat.kt similarity index 99% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/NearEarthSat.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/NearEarthSat.kt index 6d59231b..8bf5dd57 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/NearEarthSat.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/NearEarthSat.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain import kotlin.math.* diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/QthConverter.kt b/core/src/main/java/com/rtbishop/look4sat/domain/QthConverter.kt similarity index 97% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/QthConverter.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/QthConverter.kt index b279a810..80aacccd 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/QthConverter.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/QthConverter.kt @@ -15,11 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain import kotlin.math.round -class QthConverter { +object QthConverter { fun qthToPosition(qthString: String): GeoPos? { val trimmedQth = qthString.take(6) diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/model/SatData.kt b/core/src/main/java/com/rtbishop/look4sat/domain/SatData.kt similarity index 85% rename from app/src/main/java/com/rtbishop/look4sat/framework/model/SatData.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/SatData.kt index bb950034..c6c7d972 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/model/SatData.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/SatData.kt @@ -15,10 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.framework.model - -import com.rtbishop.look4sat.domain.predict4kotlin.GeoPos -import com.rtbishop.look4sat.domain.predict4kotlin.Satellite +package com.rtbishop.look4sat.domain data class SatData( val pass: Satellite, diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt b/core/src/main/java/com/rtbishop/look4sat/domain/SatEntry.kt similarity index 90% rename from core/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/SatEntry.kt index cf47dfe6..4cb6f6ab 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/SatEntry.kt @@ -15,9 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.model - -import com.rtbishop.look4sat.domain.predict4kotlin.TLE +package com.rtbishop.look4sat.domain data class SatEntry( val tle: TLE, diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt b/core/src/main/java/com/rtbishop/look4sat/domain/SatItem.kt similarity index 95% rename from core/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/SatItem.kt index cd6ca592..ae3d8e9b 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/SatItem.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.model +package com.rtbishop.look4sat.domain data class SatItem( val catNum: Int, diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SatPass.kt b/core/src/main/java/com/rtbishop/look4sat/domain/SatPass.kt similarity index 91% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SatPass.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/SatPass.kt index b0b037bd..e7295bd8 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SatPass.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/SatPass.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain data class SatPass( val aosTime: Long, @@ -26,8 +26,7 @@ data class SatPass( val tcaAzimuth: Double, val altitude: Double, val maxElevation: Double, - val satellite: Satellite, - val predictor: PassPredictor, + val satellite: Satellite ) { val catNum: Int = satellite.params.catnum val name: String = satellite.params.name diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SatPos.kt b/core/src/main/java/com/rtbishop/look4sat/domain/SatPos.kt similarity index 96% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SatPos.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/SatPos.kt index 5195c061..0969f65c 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SatPos.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/SatPos.kt @@ -15,9 +15,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain -import java.util.* import kotlin.math.* data class SatPos( @@ -29,7 +28,7 @@ data class SatPos( var range: Double = 0.0, var rangeRate: Double = 0.0, var theta: Double = 0.0, - var time: Date = Date() + var time: Long = 0L ) { private val earthRadiusKm = 6378.16 private val speedOfLight = 2.99792458E8 diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatTrans.kt b/core/src/main/java/com/rtbishop/look4sat/domain/SatTrans.kt similarity index 95% rename from core/src/main/java/com/rtbishop/look4sat/domain/model/SatTrans.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/SatTrans.kt index b664fa02..f85d510e 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatTrans.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/SatTrans.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.model +package com.rtbishop.look4sat.domain data class SatTrans( val uuid: String, diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/Satellite.kt b/core/src/main/java/com/rtbishop/look4sat/domain/Satellite.kt similarity index 97% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/Satellite.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/Satellite.kt index a2792409..fc4ec662 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/Satellite.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/Satellite.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain import java.util.* import java.util.concurrent.atomic.AtomicReference @@ -41,6 +41,10 @@ abstract class Satellite(val params: TLE) { var s4 = 0.0 val xke = 7.43669161E-2 + fun getQuarterOrbitMin(): Int { + return (24.0 * 60.0 / params.meanmo / 4.0).toInt() + } + fun willBeSeen(pos: StationPos): Boolean { return if (params.meanmo < 1e-8) false else { var lin = params.incl @@ -51,11 +55,7 @@ abstract class Satellite(val params: TLE) { } } - fun getPredictor(pos: StationPos): PassPredictor { - return PassPredictor(this, pos) - } - - fun getPosition(pos: StationPos, time: Date): SatPos { + fun getPosition(pos: StationPos, time: Long): SatPos { val satPos = SatPos() // Date/time at which the position and velocity were calculated val julUTC = calcCurrentDaynum(time) + 2444238.5 @@ -76,8 +76,7 @@ abstract class Satellite(val params: TLE) { } // Read the system clock and return the number of days since 31Dec79 00:00:00 UTC (daynum 0) - private fun calcCurrentDaynum(date: Date): Double { - val now = date.time + private fun calcCurrentDaynum(now: Long): Double { val sgp4Epoch = Calendar.getInstance(TimeZone.getTimeZone("UTC:UTC")) sgp4Epoch.clear() sgp4Epoch[1979, 11, 31, 0, 0] = 0 diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/StationPos.kt b/core/src/main/java/com/rtbishop/look4sat/domain/StationPos.kt similarity index 94% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/StationPos.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/StationPos.kt index 184deeba..9c0e4e92 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/StationPos.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/StationPos.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain data class StationPos( val latitude: Double, diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/TLE.kt b/core/src/main/java/com/rtbishop/look4sat/domain/TLE.kt similarity index 98% rename from core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/TLE.kt rename to core/src/main/java/com/rtbishop/look4sat/domain/TLE.kt index 3ed9827e..317d20e0 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/TLE.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/TLE.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict4kotlin +package com.rtbishop.look4sat.domain import java.io.InputStream import kotlin.math.pow diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/PassPredictor.kt b/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/PassPredictor.kt deleted file mode 100644 index 487876b1..00000000 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/PassPredictor.kt +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.domain.predict4kotlin - -import java.util.* - -class PassPredictor(private val satellite: Satellite, private val stationPos: StationPos) { - - private val oneQuarterOrbitMin = (24.0 * 60.0 / satellite.params.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(stationPos, date) - } - - fun getPositions(refDate: Date, stepSec: Int, minBefore: Int, orbits: Double): List { - val positions = mutableListOf() - val orbitalPeriod = 24 * 60 / satellite.params.meanmo - val endDate = Date(refDate.time + (orbitalPeriod * orbits * 60L * 1000L).toLong()) - val startDate = Date(refDate.time - minBefore * 60L * 1000L) - var currentDate = startDate - while (currentDate.before(endDate)) { - positions.add(getSatPos(currentDate)) - currentDate = Date(currentDate.time + stepSec * 1000) - } - return positions - } - - fun getPasses(refDate: Date, hoursAhead: Int, windBack: Boolean): List { - val passes = mutableListOf() - val endDate = Date(refDate.time + hoursAhead * 60L * 60L * 1000L) - var startDate = refDate - var shouldWindBack = windBack - var lastAosDate: Date - var count = 0 - if (satellite.willBeSeen(stationPos)) { - if (satellite.params.isDeepspace) { - passes.add(nextDeepSpacePass(refDate)) - } else { - do { - if (count > 0) shouldWindBack = false - val pass = nextNearEarthPass(startDate, shouldWindBack) - lastAosDate = Date(pass.aosTime) - passes.add(pass) - startDate = Date(pass.losTime + (oneQuarterOrbitMin * 3) * 60L * 1000L) - count++ - } while (lastAosDate < endDate) - } - } - return passes - } - - private fun nextDeepSpacePass(refDate: Date): SatPass { - val satPos = getSatPos(refDate) - val aos = Date(refDate.time - 24 * 60L * 60L * 1000L).time - val los = Date(refDate.time + 24 * 60L * 60L * 1000L).time - val tca = Date((aos + los) / 2).time - val az = Math.toDegrees(satPos.azimuth) - val elev = Math.toDegrees(satPos.elevation) - val alt = satPos.altitude - return SatPass(aos, az, los, az, tca, az, alt, elev, satellite, this) - } - - private fun nextNearEarthPass(refDate: Date, windBack: Boolean = false): SatPass { - val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply { - clear() - timeInMillis = refDate.time - } - - var elevation: Double - var maxElevation = 0.0 - var alt = 0.0 - var tcaAz = 0.0 - - // wind back time 1/4 of an orbit - if (windBack) calendar.add(Calendar.MINUTE, -oneQuarterOrbitMin) - var satPos = getSatPos(calendar.time) - - if (satPos.elevation > 0.0) { - // move forward in 30 second intervals until the sat goes below the horizon - do { - calendar.add(Calendar.SECOND, 30) - satPos = getSatPos(calendar.time) - } while (satPos.elevation > 0.0) - // move forward 3/4 of an orbit - calendar.add(Calendar.MINUTE, oneQuarterOrbitMin * 3) - } - - // find the next time sat comes above the horizon - do { - calendar.add(Calendar.SECOND, 60) - satPos = getSatPos(calendar.time) - elevation = satPos.elevation - if (elevation > maxElevation) { - maxElevation = elevation - alt = satPos.altitude - tcaAz = Math.toDegrees(satPos.azimuth) - } - } while (satPos.elevation < 0.0) - - // refine to 3 seconds - calendar.add(Calendar.SECOND, -60) - do { - calendar.add(Calendar.SECOND, 3) - satPos = getSatPos(calendar.time) - elevation = satPos.elevation - if (elevation > maxElevation) { - maxElevation = elevation - alt = satPos.altitude - tcaAz = Math.toDegrees(satPos.azimuth) - } - } while (satPos.elevation < 0.0) - - val aos = satPos.time.time - val aosAz = Math.toDegrees(satPos.azimuth) - - // find when sat goes below - do { - calendar.add(Calendar.SECOND, 30) - satPos = getSatPos(calendar.time) - elevation = satPos.elevation - if (elevation > maxElevation) { - maxElevation = elevation - alt = satPos.altitude - tcaAz = Math.toDegrees(satPos.azimuth) - } - } while (satPos.elevation > 0.0) - - // refine to 3 seconds - calendar.add(Calendar.SECOND, -30) - do { - calendar.add(Calendar.SECOND, 3) - satPos = getSatPos(calendar.time) - elevation = satPos.elevation - if (elevation > maxElevation) { - maxElevation = elevation - alt = satPos.altitude - tcaAz = Math.toDegrees(satPos.azimuth) - } - } while (satPos.elevation > 0.0) - - val los = satPos.time.time - val losAz = Math.toDegrees(satPos.azimuth) - val tca = Date((aos + los) / 2).time - val elev = Math.toDegrees(maxElevation) - return SatPass(aos, aosAz, los, losAz, tca, tcaAz, alt, elev, satellite, this) - } -} diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SkyPos.kt b/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SkyPos.kt deleted file mode 100644 index 835d16d0..00000000 --- a/core/src/main/java/com/rtbishop/look4sat/domain/predict4kotlin/SkyPos.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.domain.predict4kotlin - -data class SkyPos(val azimuth: Double, val elevation: Double) diff --git a/core/src/test/java/com/rtbishop/look4sat/Look4SatTest.kt b/core/src/test/java/com/rtbishop/look4sat/Look4SatTest.kt index c490f322..ad22d71d 100644 --- a/core/src/test/java/com/rtbishop/look4sat/Look4SatTest.kt +++ b/core/src/test/java/com/rtbishop/look4sat/Look4SatTest.kt @@ -1,6 +1,6 @@ package com.rtbishop.look4sat -import com.rtbishop.look4sat.domain.predict4kotlin.TLE +import com.rtbishop.look4sat.domain.TLE import org.junit.Test class Look4SatTest { diff --git a/core/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt b/core/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt index 538a6c6c..9667fb7b 100644 --- a/core/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt +++ b/core/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt @@ -17,44 +17,42 @@ */ package com.rtbishop.look4sat -import com.rtbishop.look4sat.domain.predict4kotlin.QthConverter +import com.rtbishop.look4sat.domain.QthConverter import org.junit.Test class QthConverterTest { - private val qthConverter = QthConverter() - @Test fun `Given valid QTH returns correct POS`() { - var result = qthConverter.qthToPosition("io91VL39FX") + var result = QthConverter.qthToPosition("io91VL39FX") assert(result?.latitude == 51.4792 && result.longitude == -0.2083) - result = qthConverter.qthToPosition("JN58TD") + result = QthConverter.qthToPosition("JN58TD") assert(result?.latitude == 48.1458 && result.longitude == 11.6250) - result = qthConverter.qthToPosition("gf15vc") + result = QthConverter.qthToPosition("gf15vc") assert(result?.latitude == -34.8958 && result.longitude == -56.2083) - result = qthConverter.qthToPosition("fm18LW") + result = QthConverter.qthToPosition("fm18LW") assert(result?.latitude == 38.9375 && result.longitude == -77.0417) } @Test fun `Given invalid QTH returns null`() { - var result = qthConverter.qthToPosition("ZZ00zz") + var result = QthConverter.qthToPosition("ZZ00zz") assert(result == null) - result = qthConverter.qthToPosition("JN58tz") + result = QthConverter.qthToPosition("JN58tz") assert(result == null) } @Test fun `Given valid POS returns correct QTH`() { - assert(qthConverter.positionToQTH(51.4878, -0.2146) == "IO91vl") - assert(qthConverter.positionToQTH(48.1466, 11.6083) == "JN58td") - assert(qthConverter.positionToQTH(-34.91, -56.2116) == "GF15vc") - assert(qthConverter.positionToQTH(38.92, -77.065) == "FM18lw") + assert(QthConverter.positionToQTH(51.4878, -0.2146) == "IO91vl") + assert(QthConverter.positionToQTH(48.1466, 11.6083) == "JN58td") + assert(QthConverter.positionToQTH(-34.91, -56.2116) == "GF15vc") + assert(QthConverter.positionToQTH(38.92, -77.065) == "FM18lw") } @Test fun `Given invalid POS returns null`() { - assert(qthConverter.positionToQTH(91.0542, -170.1142) == null) - assert(qthConverter.positionToQTH(89.0542, -240.1142) == null) + assert(QthConverter.positionToQTH(91.0542, -170.1142) == null) + assert(QthConverter.positionToQTH(89.0542, -240.1142) == null) } }