mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Renamed and moved several classes and interfaces
This commit is contained in:
1 parent
84240c94c6
commit
b6d019ace7
24 files changed
+155
-153
No files matched your search
+4
-4
@@ -21,11 +21,11 @@ import com.rtbishop.look4sat.domain.Transmitter
|
||||
import com.rtbishop.look4sat.domain.Satellite
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface LocalDataSource {
|
||||
interface LocalSource {
|
||||
|
||||
fun getSatItems(): Flow<List<SatItem>>
|
||||
fun getEntriesWithModes(): Flow<List<SatItem>>
|
||||
|
||||
fun getSatTransmitters(catNum: Int): Flow<List<Transmitter>>
|
||||
fun getTransmitters(catNum: Int): Flow<List<Transmitter>>
|
||||
|
||||
suspend fun getSelectedSatellites(): List<Satellite>
|
||||
|
||||
@@ -33,5 +33,5 @@ interface LocalDataSource {
|
||||
|
||||
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean)
|
||||
|
||||
suspend fun updateTransmitters(satelliteTrans: List<Transmitter>)
|
||||
suspend fun updateTransmitters(transmitters: List<Transmitter>)
|
||||
}
|
||||
+1
-1
@@ -19,7 +19,7 @@ package com.rtbishop.look4sat.data
|
||||
|
||||
import com.rtbishop.look4sat.domain.GeoPos
|
||||
|
||||
interface PreferencesSource {
|
||||
interface Preferences {
|
||||
|
||||
fun positionToQTH(lat: Double, lon: Double): String?
|
||||
|
||||
+2
-2
@@ -20,9 +20,9 @@ package com.rtbishop.look4sat.data
|
||||
import com.rtbishop.look4sat.domain.Transmitter
|
||||
import java.io.InputStream
|
||||
|
||||
interface RemoteDataSource {
|
||||
interface RemoteSource {
|
||||
|
||||
suspend fun fetchDataStream(url: String): InputStream?
|
||||
suspend fun fetchFileStream(url: String): InputStream?
|
||||
|
||||
suspend fun fetchTransmitters(): List<Transmitter>
|
||||
}
|
||||
@@ -29,43 +29,43 @@ import java.io.InputStream
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
class SatelliteRepo(
|
||||
private val preferencesSource: PreferencesSource,
|
||||
private val localDataSource: LocalDataSource,
|
||||
private val remoteDataSource: RemoteDataSource,
|
||||
private val ioDispatcher: CoroutineDispatcher
|
||||
private val preferences: Preferences,
|
||||
private val localSource: LocalSource,
|
||||
private val remoteSource: RemoteSource,
|
||||
private val repoDispatcher: CoroutineDispatcher
|
||||
) {
|
||||
|
||||
fun saveSelectedModes(modes: List<String>) {
|
||||
preferencesSource.saveModesSelection(modes)
|
||||
preferences.saveModesSelection(modes)
|
||||
}
|
||||
|
||||
fun loadSelectedModes(): List<String> {
|
||||
return preferencesSource.loadModesSelection()
|
||||
return preferences.loadModesSelection()
|
||||
}
|
||||
|
||||
fun getSatItems(): Flow<List<SatItem>> {
|
||||
return localDataSource.getSatItems()
|
||||
return localSource.getEntriesWithModes()
|
||||
}
|
||||
|
||||
fun getSatTransmitters(catNum: Int): Flow<List<Transmitter>> {
|
||||
return localDataSource.getSatTransmitters(catNum)
|
||||
return localSource.getTransmitters(catNum)
|
||||
}
|
||||
|
||||
suspend fun getSelectedSatellites(): List<Satellite> {
|
||||
return localDataSource.getSelectedSatellites()
|
||||
return localSource.getSelectedSatellites()
|
||||
}
|
||||
|
||||
suspend fun updateEntriesFromFile(stream: InputStream) = withContext(ioDispatcher) {
|
||||
localDataSource.updateEntries(importSatEntries(stream))
|
||||
suspend fun updateEntriesFromFile(stream: InputStream) = withContext(repoDispatcher) {
|
||||
localSource.updateEntries(importSatEntries(stream))
|
||||
}
|
||||
|
||||
suspend fun updateEntriesFromWeb(sources: List<String>) {
|
||||
coroutineScope {
|
||||
launch(ioDispatcher) {
|
||||
launch(repoDispatcher) {
|
||||
val streams = mutableListOf<InputStream>()
|
||||
val entries = mutableListOf<SatEntry>()
|
||||
sources.forEach { source ->
|
||||
remoteDataSource.fetchDataStream(source)?.let { stream ->
|
||||
remoteSource.fetchFileStream(source)?.let { stream ->
|
||||
if (source.contains(".zip", true)) {
|
||||
val zipStream = ZipInputStream(stream).apply { nextEntry }
|
||||
streams.add(zipStream)
|
||||
@@ -75,20 +75,20 @@ class SatelliteRepo(
|
||||
}
|
||||
}
|
||||
streams.forEach { stream -> entries.addAll(importSatEntries(stream)) }
|
||||
localDataSource.updateEntries(entries)
|
||||
localSource.updateEntries(entries)
|
||||
}
|
||||
launch(ioDispatcher) {
|
||||
val transmitters = remoteDataSource.fetchTransmitters().filter { it.isAlive }
|
||||
localDataSource.updateTransmitters(transmitters)
|
||||
launch(repoDispatcher) {
|
||||
val transmitters = remoteSource.fetchTransmitters().filter { it.isAlive }
|
||||
localSource.updateTransmitters(transmitters)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
localDataSource.updateEntriesSelection(catNums, isSelected)
|
||||
localSource.updateEntriesSelection(catNums, isSelected)
|
||||
}
|
||||
|
||||
private fun importSatEntries(stream: InputStream): List<SatEntry> {
|
||||
return TLE.parseStream(stream).map { tle -> SatEntry(tle) }
|
||||
return TLE.parseTleStream(stream).map { tle -> SatEntry(tle) }
|
||||
}
|
||||
}
|
||||
@@ -50,35 +50,32 @@ data class SatPos(
|
||||
|
||||
fun getRangeCircle(): List<GeoPos> {
|
||||
val positions = mutableListOf<GeoPos>()
|
||||
val lat = this.latitude
|
||||
val lon = this.longitude
|
||||
// rangeCircleRadiusKm
|
||||
// earthRadiusKm * acos(earthRadiusKm / (earthRadiusKm + satPos.altitude))
|
||||
val beta = acos(earthRadiusKm / (earthRadiusKm + this.altitude))
|
||||
// val radiusKm = earthRadiusKm * acos(earthRadiusKm / (earthRadiusKm + altitude))
|
||||
var tempAzimuth = 0
|
||||
while (tempAzimuth < 360) {
|
||||
val azimuth = tempAzimuth / 360.0 * 2.0 * Math.PI
|
||||
var rangelat = asin(sin(lat) * cos(beta) + cos(azimuth) * sin(beta) * cos(lat))
|
||||
val num = (cos(beta) - (sin(lat) * sin(rangelat)))
|
||||
val den = cos(lat) * cos(rangelat)
|
||||
var rangelon = if (tempAzimuth == 0 && (beta > ((Math.PI / 2.0) - lat))) {
|
||||
lon + Math.PI
|
||||
} else if (tempAzimuth == 180 && (beta > ((Math.PI / 2.0) - lat))) {
|
||||
lon + Math.PI
|
||||
var lat = asin(sin(latitude) * cos(beta) + cos(azimuth) * sin(beta) * cos(latitude))
|
||||
val num = (cos(beta) - (sin(latitude) * sin(lat)))
|
||||
val den = cos(latitude) * cos(lat)
|
||||
var lon = if (tempAzimuth == 0 && (beta > ((Math.PI / 2.0) - latitude))) {
|
||||
longitude + Math.PI
|
||||
} else if (tempAzimuth == 180 && (beta > ((Math.PI / 2.0) - latitude))) {
|
||||
longitude + Math.PI
|
||||
} else if (abs(num / den) > 1.0) {
|
||||
lon
|
||||
longitude
|
||||
} else {
|
||||
if ((180 - tempAzimuth) >= 0) {
|
||||
lon - acos(num / den)
|
||||
longitude - acos(num / den)
|
||||
} else {
|
||||
lon + acos(num / den)
|
||||
longitude + acos(num / den)
|
||||
}
|
||||
}
|
||||
while (rangelon < 0.0) rangelon += Math.PI * 2.0
|
||||
while (rangelon > Math.PI * 2.0) rangelon -= Math.PI * 2.0
|
||||
rangelat = Math.toDegrees(rangelat)
|
||||
rangelon = Math.toDegrees(rangelon)
|
||||
positions.add(GeoPos(rangelat, rangelon))
|
||||
while (lon < 0.0) lon += Math.PI * 2.0
|
||||
while (lon > Math.PI * 2.0) lon -= Math.PI * 2.0
|
||||
lat = Math.toDegrees(lat)
|
||||
lon = Math.toDegrees(lon)
|
||||
positions.add(GeoPos(lat, lon))
|
||||
tempAzimuth += 1
|
||||
}
|
||||
return positions
|
||||
|
||||
@@ -48,39 +48,41 @@ data class TLE(
|
||||
|
||||
companion object {
|
||||
|
||||
fun parseStream(stream: InputStream): List<TLE> {
|
||||
val itemParams = mutableListOf(String(), String(), String())
|
||||
val importedItems = mutableListOf<TLE>()
|
||||
fun parseTleStream(stream: InputStream): List<TLE> {
|
||||
val tleStrings = mutableListOf(String(), String(), String())
|
||||
val parsedItems = mutableListOf<TLE>()
|
||||
var lineIndex = 0
|
||||
stream.bufferedReader().forEachLine { line ->
|
||||
itemParams[lineIndex] = line
|
||||
tleStrings[lineIndex] = line
|
||||
if (lineIndex < 2) {
|
||||
lineIndex++
|
||||
} else {
|
||||
val isLineOneValid = itemParams[1].substring(0, 1) == "1"
|
||||
val isLineTwoValid = itemParams[2].substring(0, 1) == "2"
|
||||
val isLineOneValid = tleStrings[1].substring(0, 1) == "1"
|
||||
val isLineTwoValid = tleStrings[2].substring(0, 1) == "2"
|
||||
if (!isLineOneValid && !isLineTwoValid) return@forEachLine
|
||||
parseParams(itemParams)?.let { tle -> importedItems.add(tle) }
|
||||
parseTleStrings(tleStrings)?.let { tle -> parsedItems.add(tle) }
|
||||
lineIndex = 0
|
||||
}
|
||||
}
|
||||
return importedItems
|
||||
return parsedItems
|
||||
}
|
||||
|
||||
private fun parseParams(params: List<String>): TLE? {
|
||||
if (params[1].substring(0, 1) != "1" && params[2].substring(0, 1) != "2") return null
|
||||
private fun parseTleStrings(tleStrings: List<String>): TLE? {
|
||||
if (tleStrings[1].substring(0, 1) != "1" && tleStrings[2].substring(0, 1) != "2") {
|
||||
return null
|
||||
}
|
||||
try {
|
||||
val name: String = params[0].trim()
|
||||
val epoch: Double = params[1].substring(18, 32).toDouble()
|
||||
val meanmo: Double = params[2].substring(52, 63).toDouble()
|
||||
val eccn: Double = 1.0e-07 * params[2].substring(26, 33).toDouble()
|
||||
val incl: Double = params[2].substring(8, 16).toDouble()
|
||||
val raan: Double = params[2].substring(17, 25).toDouble()
|
||||
val argper: Double = params[2].substring(34, 42).toDouble()
|
||||
val meanan: Double = params[2].substring(43, 51).toDouble()
|
||||
val catnum: Int = params[1].substring(2, 7).trim().toInt()
|
||||
val bstar: Double = 1.0e-5 * params[1].substring(53, 59).toDouble() /
|
||||
10.0.pow(params[1].substring(60, 61).toDouble())
|
||||
val name: String = tleStrings[0].trim()
|
||||
val epoch: Double = tleStrings[1].substring(18, 32).toDouble()
|
||||
val meanmo: Double = tleStrings[2].substring(52, 63).toDouble()
|
||||
val eccn: Double = 1.0e-07 * tleStrings[2].substring(26, 33).toDouble()
|
||||
val incl: Double = tleStrings[2].substring(8, 16).toDouble()
|
||||
val raan: Double = tleStrings[2].substring(17, 25).toDouble()
|
||||
val argper: Double = tleStrings[2].substring(34, 42).toDouble()
|
||||
val meanan: Double = tleStrings[2].substring(43, 51).toDouble()
|
||||
val catnum: Int = tleStrings[1].substring(2, 7).trim().toInt()
|
||||
val bstar: Double = 1.0e-5 * tleStrings[1].substring(53, 59).toDouble() /
|
||||
10.0.pow(tleStrings[1].substring(60, 61).toDouble())
|
||||
return TLE(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar)
|
||||
} catch (exception: Exception) {
|
||||
return null
|
||||
|
||||
+7
-7
@@ -3,9 +3,9 @@ package com.rtbishop.look4sat
|
||||
import com.rtbishop.look4sat.domain.TLE
|
||||
import org.junit.Test
|
||||
|
||||
class Look4SatTest {
|
||||
class TleParserTest {
|
||||
|
||||
private val validParamsStream = """
|
||||
private val validTleStream = """
|
||||
ISS (ZARYA)
|
||||
1 25544U 98067A 21255.21005818 -.00120443 00000-0 -22592-2 0 9998
|
||||
2 25544 51.6451 272.4173 0002526 27.1693 64.4213 15.48396490302085
|
||||
@@ -16,7 +16,7 @@ class Look4SatTest {
|
||||
1 48869U 21057A 21254.57379002 .00002620 00000-0 56399-4 0 9993
|
||||
2 48869 51.6436 275.5624 0003404 23.4371 118.9508 15.48629868301984
|
||||
""".trimIndent().byteInputStream()
|
||||
private val invalidParamsStream = """
|
||||
private val invalidTleStream = """
|
||||
1 25544U 98067A 21255.21005818 -.00120443 00000-0 -22592-2 0 9998
|
||||
2 25544 51.6451 272.4173 0002526 27.1693 64.4213 15.48396490302085
|
||||
1 48852U 21053A 21254.65783594 .00009779 00000-0 11349-3 0 9992
|
||||
@@ -26,14 +26,14 @@ class Look4SatTest {
|
||||
""".trimIndent().byteInputStream()
|
||||
|
||||
@Test
|
||||
fun `Given valid params stream returns valid data`() {
|
||||
val parsedList = TLE.parseStream(validParamsStream)
|
||||
fun `Given valid TLE stream returns valid data`() {
|
||||
val parsedList = TLE.parseTleStream(validTleStream)
|
||||
assert(parsedList[2].catnum == 48869)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Given invalid params stream returns empty list`() {
|
||||
val parsedList = TLE.parseStream(invalidParamsStream)
|
||||
fun `Given invalid TLE stream returns empty list`() {
|
||||
val parsedList = TLE.parseTleStream(invalidTleStream)
|
||||
assert(parsedList.isEmpty())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user