Created satellite DataSources and Repository

This commit is contained in:
Arty Bishop committed 2021-04-22 12:50:18 +01:00
1 parent 3db474c763
commit d0569f4645
10 files changed
+228 -25

No files matched your search

@@ -40,9 +40,33 @@ interface SatelliteDao {
@Query("SELECT catNum FROM entries WHERE isSelected = 1")
suspend fun getSelectedCatNums(): List<Int>
@Transaction
suspend fun updateEntries(entries: List<SatEntry>) {
val selectedCatNums = getSelectedCatNums()
insertEntries(entries)
restoreEntriesSelection(selectedCatNums, true)
}
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertEntries(entries: List<SatEntry>)
@Transaction
suspend fun restoreEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
clearEntriesSelection()
catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) }
}
@Query("UPDATE entries SET isSelected = 0")
suspend fun clearEntriesSelection()
@Query("UPDATE entries SET isSelected = :isSelected WHERE catNum = :catNum")
suspend fun updateEntrySelection(catNum: Int, isSelected: Boolean)
@Transaction
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) }
}
@Transaction
suspend fun updateTransmitters(transmitters: List<SatTrans>) {
deleteTransmitters()
@@ -54,21 +78,4 @@ interface SatelliteDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertTransmitters(transmitters: List<SatTrans>)
@Transaction
suspend fun restoreEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
clearEntriesSelection()
catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) }
}
@Transaction
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) }
}
@Query("UPDATE entries SET isSelected = 0")
suspend fun clearEntriesSelection()
@Query("UPDATE entries SET isSelected = :isSelected WHERE catNum = :catNum")
suspend fun updateEntrySelection(catNum: Int, isSelected: Boolean)
}
@@ -62,7 +62,7 @@ class SatelliteRepo @Inject constructor(
runCatching {
resolver.openInputStream(uri)?.use { stream ->
val entries = importEntriesFromStreams(listOf(stream))
insertEntriesAndRestoreSelection(entries)
satelliteDao.updateEntries(entries)
}
}.onFailure { throw it }
}
@@ -81,7 +81,7 @@ class SatelliteRepo @Inject constructor(
private suspend fun importEntriesFromSources(sources: List<TleSource>) {
val streams = getStreamsForSources(sources)
val entries = importEntriesFromStreams(streams)
insertEntriesAndRestoreSelection(entries)
satelliteDao.updateEntries(entries)
}
private suspend fun importTransmitters() {
@@ -124,10 +124,4 @@ class SatelliteRepo @Inject constructor(
}
return importedEntries
}
private suspend fun insertEntriesAndRestoreSelection(entries: List<SatEntry>) {
val selectedCatNums = satelliteDao.getSelectedCatNums()
satelliteDao.insertEntries(entries)
satelliteDao.restoreEntriesSelection(selectedCatNums, true)
}
}
@@ -0,0 +1,71 @@
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.domain.model.SatEntry
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.SatelliteRepo
import com.rtbishop.look4sat.domain.model.Transmitter
import com.rtbishop.look4sat.predict4kotlin.Satellite
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.InputStream
import java.util.zip.ZipInputStream
class DefaultSatelliteRepo(
private val localSource: LocalDataSource,
private val remoteSource: RemoteDataSource,
private val ioDispatcher: CoroutineDispatcher
) : SatelliteRepo {
override fun getSatItems(): Flow<List<SatItem>> {
return localSource.getSatItems()
}
override fun getTransmittersForSat(catNum: Int): Flow<List<Transmitter>> {
return localSource.getTransmittersForSat(catNum)
}
override suspend fun getSelectedSatellites(): List<Satellite> {
return localSource.getSelectedSatellites()
}
override suspend fun importDataFromFile(stream: InputStream) = withContext(ioDispatcher) {
val entries = mutableListOf<SatEntry>()
val tleList = Satellite.importTLE(stream)
tleList.forEach { tle -> entries.add(SatEntry(tle)) }
localSource.updateEntries(entries)
}
override suspend fun importDataFromWeb(sources: List<String>) {
coroutineScope {
launch {
val entries = mutableListOf<SatEntry>()
val streams = mutableListOf<InputStream>()
sources.forEach { source ->
val stream = remoteSource.fetchFileStream(source)
if (source.contains(".zip", true)) {
val zipStream = ZipInputStream(stream).apply { nextEntry }
streams.add(zipStream)
} else {
streams.add(stream)
}
}
streams.forEach { stream ->
val importedEntries = Satellite.importTLE(stream).map { tle -> SatEntry(tle) }
entries.addAll(importedEntries)
}
localSource.updateEntries(entries)
}
launch {
val transmitters = remoteSource.fetchTransmitters().filter { it.isAlive }
localSource.updateTransmitters(transmitters)
}
}
}
override suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
localSource.updateEntriesSelection(catNums, isSelected)
}
}
@@ -0,0 +1,22 @@
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.domain.model.SatEntry
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.model.Transmitter
import com.rtbishop.look4sat.predict4kotlin.Satellite
import kotlinx.coroutines.flow.Flow
interface LocalDataSource {
fun getSatItems(): Flow<List<SatItem>>
suspend fun getSelectedSatellites(): List<Satellite>
suspend fun updateEntries(entries: List<SatEntry>)
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean)
fun getTransmittersForSat(catNum: Int): Flow<List<Transmitter>>
suspend fun updateTransmitters(transmitters: List<Transmitter>)
}
@@ -0,0 +1,11 @@
package com.rtbishop.look4sat.data
import com.rtbishop.look4sat.domain.model.Transmitter
import java.io.InputStream
interface RemoteDataSource {
fun fetchFileStream(url: String): InputStream
fun fetchTransmitters(): List<Transmitter>
}
@@ -0,0 +1,22 @@
package com.rtbishop.look4sat.domain
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.model.Transmitter
import com.rtbishop.look4sat.predict4kotlin.Satellite
import kotlinx.coroutines.flow.Flow
import java.io.InputStream
interface SatelliteRepo {
fun getSatItems(): Flow<List<SatItem>>
fun getTransmittersForSat(catNum: Int): Flow<List<Transmitter>>
suspend fun getSelectedSatellites(): List<Satellite>
suspend fun importDataFromFile(stream: InputStream)
suspend fun importDataFromWeb(sources: List<String>)
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean)
}
@@ -0,0 +1,10 @@
package com.rtbishop.look4sat.domain.model
import com.rtbishop.look4sat.predict4kotlin.TLE
data class SatEntry(
val tle: TLE,
var isSelected: Boolean = false,
val catNum: Int = tle.catnum,
val name: String = tle.name
)
@@ -0,0 +1,8 @@
package com.rtbishop.look4sat.domain.model
data class SatItem(
val catNum: Int,
val name: String,
var isSelected: Boolean,
val modes: List<String>
)
@@ -0,0 +1,46 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.domain.model
import com.rtbishop.look4sat.predict4kotlin.PassPredictor
import java.util.*
data class SatPass(
val catNum: Int,
val name: String,
val isDeepSpace: Boolean,
private val aosTime: Long,
val aosAzimuth: Double,
private val losTime: Long,
val losAzimuth: Double,
private val tcaTime: Long,
val tcaAzimuth: Double,
val altitude: Double,
val maxElevation: Double,
val predictor: PassPredictor,
var progress: Int = 0
) {
val aosDate: Date
get() = Date(aosTime)
val losDate: Date
get() = Date(losTime)
val tcaDate: Date
get() = Date(tcaTime)
}
@@ -0,0 +1,12 @@
package com.rtbishop.look4sat.domain.model
data class Transmitter(
val uuid: String,
val info: String,
val isAlive: Boolean,
var downlink: Long?,
var uplink: Long?,
val mode: String?,
val isInverted: Boolean,
val catNum: Int
)