Added more frequency data fields to Radio class

develop
Arty Bishop 2023-09-16 13:42:09 +01:00
rodzic 3e978a3ec5
commit e6f3e554fa
17 zmienionych plików z 172 dodań i 175 usunięć

Wyświetl plik

@ -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")
}

Wyświetl plik

@ -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())

Wyświetl plik

@ -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<SatPass>,
navToRadar: (Int, Long) -> Unit
refreshState: PullRefreshState, isRefreshing: Boolean, passes: List<SatPass>, navToRadar: (Int, Long) -> Unit
) {
ElevatedCard(modifier = Modifier.fillMaxSize()) {
Box(Modifier.pullRefresh(refreshState)) {

Wyświetl plik

@ -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(

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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")

Wyświetl plik

@ -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")
// }
//}

Wyświetl plik

@ -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<String>): List<Int>
@Query("SELECT COUNT(*) FROM radios")

Wyświetl plik

@ -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<String>
)
data class SatItem(val catnum: Int, val name: String)

Wyświetl plik

@ -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

Wyświetl plik

@ -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() }
}

Wyświetl plik

@ -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<DomainRadio>.toFrameworkRadios() = this.map { radio -> radio.toFramework() }

Wyświetl plik

@ -17,9 +17,4 @@
*/
package com.rtbishop.look4sat.domain.model
data class SatItem(
val catnum: Int,
val name: String,
// val modes: List<String>,
val isSelected: Boolean
)
data class SatItem(val catnum: Int, val name: String, val isSelected: Boolean)

Wyświetl plik

@ -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

Wyświetl plik

@ -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))
}

Wyświetl plik

@ -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<String>): 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<String>): 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<String>): 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<String>): 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
}
}

Wyświetl plik

@ -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