Added various minor fixes, cleaned up classes

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:45 +00:00
1 parent 5a8108384f
commit fc0b995bac
35 files changed
+295 -310

No files matched your search

+4 -6
View File
@@ -1,11 +1,13 @@
@file:Suppress("UnstableApiUsage")
plugins {
id("com.android.library")
id("com.google.devtools.ksp")
id("org.jetbrains.kotlin.android")
}
kotlin {
jvmToolchain(17)
}
android {
namespace = "com.rtbishop.look4sat.data"
compileSdk = 33
@@ -13,10 +15,6 @@ android {
minSdk = 21
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
dependencies {
@@ -2,15 +2,15 @@ package com.rtbishop.look4sat.data.framework
import android.bluetooth.BluetoothManager
import android.util.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.io.OutputStream
import java.util.*
import kotlin.math.abs
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
class BluetoothReporter(
private val manager: BluetoothManager,
private val bluetoothManager: BluetoothManager,
private val reporterScope: CoroutineScope
) {
@@ -30,7 +30,7 @@ class BluetoothReporter(
if (!connected) {
rotationConnectionJob = reporterScope.launch {
try {
manager.adapter.getRemoteDevice(deviceId)?.let { device ->
bluetoothManager.adapter.getRemoteDevice(deviceId)?.let { device ->
device.createInsecureRfcommSocketToServiceRecord(sppid)?.let { socket ->
connecting = true
socket.connect()
@@ -22,36 +22,38 @@ import com.rtbishop.look4sat.domain.model.SatEntry
import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
import com.rtbishop.look4sat.domain.source.IDataSource
import com.rtbishop.look4sat.domain.source.ILocalStorage
import com.rtbishop.look4sat.domain.source.IFileSource
import com.rtbishop.look4sat.domain.source.ILocalSource
import com.rtbishop.look4sat.domain.source.IRemoteSource
import com.rtbishop.look4sat.domain.utility.DataParser
import java.io.InputStream
import java.util.zip.ZipInputStream
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.async
import kotlinx.coroutines.withContext
import java.io.InputStream
import java.util.zip.ZipInputStream
class DatabaseRepo(
private val dispatcher: CoroutineDispatcher,
private val dataParser: DataParser,
private val dataSource: IDataSource,
private val localStorage: ILocalStorage,
private val settingsRepository: ISettingsRepo
private val fileSource: IFileSource,
private val localSource: ILocalSource,
private val remoteSource: IRemoteSource,
private val settingsRepo: ISettingsRepo
) : IDatabaseRepo {
override suspend fun updateFromFile(uri: String) = withContext(dispatcher) {
val importedSatellites = dataSource.getFileStream(uri)?.let { importSatellites(it) }
importedSatellites?.let { localStorage.insertEntries(it) }
val importedSatellites = fileSource.getFileStream(uri)?.let { importSatellites(it) }
importedSatellites?.let { localSource.insertEntries(it) }
setUpdateSuccessful(System.currentTimeMillis())
}
override suspend fun updateFromWeb() = withContext(dispatcher) {
val sourcesMap = settingsRepository.satelliteSourcesMap
override suspend fun updateFromRemote() = withContext(dispatcher) {
val sourcesMap = settingsRepo.satelliteSourcesMap
val importedEntries = mutableListOf<SatEntry>()
val importedRadios = mutableListOf<SatRadio>()
// fetch
val jobsMap = sourcesMap.mapValues { async { dataSource.getNetworkStream(it.value) } }
val jobRadios = async { dataSource.getNetworkStream(settingsRepository.radioSourceUrl) }
val jobsMap = sourcesMap.mapValues { async { remoteSource.getRemoteStream(it.value) } }
val jobRadios = async { remoteSource.getRemoteStream(settingsRepo.radioSourceUrl) }
// parse
jobsMap.mapValues { job -> job.value.await() }.forEach { entry ->
entry.value?.let { stream ->
@@ -60,7 +62,7 @@ class DatabaseRepo(
// parse tle stream
val satellites = importSatellites(stream)
val catnums = satellites.map { it.data.catnum }
settingsRepository.saveSatType(type, catnums)
settingsRepo.saveSatType(type, catnums)
importedEntries.addAll(satellites)
}
@@ -69,7 +71,7 @@ class DatabaseRepo(
val unzipped = ZipInputStream(stream).apply { nextEntry }
val satellites = importSatellites(unzipped)
val catnums = satellites.map { it.data.catnum }
settingsRepository.saveSatType(type, catnums)
settingsRepo.saveSatType(type, catnums)
importedEntries.addAll(satellites)
}
@@ -78,7 +80,7 @@ class DatabaseRepo(
val parsed = dataParser.parseCSVStream(stream)
val satellites = parsed.map { data -> SatEntry(data) }
val catnums = satellites.map { it.data.catnum }
settingsRepository.saveSatType(type, catnums)
settingsRepo.saveSatType(type, catnums)
importedEntries.addAll(satellites)
}
}
@@ -86,21 +88,21 @@ class DatabaseRepo(
}
jobRadios.await()?.let { importedRadios.addAll(dataParser.parseJSONStream(it)) }
// insert
localStorage.insertEntries(importedEntries)
localStorage.insertRadios(importedRadios)
localSource.insertEntries(importedEntries)
localSource.insertRadios(importedRadios)
setUpdateSuccessful(System.currentTimeMillis())
}
override suspend fun clearAllData() = withContext(dispatcher) {
localStorage.deleteEntries()
localStorage.deleteRadios()
localSource.deleteEntries()
localSource.deleteRadios()
setUpdateSuccessful(0L)
}
private suspend fun setUpdateSuccessful(timestamp: Long) = withContext(dispatcher) {
val satellitesTotal = localStorage.getEntriesTotal()
val radiosTotal = localStorage.getRadiosTotal()
settingsRepository.saveDatabaseState(DatabaseState(satellitesTotal, radiosTotal, timestamp))
val satellitesTotal = localSource.getEntriesTotal()
val radiosTotal = localSource.getRadiosTotal()
settingsRepo.saveDatabaseState(DatabaseState(satellitesTotal, radiosTotal, timestamp))
}
private suspend fun importSatellites(stream: InputStream): List<SatEntry> {
@@ -24,7 +24,7 @@ import com.rtbishop.look4sat.domain.predict.SatPos
import com.rtbishop.look4sat.domain.predict.Satellite
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
import com.rtbishop.look4sat.domain.source.ILocalStorage
import com.rtbishop.look4sat.domain.source.ILocalSource
import com.rtbishop.look4sat.domain.utility.round
import com.rtbishop.look4sat.domain.utility.toDegrees
import kotlinx.coroutines.CoroutineDispatcher
@@ -35,7 +35,7 @@ import kotlinx.coroutines.withContext
class SatelliteRepo(
private val dispatcher: CoroutineDispatcher,
private val localStorage: ILocalStorage,
private val localStorage: ILocalSource,
private val settingsRepo: ISettingsRepo
) : ISatelliteRepo {
@@ -3,7 +3,7 @@ package com.rtbishop.look4sat.data.repository
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.domain.repository.ISelectionRepo
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
import com.rtbishop.look4sat.domain.source.ILocalStorage
import com.rtbishop.look4sat.domain.source.ILocalSource
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -15,7 +15,7 @@ import kotlinx.coroutines.withContext
@OptIn(ExperimentalCoroutinesApi::class)
class SelectionRepo(
private val dispatcher: CoroutineDispatcher,
private val localStorage: ILocalStorage,
private val localSource: ILocalSource,
private val settingsRepo: ISettingsRepo
) : ISelectionRepo {
private val currentItems = MutableStateFlow<List<SatItem>>(emptyList())
@@ -34,7 +34,7 @@ class SelectionRepo(
override suspend fun getEntriesFlow() = withContext(dispatcher) {
val selectedIds = settingsRepo.satelliteSelection.value
currentItems.value = localStorage.getEntriesList().map { item ->
currentItems.value = localSource.getEntriesList().map { item ->
item.copy(isSelected = item.catnum in selectedIds)
}
return@withContext itemsWithQuery
@@ -15,7 +15,7 @@
* 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.data.framework
package com.rtbishop.look4sat.data.repository
import android.content.SharedPreferences
import android.location.Criteria
@@ -28,14 +28,15 @@ import com.rtbishop.look4sat.domain.model.OtherSettings
import com.rtbishop.look4sat.domain.model.PassesSettings
import com.rtbishop.look4sat.domain.predict.GeoPos
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
import com.rtbishop.look4sat.domain.utility.QthConverter
import com.rtbishop.look4sat.domain.utility.positionToQth
import com.rtbishop.look4sat.domain.utility.qthToPosition
import com.rtbishop.look4sat.domain.utility.round
import java.util.concurrent.Executors
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import java.util.concurrent.Executors
class SettingsRepo(
private val manager: LocationManager, private val preferences: SharedPreferences
private val locationManager: LocationManager, private val preferences: SharedPreferences
) : ISettingsRepo {
private val keyModes = "satModes"
@@ -73,12 +74,12 @@ class SettingsRepo(
override val stationPosition: StateFlow<GeoPos> = _stationPosition
override fun setGpsPosition(): Boolean {
if (!LocationManagerCompat.isLocationEnabled(manager)) return false
if (!LocationManagerCompat.isLocationEnabled(locationManager)) return false
try {
val criteria = Criteria().apply { isCostAllowed = true }
val provider = manager.getBestProvider(criteria, true) ?: defaultProvider
val provider = locationManager.getBestProvider(criteria, true) ?: defaultProvider
println("Requesting location for $provider provider")
LocationManagerCompat.getCurrentLocation(manager, provider, timeoutSignal, executor) {
LocationManagerCompat.getCurrentLocation(locationManager, provider, timeoutSignal, executor) {
it?.let { setGeoPosition(it.latitude, it.longitude, it.altitude) }
}
} catch (exception: SecurityException) {
@@ -89,13 +90,13 @@ class SettingsRepo(
override fun setGeoPosition(latitude: Double, longitude: Double, altitude: Double): Boolean {
val newLongitude = if (longitude > 180.0) longitude - 180 else longitude
val locator = QthConverter.positionToQth(latitude, newLongitude) ?: return false
val locator = positionToQth(latitude, newLongitude) ?: return false
saveGeoPos(latitude, newLongitude, altitude, locator)
return true
}
override fun setQthPosition(locator: String): Boolean {
val position = QthConverter.qthToPosition(locator) ?: return false
val position = qthToPosition(locator) ?: return false
saveGeoPos(position.latitude, position.longitude, 0.0, locator)
return true
}
@@ -0,0 +1,16 @@
package com.rtbishop.look4sat.data.source
import android.content.ContentResolver
import android.net.Uri
import com.rtbishop.look4sat.domain.source.IFileSource
import java.io.InputStream
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
class FileSource(
private val contentResolver: ContentResolver, private val dispatcher: CoroutineDispatcher
) : IFileSource {
override suspend fun getFileStream(uri: String): InputStream? {
return withContext(dispatcher) { contentResolver.openInputStream(Uri.parse(uri)) }
}
}
@@ -17,18 +17,18 @@
*/
package com.rtbishop.look4sat.data.source
import com.rtbishop.look4sat.data.database.dao.StorageDao
import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.domain.predict.Satellite
import com.rtbishop.look4sat.domain.source.ILocalStorage
import com.rtbishop.look4sat.data.database.entity.SatEntry as FrameworkEntry
import com.rtbishop.look4sat.data.database.entity.SatItem as FrameworkItem
import com.rtbishop.look4sat.data.database.entity.SatRadio as FrameworkRadio
import com.rtbishop.look4sat.domain.model.SatEntry as DomainEntry
import com.rtbishop.look4sat.domain.model.SatItem as DomainItem
import com.rtbishop.look4sat.domain.model.SatRadio as DomainRadio
import com.rtbishop.look4sat.data.database.dao.StorageDao
import com.rtbishop.look4sat.domain.model.SatRadio
import com.rtbishop.look4sat.domain.predict.Satellite
import com.rtbishop.look4sat.domain.source.ILocalSource
class LocalStorage(private val storageDao: StorageDao) : ILocalStorage {
class LocalSource(private val storageDao: StorageDao) : ILocalSource {
//region # Entries region
@@ -17,26 +17,18 @@
*/
package com.rtbishop.look4sat.data.source
import android.content.ContentResolver
import android.net.Uri
import com.rtbishop.look4sat.domain.source.IDataSource
import com.rtbishop.look4sat.domain.source.IRemoteSource
import java.io.InputStream
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.InputStream
class DataSource(
private val contentResolver: ContentResolver,
private val httpClient: OkHttpClient,
private val dispatcher: CoroutineDispatcher
) : IDataSource {
class RemoteSource(
private val httpClient: OkHttpClient, private val dispatcher: CoroutineDispatcher
) : IRemoteSource {
override suspend fun getFileStream(uri: String): InputStream? {
return withContext(dispatcher) { contentResolver.openInputStream(Uri.parse(uri)) }
}
override suspend fun getNetworkStream(url: String): InputStream? = withContext(dispatcher) {
override suspend fun getRemoteStream(url: String): InputStream? = withContext(dispatcher) {
try {
val request = Request.Builder().url(url).build()
httpClient.newCall(request).execute().body?.byteStream()