diff --git a/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt b/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt index de6ee3f4..e55fc2f8 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/database/SatelliteDao.kt @@ -40,9 +40,33 @@ interface SatelliteDao { @Query("SELECT catNum FROM entries WHERE isSelected = 1") suspend fun getSelectedCatNums(): List + @Transaction + suspend fun updateEntries(entries: List) { + val selectedCatNums = getSelectedCatNums() + insertEntries(entries) + restoreEntriesSelection(selectedCatNums, true) + } + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertEntries(entries: List) + @Transaction + suspend fun restoreEntriesSelection(catNums: List, 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, isSelected: Boolean) { + catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) } + } + @Transaction suspend fun updateTransmitters(transmitters: List) { deleteTransmitters() @@ -54,21 +78,4 @@ interface SatelliteDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertTransmitters(transmitters: List) - - @Transaction - suspend fun restoreEntriesSelection(catNums: List, isSelected: Boolean) { - clearEntriesSelection() - catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) } - } - - @Transaction - suspend fun updateEntriesSelection(catNums: List, 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) } diff --git a/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt b/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt index c5998e72..16cf272f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt +++ b/app/src/main/java/com/rtbishop/look4sat/data/repository/SatelliteRepo.kt @@ -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) { 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) { - val selectedCatNums = satelliteDao.getSelectedCatNums() - satelliteDao.insertEntries(entries) - satelliteDao.restoreEntriesSelection(selectedCatNums, true) - } } diff --git a/core/src/main/java/com/rtbishop/look4sat/data/DefaultSatelliteRepo.kt b/core/src/main/java/com/rtbishop/look4sat/data/DefaultSatelliteRepo.kt new file mode 100644 index 00000000..19e68a70 --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/data/DefaultSatelliteRepo.kt @@ -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> { + return localSource.getSatItems() + } + + override fun getTransmittersForSat(catNum: Int): Flow> { + return localSource.getTransmittersForSat(catNum) + } + + override suspend fun getSelectedSatellites(): List { + return localSource.getSelectedSatellites() + } + + override suspend fun importDataFromFile(stream: InputStream) = withContext(ioDispatcher) { + val entries = mutableListOf() + val tleList = Satellite.importTLE(stream) + tleList.forEach { tle -> entries.add(SatEntry(tle)) } + localSource.updateEntries(entries) + } + + override suspend fun importDataFromWeb(sources: List) { + coroutineScope { + launch { + val entries = mutableListOf() + val streams = mutableListOf() + 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, isSelected: Boolean) { + localSource.updateEntriesSelection(catNums, isSelected) + } +} diff --git a/core/src/main/java/com/rtbishop/look4sat/data/LocalDataSource.kt b/core/src/main/java/com/rtbishop/look4sat/data/LocalDataSource.kt new file mode 100644 index 00000000..a96ba648 --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/data/LocalDataSource.kt @@ -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> + + suspend fun getSelectedSatellites(): List + + suspend fun updateEntries(entries: List) + + suspend fun updateEntriesSelection(catNums: List, isSelected: Boolean) + + fun getTransmittersForSat(catNum: Int): Flow> + + suspend fun updateTransmitters(transmitters: List) +} diff --git a/core/src/main/java/com/rtbishop/look4sat/data/RemoteDataSource.kt b/core/src/main/java/com/rtbishop/look4sat/data/RemoteDataSource.kt new file mode 100644 index 00000000..29766462 --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/data/RemoteDataSource.kt @@ -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 +} diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/SatelliteRepo.kt b/core/src/main/java/com/rtbishop/look4sat/domain/SatelliteRepo.kt new file mode 100644 index 00000000..1f9b193e --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/domain/SatelliteRepo.kt @@ -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> + + fun getTransmittersForSat(catNum: Int): Flow> + + suspend fun getSelectedSatellites(): List + + suspend fun importDataFromFile(stream: InputStream) + + suspend fun importDataFromWeb(sources: List) + + suspend fun updateEntriesSelection(catNums: List, isSelected: Boolean) +} \ No newline at end of file diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt b/core/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt new file mode 100644 index 00000000..6db2f6f6 --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt @@ -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 +) diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt b/core/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt new file mode 100644 index 00000000..7d84d1d2 --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt @@ -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 +) diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/model/SatPass.kt b/core/src/main/java/com/rtbishop/look4sat/domain/model/SatPass.kt new file mode 100644 index 00000000..df6f47db --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/domain/model/SatPass.kt @@ -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 . + */ +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) +} diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/model/Transmitter.kt b/core/src/main/java/com/rtbishop/look4sat/domain/model/Transmitter.kt new file mode 100644 index 00000000..a7ccf6f4 --- /dev/null +++ b/core/src/main/java/com/rtbishop/look4sat/domain/model/Transmitter.kt @@ -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 +)