diff --git a/app/build.gradle b/app/build.gradle index a44a13de..48c38e9d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,7 +55,7 @@ android { } dependencies { - implementation project(":data") + implementation project(":base") implementation "androidx.core:core-splashscreen:1.0.0-beta01" implementation "androidx.constraintlayout:constraintlayout:2.1.3" implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1" diff --git a/app/schemas/com.rtbishop.look4sat.framework.data.StorageDb/1.json b/app/schemas/com.rtbishop.look4sat.framework.data.LocalDatabase/1.json similarity index 100% rename from app/schemas/com.rtbishop.look4sat.framework.data.StorageDb/1.json rename to app/schemas/com.rtbishop.look4sat.framework.data.LocalDatabase/1.json diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/LocationHandler.kt b/app/src/main/java/com/rtbishop/look4sat/framework/LocationManager.kt similarity index 93% rename from app/src/main/java/com/rtbishop/look4sat/framework/LocationHandler.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/LocationManager.kt index 7d508471..3658d3e6 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/LocationHandler.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/LocationManager.kt @@ -26,12 +26,12 @@ import android.location.LocationManager import android.os.Bundle import androidx.core.content.ContextCompat import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.domain.ILocationHandler -import com.rtbishop.look4sat.domain.ISettings -import com.rtbishop.look4sat.domain.QthConverter +import com.rtbishop.look4sat.domain.ILocationManager +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.domain.model.DataState import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.domain.round +import com.rtbishop.look4sat.utility.QthConverter +import com.rtbishop.look4sat.utility.round import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -39,12 +39,12 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class LocationHandler @Inject constructor( +class LocationManager @Inject constructor( @ApplicationContext private val context: Context, - private val settings: ISettings, -) : LocationListener, ILocationHandler { + private val manager: LocationManager, + private val settings: ISettingsManager, +) : LocationListener, ILocationManager { - private val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager private val providerDef = LocationManager.PASSIVE_PROVIDER private val providerNet = LocationManager.NETWORK_PROVIDER private val providerGps = LocationManager.GPS_PROVIDER diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/OrientationHandler.kt b/app/src/main/java/com/rtbishop/look4sat/framework/OrientationManager.kt similarity index 90% rename from app/src/main/java/com/rtbishop/look4sat/framework/OrientationHandler.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/OrientationManager.kt index c3a7368c..ab2b2143 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/OrientationHandler.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/OrientationManager.kt @@ -21,12 +21,13 @@ import android.hardware.Sensor import android.hardware.SensorEvent import android.hardware.SensorEventListener import android.hardware.SensorManager +import com.rtbishop.look4sat.domain.predict.RAD2DEG import javax.inject.Inject import javax.inject.Singleton import kotlin.math.round @Singleton -class OrientationHandler @Inject constructor(private val sensorManager: SensorManager) : +class OrientationManager @Inject constructor(private val sensorManager: SensorManager) : SensorEventListener { interface OrientationListener { @@ -36,7 +37,6 @@ class OrientationHandler @Inject constructor(private val sensorManager: SensorMa private val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) private val rotationMatrix = FloatArray(9) private val orientationValues = FloatArray(3) - private val oneRadDegrees = 57.295779513f private var sensorAccuracy: Int = SensorManager.SENSOR_STATUS_UNRELIABLE private var orientationListener: OrientationListener? = null @@ -67,9 +67,9 @@ class OrientationHandler @Inject constructor(private val sensorManager: SensorMa private fun updateOrientation(rotationVector: FloatArray) { SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVector) SensorManager.getOrientation(rotationMatrix, orientationValues) - val azimuth = orientationValues[0] * oneRadDegrees - val pitch = orientationValues[1] * oneRadDegrees - val roll = orientationValues[2] * oneRadDegrees + val azimuth = (orientationValues[0] * RAD2DEG).toFloat() + val pitch = (orientationValues[1] * RAD2DEG).toFloat() + val roll = (orientationValues[2] * RAD2DEG).toFloat() val magneticAzimuth = (azimuth + 360f) % 360f val roundedAzimuth = round(magneticAzimuth * 10) / 10 val roundedPitch = round(pitch * 10) / 10 diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsHandler.kt b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt similarity index 97% rename from app/src/main/java/com/rtbishop/look4sat/framework/SettingsHandler.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt index d4af3437..ed04678e 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsHandler.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt @@ -19,13 +19,13 @@ package com.rtbishop.look4sat.framework import android.content.SharedPreferences import androidx.core.content.edit -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.domain.predict.GeoPos import javax.inject.Inject import javax.inject.Singleton @Singleton -class SettingsHandler @Inject constructor(private val prefs: SharedPreferences) : ISettings { +class SettingsManager @Inject constructor(private val prefs: SharedPreferences) : ISettingsManager { companion object { const val keyDataSources = "dataSources" diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/Provider.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/FileDataSource.kt similarity index 77% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/Provider.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/FileDataSource.kt index aaba4089..afa5d73d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/Provider.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/FileDataSource.kt @@ -19,24 +19,18 @@ package com.rtbishop.look4sat.framework.data import android.content.ContentResolver import android.net.Uri -import com.rtbishop.look4sat.data.IProvider +import com.rtbishop.look4sat.domain.data.IFileDataSource import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext import java.io.InputStream -import java.net.URL -class Provider( +class FileDataSource( private val contentResolver: ContentResolver, private val ioDispatcher: CoroutineDispatcher -) : IProvider { +) : IFileDataSource { @Suppress("BlockingMethodInNonBlockingContext") - override suspend fun getLocalFileStream(uri: String): InputStream? { + override suspend fun getDataStream(uri: String): InputStream? { return withContext(ioDispatcher) { contentResolver.openInputStream(Uri.parse(uri)) } } - - @Suppress("BlockingMethodInNonBlockingContext") - override suspend fun getRemoteFileStream(url: String): InputStream? { - return withContext(ioDispatcher) { URL(url).openStream() } - } } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDb.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalDatabase.kt similarity index 87% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDb.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/LocalDatabase.kt index 4bf5c2ee..9bf761e3 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/StorageDb.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalDatabase.kt @@ -19,11 +19,13 @@ package com.rtbishop.look4sat.framework.data import androidx.room.Database import androidx.room.RoomDatabase +import com.rtbishop.look4sat.framework.data.dao.EntriesDao +import com.rtbishop.look4sat.framework.data.dao.RadiosDao import com.rtbishop.look4sat.framework.model.SatEntry import com.rtbishop.look4sat.framework.model.SatRadio @Database(entities = [SatEntry::class, SatRadio::class], version = 1, exportSchema = true) -abstract class StorageDb : RoomDatabase() { +abstract class LocalDatabase : RoomDatabase() { abstract fun entriesDao(): EntriesDao diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/Storage.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalEntrySource.kt similarity index 63% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/Storage.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/LocalEntrySource.kt index c6d17104..61c870b9 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/Storage.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalEntrySource.kt @@ -17,21 +17,18 @@ */ package com.rtbishop.look4sat.framework.data -import com.rtbishop.look4sat.data.IStorage +import com.rtbishop.look4sat.domain.data.ILocalEntrySource import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.framework.data.dao.EntriesDao import com.rtbishop.look4sat.domain.model.SatEntry as DomainEntry import com.rtbishop.look4sat.domain.model.SatItem as DomainItem -import com.rtbishop.look4sat.domain.model.SatRadio as DomainRadio import com.rtbishop.look4sat.framework.model.SatEntry as FrameworkEntry import com.rtbishop.look4sat.framework.model.SatItem as FrameworkItem -import com.rtbishop.look4sat.framework.model.SatRadio as FrameworkRadio -class Storage(private val entriesDao: EntriesDao, private val radiosDao: RadiosDao) : IStorage { +class LocalEntrySource(private val entriesDao: EntriesDao) : ILocalEntrySource { override fun getEntriesTotal() = entriesDao.getEntriesTotal() - override fun getRadiosTotal() = radiosDao.getRadiosTotal() - override suspend fun getEntriesWithModes(): List { return entriesDao.getEntriesWithModes().toDomainItems() } @@ -45,42 +42,17 @@ class Storage(private val entriesDao: EntriesDao, private val radiosDao: RadiosD return selectedSatellites } - override suspend fun getRadiosWithId(id: Int): List { - return radiosDao.getRadiosWithId(id).toDomainRadios() - } - override suspend fun insertEntries(entries: List) { entriesDao.insertEntries(entries.toFrameworkEntries()) } - override suspend fun insertRadios(radios: List) { - radiosDao.insertRadios(radios.toFrameworkRadios()) - } - - override suspend fun clearAllData() { - entriesDao.deleteEntries() - radiosDao.deleteRadios() - } + override suspend fun deleteEntries() = entriesDao.deleteEntries() private fun DomainEntry.toFramework() = FrameworkEntry(this.data, this.comment) - private fun DomainRadio.toFramework() = FrameworkRadio( - this.uuid, this.info, this.isAlive, this.downlink, this.uplink, - this.mode, this.isInverted, this.catnum, this.comment - ) - private fun FrameworkItem.toDomain() = DomainItem(this.catnum, this.name, this.modes, false) - private fun FrameworkRadio.toDomain() = DomainRadio( - this.uuid, this.info, this.isAlive, this.downlink, this.uplink, - this.mode, this.isInverted, this.catnum, this.comment - ) - private fun List.toFrameworkEntries() = this.map { entry -> entry.toFramework() } - private fun List.toFrameworkRadios() = this.map { radio -> radio.toFramework() } - private fun List.toDomainItems() = this.map { item -> item.toDomain() } - - private fun List.toDomainRadios() = this.map { radio -> radio.toDomain() } } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalRadioSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalRadioSource.kt new file mode 100644 index 00000000..904fe9da --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalRadioSource.kt @@ -0,0 +1,52 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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.framework.data + +import com.rtbishop.look4sat.domain.data.ILocalRadioSource +import com.rtbishop.look4sat.framework.data.dao.RadiosDao +import com.rtbishop.look4sat.domain.model.SatRadio as DomainRadio +import com.rtbishop.look4sat.framework.model.SatRadio as FrameworkRadio + +class LocalRadioSource(private val radiosDao: RadiosDao) : ILocalRadioSource { + + override fun getRadiosTotal() = radiosDao.getRadiosTotal() + + override suspend fun getRadiosWithId(id: Int): List { + return radiosDao.getRadiosWithId(id).toDomainRadios() + } + + override suspend fun insertRadios(radios: List) { + radiosDao.insertRadios(radios.toFrameworkRadios()) + } + + override suspend fun deleteRadios() = radiosDao.deleteRadios() + + private fun DomainRadio.toFramework() = FrameworkRadio( + this.uuid, this.info, this.isAlive, this.downlink, this.uplink, + this.mode, this.isInverted, this.catnum, this.comment + ) + + private fun FrameworkRadio.toDomain() = DomainRadio( + this.uuid, this.info, this.isAlive, this.downlink, this.uplink, + this.mode, this.isInverted, this.catnum, this.comment + ) + + private fun List.toFrameworkRadios() = this.map { radio -> radio.toFramework() } + + private fun List.toDomainRadios() = this.map { radio -> radio.toDomain() } +} diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/RemoteDataSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/RemoteDataSource.kt new file mode 100644 index 00000000..100293e3 --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/RemoteDataSource.kt @@ -0,0 +1,32 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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.framework.data + +import com.rtbishop.look4sat.domain.data.IRemoteDataSource +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.withContext +import java.io.InputStream +import java.net.URL + +class RemoteDataSource(private val ioDispatcher: CoroutineDispatcher) : IRemoteDataSource { + + @Suppress("BlockingMethodInNonBlockingContext") + override suspend fun getDataStream(url: String): InputStream? = withContext(ioDispatcher) { + URL(url).openStream() + } +} diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/EntriesDao.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/dao/EntriesDao.kt similarity index 96% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/EntriesDao.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/dao/EntriesDao.kt index ecff8711..ef4d972e 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/EntriesDao.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/dao/EntriesDao.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.framework.data +package com.rtbishop.look4sat.framework.data.dao import androidx.room.* import com.rtbishop.look4sat.framework.model.SatEntry diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/RadiosDao.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/dao/RadiosDao.kt similarity index 96% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/RadiosDao.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/dao/RadiosDao.kt index 3e0d42ae..b152ca42 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/RadiosDao.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/dao/RadiosDao.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.framework.data +package com.rtbishop.look4sat.framework.data.dao import androidx.room.* import com.rtbishop.look4sat.framework.model.SatRadio diff --git a/app/src/main/java/com/rtbishop/look4sat/injection/AppModule.kt b/app/src/main/java/com/rtbishop/look4sat/injection/AppModule.kt index f93d43f4..1f4eeb47 100644 --- a/app/src/main/java/com/rtbishop/look4sat/injection/AppModule.kt +++ b/app/src/main/java/com/rtbishop/look4sat/injection/AppModule.kt @@ -17,7 +17,6 @@ */ package com.rtbishop.look4sat.injection -import android.content.ContentResolver import android.content.Context import android.content.SharedPreferences import android.hardware.SensorManager @@ -27,21 +26,12 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import javax.inject.Qualifier import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) object AppModule { - @Provides - @Singleton - fun provideContentResolver(@ApplicationContext context: Context): ContentResolver { - return context.contentResolver - } - @Provides @Singleton fun provideLocationManager(@ApplicationContext context: Context): LocationManager { @@ -59,20 +49,4 @@ object AppModule { fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences { return context.getSharedPreferences("default", Context.MODE_PRIVATE) } - - @Provides - @DefaultDispatcher - fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default - - @Provides - @IoDispatcher - fun provideIoDispatcher(): CoroutineDispatcher = Dispatchers.IO } - -@Qualifier -@Retention(AnnotationRetention.BINARY) -annotation class DefaultDispatcher - -@Qualifier -@Retention(AnnotationRetention.BINARY) -annotation class IoDispatcher diff --git a/app/src/main/java/com/rtbishop/look4sat/injection/BaseModule.kt b/app/src/main/java/com/rtbishop/look4sat/injection/BaseModule.kt new file mode 100644 index 00000000..d1caffc8 --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/injection/BaseModule.kt @@ -0,0 +1,76 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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.injection + +import android.content.Context +import androidx.room.Room +import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ILocationManager +import com.rtbishop.look4sat.domain.ISatelliteManager +import com.rtbishop.look4sat.domain.ISettingsManager +import com.rtbishop.look4sat.domain.data.DataRepository +import com.rtbishop.look4sat.domain.predict.SatelliteManager +import com.rtbishop.look4sat.framework.LocationManager +import com.rtbishop.look4sat.framework.SettingsManager +import com.rtbishop.look4sat.framework.data.* +import com.rtbishop.look4sat.utility.DataParser +import com.rtbishop.look4sat.utility.DataReporter +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object BaseModule { + + @Provides + @Singleton + fun provideDataRepository(@ApplicationContext context: Context): IDataRepository { + val db = Room.databaseBuilder(context, LocalDatabase::class.java, "Look4SatDb") + .fallbackToDestructiveMigration().build() + val parser = DataParser(Dispatchers.Default) + val fileSource = FileDataSource(context.contentResolver, Dispatchers.IO) + val entries = LocalEntrySource(db.entriesDao()) + val radios = LocalRadioSource(db.radiosDao()) + val remoteSource = RemoteDataSource(Dispatchers.IO) + val repositoryScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + return DataRepository(parser, fileSource, entries, radios, remoteSource, repositoryScope) + } + + @Provides + @Singleton + fun provideDataReporter(): DataReporter = DataReporter(CoroutineScope(Dispatchers.IO)) + + @Provides + @Singleton + fun provideLocationManager(manager: LocationManager): ILocationManager = manager + + @Provides + @Singleton + fun provideSatelliteManager(): ISatelliteManager = SatelliteManager(Dispatchers.Default) + + @Provides + @Singleton + fun provideSettingsManager(manager: SettingsManager): ISettingsManager = manager +} diff --git a/app/src/main/java/com/rtbishop/look4sat/injection/DataModule.kt b/app/src/main/java/com/rtbishop/look4sat/injection/DataModule.kt deleted file mode 100644 index 0fa812e9..00000000 --- a/app/src/main/java/com/rtbishop/look4sat/injection/DataModule.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Look4Sat. Amateur radio satellite tracker and pass predictor. - * Copyright (C) 2019-2022 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.injection - -import android.content.Context -import android.content.SharedPreferences -import androidx.room.Room -import com.rtbishop.look4sat.data.DataParser -import com.rtbishop.look4sat.data.Repository -import com.rtbishop.look4sat.domain.DataReporter -import com.rtbishop.look4sat.domain.ILocationHandler -import com.rtbishop.look4sat.domain.IRepository -import com.rtbishop.look4sat.domain.ISettings -import com.rtbishop.look4sat.domain.predict.Predictor -import com.rtbishop.look4sat.framework.LocationHandler -import com.rtbishop.look4sat.framework.SettingsHandler -import com.rtbishop.look4sat.framework.data.Provider -import com.rtbishop.look4sat.framework.data.Storage -import com.rtbishop.look4sat.framework.data.StorageDb -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object DataModule { - - @Provides - @Singleton - fun provideSatelliteRepo( - @ApplicationContext context: Context, - @IoDispatcher ioDispatcher: CoroutineDispatcher, - @DefaultDispatcher defaultDispatcher: CoroutineDispatcher - ): IRepository { - val db = Room.databaseBuilder(context, StorageDb::class.java, "Look4SatDb") - .fallbackToDestructiveMigration().build() - val dataParser = DataParser(defaultDispatcher) - val localSource = Storage(db.entriesDao(), db.radiosDao()) - val remoteSource = Provider(context.contentResolver, ioDispatcher) - val repositoryScope = CoroutineScope(SupervisorJob()) - return Repository(dataParser, localSource, remoteSource, repositoryScope) - } - - @Provides - @Singleton - fun provideSettingsHandler(sharedPreferences: SharedPreferences): ISettings { - return SettingsHandler(sharedPreferences) - } - - @Provides - @Singleton - fun provideLocationHandler( - @ApplicationContext context: Context, - settings: ISettings - ): ILocationHandler { - return LocationHandler(context, settings) - } - - @Provides - @Singleton - fun providePredictor(@DefaultDispatcher dispatcher: CoroutineDispatcher): Predictor { - return Predictor(dispatcher) - } - - @Provides - @Singleton - fun provideDataReporter(@IoDispatcher dispatcher: CoroutineDispatcher): DataReporter { - return DataReporter(dispatcher) - } -} diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt index e3090ac7..35c438df 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt @@ -18,8 +18,8 @@ package com.rtbishop.look4sat.presentation.entriesScreen import androidx.lifecycle.* -import com.rtbishop.look4sat.domain.IRepository -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.domain.model.DataState import com.rtbishop.look4sat.domain.model.SatItem import dagger.hilt.android.lifecycle.HiltViewModel @@ -29,8 +29,8 @@ import javax.inject.Inject @HiltViewModel class EntriesViewModel @Inject constructor( - private val repository: IRepository, - private val settings: ISettings + private val repository: IDataRepository, + private val settings: ISettingsManager ) : ViewModel(), EntriesAdapter.EntriesClickListener { private val transModes = MutableLiveData(settings.loadModesSelection()) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt index 6c1c9547..432f66ff 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/ModesDialog.kt @@ -27,7 +27,7 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.SimpleItemAnimator import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.DialogModesBinding -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.presentation.setNavResult import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -36,7 +36,7 @@ import javax.inject.Inject class ModesDialog : AppCompatDialogFragment(), ModesAdapter.ModesClickListener { @Inject - lateinit var preferences: ISettings + lateinit var preferences: ISettingsManager private lateinit var binding: DialogModesBinding private val allModes = listOf( "AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3", diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt index 96d66fdb..2fd4feff 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt @@ -18,13 +18,13 @@ package com.rtbishop.look4sat.presentation.mapScreen import androidx.lifecycle.* -import com.rtbishop.look4sat.domain.IRepository -import com.rtbishop.look4sat.domain.ISettings -import com.rtbishop.look4sat.domain.QthConverter +import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ISatelliteManager +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.domain.predict.Predictor import com.rtbishop.look4sat.domain.predict.SatPos import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.utility.QthConverter import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.* import java.util.* @@ -34,9 +34,9 @@ import kotlin.math.min @HiltViewModel class MapViewModel @Inject constructor( - private val predictor: Predictor, - private val repository: IRepository, - private val settings: ISettings, + private val satelliteManager: ISatelliteManager, + private val repository: IDataRepository, + private val settings: ISettingsManager, ) : ViewModel() { private val stationPosition = settings.loadStationPosition() @@ -115,7 +115,7 @@ class MapViewModel @Inject constructor( val currentTrack = mutableListOf() val endDate = Date(date.time + (satellite.orbitalPeriod * 2.4 * 60000L).toLong()) var oldLongitude = 0.0 - predictor.getSatTrack(satellite, pos, date.time, endDate.time).forEach { satPos -> + satelliteManager.getTrack(satellite, pos, date.time, endDate.time).forEach { satPos -> val osmLat = clipLat(Math.toDegrees(satPos.latitude)) val osmLon = clipLon(Math.toDegrees(satPos.longitude)) val currentPosition = GeoPos(osmLat, osmLon) @@ -142,7 +142,7 @@ class MapViewModel @Inject constructor( private suspend fun getPositions(satellites: List, pos: GeoPos, date: Date) { val positions = mutableMapOf() satellites.forEach { satellite -> - val satPos = predictor.getSatPos(satellite, pos, date.time) + val satPos = satelliteManager.getPosition(satellite, pos, date.time) val osmLat = clipLat(Math.toDegrees(satPos.latitude)) val osmLon = clipLon(Math.toDegrees(satPos.longitude)) positions[satellite] = GeoPos(osmLat, osmLon) @@ -151,12 +151,12 @@ class MapViewModel @Inject constructor( } private suspend fun getSatFootprint(satellite: Satellite, pos: GeoPos, date: Date) { - val satPos = predictor.getSatPos(satellite, pos, date.time) + val satPos = satelliteManager.getPosition(satellite, pos, date.time) _footprint.postValue(satPos) } private suspend fun getSatData(satellite: Satellite, pos: GeoPos, date: Date) { - val satPos = predictor.getSatPos(satellite, pos, date.time) + val satPos = satelliteManager.getPosition(satellite, pos, date.time) val osmLat = clipLat(Math.toDegrees(satPos.latitude)) val osmLon = clipLon(Math.toDegrees(satPos.longitude)) val osmPos = GeoPos(osmLat, osmLon) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/FilterDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/FilterDialog.kt index 4e5136f5..3a389d54 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/FilterDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/FilterDialog.kt @@ -25,7 +25,7 @@ import android.view.WindowManager import androidx.appcompat.app.AppCompatDialogFragment import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.DialogFilterBinding -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.presentation.setNavResult import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -34,7 +34,7 @@ import javax.inject.Inject class FilterDialog : AppCompatDialogFragment() { @Inject - lateinit var preferences: ISettings + lateinit var preferences: ISettingsManager override fun onCreateView(inflater: LayoutInflater, group: ViewGroup?, state: Bundle?): View? { return inflater.inflate(R.layout.dialog_filter, group, false) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt index a1b60aed..4dc3d25f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt @@ -31,8 +31,8 @@ import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.FragmentPassesBinding import com.rtbishop.look4sat.domain.model.DataState import com.rtbishop.look4sat.domain.predict.SatPass -import com.rtbishop.look4sat.domain.toTimerString import com.rtbishop.look4sat.presentation.getNavResult +import com.rtbishop.look4sat.utility.toTimerString import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesViewModel.kt index 249a1a36..2c3570d3 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesViewModel.kt @@ -18,10 +18,10 @@ package com.rtbishop.look4sat.presentation.passesScreen import androidx.lifecycle.* -import com.rtbishop.look4sat.domain.IRepository -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ISatelliteManager +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.predict.Predictor import com.rtbishop.look4sat.domain.predict.SatPass import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.* @@ -29,9 +29,9 @@ import javax.inject.Inject @HiltViewModel class PassesViewModel @Inject constructor( - private val predictor: Predictor, - private val repository: IRepository, - private val settings: ISettings + private val satelliteManager: ISatelliteManager, + private val repository: IDataRepository, + private val settings: ISettingsManager ) : ViewModel() { private var passesProcessing: Job? = null @@ -41,12 +41,12 @@ class PassesViewModel @Inject constructor( init { viewModelScope.launch { - predictor.calculatedPasses.collect { passes -> + satelliteManager.calculatedPasses.collect { passes -> passesProcessing?.cancelAndJoin() passesProcessing = viewModelScope.launch { while (isActive) { val time = System.currentTimeMillis() - val newPasses = predictor.processPasses(passes, time) + val newPasses = satelliteManager.processPasses(passes, time) _passes.postValue(DataState.Success(newPasses)) delay(1000) } @@ -73,7 +73,7 @@ class PassesViewModel @Inject constructor( val stationPos = settings.loadStationPosition() val selectedIds = settings.loadEntriesSelection() val satellites = repository.getEntriesWithIds(selectedIds) - predictor.forceCalculation(satellites, stationPos, timeRef, hoursAhead, minElevation) + satelliteManager.calculatePasses(satellites, stationPos, timeRef, hoursAhead, minElevation) } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt index 8278ba06..6884bb64 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt @@ -30,7 +30,7 @@ import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.FragmentRadarBinding import com.rtbishop.look4sat.domain.predict.SatPass import com.rtbishop.look4sat.domain.predict.SatPos -import com.rtbishop.look4sat.domain.toTimerString +import com.rtbishop.look4sat.utility.toTimerString import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarViewModel.kt index 9d85cb51..33b2106f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarViewModel.kt @@ -19,16 +19,16 @@ package com.rtbishop.look4sat.presentation.radarScreen import android.hardware.GeomagneticField import androidx.lifecycle.* -import com.rtbishop.look4sat.domain.DataReporter -import com.rtbishop.look4sat.domain.IRepository -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ISatelliteManager +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.domain.model.SatRadio import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.domain.predict.Predictor import com.rtbishop.look4sat.domain.predict.SatPass import com.rtbishop.look4sat.domain.predict.SatPos -import com.rtbishop.look4sat.domain.round -import com.rtbishop.look4sat.framework.OrientationHandler +import com.rtbishop.look4sat.framework.OrientationManager +import com.rtbishop.look4sat.utility.DataReporter +import com.rtbishop.look4sat.utility.round import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay import kotlinx.coroutines.isActive @@ -38,12 +38,12 @@ import javax.inject.Inject @HiltViewModel class RadarViewModel @Inject constructor( - private val orientationHandler: OrientationHandler, + private val orientationManager: OrientationManager, private val reporter: DataReporter, - private val predictor: Predictor, - private val repository: IRepository, - private val settings: ISettings -) : ViewModel(), OrientationHandler.OrientationListener { + private val satelliteManager: ISatelliteManager, + private val repository: IDataRepository, + private val settings: ISettingsManager +) : ViewModel(), OrientationManager.OrientationListener { private val stationPos = settings.loadStationPosition() private val _passData = MutableLiveData() @@ -54,7 +54,7 @@ class RadarViewModel @Inject constructor( val orientation: LiveData> = _orientation fun getPass(catNum: Int, aosTime: Long) = liveData { - predictor.calculatedPasses.collect { passes -> + satelliteManager.calculatedPasses.collect { passes -> val pass = passes.find { pass -> pass.catNum == catNum && pass.aosTime == aosTime } pass?.let { satPass -> emit(satPass) @@ -65,11 +65,11 @@ class RadarViewModel @Inject constructor( } fun enableSensor() { - if (settings.getUseCompass()) orientationHandler.startListening(this) + if (settings.getUseCompass()) orientationManager.startListening(this) } fun disableSensor() { - if (settings.getUseCompass()) orientationHandler.stopListening() + if (settings.getUseCompass()) orientationManager.stopListening() } fun getUseCompass(): Boolean = settings.getUseCompass() @@ -92,10 +92,10 @@ class RadarViewModel @Inject constructor( if (!satPass.isDeepSpace) { val startDate = satPass.aosTime val endDate = satPass.losTime - satTrack = predictor.getSatTrack(satPass.satellite, stationPos, startDate, endDate) + satTrack = satelliteManager.getTrack(satPass.satellite, stationPos, startDate, endDate) } while (isActive) { - val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date().time) + val satPos = satelliteManager.getPosition(satPass.satellite, stationPos, Date().time) if (settings.getRotatorEnabled()) { val server = settings.getRotatorServer() val port = settings.getRotatorPort().toInt() @@ -115,7 +115,7 @@ class RadarViewModel @Inject constructor( val transmitters = repository.getRadiosWithId(pass.catNum) while (isActive) { val time = System.currentTimeMillis() - val list = predictor.processRadios(pass.satellite, stationPos, transmitters, time) + val list = satelliteManager.processRadios(pass.satellite, stationPos, transmitters, time) _transmitters.postValue(list) delay(1000) } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/LocatorDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/LocatorDialog.kt index 6c6f6b3e..7c98c377 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/LocatorDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/LocatorDialog.kt @@ -25,7 +25,7 @@ import android.view.WindowManager import androidx.appcompat.app.AppCompatDialogFragment import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.DialogLocatorBinding -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.presentation.setNavResult import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -34,7 +34,7 @@ import javax.inject.Inject class LocatorDialog : AppCompatDialogFragment() { @Inject - lateinit var preferences: ISettings + lateinit var preferences: ISettingsManager override fun onCreateView(inflater: LayoutInflater, group: ViewGroup?, state: Bundle?): View? { return inflater.inflate(R.layout.dialog_locator, group, false) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/PositionDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/PositionDialog.kt index 7b695a08..b10aeb81 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/PositionDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/PositionDialog.kt @@ -25,7 +25,7 @@ import android.view.WindowManager import androidx.appcompat.app.AppCompatDialogFragment import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.DialogPositionBinding -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.presentation.setNavResult import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -34,7 +34,7 @@ import javax.inject.Inject class PositionDialog : AppCompatDialogFragment() { @Inject - lateinit var preferences: ISettings + lateinit var preferences: ISettingsManager override fun onCreateView(inflater: LayoutInflater, group: ViewGroup?, state: Bundle?): View? { return inflater.inflate(R.layout.dialog_position, group, false) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt index 57e835d1..4158e399 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt @@ -34,11 +34,11 @@ import androidx.navigation.fragment.findNavController import com.rtbishop.look4sat.BuildConfig import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.FragmentSettingsBinding -import com.rtbishop.look4sat.domain.isValidIPv4 -import com.rtbishop.look4sat.domain.isValidPort import com.rtbishop.look4sat.domain.model.DataState import com.rtbishop.look4sat.domain.predict.GeoPos import com.rtbishop.look4sat.presentation.getNavResult +import com.rtbishop.look4sat.utility.isValidIPv4 +import com.rtbishop.look4sat.utility.isValidPort import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt index a4fd83aa..ac78f754 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt @@ -19,9 +19,9 @@ package com.rtbishop.look4sat.presentation.settingsScreen import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData -import com.rtbishop.look4sat.domain.ILocationHandler -import com.rtbishop.look4sat.domain.IRepository -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ILocationManager +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.domain.model.DataState import com.rtbishop.look4sat.domain.predict.GeoPos import dagger.hilt.android.lifecycle.HiltViewModel @@ -30,9 +30,9 @@ import javax.inject.Inject @HiltViewModel class SettingsViewModel @Inject constructor( - private val locationHandler: ILocationHandler, - private val repository: IRepository, - private val settings: ISettings + private val locationManager: ILocationManager, + private val repository: IDataRepository, + private val settings: ISettingsManager ) : ViewModel() { val entriesTotal = repository.getEntriesTotal().asLiveData() @@ -79,17 +79,17 @@ class SettingsViewModel @Inject constructor( fun setUpdateHandled() = repository.setUpdateStateHandled() - val stationPosition: SharedFlow> = locationHandler.stationPosition + val stationPosition: SharedFlow> = locationManager.stationPosition - fun getStationPosition(): GeoPos = locationHandler.getStationPosition() + fun getStationPosition(): GeoPos = locationManager.getStationPosition() - fun setStationPosition(lat: Double, lon: Double) = locationHandler.setStationPosition(lat, lon) + fun setStationPosition(lat: Double, lon: Double) = locationManager.setStationPosition(lat, lon) - fun setPositionFromGps() = locationHandler.setPositionFromGps() + fun setPositionFromGps() = locationManager.setPositionFromGps() - fun setPositionFromNet() = locationHandler.setPositionFromNet() + fun setPositionFromNet() = locationManager.setPositionFromNet() - fun setPositionFromQth(qthString: String) = locationHandler.setPositionFromQth(qthString) + fun setPositionFromQth(qthString: String) = locationManager.setPositionFromQth(qthString) - fun setPositionHandled() = locationHandler.setPositionHandled() + fun setPositionHandled() = locationManager.setPositionHandled() } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SourcesDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SourcesDialog.kt index 4cc64d05..e153c673 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SourcesDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SourcesDialog.kt @@ -27,7 +27,7 @@ import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import com.rtbishop.look4sat.R import com.rtbishop.look4sat.databinding.DialogSourcesBinding -import com.rtbishop.look4sat.domain.ISettings +import com.rtbishop.look4sat.domain.ISettingsManager import com.rtbishop.look4sat.framework.model.DataSource import com.rtbishop.look4sat.presentation.setNavResult import dagger.hilt.android.AndroidEntryPoint @@ -37,7 +37,7 @@ import javax.inject.Inject class SourcesDialog : AppCompatDialogFragment(), SourcesAdapter.SourcesClickListener { @Inject - lateinit var settings: ISettings + lateinit var settings: ISettingsManager private lateinit var binding: DialogSourcesBinding private lateinit var sourcesAdapter: SourcesAdapter diff --git a/data/.gitignore b/base/.gitignore similarity index 100% rename from data/.gitignore rename to base/.gitignore diff --git a/data/build.gradle b/base/build.gradle similarity index 100% rename from data/build.gradle rename to base/build.gradle diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/IRepository.kt b/base/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt similarity index 98% rename from data/src/main/java/com/rtbishop/look4sat/domain/IRepository.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt index d315ec90..5388d73d 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/IRepository.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt @@ -24,7 +24,7 @@ import com.rtbishop.look4sat.domain.predict.Satellite import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow -interface IRepository { +interface IDataRepository { val updateState: StateFlow> diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/ILocationHandler.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ILocationManager.kt similarity index 97% rename from data/src/main/java/com/rtbishop/look4sat/domain/ILocationHandler.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/ILocationManager.kt index d51202cc..55493384 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/ILocationHandler.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/ILocationManager.kt @@ -21,7 +21,7 @@ import com.rtbishop.look4sat.domain.model.DataState import com.rtbishop.look4sat.domain.predict.GeoPos import kotlinx.coroutines.flow.SharedFlow -interface ILocationHandler { +interface ILocationManager { val stationPosition: SharedFlow> diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/ISatelliteManager.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ISatelliteManager.kt new file mode 100644 index 00000000..acc8f6e1 --- /dev/null +++ b/base/src/main/java/com/rtbishop/look4sat/domain/ISatelliteManager.kt @@ -0,0 +1,34 @@ +package com.rtbishop.look4sat.domain + +import com.rtbishop.look4sat.domain.model.SatRadio +import com.rtbishop.look4sat.domain.predict.GeoPos +import com.rtbishop.look4sat.domain.predict.SatPass +import com.rtbishop.look4sat.domain.predict.SatPos +import com.rtbishop.look4sat.domain.predict.Satellite +import kotlinx.coroutines.flow.SharedFlow + +interface ISatelliteManager { + + val calculatedPasses: SharedFlow> + + suspend fun getPosition(sat: Satellite, pos: GeoPos, time: Long): SatPos + + suspend fun getTrack(sat: Satellite, pos: GeoPos, start: Long, end: Long): List + + suspend fun processRadios( + sat: Satellite, + pos: GeoPos, + radios: List, + time: Long + ): List + + suspend fun processPasses(passList: List, time: Long): List + + suspend fun calculatePasses( + satList: List, + pos: GeoPos, + time: Long, + hoursAhead: Int = 8, + minElevation: Double = 16.0 + ) +} diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/ISettings.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt similarity index 98% rename from data/src/main/java/com/rtbishop/look4sat/domain/ISettings.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt index 17b97a9e..17ec4b63 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/ISettings.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt @@ -19,7 +19,7 @@ package com.rtbishop.look4sat.domain import com.rtbishop.look4sat.domain.predict.GeoPos -interface ISettings { +interface ISettingsManager { val defaultSources: List get() = listOf( diff --git a/data/src/main/java/com/rtbishop/look4sat/data/Repository.kt b/base/src/main/java/com/rtbishop/look4sat/domain/data/DataRepository.kt similarity index 69% rename from data/src/main/java/com/rtbishop/look4sat/data/Repository.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/data/DataRepository.kt index 1d851254..42eba294 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/Repository.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/data/DataRepository.kt @@ -15,23 +15,26 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.data +package com.rtbishop.look4sat.domain.data -import com.rtbishop.look4sat.domain.IRepository +import com.rtbishop.look4sat.domain.IDataRepository import com.rtbishop.look4sat.domain.model.DataState import com.rtbishop.look4sat.domain.model.SatEntry +import com.rtbishop.look4sat.utility.DataParser import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import java.io.InputStream import java.util.zip.ZipInputStream -class Repository( +class DataRepository( private val dataParser: DataParser, - private val storage: IStorage, - private val provider: IProvider, - private val repoScope: CoroutineScope -) : IRepository { + private val fileSource: IFileDataSource, + private val entrySource: ILocalEntrySource, + private val radioSource: ILocalRadioSource, + private val remoteSource: IRemoteDataSource, + private val repositoryScope: CoroutineScope +) : IDataRepository { private val exceptionHandler = CoroutineExceptionHandler { _, exception -> _updateState.value = DataState.Error(exception.message) @@ -40,22 +43,22 @@ class Repository( private val _updateState = MutableStateFlow>(DataState.Handled) override val updateState: StateFlow> = _updateState - override fun getEntriesTotal() = storage.getEntriesTotal() + override fun getEntriesTotal() = entrySource.getEntriesTotal() - override fun getRadiosTotal() = storage.getRadiosTotal() + override fun getRadiosTotal() = radioSource.getRadiosTotal() - override suspend fun getEntriesWithModes() = storage.getEntriesWithModes() + override suspend fun getEntriesWithModes() = entrySource.getEntriesWithModes() - override suspend fun getEntriesWithIds(ids: List) = storage.getEntriesWithIds(ids) + override suspend fun getEntriesWithIds(ids: List) = entrySource.getEntriesWithIds(ids) - override suspend fun getRadiosWithId(id: Int) = storage.getRadiosWithId(id) + override suspend fun getRadiosWithId(id: Int) = radioSource.getRadiosWithId(id) override fun updateFromFile(uri: String) { - repoScope.launch(exceptionHandler) { + repositoryScope.launch(exceptionHandler) { _updateState.value = DataState.Loading - provider.getLocalFileStream(uri)?.let { fileStream -> + fileSource.getDataStream(uri)?.let { fileStream -> delay(updateStateDelay) - storage.insertEntries(importSatellites(fileStream)) + entrySource.insertEntries(importSatellites(fileStream)) } _updateState.value = DataState.Success(0L) } @@ -63,12 +66,12 @@ class Repository( override fun updateFromWeb(urls: List) { _updateState.value = DataState.Loading - repoScope.launch(exceptionHandler) { + repositoryScope.launch(exceptionHandler) { val jobsMap = mutableMapOf>() val streamsMap = mutableMapOf() val streams = mutableListOf() val entries = mutableListOf() - urls.forEach { jobsMap[it] = async { provider.getRemoteFileStream(it) } } + urls.forEach { jobsMap[it] = async { remoteSource.getDataStream(it) } } jobsMap.forEach { job -> streamsMap[job.key] = job.value.await() } streamsMap.forEach { stream -> stream.value?.let { inputStream -> @@ -85,11 +88,11 @@ class Repository( } } streams.forEach { stream -> entries.addAll(importSatellites(stream)) } - storage.insertEntries(entries) + entrySource.insertEntries(entries) } - repoScope.launch(exceptionHandler) { - provider.getRemoteFileStream(provider.radioApi)?.let { stream -> - storage.insertRadios(dataParser.parseJSONStream(stream)) + repositoryScope.launch(exceptionHandler) { + remoteSource.getDataStream(remoteSource.radioApi)?.let { stream -> + radioSource.insertRadios(dataParser.parseJSONStream(stream)) _updateState.value = DataState.Success(0L) } } @@ -100,10 +103,11 @@ class Repository( } override fun clearAllData() { - repoScope.launch { + repositoryScope.launch { _updateState.value = DataState.Loading delay(updateStateDelay) - storage.clearAllData() + entrySource.deleteEntries() + radioSource.deleteRadios() _updateState.value = DataState.Success(0L) } } diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/data/IFileDataSource.kt b/base/src/main/java/com/rtbishop/look4sat/domain/data/IFileDataSource.kt new file mode 100644 index 00000000..51b4d912 --- /dev/null +++ b/base/src/main/java/com/rtbishop/look4sat/domain/data/IFileDataSource.kt @@ -0,0 +1,25 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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.data + +import java.io.InputStream + +interface IFileDataSource { + + suspend fun getDataStream(uri: String): InputStream? +} diff --git a/data/src/main/java/com/rtbishop/look4sat/data/IStorage.kt b/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalEntrySource.kt similarity index 80% rename from data/src/main/java/com/rtbishop/look4sat/data/IStorage.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalEntrySource.kt index 60ce731c..a9692d8c 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/IStorage.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalEntrySource.kt @@ -15,29 +15,22 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.data +package com.rtbishop.look4sat.domain.data import com.rtbishop.look4sat.domain.model.SatEntry import com.rtbishop.look4sat.domain.model.SatItem -import com.rtbishop.look4sat.domain.model.SatRadio import com.rtbishop.look4sat.domain.predict.Satellite import kotlinx.coroutines.flow.Flow -interface IStorage { +interface ILocalEntrySource { fun getEntriesTotal(): Flow - fun getRadiosTotal(): Flow - suspend fun getEntriesWithModes(): List suspend fun getEntriesWithIds(ids: List): List - suspend fun getRadiosWithId(id: Int): List - suspend fun insertEntries(entries: List) - suspend fun insertRadios(radios: List) - - suspend fun clearAllData() + suspend fun deleteEntries() } diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalRadioSource.kt b/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalRadioSource.kt new file mode 100644 index 00000000..8418ef01 --- /dev/null +++ b/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalRadioSource.kt @@ -0,0 +1,32 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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.data + +import com.rtbishop.look4sat.domain.model.SatRadio +import kotlinx.coroutines.flow.Flow + +interface ILocalRadioSource { + + fun getRadiosTotal(): Flow + + suspend fun getRadiosWithId(id: Int): List + + suspend fun insertRadios(radios: List) + + suspend fun deleteRadios() +} diff --git a/data/src/main/java/com/rtbishop/look4sat/data/IProvider.kt b/base/src/main/java/com/rtbishop/look4sat/domain/data/IRemoteDataSource.kt similarity index 83% rename from data/src/main/java/com/rtbishop/look4sat/data/IProvider.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/data/IRemoteDataSource.kt index 23de2d10..3468702d 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/IProvider.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/data/IRemoteDataSource.kt @@ -15,15 +15,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.data +package com.rtbishop.look4sat.domain.data import java.io.InputStream -interface IProvider { +interface IRemoteDataSource { val radioApi: String get() = "https://db.satnogs.org/api/transmitters/?format=json" - suspend fun getLocalFileStream(uri: String): InputStream? - - suspend fun getRemoteFileStream(url: String): InputStream? + suspend fun getDataStream(url: String): InputStream? } diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/model/DataState.kt b/base/src/main/java/com/rtbishop/look4sat/domain/model/DataState.kt similarity index 100% rename from data/src/main/java/com/rtbishop/look4sat/domain/model/DataState.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/model/DataState.kt diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt b/base/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt similarity index 100% rename from data/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt b/base/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt similarity index 100% rename from data/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt b/base/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt similarity index 100% rename from data/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt similarity index 95% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt index 8ede45f3..98fb8dab 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt @@ -35,45 +35,45 @@ class DeepSpaceSat(data: OrbitalData) : Satellite(data) { init { // Recover original mean motion (xnodp) and semimajor axis (aodp) from input elements - val a1 = (xke / super.data.xno).pow(twoThirds) - dsv.cosio = cos(super.data.xincl) + val a1 = (XKE / data.xno).pow(TWO_THIRDS) + dsv.cosio = cos(data.xincl) dsv.theta2 = dsv.cosio * dsv.cosio x3thm1 = 3.0 * dsv.theta2 - 1 - dsv.eosq = super.data.eccn * super.data.eccn + dsv.eosq = data.eccn * data.eccn dsv.betao2 = 1.0 - dsv.eosq dsv.betao = sqrt(dsv.betao2) - val del1 = 1.5 * ck2 * x3thm1 / (a1 * a1 * dsv.betao * dsv.betao2) - val ao = a1 * (1.0 - del1 * (0.5 * twoThirds + del1 * (1.0 + 134.0 / 81.0 * del1))) - val delo = 1.5 * ck2 * x3thm1 / (ao * ao * dsv.betao * dsv.betao2) - dsv.xnodp = super.data.xno / (1.0 + delo) + val del1 = 1.5 * CK2 * x3thm1 / (a1 * a1 * dsv.betao * dsv.betao2) + val ao = a1 * (1.0 - del1 * (0.5 * TWO_THIRDS + del1 * (1.0 + 134.0 / 81.0 * del1))) + val delo = 1.5 * CK2 * x3thm1 / (ao * ao * dsv.betao * dsv.betao2) + dsv.xnodp = data.xno / (1.0 + delo) dsv.aodp = ao / (1.0 - delo) // For perigee below 156 km, the values of S and QOMS2T are altered - setPerigee((dsv.aodp * (1.0 - super.data.eccn) - 1.0) * earthRadius) + setPerigee((dsv.aodp * (1.0 - data.eccn) - 1.0) * EARTH_RADIUS) val pinvsq = invert(dsv.aodp * dsv.aodp * dsv.betao2 * dsv.betao2) - dsv.sing = sin(super.data.omegao) - dsv.cosg = cos(super.data.omegao) + dsv.sing = sin(data.omegao) + dsv.cosg = cos(data.omegao) val tsi = invert(dsv.aodp - s4) - val eta = dsv.aodp * super.data.eccn * tsi + val eta = dsv.aodp * data.eccn * tsi val etasq = eta * eta - val eeta = super.data.eccn * eta + val eeta = data.eccn * eta val psisq = abs(1.0 - etasq) val coef = qoms24 * tsi.pow(4.0) val coef1 = coef / psisq.pow(3.5) val c2 = coef1 * dsv.xnodp * (dsv.aodp * (1.0 + 1.5 * etasq + eeta * (4.0 + etasq)) - + 0.75 * ck2 * tsi / psisq * x3thm1 * (8.0 + 3.0 * etasq * (8.0 + etasq))) - c1 = super.data.bstar * c2 - dsv.sinio = sin(super.data.xincl) - val a3ovk2 = -j3Harmonic / ck2 + + 0.75 * CK2 * tsi / psisq * x3thm1 * (8.0 + 3.0 * etasq * (8.0 + etasq))) + c1 = data.bstar * c2 + dsv.sinio = sin(data.xincl) + val a3ovk2 = -J3_HARMONIC / CK2 x1mth2 = 1.0 - dsv.theta2 c4 = - 2 * dsv.xnodp * coef1 * dsv.aodp * dsv.betao2 * (eta * (2.0 + 0.5 * etasq) + super.data.eccn - * (0.5 + 2 * etasq) - 2 * ck2 * tsi / (dsv.aodp * psisq) + 2 * dsv.xnodp * coef1 * dsv.aodp * dsv.betao2 * (eta * (2.0 + 0.5 * etasq) + data.eccn + * (0.5 + 2 * etasq) - 2 * CK2 * tsi / (dsv.aodp * psisq) * (-3 * x3thm1 * (1.0 - 2 * eeta + etasq * (1.5 - 0.5 * eeta)) + (0.75 * x1mth2 - * (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * super.data.omegao)))) + * (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * data.omegao)))) val theta4 = dsv.theta2 * dsv.theta2 - val temp1 = 3.0 * ck2 * pinvsq * dsv.xnodp - val temp2 = temp1 * ck2 * pinvsq - val temp3 = 1.25 * ck4 * pinvsq * pinvsq * dsv.xnodp + val temp1 = 3.0 * CK2 * pinvsq * dsv.xnodp + val temp2 = temp1 * CK2 * pinvsq + val temp3 = 1.25 * CK4 * pinvsq * pinvsq * dsv.xnodp dsv.xmdot = dsv.xnodp + 0.5 * temp1 * dsv.betao * x3thm1 + 0.0625 * temp2 * dsv.betao * (13 - 78 * dsv.theta2 + 137 * theta4) val x1m5th = 1.0 - 5 * dsv.theta2 @@ -105,12 +105,12 @@ class DeepSpaceSat(data: OrbitalData) : Satellite(data) { dsv.xn = dsv.xnodp dsv.t = tSince deep.dpsec(data) - val a = (xke / dsv.xn).pow(twoThirds) * tempa * tempa + val a = (XKE / dsv.xn).pow(TWO_THIRDS) * tempa * tempa dsv.em = dsv.em - tempe deep.dpper() val xl = dsv.xll + dsv.omgadf + dsv.xnode val beta = sqrt(1.0 - dsv.em * dsv.em) - dsv.xn = xke / a.pow(1.5) + dsv.xn = XKE / a.pow(1.5) // Long period periodics val axn = dsv.em * cos(dsv.omgadf) @@ -136,8 +136,8 @@ class DeepSpaceSat(data: OrbitalData) : Satellite(data) { val pl = a * temp[0] temp[9] = a * (1.0 - ecose) temp[1] = invert(temp[9]) - temp[10] = xke * sqrt(a) * esine * temp[1] - temp[11] = xke * sqrt(pl) * temp[1] + temp[10] = XKE * sqrt(a) * esine * temp[1] + temp[11] = XKE * sqrt(pl) * temp[1] temp[2] = a * temp[1] val betal = sqrt(temp[0]) temp[3] = invert(1.0 + betal) @@ -147,7 +147,7 @@ class DeepSpaceSat(data: OrbitalData) : Satellite(data) { val sin2u = 2.0 * sinu * cosu val cos2u = 2.0 * cosu * cosu - 1 temp[0] = invert(pl) - temp[1] = ck2 * temp[0] + temp[1] = CK2 * temp[0] temp[2] = temp[1] * temp[0] // Update for short periodics @@ -614,8 +614,8 @@ class DeepSpaceSat(data: OrbitalData) : Satellite(data) { } else { applyPeriodics() // This is a patch to Lyddane modification suggested by Rob Matson - if (abs(xnoh - dsv.xnode) > Math.PI) { - if (dsv.xnode < xnoh) dsv.xnode += twoPi else dsv.xnode -= twoPi + if (abs(xnoh - dsv.xnode) > PI) { + if (dsv.xnode < xnoh) dsv.xnode += TWO_PI else dsv.xnode -= TWO_PI } dsv.xll = dsv.xll + pl dsv.omgadf = xls - dsv.xll - cos(dsv.xinc) * dsv.xnode @@ -631,8 +631,8 @@ class DeepSpaceSat(data: OrbitalData) : Satellite(data) { dsv.xinc = params.xincl + ssi * dsv.t if (dsv.xinc < 0) { dsv.xinc = -dsv.xinc - dsv.xnode = dsv.xnode + Math.PI - dsv.omgadf = dsv.omgadf - Math.PI + dsv.xnode = dsv.xnode + PI + dsv.omgadf = dsv.omgadf - PI } if (!resonance) return do processEpochRestartLoop() while (doLoop && epochRestart) diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/GeoPos.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/GeoPos.kt similarity index 100% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/GeoPos.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/GeoPos.kt diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt similarity index 86% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt index ba4ffc45..6c64dfdf 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt @@ -53,25 +53,25 @@ class NearEarthSat(data: OrbitalData) : Satellite(data) { init { // Recover original mean motion (xnodp) and semimajor axis (aodp) from input elements - val a1 = (xke / super.data.xno).pow(twoThirds) - cosio = cos(super.data.xincl) + val a1 = (XKE / data.xno).pow(TWO_THIRDS) + cosio = cos(data.xincl) val theta2 = sqr(cosio) x3thm1 = 3.0 * theta2 - 1.0 - val eo = super.data.eccn + val eo = data.eccn val eosq = sqr(eo) val betao2 = 1.0 - eosq val betao = sqrt(betao2) - val del1 = 1.5 * ck2 * x3thm1 / (sqr(a1) * betao * betao2) - val ao = a1 * (1.0 - del1 * (0.5 * twoThirds + del1 * (1.0 + 134.0 / 81.0 * del1))) - val delo = 1.5 * ck2 * x3thm1 / (sqr(ao) * betao * betao2) - xnodp = super.data.xno / (1.0 + delo) + val del1 = 1.5 * CK2 * x3thm1 / (sqr(a1) * betao * betao2) + val ao = a1 * (1.0 - del1 * (0.5 * TWO_THIRDS + del1 * (1.0 + 134.0 / 81.0 * del1))) + val delo = 1.5 * CK2 * x3thm1 / (sqr(ao) * betao * betao2) + xnodp = data.xno / (1.0 + delo) aodp = ao / (1.0 - delo) // For perigee less than 220 kilometers, the "simple" flag is set - sgp4Simple = aodp * (1.0 - eo) < 220 / earthRadius + 1.0 + sgp4Simple = aodp * (1.0 - eo) < 220 / EARTH_RADIUS + 1.0 // For perigees below 156 km, the values of S and QOMS2T are altered - setPerigee((aodp * (1.0 - eo) - 1.0) * earthRadius) + setPerigee((aodp * (1.0 - eo) - 1.0) * EARTH_RADIUS) val pinvsq = invert(sqr(aodp) * sqr(betao2)) val tsi = invert(aodp - s4) eta = aodp * eo * tsi @@ -80,24 +80,24 @@ class NearEarthSat(data: OrbitalData) : Satellite(data) { val psisq = abs(1.0 - etasq) val coef = qoms24 * tsi.pow(4.0) val coef1 = coef / psisq.pow(3.5) - val bstar = super.data.bstar + val bstar = data.bstar val c2 = coef1 * xnodp * (aodp * (1.0 + 1.5 * etasq + eeta * (4.0 + etasq)) + 0.75 - * ck2 * tsi / psisq * x3thm1 * (8.0 + 3.0 * etasq * (8.0 + etasq))) + * CK2 * tsi / psisq * x3thm1 * (8.0 + 3.0 * etasq * (8.0 + etasq))) c1 = bstar * c2 - sinio = sin(super.data.xincl) - val a3ovk2 = -j3Harmonic / ck2 + sinio = sin(data.xincl) + val a3ovk2 = -J3_HARMONIC / CK2 val c3 = coef * tsi * a3ovk2 * xnodp * sinio / eo x1mth2 = 1.0 - theta2 - val omegao = super.data.omegao + val omegao = data.omegao c4 = 2 * xnodp * coef1 * aodp * betao2 * (eta * (2.0 + 0.5 * etasq) + eo * (0.5 + 2 * etasq) - - 2 * ck2 * tsi / (aodp * psisq) * (-3 * x3thm1 * (1.0 - 2 * eeta + etasq + - 2 * CK2 * tsi / (aodp * psisq) * (-3 * x3thm1 * (1.0 - 2 * eeta + etasq * (1.5 - 0.5 * eeta)) + 0.75 * x1mth2 * (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * omegao))) c5 = 2.0 * coef1 * aodp * betao2 * (1.0 + 2.75 * (etasq + eeta) + eeta * etasq) val theta4 = sqr(theta2) - val temp1 = 3.0 * ck2 * pinvsq * xnodp - val temp2 = temp1 * ck2 * pinvsq - val temp3 = 1.25 * ck4 * pinvsq * pinvsq * xnodp + val temp1 = 3.0 * CK2 * pinvsq * xnodp + val temp2 = temp1 * CK2 * pinvsq + val temp3 = 1.25 * CK4 * pinvsq * pinvsq * xnodp xmdot = xnodp + 0.5 * temp1 * betao * x3thm1 + (0.0625 * temp2 * betao * (13.0 - 78.0 * theta2 + 137.0 * theta4)) val x1m5th = 1.0 - 5.0 * theta2 @@ -107,12 +107,12 @@ class NearEarthSat(data: OrbitalData) : Satellite(data) { xnodot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * theta2) + 2.0 * temp3 * (3.0 - 7.0 * theta2)) * cosio omgcof = bstar * c3 * cos(omegao) - xmcof = -twoThirds * coef * bstar / eeta + xmcof = -TWO_THIRDS * coef * bstar / eeta xnodcf = 3.5 * betao2 * xhdot1 * c1 t2cof = 1.5 * c1 xlcof = 0.125 * a3ovk2 * sinio * (3.0 + 5 * cosio) / (1.0 + cosio) aycof = 0.25 * a3ovk2 * sinio - val xmo = super.data.xmo + val xmo = data.xmo delmo = (1.0 + eta * cos(xmo)).pow(3.0) sinmo = sin(xmo) x7thm1 = 7.0 * theta2 - 1 @@ -166,7 +166,7 @@ class NearEarthSat(data: OrbitalData) : Satellite(data) { val e = eo - tempe val xl = xmp + omega + xnode + xnodp * templ val beta = sqrt(1.0 - e * e) - val xn = xke / a.pow(1.5) + val xn = XKE / a.pow(1.5) // Long period periodics val axn = e * cos(omega) @@ -195,8 +195,8 @@ class NearEarthSat(data: OrbitalData) : Satellite(data) { val pl = a * temp[0] val r = a * (1.0 - ecose) temp[1] = invert(r) - val rdot = xke * sqrt(a) * esine * temp[1] - val rfdot = xke * sqrt(pl) * temp[1] + val rdot = XKE * sqrt(a) * esine * temp[1] + val rfdot = XKE * sqrt(pl) * temp[1] temp[2] = a * temp[1] val betal = sqrt(temp[0]) temp[3] = invert(1.0 + betal) @@ -206,7 +206,7 @@ class NearEarthSat(data: OrbitalData) : Satellite(data) { val sin2u = 2.0 * sinu * cosu val cos2u = 2.0 * cosu * cosu - 1 temp[0] = invert(pl) - temp[1] = ck2 * temp[0] + temp[1] = CK2 * temp[0] temp[2] = temp[1] * temp[0] // Update for short periodics diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt similarity index 84% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt index 283db460..37065018 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt @@ -28,11 +28,11 @@ data class OrbitalData( val meanan: Double, val catnum: Int, val bstar: Double, - val xincl: Double = Math.toRadians(incl), - val xnodeo: Double = Math.toRadians(raan), - val omegao: Double = Math.toRadians(argper), - val xmo: Double = Math.toRadians(meanan), - val xno: Double = meanmo * Math.PI * 2.0 / 1440, + val xincl: Double = incl * DEG2RAD, + val xnodeo: Double = raan * DEG2RAD, + val omegao: Double = argper * DEG2RAD, + val xmo: Double = meanan * DEG2RAD, + val xno: Double = meanmo * TWO_PI / MIN_PER_DAY, val isDeepspace: Boolean = meanmo < 6.4 ) { diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/SatPass.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPass.kt similarity index 100% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/SatPass.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPass.kt diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt similarity index 86% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt index 5ae5b682..e54c1230 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt @@ -30,15 +30,13 @@ data class SatPos( var theta: Double = 0.0, var time: Long = 0L ) { - private val earthRadiusKm = 6378.16 - private val speedOfLight = 2.99792458E8 fun getDownlinkFreq(freq: Long): Long { - return (freq.toDouble() * (speedOfLight - distanceRate * 1000.0) / speedOfLight).toLong() + return (freq.toDouble() * (SPEED_OF_LIGHT - distanceRate * 1000.0) / SPEED_OF_LIGHT).toLong() } fun getUplinkFreq(freq: Long): Long { - return (freq.toDouble() * (speedOfLight + distanceRate * 1000.0) / speedOfLight).toLong() + return (freq.toDouble() * (SPEED_OF_LIGHT + distanceRate * 1000.0) / SPEED_OF_LIGHT).toLong() } fun getOrbitalVelocity(): Double { @@ -50,7 +48,7 @@ data class SatPos( fun getRangeCircle(): List { val positions = mutableListOf() - val beta = acos(earthRadiusKm / (earthRadiusKm + altitude)) + val beta = acos(EARTH_RADIUS / (EARTH_RADIUS + altitude)) var tempAzimuth = 0 while (tempAzimuth < 360) { val azimuth = tempAzimuth / 360.0 * 2.0 * Math.PI @@ -81,6 +79,6 @@ data class SatPos( } fun getRangeCircleRadiusKm(): Double { - return earthRadiusKm * acos(earthRadiusKm / (earthRadiusKm + altitude)) + return EARTH_RADIUS * acos(EARTH_RADIUS / (EARTH_RADIUS + altitude)) } } diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt similarity index 81% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt index 08d5525f..2e7e6035 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt @@ -19,36 +19,40 @@ package com.rtbishop.look4sat.domain.predict import kotlin.math.* +const val PI = 3.141592653589793 +const val DEG2RAD = 0.017453292519943295 +const val RAD2DEG = 57.29577951308232 +const val EARTH_RADIUS = 6378.137 +const val EPSILON = 1.0E-12 +const val FLAT_FACTOR = 3.35281066474748E-3 +const val J3_HARMONIC = -2.53881E-6 +const val MIN_PER_DAY = 1.44E3 +const val SEC_PER_DAY = 8.6400E4 +const val SPEED_OF_LIGHT = 2.99792458E8 +const val TWO_PI = PI * 2.0 +const val TWO_THIRDS = 2.0 / 3.0 +const val CK2 = 5.413079E-4 +const val CK4 = 6.209887E-7 +const val XKE = 7.43669161E-2 + abstract class Satellite(val data: OrbitalData) { - private val flatFactor = 3.35281066474748E-3 - private val deg2Rad = 1.745329251994330E-2 - private val secPerDay = 8.6400E4 - private val minPerDay = 1.44E3 - private val epsilon = 1.0E-12 private val position = Vector4() private val velocity = Vector4() private var gsPosTheta = 0.0 private var perigee = 0.0 val orbitalPeriod = 24 * 60 / data.meanmo - val earthRadius = 6378.137 - val j3Harmonic = -2.53881E-6 - val twoPi = Math.PI * 2.0 - val twoThirds = 2.0 / 3.0 - val xke = 7.43669161E-2 - val ck2 = 5.413079E-4 - val ck4 = 6.209887E-7 var qoms24 = 0.0 var s4 = 0.0 internal fun willBeSeen(pos: GeoPos): Boolean { return if (data.meanmo < 1e-8) false else { - val sma = 331.25 * exp(ln(1440.0 / data.meanmo) * (2.0 / 3.0)) - val apogee = sma * (1.0 + data.eccn) - earthRadius + val sma = 331.25 * exp(ln(MIN_PER_DAY / data.meanmo) * (2.0 / 3.0)) + val apogee = sma * (1.0 + data.eccn) - EARTH_RADIUS var lin = data.incl if (lin >= 90.0) lin = 180.0 - lin - acos(earthRadius / (apogee + earthRadius)) + lin * deg2Rad > abs(pos.latitude * deg2Rad) + acos(EARTH_RADIUS / (apogee + EARTH_RADIUS)) + lin * DEG2RAD > abs(pos.latitude * DEG2RAD) } } @@ -58,7 +62,7 @@ abstract class Satellite(val data: OrbitalData) { val julUTC = calcCurrentDaynum(time) + 2444238.5 // Convert satellite's epoch time to Julian and calculate time since epoch in minutes val julEpoch = juliandDateOfEpoch(data.epoch) - val tsince = (julUTC - julEpoch) * minPerDay + val tsince = (julUTC - julEpoch) * MIN_PER_DAY calculateSDP4orSGP4(tsince) // Scale position and velocity vectors to km and km/sec convertSatState(position, velocity) @@ -103,8 +107,8 @@ abstract class Satellite(val data: OrbitalData) { // Converts the sat position and velocity vectors to km and km/sec private fun convertSatState(pos: Vector4, vel: Vector4) { - scaleVector(earthRadius, pos) - scaleVector(earthRadius * minPerDay / secPerDay, vel) + scaleVector(EARTH_RADIUS, pos) + scaleVector(EARTH_RADIUS * MIN_PER_DAY / SEC_PER_DAY, vel) } // Calculates the topocentric coordinates of the object with ECI pos and vel at time @@ -134,16 +138,16 @@ abstract class Satellite(val data: OrbitalData) { velocityVector.z - obsVel.z ) magnitude(range) - val sinLat = sin(deg2Rad * gsPos.latitude) - val cosLat = cos(deg2Rad * gsPos.latitude) + val sinLat = sin(DEG2RAD * gsPos.latitude) + val cosLat = cos(DEG2RAD * gsPos.latitude) val sinTheta = sin(gsPosTheta) val cosTheta = cos(gsPosTheta) val topS = sinLat * cosTheta * range.x + sinLat * sinTheta * range.y - cosLat * range.z val topE = -sinTheta * range.x + cosTheta * range.y val topZ = cosLat * cosTheta * range.x + cosLat * sinTheta * range.y + sinLat * range.z var azim = atan(-topE / topS) - if (topS > 0.0) azim += Math.PI - if (azim < 0.0) azim += twoPi + if (topS > 0.0) azim += PI + if (azim < 0.0) azim += TWO_PI satPos.azimuth = azim satPos.elevation = asin(topZ / range.w) satPos.distance = range.w @@ -158,14 +162,14 @@ abstract class Satellite(val data: OrbitalData) { obsVel: Vector4 ) { val mFactor = 7.292115E-5 - gsPosTheta = mod2PI(thetaGJD(time) + deg2Rad * gsPos.longitude) + gsPosTheta = mod2PI(thetaGJD(time) + DEG2RAD * gsPos.longitude) val c = - invert(sqrt(1.0 + flatFactor * (flatFactor - 2) * sqr(sin(deg2Rad * gsPos.latitude)))) - val sq = sqr(1.0 - flatFactor) * c - val achcp = (earthRadius * c) * cos(deg2Rad * gsPos.latitude) + invert(sqrt(1.0 + FLAT_FACTOR * (FLAT_FACTOR - 2) * sqr(sin(DEG2RAD * gsPos.latitude)))) + val sq = sqr(1.0 - FLAT_FACTOR) * c + val achcp = (EARTH_RADIUS * c) * cos(DEG2RAD * gsPos.latitude) obsPos.setXYZ( achcp * cos(gsPosTheta), achcp * sin(gsPosTheta), - (earthRadius * sq) * sin(deg2Rad * gsPos.latitude) + (EARTH_RADIUS * sq) * sin(DEG2RAD * gsPos.latitude) ) obsVel.setXYZ(-mFactor * obsPos.y, mFactor * obsPos.x, 0.0) magnitude(obsPos) @@ -181,7 +185,7 @@ abstract class Satellite(val data: OrbitalData) { satPos.theta = atan2(position.y, position.x) satPos.longitude = mod2PI(satPos.theta - thetaGJD(time)) val r = sqrt(sqr(position.x) + sqr(position.y)) - val e2 = flatFactor * (2.0 - flatFactor) + val e2 = FLAT_FACTOR * (2.0 - FLAT_FACTOR) satPos.latitude = atan2(position.z, r) var phi: Double var c: Double @@ -190,13 +194,13 @@ abstract class Satellite(val data: OrbitalData) { do { phi = satPos.latitude c = invert(sqrt(1.0 - e2 * sqr(sin(phi)))) - satPos.latitude = atan2(position.z + earthRadius * c * e2 * sin(phi), r) - converged = abs(satPos.latitude - phi) < epsilon + satPos.latitude = atan2(position.z + EARTH_RADIUS * c * e2 * sin(phi), r) + converged = abs(satPos.latitude - phi) < EPSILON } while (i++ < 10 && !converged) - satPos.altitude = r / cos(satPos.latitude) - earthRadius * c + satPos.altitude = r / cos(satPos.latitude) - EARTH_RADIUS * c var temp = satPos.latitude if (temp > Math.PI / 2.0) { - temp -= twoPi + temp -= TWO_PI satPos.latitude = temp } } @@ -258,9 +262,9 @@ abstract class Satellite(val data: OrbitalData) { // Calculates the modulus of 2 * PI internal fun mod2PI(value: Double): Double { var retVal = value - val i = (retVal / twoPi).toInt() - retVal -= i * twoPi - if (retVal < 0.0) retVal += twoPi + val i = (retVal / TWO_PI).toInt() + retVal -= i * TWO_PI + if (retVal < 0.0) retVal += TWO_PI return retVal } @@ -276,7 +280,7 @@ abstract class Satellite(val data: OrbitalData) { temp[5] = axn * temp[8] temp[6] = ayn * temp[7] val epw = (capu - temp[4] + temp[3] - temp[2]) / (1.0 - temp[5] - temp[6]) + temp[2] - if (abs(epw - temp[2]) <= epsilon) converged = true else temp[2] = epw + if (abs(epw - temp[2]) <= EPSILON) converged = true else temp[2] = epw } while (i++ < 10 && !converged) } @@ -292,8 +296,8 @@ abstract class Satellite(val data: OrbitalData) { qoms24 = 1.880279E-09 if (perigee < 156.0) { s4 = if (perigee <= 98.0) 20.0 else perigee - 78.0 - qoms24 = ((120 - s4) / earthRadius).pow(4.0) - s4 = s4 / earthRadius + 1.0 + qoms24 = ((120 - s4) / EARTH_RADIUS).pow(4.0) + s4 = s4 / EARTH_RADIUS + 1.0 } } @@ -314,9 +318,9 @@ abstract class Satellite(val data: OrbitalData) { private fun modulus(arg1: Double): Double { var returnValue = arg1 - val i = floor(returnValue / secPerDay).toInt() - returnValue -= i * secPerDay - if (returnValue < 0.0) returnValue += secPerDay + val i = floor(returnValue / SEC_PER_DAY).toInt() + returnValue -= i * SEC_PER_DAY + if (returnValue < 0.0) returnValue += SEC_PER_DAY return returnValue } @@ -332,7 +336,7 @@ abstract class Satellite(val data: OrbitalData) { val aJD = theJD - ut val tu = (aJD - 2451545.0) / 36525.0 var gmst = 24110.54841 + tu * (8640184.812866 + tu * (0.093104 - tu * 6.2E-6)) - gmst = modulus(gmst + secPerDay * earthRotPerSidDay * ut) - return twoPi * gmst / secPerDay + gmst = modulus(gmst + SEC_PER_DAY * earthRotPerSidDay * ut) + return TWO_PI * gmst / SEC_PER_DAY } } diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/predict/Predictor.kt b/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatelliteManager.kt similarity index 87% rename from data/src/main/java/com/rtbishop/look4sat/domain/predict/Predictor.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/predict/SatelliteManager.kt index 46f316f7..623fe251 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/predict/Predictor.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatelliteManager.kt @@ -17,23 +17,29 @@ */ package com.rtbishop.look4sat.domain.predict +import com.rtbishop.look4sat.domain.ISatelliteManager import com.rtbishop.look4sat.domain.model.SatRadio import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.withContext -class Predictor(private val predictorDispatcher: CoroutineDispatcher) { +class SatelliteManager(private val defaultDispatcher: CoroutineDispatcher) : ISatelliteManager { private val _calculatedPasses = MutableSharedFlow>(replay = 1) - val calculatedPasses: SharedFlow> = _calculatedPasses + override val calculatedPasses: SharedFlow> = _calculatedPasses - suspend fun getSatPos(sat: Satellite, pos: GeoPos, time: Long): SatPos { - return withContext(predictorDispatcher) { sat.getPosition(pos, time) } + override suspend fun getPosition(sat: Satellite, pos: GeoPos, time: Long): SatPos { + return withContext(defaultDispatcher) { sat.getPosition(pos, time) } } - suspend fun getSatTrack(sat: Satellite, pos: GeoPos, start: Long, end: Long): List { - return withContext(predictorDispatcher) { + override suspend fun getTrack( + sat: Satellite, + pos: GeoPos, + start: Long, + end: Long + ): List { + return withContext(defaultDispatcher) { val positions = mutableListOf() var currentTime = start while (currentTime < end) { @@ -44,8 +50,13 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) { } } - suspend fun processRadios(sat: Satellite, pos: GeoPos, radios: List, time: Long): List { - return withContext(predictorDispatcher) { + override suspend fun processRadios( + sat: Satellite, + pos: GeoPos, + radios: List, + time: Long + ): List { + return withContext(defaultDispatcher) { val satPos = sat.getPosition(pos, time) val copiedList = radios.map { it.copy() } copiedList.forEach { transmitter -> @@ -60,8 +71,8 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) { } } - suspend fun processPasses(passList: List, time: Long): List { - return withContext(predictorDispatcher) { + override suspend fun processPasses(passList: List, time: Long): List { + return withContext(defaultDispatcher) { passList.forEach { pass -> if (!pass.isDeepSpace) { val timeStart = pass.aosTime @@ -76,17 +87,17 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) { } } - suspend fun forceCalculation( + override suspend fun calculatePasses( satList: List, pos: GeoPos, time: Long, - hoursAhead: Int = 8, - minElevation: Double = 16.0 + hoursAhead: Int, + minElevation: Double ) { if (satList.isEmpty()) { _calculatedPasses.emit(emptyList()) } else { - withContext(predictorDispatcher) { + withContext(defaultDispatcher) { val allPasses = mutableListOf() satList.forEach { satellite -> allPasses.addAll(satellite.getPasses(pos, time, hoursAhead)) diff --git a/data/src/main/java/com/rtbishop/look4sat/data/DataParser.kt b/base/src/main/java/com/rtbishop/look4sat/utility/DataParser.kt similarity index 80% rename from data/src/main/java/com/rtbishop/look4sat/data/DataParser.kt rename to base/src/main/java/com/rtbishop/look4sat/utility/DataParser.kt index 7a1ecea6..23a95de2 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/DataParser.kt +++ b/base/src/main/java/com/rtbishop/look4sat/utility/DataParser.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.data +package com.rtbishop.look4sat.utility import com.rtbishop.look4sat.domain.model.SatRadio import com.rtbishop.look4sat.domain.predict.OrbitalData @@ -26,42 +26,44 @@ import org.json.JSONObject import java.io.InputStream import kotlin.math.pow -class DataParser(private val parserDispatcher: CoroutineDispatcher) { +class DataParser(private val defaultDispatcher: CoroutineDispatcher) { - suspend fun parseCSVStream(csvStream: InputStream): List = withContext(parserDispatcher) { - val parsedItems = mutableListOf() - csvStream.bufferedReader().useLines { lines -> - lines.forEachIndexed { index, line -> - if (index != 0) { - val values = line.split(",") - parseCSV(values)?.let { tle -> parsedItems.add(tle) } + suspend fun parseCSVStream(csvStream: InputStream): List = + withContext(defaultDispatcher) { + val parsedItems = mutableListOf() + csvStream.bufferedReader().useLines { lines -> + lines.forEachIndexed { index, line -> + if (index != 0) { + val values = line.split(",") + parseCSV(values)?.let { tle -> parsedItems.add(tle) } + } } } + return@withContext parsedItems } - return@withContext parsedItems - } - suspend fun parseTLEStream(tleStream: InputStream): List = withContext(parserDispatcher) { - val tleStrings = mutableListOf(String(), String(), String()) - val parsedItems = mutableListOf() - var lineIndex = 0 - tleStream.bufferedReader().forEachLine { line -> - tleStrings[lineIndex] = line - if (lineIndex < 2) { - lineIndex++ - } else { - val isLineOneValid = tleStrings[1].substring(0, 1) == "1" - val isLineTwoValid = tleStrings[2].substring(0, 1) == "2" - if (!isLineOneValid && !isLineTwoValid) return@forEachLine - parseTLE(tleStrings)?.let { tle -> parsedItems.add(tle) } - lineIndex = 0 + suspend fun parseTLEStream(tleStream: InputStream): List = + withContext(defaultDispatcher) { + val tleStrings = mutableListOf(String(), String(), String()) + val parsedItems = mutableListOf() + var lineIndex = 0 + tleStream.bufferedReader().forEachLine { line -> + tleStrings[lineIndex] = line + if (lineIndex < 2) { + lineIndex++ + } else { + val isLineOneValid = tleStrings[1].substring(0, 1) == "1" + val isLineTwoValid = tleStrings[2].substring(0, 1) == "2" + if (!isLineOneValid && !isLineTwoValid) return@forEachLine + parseTLE(tleStrings)?.let { tle -> parsedItems.add(tle) } + lineIndex = 0 + } } + return@withContext parsedItems } - return@withContext parsedItems - } suspend fun parseJSONStream(jsonStream: InputStream): List { - return withContext(parserDispatcher) { + return withContext(defaultDispatcher) { val parsedItems = mutableListOf() try { val jsonArray = JSONArray(jsonStream.bufferedReader().readText()) diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/DataReporter.kt b/base/src/main/java/com/rtbishop/look4sat/utility/DataReporter.kt similarity index 91% rename from data/src/main/java/com/rtbishop/look4sat/domain/DataReporter.kt rename to base/src/main/java/com/rtbishop/look4sat/utility/DataReporter.kt index 9212cf04..b670a921 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/DataReporter.kt +++ b/base/src/main/java/com/rtbishop/look4sat/utility/DataReporter.kt @@ -15,16 +15,18 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain +package com.rtbishop.look4sat.utility -import kotlinx.coroutines.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.launch import java.net.InetSocketAddress import java.nio.ByteBuffer import java.nio.channels.SocketChannel -class DataReporter(reporterDispatcher: CoroutineDispatcher) { +class DataReporter(private val reporterScope: CoroutineScope) { - private val reporterScope = CoroutineScope(reporterDispatcher) private var rotationSocketChannel: SocketChannel? = null private var rotationReporting: Job? = null diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/Extensions.kt b/base/src/main/java/com/rtbishop/look4sat/utility/Extensions.kt similarity index 98% rename from data/src/main/java/com/rtbishop/look4sat/domain/Extensions.kt rename to base/src/main/java/com/rtbishop/look4sat/utility/Extensions.kt index 00f3c003..3c26b063 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/Extensions.kt +++ b/base/src/main/java/com/rtbishop/look4sat/utility/Extensions.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 +package com.rtbishop.look4sat.utility import java.net.InetSocketAddress import java.net.Socket diff --git a/data/src/main/java/com/rtbishop/look4sat/domain/QthConverter.kt b/base/src/main/java/com/rtbishop/look4sat/utility/QthConverter.kt similarity index 98% rename from data/src/main/java/com/rtbishop/look4sat/domain/QthConverter.kt rename to base/src/main/java/com/rtbishop/look4sat/utility/QthConverter.kt index 8413fc6b..12bcb946 100644 --- a/data/src/main/java/com/rtbishop/look4sat/domain/QthConverter.kt +++ b/base/src/main/java/com/rtbishop/look4sat/utility/QthConverter.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 +package com.rtbishop.look4sat.utility import com.rtbishop.look4sat.domain.predict.GeoPos diff --git a/data/src/test/java/com/rtbishop/look4sat/DataParserTest.kt b/base/src/test/java/com/rtbishop/look4sat/DataParserTest.kt similarity index 99% rename from data/src/test/java/com/rtbishop/look4sat/DataParserTest.kt rename to base/src/test/java/com/rtbishop/look4sat/DataParserTest.kt index 8a1b938e..0b4da953 100644 --- a/data/src/test/java/com/rtbishop/look4sat/DataParserTest.kt +++ b/base/src/test/java/com/rtbishop/look4sat/DataParserTest.kt @@ -17,7 +17,7 @@ */ package com.rtbishop.look4sat -import com.rtbishop.look4sat.data.DataParser +import com.rtbishop.look4sat.utility.DataParser import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.runTest diff --git a/data/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt b/base/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt similarity index 97% rename from data/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt rename to base/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt index ecdb32e6..e5f0317d 100644 --- a/data/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt +++ b/base/src/test/java/com/rtbishop/look4sat/QthConverterTest.kt @@ -17,7 +17,7 @@ */ package com.rtbishop.look4sat -import com.rtbishop.look4sat.domain.QthConverter +import com.rtbishop.look4sat.utility.QthConverter import org.junit.Test class QthConverterTest { diff --git a/build.gradle b/build.gradle index 0e9b3697..5e9a22d8 100644 --- a/build.gradle +++ b/build.gradle @@ -6,8 +6,8 @@ buildscript { } plugins { - id "com.android.application" version '7.1.2' apply false - id "com.android.library" version '7.1.2' apply false + id "com.android.application" version "7.1.2" apply false + id "com.android.library" version "7.1.2" apply false id "org.jetbrains.kotlin.android" version "1.6.10" apply false } diff --git a/settings.gradle b/settings.gradle index 701ee240..2f09b498 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,4 +14,4 @@ dependencyResolutionManagement { } rootProject.name = "Look4Sat" include ":app" -include ":data" +include ":base"