From e6f3e554fa96de293eb0c508c46c49ee5ce8d9c0 Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Sat, 16 Sep 2023 13:42:09 +0100 Subject: [PATCH] Added more frequency data fields to Radio class --- app/build.gradle.kts | 22 +-- .../com/rtbishop/look4sat/MainContainer.kt | 5 +- .../presentation/passes/PassesScreen.kt | 92 +++++++------ .../presentation/radar/RadarScreen.kt | 6 +- build.gradle.kts | 6 +- data/build.gradle.kts | 2 +- .../look4sat/data/database/MainDatabase.kt | 21 ++- .../look4sat/data/database/dao/StorageDao.kt | 2 +- .../look4sat/data/database/entity/SatItem.kt | 12 +- .../look4sat/data/database/entity/SatRadio.kt | 9 +- .../look4sat/data/repository/SatelliteRepo.kt | 4 +- .../look4sat/data/source/LocalSource.kt | 8 +- .../rtbishop/look4sat/domain/model/SatItem.kt | 7 +- .../look4sat/domain/model/SatRadio.kt | 9 +- .../look4sat/domain/predict/Satellite.kt | 10 ++ .../look4sat/domain/utility/DataParser.kt | 130 ++++++++---------- .../look4sat/domain/DataParserTest.kt | 2 +- 17 files changed, 172 insertions(+), 175 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4aa74d8a..b932bec4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -30,7 +30,7 @@ android { proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } - composeOptions { kotlinCompilerExtensionVersion = "1.5.2" } + composeOptions { kotlinCompilerExtensionVersion = "1.5.3" } } dependencies { @@ -43,21 +43,21 @@ dependencies { ksp("androidx.room:room-compiler:2.5.2") implementation("androidx.activity:activity-compose:1.7.2") - implementation("androidx.compose.animation:animation:1.5.0") - implementation("androidx.compose.compiler:compiler:1.5.2") + implementation("androidx.compose.animation:animation:1.5.1") + implementation("androidx.compose.compiler:compiler:1.5.3") implementation("androidx.compose.material3:material3:1.1.1") - implementation("androidx.compose.runtime:runtime:1.5.0") - implementation("androidx.compose.ui:ui-tooling-preview:1.5.0") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1") - implementation("androidx.navigation:navigation-compose:2.7.1") + implementation("androidx.compose.runtime:runtime:1.5.1") + implementation("androidx.compose.ui:ui-tooling-preview:1.5.1") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2") + implementation("androidx.navigation:navigation-compose:2.7.2") implementation("com.squareup.okhttp3:okhttp:4.10.0") - implementation("org.osmdroid:osmdroid-android:6.1.16") - debugImplementation("androidx.compose.ui:ui-tooling:1.5.0") - debugImplementation("androidx.compose.ui:ui-test-manifest:1.5.0") + implementation("org.osmdroid:osmdroid-android:6.1.17") + debugImplementation("androidx.compose.ui:ui-tooling:1.5.1") + debugImplementation("androidx.compose.ui:ui-test-manifest:1.5.1") testImplementation("junit:junit:4.13.2") testImplementation("io.mockk:mockk:1.13.7") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") - androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.5.0") + androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.5.1") } diff --git a/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt b/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt index cdee1a1c..b87edbdd 100644 --- a/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt +++ b/app/src/main/java/com/rtbishop/look4sat/MainContainer.kt @@ -6,7 +6,6 @@ import android.hardware.Sensor import android.hardware.SensorManager import android.location.LocationManager import androidx.room.Room -import com.rtbishop.look4sat.data.database.MIGRATION_1_2 import com.rtbishop.look4sat.data.database.MainDatabase import com.rtbishop.look4sat.data.framework.BluetoothReporter import com.rtbishop.look4sat.data.framework.NetworkReporter @@ -71,8 +70,8 @@ class MainContainer(private val context: Context) { } private fun provideLocalSource(): ILocalSource { - val database = Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb").apply { - addMigrations(MIGRATION_1_2) + val database = Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDBv313").apply { +// addMigrations(MIGRATION_1_2) fallbackToDestructiveMigration() }.build() return LocalSource(database.storageDao()) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt index 5029e514..4d689d92 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt @@ -27,6 +27,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.PlatformTextStyle +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -59,35 +61,50 @@ fun PassesScreen(uiState: PassesState, navToRadar: (Int, Long) -> Unit) { } } Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { - ElevatedCard(modifier = Modifier.height(52.dp)) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxSize() - ) { - IconButton(onClick = { toggleDialog() }) { - Icon( - painter = painterResource(id = R.drawable.ic_filter), - contentDescription = null - ) - } - Column(verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.weight(1f)) { - Text(text = "Next - Id:${uiState.nextId}", maxLines = 1, overflow = TextOverflow.Ellipsis) - Text(text = uiState.nextName, maxLines = 1, overflow = TextOverflow.Ellipsis) - } + TopBar(nextId = uiState.nextId, nextName = uiState.nextName, nextTime = uiState.nextTime, toggleDialog) + PassesCard(refreshState, uiState.isRefreshing, uiState.itemsList, navToRadar) + } +} + +@Composable +@Preview(showBackground = true) +private fun TopBarPreview() { + MainTheme { TopBar(nextId = 45555, nextName = "Stuff", nextTime = "88:88:88") {} } +} + +@Composable +private fun TopBar(nextId: Int, nextName: String, nextTime: String, toggleDialog: () -> Unit) { + ElevatedCard(modifier = Modifier.height(48.dp)) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxSize() + ) { + Icon( + painter = painterResource(id = R.drawable.ic_sputnik), + contentDescription = null, + modifier = Modifier.padding(12.dp) + ) + Column(verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.weight(1f)) { Text( - text = uiState.nextTime, - fontSize = 36.sp, - fontWeight = FontWeight.Bold, + text = "AOS - Id:$nextId", color = MaterialTheme.colorScheme.primary, - textAlign = TextAlign.End, - modifier = Modifier - .weight(1f) - .padding(bottom = 2.dp, end = 8.dp) + maxLines = 1, + overflow = TextOverflow.Ellipsis ) + Text(text = nextName, fontWeight = FontWeight.Medium, maxLines = 1, overflow = TextOverflow.Ellipsis) + } + Text( + text = nextTime, + fontSize = 32.sp, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.primary, + style = TextStyle(platformStyle = PlatformTextStyle(includeFontPadding = false)) + ) + IconButton(onClick = { toggleDialog() }) { + Icon(painter = painterResource(id = R.drawable.ic_filter), contentDescription = null) } } - PassesCard(refreshState, uiState.isRefreshing, uiState.itemsList, navToRadar) } } @@ -98,7 +115,7 @@ private fun PassPreview() { "Satellite", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 45000, 0.0 ) val satellite = NearEarthSatellite(data) - val pass = SatPass(1L, 25.0, 10L, 75.0, 850, 45.0, satellite, 0.5f) + val pass = SatPass(1L, 0.0, 10L, 180.0, 850, 45.0, satellite, 0.5f) MainTheme { Pass(pass = pass, { _, _ -> }) } } @@ -149,17 +166,21 @@ private fun Pass(pass: SatPass, navToRadar: (Int, Long) -> Unit, modifier: Modif ) { Text( text = stringResource(id = R.string.pass_aosAz, pass.aosAzimuth), - fontSize = 15.sp + textAlign = TextAlign.Start, + fontSize = 15.sp, + modifier = Modifier.weight(1f) ) Text( text = stringResource(id = R.string.pass_altitude, pass.altitude), textAlign = TextAlign.Center, fontSize = 15.sp, - modifier = Modifier.weight(1f) + modifier = Modifier.weight(2f) ) Text( text = stringResource(id = R.string.pass_losAz, pass.losAzimuth), - fontSize = 15.sp + textAlign = TextAlign.End, + fontSize = 15.sp, + modifier = Modifier.weight(1f) ) } Row( @@ -168,10 +189,7 @@ private fun Pass(pass: SatPass, navToRadar: (Int, Long) -> Unit, modifier: Modif modifier = Modifier.fillMaxWidth() ) { val deepTime = stringResource(id = R.string.pass_placeholder) - Text( - text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.aosTime)), - fontSize = 15.sp - ) + Text(text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.aosTime)), fontSize = 15.sp) LinearProgressIndicator( progress = if (pass.isDeepSpace) 1f else pass.progress, modifier = modifier @@ -179,10 +197,7 @@ private fun Pass(pass: SatPass, navToRadar: (Int, Long) -> Unit, modifier: Modif .padding(top = 3.dp), trackColor = MaterialTheme.colorScheme.inverseSurface ) - Text( - text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.losTime)), - fontSize = 15.sp - ) + Text(text = if (pass.isDeepSpace) deepTime else sdf.format(Date(pass.losTime)), fontSize = 15.sp) } } } @@ -192,10 +207,7 @@ private fun Pass(pass: SatPass, navToRadar: (Int, Long) -> Unit, modifier: Modif @OptIn(ExperimentalFoundationApi::class) @Composable private fun PassesCard( - refreshState: PullRefreshState, - isRefreshing: Boolean, - passes: List, - navToRadar: (Int, Long) -> Unit + refreshState: PullRefreshState, isRefreshing: Boolean, passes: List, navToRadar: (Int, Long) -> Unit ) { ElevatedCard(modifier = Modifier.fillMaxSize()) { Box(Modifier.pullRefresh(refreshState)) { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt index 8a1dc7d6..069e381f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt @@ -121,13 +121,13 @@ private fun TransmitterItem(radio: SatRadio) { } Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) { Text( - text = stringResource(id = R.string.radio_downlink, radio.downlink ?: 0L), + text = stringResource(id = R.string.radio_downlink, radio.downlinkLow ?: 0L), textAlign = TextAlign.Center, fontSize = 15.sp, modifier = Modifier.weight(0.5f) ) Text( - text = stringResource(id = R.string.radio_uplink, radio.uplink ?: 0L), + text = stringResource(id = R.string.radio_uplink, radio.uplinkLow ?: 0L), textAlign = TextAlign.Center, fontSize = 15.sp, modifier = Modifier.weight(0.5f) @@ -139,7 +139,7 @@ private fun TransmitterItem(radio: SatRadio) { modifier = Modifier.fillMaxWidth() ) { Text( - text = radio.mode ?: "", + text = radio.downlinkMode ?: "", fontSize = 15.sp ) Text( diff --git a/build.gradle.kts b/build.gradle.kts index 83c8b9eb..db084758 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,9 @@ plugins { id("com.android.application") version "8.1.1" apply false id("com.android.library") version "8.1.1" apply false - id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false - id("org.jetbrains.kotlin.android") version "1.9.0" apply false - id("org.jetbrains.kotlin.jvm") version "1.9.0" apply false + id("com.google.devtools.ksp") version "1.9.10-1.0.13" apply false + id("org.jetbrains.kotlin.android") version "1.9.10" apply false + id("org.jetbrains.kotlin.jvm") version "1.9.10" apply false } tasks.register("clean", Delete::class.java) { diff --git a/data/build.gradle.kts b/data/build.gradle.kts index eb5b77ba..1f2ac72c 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -20,7 +20,7 @@ android { dependencies { implementation(project(":domain")) - implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.room:room-runtime:2.5.2") implementation("androidx.room:room-ktx:2.5.2") ksp("androidx.room:room-compiler:2.5.2") diff --git a/data/src/main/java/com/rtbishop/look4sat/data/database/MainDatabase.kt b/data/src/main/java/com/rtbishop/look4sat/data/database/MainDatabase.kt index 7ebf68d1..e0a972bf 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/database/MainDatabase.kt +++ b/data/src/main/java/com/rtbishop/look4sat/data/database/MainDatabase.kt @@ -19,23 +19,20 @@ package com.rtbishop.look4sat.data.database import androidx.room.Database import androidx.room.RoomDatabase -import androidx.room.migration.Migration -import androidx.sqlite.db.SupportSQLiteDatabase import com.rtbishop.look4sat.data.database.dao.StorageDao import com.rtbishop.look4sat.data.database.entity.SatEntry import com.rtbishop.look4sat.data.database.entity.SatRadio -@Database(entities = [SatEntry::class, SatRadio::class], version = 2, exportSchema = false) +@Database(entities = [SatEntry::class, SatRadio::class], version = 1, exportSchema = false) abstract class MainDatabase : RoomDatabase() { - abstract fun storageDao(): StorageDao } -val MIGRATION_1_2 = object : Migration(1, 2) { - override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("CREATE TABLE entries_backup (name TEXT NOT NULL, epoch REAL NOT NULL, meanmo REAL NOT NULL, eccn REAL NOT NULL, incl REAL NOT NULL, raan REAL NOT NULL, argper REAL NOT NULL, meanan REAL NOT NULL, catnum INTEGER NOT NULL, bstar REAL NOT NULL, xincl REAL NOT NULL, xnodeo REAL NOT NULL, omegao REAL NOT NULL, xmo REAL NOT NULL, xno REAL NOT NULL, orbitalPeriod REAL NOT NULL, isDeepSpace INTEGER NOT NULL, comment TEXT, PRIMARY KEY(catnum))") - database.execSQL("INSERT INTO entries_backup (name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar, xincl, xnodeo, omegao, xmo, xno, orbitalPeriod, isDeepSpace, comment) SELECT name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar, xincl, xnodeo, omegao, xmo, xno, 1440 / meanmo, 1440 / meanmo >= 225.0, comment FROM entries") - database.execSQL("DROP TABLE entries") - database.execSQL("ALTER TABLE entries_backup RENAME TO entries") - } -} +//val MIGRATION_1_2 = object : Migration(1, 2) { +// override fun migrate(database: SupportSQLiteDatabase) { +// database.execSQL("CREATE TABLE entries_backup (name TEXT NOT NULL, epoch REAL NOT NULL, meanmo REAL NOT NULL, eccn REAL NOT NULL, incl REAL NOT NULL, raan REAL NOT NULL, argper REAL NOT NULL, meanan REAL NOT NULL, catnum INTEGER NOT NULL, bstar REAL NOT NULL, xincl REAL NOT NULL, xnodeo REAL NOT NULL, omegao REAL NOT NULL, xmo REAL NOT NULL, xno REAL NOT NULL, orbitalPeriod REAL NOT NULL, isDeepSpace INTEGER NOT NULL, comment TEXT, PRIMARY KEY(catnum))") +// database.execSQL("INSERT INTO entries_backup (name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar, xincl, xnodeo, omegao, xmo, xno, orbitalPeriod, isDeepSpace, comment) SELECT name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar, xincl, xnodeo, omegao, xmo, xno, 1440 / meanmo, 1440 / meanmo >= 225.0, comment FROM entries") +// database.execSQL("DROP TABLE entries") +// database.execSQL("ALTER TABLE entries_backup RENAME TO entries") +// } +//} diff --git a/data/src/main/java/com/rtbishop/look4sat/data/database/dao/StorageDao.kt b/data/src/main/java/com/rtbishop/look4sat/data/database/dao/StorageDao.kt index 1e1e7708..07231779 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/database/dao/StorageDao.kt +++ b/data/src/main/java/com/rtbishop/look4sat/data/database/dao/StorageDao.kt @@ -46,7 +46,7 @@ interface StorageDao { @Query("DELETE FROM entries") suspend fun deleteEntries() - @Query("SELECT catnum FROM radios WHERE mode IN (:modes)") + @Query("SELECT catnum FROM radios WHERE downlinkMode IN (:modes)") suspend fun getIdsWithModes(modes: List): List @Query("SELECT COUNT(*) FROM radios") diff --git a/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatItem.kt b/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatItem.kt index 004b5bd2..c67f0711 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatItem.kt +++ b/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatItem.kt @@ -17,14 +17,4 @@ */ package com.rtbishop.look4sat.data.database.entity -data class SatItem( - val catnum: Int, - val name: String -// @Relation( -// parentColumn = "catnum", -// entity = SatRadio::class, -// entityColumn = "catnum", -// projection = ["mode"] -// ) -// val modes: List -) +data class SatItem(val catnum: Int, val name: String) diff --git a/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatRadio.kt b/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatRadio.kt index f53756cd..5f04a703 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatRadio.kt +++ b/data/src/main/java/com/rtbishop/look4sat/data/database/entity/SatRadio.kt @@ -25,9 +25,12 @@ data class SatRadio( @PrimaryKey val uuid: String, val info: String, val isAlive: Boolean, - var downlink: Long?, - var uplink: Long?, - val mode: String?, + var downlinkLow: Long?, + var downlinkHigh: Long?, + val downlinkMode: String?, + var uplinkLow: Long?, + var uplinkHigh: Long?, + val uplinkMode: String?, val isInverted: Boolean, val catnum: Int?, var comment: String? = null diff --git a/data/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt b/data/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt index 9d5c0d45..5ec57cf2 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt +++ b/data/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt @@ -76,8 +76,8 @@ class SatelliteRepo( val satPos = sat.getPosition(pos, time) val copiedList = radios.map { it.copy() } copiedList.forEach { transmitter -> - transmitter.downlink?.let { transmitter.downlink = satPos.getDownlinkFreq(it) } - transmitter.uplink?.let { transmitter.uplink = satPos.getUplinkFreq(it) } + transmitter.downlinkLow?.let { transmitter.downlinkLow = satPos.getDownlinkFreq(it) } + transmitter.uplinkLow?.let { transmitter.uplinkLow = satPos.getUplinkFreq(it) } } copiedList.map { it.copy() } } diff --git a/data/src/main/java/com/rtbishop/look4sat/data/source/LocalSource.kt b/data/src/main/java/com/rtbishop/look4sat/data/source/LocalSource.kt index 6d72612e..728fbfb9 100644 --- a/data/src/main/java/com/rtbishop/look4sat/data/source/LocalSource.kt +++ b/data/src/main/java/com/rtbishop/look4sat/data/source/LocalSource.kt @@ -80,13 +80,13 @@ class LocalSource(private val storageDao: StorageDao) : ILocalSource { override suspend fun deleteRadios() = storageDao.deleteRadios() private fun DomainRadio.toFramework() = FrameworkRadio( - this.uuid, this.info, this.isAlive, this.downlink, this.uplink, - this.mode, this.isInverted, this.catnum, this.comment + this.uuid, this.info, this.isAlive, this.downlinkLow, this.downlinkHigh, this.downlinkMode, + this.uplinkLow, this.uplinkHigh, this.uplinkMode, 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 + this.uuid, this.info, this.isAlive, this.downlinkLow, this.downlinkHigh, this.downlinkMode, + this.uplinkLow, this.uplinkHigh, this.uplinkMode, this.isInverted, this.catnum, this.comment ) private fun List.toFrameworkRadios() = this.map { radio -> radio.toFramework() } diff --git a/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt b/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt index cc202c86..450a2b80 100644 --- a/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt +++ b/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt @@ -17,9 +17,4 @@ */ package com.rtbishop.look4sat.domain.model -data class SatItem( - val catnum: Int, - val name: String, -// val modes: List, - val isSelected: Boolean -) +data class SatItem(val catnum: Int, val name: String, val isSelected: Boolean) diff --git a/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt b/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt index 250e42d4..420bdd55 100644 --- a/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt +++ b/domain/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt @@ -21,9 +21,12 @@ data class SatRadio( val uuid: String, val info: String, val isAlive: Boolean, - var downlink: Long?, - var uplink: Long?, - val mode: String?, + var downlinkLow: Long?, + var downlinkHigh: Long?, + val downlinkMode: String?, + var uplinkLow: Long?, + var uplinkHigh: Long?, + val uplinkMode: String?, val isInverted: Boolean, val catnum: Int?, var comment: String? = null diff --git a/domain/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt b/domain/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt index 870924e4..340725a7 100644 --- a/domain/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt +++ b/domain/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt @@ -383,6 +383,16 @@ abstract class Satellite(val data: OrbitalData) { return acos(dot(v1, v2) / (v1.w * v2.w)) } + /** + * The function Delta_ET has been added to allow calculations on the + * position of the sun. It provides the difference between UT (approximately + * the same as UTC) and ET (now referred to as TDT) This function is based + * on a least squares fit of data from 1950 to 1991 and will need to be + * updated periodically. + * + * Values determined using data from 1950-1991 in the 1990 Astronomical + * Almanac. See DELTA_ET.WQ1 for details. + */ private fun deltaEt(year: Double): Double { return 26.465 + 0.747622 * (year - 1950) + (1.886913 * sin(TWO_PI * (year - 1975) / 33)) } diff --git a/domain/src/main/java/com/rtbishop/look4sat/domain/utility/DataParser.kt b/domain/src/main/java/com/rtbishop/look4sat/domain/utility/DataParser.kt index 61fbc83d..b175b900 100644 --- a/domain/src/main/java/com/rtbishop/look4sat/domain/utility/DataParser.kt +++ b/domain/src/main/java/com/rtbishop/look4sat/domain/utility/DataParser.kt @@ -19,12 +19,12 @@ package com.rtbishop.look4sat.domain.utility import com.rtbishop.look4sat.domain.model.SatRadio import com.rtbishop.look4sat.domain.predict.OrbitalData +import java.io.InputStream +import kotlin.math.pow import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext import org.json.JSONArray import org.json.JSONObject -import java.io.InputStream -import kotlin.math.pow class DataParser(private val dispatcher: CoroutineDispatcher) { @@ -74,75 +74,30 @@ class DataParser(private val dispatcher: CoroutineDispatcher) { } } - private fun parseCSV(values: List): OrbitalData? { - try { - val name = values[0] - val year = values[2].substring(0, 4) - val month = values[2].substring(5, 7) - val dayOfMonth = values[2].substring(8, 10) - val dayInt = getDayOfYear(year.toInt(), month.toInt(), dayOfMonth.toInt()) - val day = if (dayInt < 10) "00$dayInt" else if (dayInt < 100) "0$dayInt" else "$dayInt" - val hour = values[2].substring(11, 13).toInt() * 3600000 // ms in one hour - val min = values[2].substring(14, 16).toInt() * 60000 // ms in one minute - val sec = values[2].substring(17, 19).toInt() * 1000 // ms in one second - val ms = values[2].substring(20, 26).toInt() / 1000.0 // microseconds to ms - val frac = ((hour + min + sec + ms) / 86400000.0).toString() - val epoch = "${year.substring(2)}$day${frac.substring(1)}".toDouble() - val meanmo = values[3].toDouble() - val eccn = values[4].toDouble() - val incl = values[5].toDouble() - val raan = values[6].toDouble() - val argper = values[7].toDouble() - val meanan = values[8].toDouble() - val catnum = values[11].toInt() - val bstar = values[14].toDouble() - return OrbitalData(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar) - } catch (exception: Exception) { - return null - } - } - - private fun parseTLE(tle: List): OrbitalData? { - if (tle[1].substring(0, 1) != "1" && tle[2].substring(0, 1) != "2") { - return null - } - try { - val name: String = tle[0].trim() - val epoch: Double = tle[1].substring(18, 32).toDouble() - val meanmo: Double = tle[2].substring(52, 63).toDouble() - val eccn: Double = tle[2].substring(26, 33).toDouble() / 10000000.0 - val incl: Double = tle[2].substring(8, 16).toDouble() - val raan: Double = tle[2].substring(17, 25).toDouble() - val argper: Double = tle[2].substring(34, 42).toDouble() - val meanan: Double = tle[2].substring(43, 51).toDouble() - val catnum: Int = tle[1].substring(2, 7).trim().toInt() - val bstar: Double = 1.0e-5 * tle[1].substring(53, 59).toDouble() / 10.0.pow( - tle[1].substring(60, 61).toDouble() - ) - return OrbitalData(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar) - } catch (exception: Exception) { - return null - } - } - - private fun parseJSON(json: JSONObject): SatRadio? { - try { - val uuid = json.getString("uuid") - val info = json.getString("description") - val isAlive = json.getBoolean("alive") - val downlink = if (json.isNull("downlink_low")) null - else json.getLong("downlink_low") - val uplink = if (json.isNull("uplink_low")) null - else json.getLong("uplink_low") - val mode = if (json.isNull("mode")) null - else json.getString("mode") - val isInverted = json.getBoolean("invert") - val catnum = if (json.isNull("norad_cat_id")) null - else json.getInt("norad_cat_id") - return SatRadio(uuid, info, isAlive, downlink, uplink, mode, isInverted, catnum) - } catch (exception: Exception) { - return null - } + private fun parseCSV(values: List): OrbitalData? = try { + val name = values[0] + val year = values[2].substring(0, 4) + val month = values[2].substring(5, 7) + val dayOfMonth = values[2].substring(8, 10) + val dayInt = getDayOfYear(year.toInt(), month.toInt(), dayOfMonth.toInt()) + val day = if (dayInt < 10) "00$dayInt" else if (dayInt < 100) "0$dayInt" else "$dayInt" + val hour = values[2].substring(11, 13).toInt() * 3600000 // ms in one hour + val min = values[2].substring(14, 16).toInt() * 60000 // ms in one minute + val sec = values[2].substring(17, 19).toInt() * 1000 // ms in one second + val ms = values[2].substring(20, 26).toInt() / 1000.0 // microseconds to ms + val frac = ((hour + min + sec + ms) / 86400000.0).toString() + val epoch = "${year.substring(2)}$day${frac.substring(1)}".toDouble() + val meanmo = values[3].toDouble() + val eccn = values[4].toDouble() + val incl = values[5].toDouble() + val raan = values[6].toDouble() + val argper = values[7].toDouble() + val meanan = values[8].toDouble() + val catnum = values[11].toInt() + val bstar = values[14].toDouble() + OrbitalData(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar) + } catch (exception: Exception) { + null } private fun getDayOfYear(year: Int, month: Int, dayOfMonth: Int): Int { @@ -154,4 +109,37 @@ class DataParser(private val dispatcher: CoroutineDispatcher) { for (i in 0 until month - 1) dayOfYear += daysArray[i] return dayOfYear } + + private fun parseTLE(tle: List): OrbitalData? = try { + val name: String = tle[0].trim() + val epoch: Double = tle[1].substring(18, 32).toDouble() + val meanmo: Double = tle[2].substring(52, 63).toDouble() + val eccn: Double = tle[2].substring(26, 33).toDouble() / 10000000.0 + val incl: Double = tle[2].substring(8, 16).toDouble() + val raan: Double = tle[2].substring(17, 25).toDouble() + val argper: Double = tle[2].substring(34, 42).toDouble() + val meanan: Double = tle[2].substring(43, 51).toDouble() + val catnum: Int = tle[1].substring(2, 7).trim().toInt() + val bstar: Double = 1.0e-5 * tle[1].substring(53, 59).toDouble() / 10.0.pow(tle[1].substring(60, 61).toDouble()) + OrbitalData(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar) + } catch (exception: Exception) { + null + } + + private fun parseJSON(json: JSONObject): SatRadio? = try { + val uuid = json.getString("uuid") + val info = json.getString("description") + val alive = json.getBoolean("alive") + val dlinkLow = if (json.isNull("downlink_low")) null else json.getLong("downlink_low") + val dlinkHigh = if (json.isNull("downlink_high")) null else json.getLong("downlink_high") + val dlinkMode = if (json.isNull("mode")) null else json.getString("mode") + val ulinkLow = if (json.isNull("uplink_low")) null else json.getLong("uplink_low") + val ulinkHigh = if (json.isNull("uplink_high")) null else json.getLong("uplink_high") + val ulinkMode = if (json.isNull("uplink_mode")) null else json.getString("uplink_mode") + val inverted = json.getBoolean("invert") + val catnum = if (json.isNull("norad_cat_id")) null else json.getInt("norad_cat_id") + SatRadio(uuid, info, alive, dlinkLow, dlinkHigh, dlinkMode, ulinkLow, ulinkHigh, ulinkMode, inverted, catnum) + } catch (exception: Exception) { + null + } } diff --git a/domain/src/test/java/com/rtbishop/look4sat/domain/DataParserTest.kt b/domain/src/test/java/com/rtbishop/look4sat/domain/DataParserTest.kt index 7436d5a7..0fb5cee0 100644 --- a/domain/src/test/java/com/rtbishop/look4sat/domain/DataParserTest.kt +++ b/domain/src/test/java/com/rtbishop/look4sat/domain/DataParserTest.kt @@ -74,7 +74,7 @@ class DataParserTest { @Test fun `Given valid JSON stream returns valid data`() = runTest(testDispatcher) { - assert(dataParser.parseJSONStream(validJSONStream)[0].downlink == 136658500L) + assert(dataParser.parseJSONStream(validJSONStream)[0].downlinkLow == 136658500L) } @Test