diff --git a/app/schemas/com.rtbishop.look4sat.framework.data.LocalDatabase/1.json b/app/schemas/com.rtbishop.look4sat.framework.data.MainDatabase/1.json similarity index 100% rename from app/schemas/com.rtbishop.look4sat.framework.data.LocalDatabase/1.json rename to app/schemas/com.rtbishop.look4sat.framework.data.MainDatabase/1.json diff --git a/app/schemas/com.rtbishop.look4sat.framework.data.LocalDatabase/2.json b/app/schemas/com.rtbishop.look4sat.framework.data.MainDatabase/2.json similarity index 98% rename from app/schemas/com.rtbishop.look4sat.framework.data.LocalDatabase/2.json rename to app/schemas/com.rtbishop.look4sat.framework.data.MainDatabase/2.json index ddac2a28..1213ef47 100644 --- a/app/schemas/com.rtbishop.look4sat.framework.data.LocalDatabase/2.json +++ b/app/schemas/com.rtbishop.look4sat.framework.data.MainDatabase/2.json @@ -118,10 +118,10 @@ } ], "primaryKey": { + "autoGenerate": false, "columnNames": [ "catnum" - ], - "autoGenerate": false + ] }, "indices": [], "foreignKeys": [] @@ -186,10 +186,10 @@ } ], "primaryKey": { + "autoGenerate": false, "columnNames": [ "uuid" - ], - "autoGenerate": false + ] }, "indices": [], "foreignKeys": [] diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 45364ace..95921e4a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ diff --git a/app/src/main/java/com/rtbishop/look4sat/MainActivity.kt b/app/src/main/java/com/rtbishop/look4sat/MainActivity.kt new file mode 100644 index 00000000..11c16578 --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/MainActivity.kt @@ -0,0 +1,47 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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 + +import android.content.Context +import android.content.pm.ActivityInfo +import android.content.res.Configuration +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen +import com.rtbishop.look4sat.presentation.MainScreen +import com.rtbishop.look4sat.presentation.MainTheme +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class MainActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + installSplashScreen() + super.onCreate(savedInstanceState) + setContent { MainTheme { MainScreen() } } + } + + override fun attachBaseContext(newBase: Context?) { + val newConfig = Configuration(newBase?.resources?.configuration) + newConfig.fontScale = 1.0f + applyOverrideConfiguration(newConfig) + super.attachBaseContext(newBase) + } +} diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/MainApplication.kt b/app/src/main/java/com/rtbishop/look4sat/MainApplication.kt similarity index 82% rename from app/src/main/java/com/rtbishop/look4sat/presentation/MainApplication.kt rename to app/src/main/java/com/rtbishop/look4sat/MainApplication.kt index 0bef3410..7ef73f5c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/MainApplication.kt +++ b/app/src/main/java/com/rtbishop/look4sat/MainApplication.kt @@ -15,12 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation +package com.rtbishop.look4sat import android.app.Application -import com.rtbishop.look4sat.BuildConfig import com.rtbishop.look4sat.domain.IDataRepository -import com.rtbishop.look4sat.framework.SettingsManager +import com.rtbishop.look4sat.domain.ISettingsSource import dagger.hilt.android.HiltAndroidApp import timber.log.Timber import java.text.SimpleDateFormat @@ -31,10 +30,10 @@ import javax.inject.Inject class MainApplication : Application() { @Inject - lateinit var repository: IDataRepository + lateinit var dataRepository: IDataRepository @Inject - lateinit var settingsManager: SettingsManager + lateinit var settingsSource: ISettingsSource override fun onCreate() { super.onCreate() @@ -45,12 +44,12 @@ class MainApplication : Application() { } private fun checkAutoUpdate() { - if (settingsManager.isUpdateEnabled()) { - val timeDelta = System.currentTimeMillis() - settingsManager.getLastUpdateTime() + if (settingsSource.isUpdateEnabled()) { + val timeDelta = System.currentTimeMillis() - settingsSource.getLastUpdateTime() if (timeDelta > 172800000) { // 48 hours in ms val sdf = SimpleDateFormat("d MMM yyyy - HH:mm:ss", Locale.getDefault()) Timber.d("Started periodic data update on ${sdf.format(Date())}") - repository.updateFromWeb() + dataRepository.updateFromWeb() } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/MainModule.kt b/app/src/main/java/com/rtbishop/look4sat/MainModule.kt new file mode 100644 index 00000000..553d627f --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/MainModule.kt @@ -0,0 +1,102 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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 + +import android.bluetooth.BluetoothManager +import android.content.Context +import android.hardware.Sensor +import android.hardware.SensorManager +import android.location.LocationManager +import androidx.room.Room +import com.rtbishop.look4sat.data.DataParser +import com.rtbishop.look4sat.data.DataRepository +import com.rtbishop.look4sat.domain.* +import com.rtbishop.look4sat.framework.* +import com.rtbishop.look4sat.framework.data.* +import com.rtbishop.look4sat.framework.data.local.EntriesStorage +import com.rtbishop.look4sat.framework.data.local.RadiosStorage +import com.rtbishop.look4sat.framework.data.remote.FileSource +import com.rtbishop.look4sat.framework.data.remote.NetworkSource +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object MainModule { + + @Provides + @Singleton + fun provideBluetoothReporter(@ApplicationContext context: Context): BluetoothReporter { + val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + return BluetoothReporter(manager, CoroutineScope(Dispatchers.IO)) + } + + @Provides + @Singleton + fun provideNetworkReporter(): NetworkReporter = NetworkReporter(CoroutineScope(Dispatchers.IO)) + + @Provides + @Singleton + fun provideDataRepository( + @ApplicationContext context: Context, settings: ISettingsSource + ): IDataRepository { + val db = Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb") + .addMigrations(MIGRATION_1_2).fallbackToDestructiveMigration().build() + val parser = DataParser(Dispatchers.Default) + val fileSource = FileSource(context.contentResolver, Dispatchers.IO) + val entries = EntriesStorage(db.entriesDao()) + val radios = RadiosStorage(db.radiosDao()) + val remoteSource = NetworkSource(Dispatchers.IO) + val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default) + return DataRepository(parser, fileSource, entries, radios, remoteSource, scope, settings) + } + + @Provides + @Singleton + fun provideLocationSource( + @ApplicationContext context: Context, settings: ISettingsSource + ): ILocationSource { + val manager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + return LocationSource(manager, settings) + } + + @Provides + @Singleton + fun provideOrientationSource(@ApplicationContext context: Context): OrientationSource { + val manager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager + val sensor = manager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) + return OrientationSource(manager, sensor) + } + + @Provides + @Singleton + fun provideSatelliteManager(): ISatelliteManager = SatelliteManager(Dispatchers.Default) + + @Provides + @Singleton + fun provideSettingsSource(@ApplicationContext context: Context): ISettingsSource { + return SettingsSource(context.getSharedPreferences("default", Context.MODE_PRIVATE)) + } +} diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/BTReporter.kt b/app/src/main/java/com/rtbishop/look4sat/framework/BluetoothReporter.kt similarity index 95% rename from app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/BTReporter.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/BluetoothReporter.kt index e08217ec..6b075bb0 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/BTReporter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/BluetoothReporter.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.radarScreen +package com.rtbishop.look4sat.framework import android.bluetooth.BluetoothManager import android.util.Log @@ -9,7 +9,10 @@ import java.io.OutputStream import java.util.* import kotlin.math.abs -class BTReporter(private val manager: BluetoothManager, private val reporterScope: CoroutineScope) { +class BluetoothReporter( + private val manager: BluetoothManager, + private val reporterScope: CoroutineScope +) { private val tag = "BTReporter" private val sppid: UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb") diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/LocationManager.kt b/app/src/main/java/com/rtbishop/look4sat/framework/LocationManager.kt deleted file mode 100644 index 6165edcd..00000000 --- a/app/src/main/java/com/rtbishop/look4sat/framework/LocationManager.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Look4Sat. Amateur radio satellite tracker and pass predictor. - * Copyright (C) 2019-2022 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.framework - -import android.Manifest -import android.content.Context -import android.content.pm.PackageManager -import android.location.Location -import android.location.LocationListener -import android.location.LocationManager -import android.os.Bundle -import androidx.core.content.ContextCompat -import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.domain.ILocationManager -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.utility.QthConverter -import com.rtbishop.look4sat.utility.round -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class LocationManager @Inject constructor( - @ApplicationContext private val context: Context, - private val manager: LocationManager, - private val settings: ISettingsManager, -) : LocationListener, ILocationManager { - - private val providerDef = LocationManager.PASSIVE_PROVIDER - private val providerNet = LocationManager.NETWORK_PROVIDER - private val providerGps = LocationManager.GPS_PROVIDER - private val locationCoarse = Manifest.permission.ACCESS_COARSE_LOCATION - private val locationFine = Manifest.permission.ACCESS_FINE_LOCATION - private val _stationPosition = MutableStateFlow>(DataState.Handled) - private var currentLocator = settings.loadStationLocator() - private var currentPosition = settings.loadStationPosition() - - override val stationPosition: StateFlow> = _stationPosition - - override fun getStationLocator(): String = currentLocator - - override fun getStationPosition(): GeoPos = currentPosition - - override fun setStationPosition(latitude: Double, longitude: Double) { - if (QthConverter.isValidPosition(latitude, longitude)) { - val tempLon = if (longitude > 180.0) longitude - 180 else longitude - val newLat = latitude.round(4) - val newLon = tempLon.round(4) - QthConverter.positionToQth(newLat, newLon)?.let { locator -> - currentLocator = locator - currentPosition = GeoPos(newLat, newLon) - settings.saveStationLocator(locator) - settings.saveStationPosition(currentPosition) - _stationPosition.value = DataState.Success(currentPosition) - } - } else { - _stationPosition.value = - DataState.Error(context.getString(R.string.location_manual_error)) - } - } - - override fun setPositionFromGps() { - val result = ContextCompat.checkSelfPermission(context, locationFine) - if (manager.isProviderEnabled(providerGps) && result == PackageManager.PERMISSION_GRANTED) { - val location = manager.getLastKnownLocation(providerDef) - if (location != null) { - setStationPosition(location.latitude, location.longitude) - } else { - _stationPosition.value = DataState.Loading - manager.requestLocationUpdates(providerGps, 0L, 0f, this) - } - } else { - _stationPosition.value = DataState.Error(context.getString(R.string.location_null)) - } - } - - override fun setPositionFromNet() { - val result = ContextCompat.checkSelfPermission(context, locationCoarse) - if (manager.isProviderEnabled(providerNet) && result == PackageManager.PERMISSION_GRANTED) { - val location = manager.getLastKnownLocation(providerDef) - if (location != null) { - setStationPosition(location.latitude, location.longitude) - } else { - _stationPosition.value = DataState.Loading - manager.requestLocationUpdates(providerNet, 0L, 0f, this) - } - } else { - _stationPosition.value = DataState.Error(context.getString(R.string.location_null)) - } - } - - override fun setPositionFromQth(locator: String) { - val position = QthConverter.qthToPosition(locator) - if (position != null) { - currentLocator = locator - currentPosition = position - settings.saveStationLocator(locator) - settings.saveStationPosition(currentPosition) - _stationPosition.value = DataState.Success(currentPosition) - } else { - _stationPosition.value = DataState.Error(context.getString(R.string.location_qth_error)) - } - } - - override fun setPositionHandled() { - _stationPosition.value = DataState.Handled - } - - override fun onLocationChanged(location: Location) { - manager.removeUpdates(this) - setStationPosition(location.latitude, location.longitude) - } - - override fun onProviderEnabled(provider: String) {} - - override fun onProviderDisabled(provider: String) {} - - @Deprecated("Deprecated in Java") - override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {} -} diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/LocationSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/LocationSource.kt new file mode 100644 index 00000000..bbb0f854 --- /dev/null +++ b/app/src/main/java/com/rtbishop/look4sat/framework/LocationSource.kt @@ -0,0 +1,87 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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.framework + +import android.location.Location +import android.location.LocationManager +import androidx.core.location.LocationListenerCompat +import androidx.core.location.LocationManagerCompat +import com.rtbishop.look4sat.domain.ILocationSource +import com.rtbishop.look4sat.domain.ISettingsSource +import com.rtbishop.look4sat.model.StationPos +import com.rtbishop.look4sat.utility.QthConverter +import com.rtbishop.look4sat.utility.round +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import timber.log.Timber + +class LocationSource( + private val manager: LocationManager, + private val settings: ISettingsSource, +) : ILocationSource, LocationListenerCompat { + + private val _stationPosition = MutableStateFlow(settings.loadStationPosition()) + override val stationPosition: StateFlow = _stationPosition + + override fun setGpsPosition(): Boolean { + if (!LocationManagerCompat.isLocationEnabled(manager)) return false + forceLocationUpdate(LocationManager.GPS_PROVIDER) + forceLocationUpdate(LocationManager.NETWORK_PROVIDER) + return true + } + + override fun setGeoPosition(latitude: Double, longitude: Double): Boolean { + manager.removeUpdates(this) + val newLongitude = if (longitude > 180.0) longitude - 180 else longitude + val locator = QthConverter.positionToQth(latitude, newLongitude) ?: return false + saveStationPosition(latitude, newLongitude, locator) + return true + } + + override fun setQthPosition(locator: String): Boolean { + val position = QthConverter.qthToPosition(locator) ?: return false + saveStationPosition(position.lat, position.lon, locator) + return true + } + + override fun onLocationChanged(location: Location) { + setGeoPosition(location.latitude, location.longitude) + } + + private fun forceLocationUpdate(provider: String) { + try { + val location = manager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER) + if (location == null || System.currentTimeMillis() - location.time > 600000) { + Timber.d("Requesting $provider location update") + manager.requestLocationUpdates(provider, 0L, 0f, this) + } else { + setGeoPosition(location.latitude, location.longitude) + } + } catch (exception: SecurityException) { + Timber.d("No permissions were given") + } + } + + private fun saveStationPosition(latitude: Double, longitude: Double, locator: String) { + val newLat = latitude.round(4) + val newLon = longitude.round(4) + Timber.d("Received new Position($newLat, $newLon) & Locator $locator") + _stationPosition.value = StationPos(newLat, newLon, locator, System.currentTimeMillis()) + settings.saveStationPosition(stationPosition.value) + } +} diff --git a/base/src/main/java/com/rtbishop/look4sat/utility/DataReporter.kt b/app/src/main/java/com/rtbishop/look4sat/framework/NetworkReporter.kt similarity index 96% rename from base/src/main/java/com/rtbishop/look4sat/utility/DataReporter.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/NetworkReporter.kt index 643b8190..89128137 100644 --- a/base/src/main/java/com/rtbishop/look4sat/utility/DataReporter.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/NetworkReporter.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.utility +package com.rtbishop.look4sat.framework import java.net.InetSocketAddress import java.nio.ByteBuffer @@ -25,7 +25,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.launch -class DataReporter(private val reporterScope: CoroutineScope) { +class NetworkReporter(private val reporterScope: CoroutineScope) { private var rotationSocketChannel: SocketChannel? = null private var rotationReporting: Job? = null diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/OrientationManager.kt b/app/src/main/java/com/rtbishop/look4sat/framework/OrientationSource.kt similarity index 57% rename from app/src/main/java/com/rtbishop/look4sat/framework/OrientationManager.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/OrientationSource.kt index ab2b2143..5d46789f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/OrientationManager.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/OrientationSource.kt @@ -21,47 +21,36 @@ import android.hardware.Sensor import android.hardware.SensorEvent import android.hardware.SensorEventListener import android.hardware.SensorManager -import com.rtbishop.look4sat.domain.predict.RAD2DEG -import javax.inject.Inject -import javax.inject.Singleton +import com.rtbishop.look4sat.domain.RAD2DEG +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlin.math.round -@Singleton -class OrientationManager @Inject constructor(private val sensorManager: SensorManager) : - SensorEventListener { +class OrientationSource( + private val manager: SensorManager, private val sensor: Sensor? +) : SensorEventListener { - interface OrientationListener { - fun onOrientationChanged(azimuth: Float, pitch: Float, roll: Float) - } - - private val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) private val rotationMatrix = FloatArray(9) private val orientationValues = FloatArray(3) private var sensorAccuracy: Int = SensorManager.SENSOR_STATUS_UNRELIABLE - private var orientationListener: OrientationListener? = null - fun startListening(listener: OrientationListener) { - if (sensor != null && orientationListener !== listener) { - orientationListener = listener - sensorManager.registerListener(this, sensor, 16000) - } else return + private val _orientation = MutableStateFlow(Pair(0f, 0f)) + val orientation: StateFlow> = _orientation + + fun startListening() = sensor?.let { + manager.registerListener(this, it, 16000) } - fun stopListening() { - sensorManager.unregisterListener(this) - orientationListener = null - } + fun stopListening() = manager.unregisterListener(this) override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { sensorAccuracy = accuracy } - override fun onSensorChanged(event: SensorEvent) { - when { - orientationListener == null -> return - sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE -> return - event.sensor == sensor -> updateOrientation(event.values) - } + override fun onSensorChanged(event: SensorEvent) = when { + sensorAccuracy == SensorManager.SENSOR_STATUS_UNRELIABLE -> {} + event.sensor == sensor -> updateOrientation(event.values) + else -> {} } private fun updateOrientation(rotationVector: FloatArray) { @@ -69,11 +58,11 @@ class OrientationManager @Inject constructor(private val sensorManager: SensorMa SensorManager.getOrientation(rotationMatrix, orientationValues) val azimuth = (orientationValues[0] * RAD2DEG).toFloat() val pitch = (orientationValues[1] * RAD2DEG).toFloat() - val roll = (orientationValues[2] * RAD2DEG).toFloat() +// val roll = (orientationValues[2] * RAD2DEG).toFloat() val magneticAzimuth = (azimuth + 360f) % 360f val roundedAzimuth = round(magneticAzimuth * 10) / 10 val roundedPitch = round(pitch * 10) / 10 - val roundedRoll = round(roll * 10) / 10 - orientationListener?.onOrientationChanged(roundedAzimuth, roundedPitch, roundedRoll) +// val roundedRoll = round(roll * 10) / 10 + _orientation.value = Pair(roundedAzimuth, roundedPitch) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsSource.kt similarity index 86% rename from app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/SettingsSource.kt index 11cde9cc..725be84c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/SettingsManager.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/SettingsSource.kt @@ -19,13 +19,10 @@ package com.rtbishop.look4sat.framework import android.content.SharedPreferences import androidx.core.content.edit -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.predict.GeoPos -import javax.inject.Inject -import javax.inject.Singleton +import com.rtbishop.look4sat.domain.ISettingsSource +import com.rtbishop.look4sat.model.StationPos -@Singleton -class SettingsManager @Inject constructor(private val prefs: SharedPreferences) : ISettingsManager { +class SettingsSource(private val prefs: SharedPreferences) : ISettingsSource { companion object { const val keyModes = "satModes" @@ -46,29 +43,23 @@ class SettingsManager @Inject constructor(private val prefs: SharedPreferences) const val keyLatitude = "stationLat" const val keyLongitude = "stationLon" const val keyLocator = "stationQTH" + const val keyLocTimestamp = "locTimestamp" const val keySelection = "selection" } - override fun loadStationLocator(): String { - return prefs.getString(keyLocator, null) ?: "" + override fun loadStationPosition(): StationPos { + val latitude = prefs.getString(keyLatitude, null) ?: "0.0" + val longitude = prefs.getString(keyLongitude, null) ?: "0.0" + val qthLocator = prefs.getString(keyLocator, null) ?: "" + val timestamp = prefs.getLong(keyLocTimestamp, 0L) + return StationPos(latitude.toDouble(), longitude.toDouble(), qthLocator, timestamp) } - override fun saveStationLocator(locator: String) { - prefs.edit { putString(keyLocator, locator) } - } - - override fun loadStationPosition(): GeoPos { - val defaultSP = "0.0" - val latitude = prefs.getString(keyLatitude, null) ?: defaultSP - val longitude = prefs.getString(keyLongitude, null) ?: defaultSP - return GeoPos(latitude.toDouble(), longitude.toDouble()) - } - - override fun saveStationPosition(position: GeoPos) { - prefs.edit { - putString(keyLatitude, position.lat.toString()) - putString(keyLongitude, position.lon.toString()) - } + override fun saveStationPosition(stationPos: StationPos) = prefs.edit { + putString(keyLatitude, stationPos.latitude.toString()) + putString(keyLongitude, stationPos.longitude.toString()) + putString(keyLocator, stationPos.qthLocator) + putLong(keyLocTimestamp, stationPos.timestamp) } override fun saveEntriesSelection(catnums: List) { diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalDatabase.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/MainDatabase.kt similarity index 98% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/LocalDatabase.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/MainDatabase.kt index 7e3635f3..ab40b90d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalDatabase.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/MainDatabase.kt @@ -27,7 +27,7 @@ import com.rtbishop.look4sat.framework.model.SatEntry import com.rtbishop.look4sat.framework.model.SatRadio @Database(entities = [SatEntry::class, SatRadio::class], version = 2, exportSchema = true) -abstract class LocalDatabase : RoomDatabase() { +abstract class MainDatabase : RoomDatabase() { abstract fun entriesDao(): EntriesDao diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalEntrySource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/local/EntriesStorage.kt similarity index 85% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/LocalEntrySource.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/local/EntriesStorage.kt index c09d9be3..68ba01f2 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalEntrySource.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/local/EntriesStorage.kt @@ -15,17 +15,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.framework.data +package com.rtbishop.look4sat.framework.data.local -import com.rtbishop.look4sat.domain.data.ILocalEntrySource -import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.data.IEntriesStorage +import com.rtbishop.look4sat.domain.Satellite import com.rtbishop.look4sat.framework.data.dao.EntriesDao -import com.rtbishop.look4sat.domain.model.SatEntry as DomainEntry -import com.rtbishop.look4sat.domain.model.SatItem as DomainItem import com.rtbishop.look4sat.framework.model.SatEntry as FrameworkEntry import com.rtbishop.look4sat.framework.model.SatItem as FrameworkItem +import com.rtbishop.look4sat.model.SatEntry as DomainEntry +import com.rtbishop.look4sat.model.SatItem as DomainItem -class LocalEntrySource(private val entriesDao: EntriesDao) : ILocalEntrySource { +class EntriesStorage(private val entriesDao: EntriesDao) : IEntriesStorage { override fun getEntriesTotal() = entriesDao.getEntriesTotal() diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalRadioSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/local/RadiosStorage.kt similarity index 87% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/LocalRadioSource.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/local/RadiosStorage.kt index 315a7f56..9712ee41 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/LocalRadioSource.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/local/RadiosStorage.kt @@ -15,14 +15,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.framework.data +package com.rtbishop.look4sat.framework.data.local -import com.rtbishop.look4sat.domain.model.SatRadio as DomainRadio -import com.rtbishop.look4sat.framework.model.SatRadio as FrameworkRadio -import com.rtbishop.look4sat.domain.data.ILocalRadioSource +import com.rtbishop.look4sat.data.IRadiosStorage import com.rtbishop.look4sat.framework.data.dao.RadiosDao +import com.rtbishop.look4sat.framework.model.SatRadio as FrameworkRadio +import com.rtbishop.look4sat.model.SatRadio as DomainRadio -class LocalRadioSource(private val radiosDao: RadiosDao) : ILocalRadioSource { +class RadiosStorage(private val radiosDao: RadiosDao) : IRadiosStorage { override fun getRadiosTotal() = radiosDao.getRadiosTotal() @@ -31,7 +31,6 @@ class LocalRadioSource(private val radiosDao: RadiosDao) : ILocalRadioSource { } override suspend fun insertRadios(radios: List) { - radiosDao.deleteRadios() radiosDao.insertRadios(radios.toFrameworkRadios()) } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/FileDataSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/remote/FileSource.kt similarity index 76% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/FileDataSource.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/remote/FileSource.kt index afa5d73d..e3a3665c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/FileDataSource.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/remote/FileSource.kt @@ -15,22 +15,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.framework.data +package com.rtbishop.look4sat.framework.data.remote import android.content.ContentResolver import android.net.Uri -import com.rtbishop.look4sat.domain.data.IFileDataSource +import com.rtbishop.look4sat.data.IFileSource import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext import java.io.InputStream -class FileDataSource( +class FileSource( private val contentResolver: ContentResolver, - private val ioDispatcher: CoroutineDispatcher -) : IFileDataSource { + private val coroutineDispatcher: CoroutineDispatcher +) : IFileSource { - @Suppress("BlockingMethodInNonBlockingContext") override suspend fun getDataStream(uri: String): InputStream? { - return withContext(ioDispatcher) { contentResolver.openInputStream(Uri.parse(uri)) } + return withContext(coroutineDispatcher) { contentResolver.openInputStream(Uri.parse(uri)) } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/data/RemoteDataSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/data/remote/NetworkSource.kt similarity index 64% rename from app/src/main/java/com/rtbishop/look4sat/framework/data/RemoteDataSource.kt rename to app/src/main/java/com/rtbishop/look4sat/framework/data/remote/NetworkSource.kt index 9c3c00c0..50c72886 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/data/RemoteDataSource.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/data/remote/NetworkSource.kt @@ -15,25 +15,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.framework.data +package com.rtbishop.look4sat.framework.data.remote -import com.rtbishop.look4sat.domain.data.IRemoteDataSource +import com.rtbishop.look4sat.data.INetworkSource import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.withContext -import okhttp3.OkHttpClient -import okhttp3.Request import java.io.InputStream +import java.net.URL -class RemoteDataSource( - private val httpClient: OkHttpClient, private val ioDispatcher: CoroutineDispatcher -) : IRemoteDataSource { +class NetworkSource(private val coroutineDispatcher: CoroutineDispatcher) : INetworkSource { - override suspend fun getDataStream(url: String): InputStream? = withContext(ioDispatcher) { - try { - val request = Request.Builder().url(url).build() - httpClient.newCall(request).execute().body?.byteStream() - } catch (exception: Exception) { - null - } + override suspend fun getDataStream(url: String): InputStream? { + return withContext(coroutineDispatcher) { URL(url).openStream() } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt b/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt index 48f231c0..d39b8a16 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/model/SatEntry.kt @@ -19,7 +19,7 @@ package com.rtbishop.look4sat.framework.model import androidx.room.Embedded import androidx.room.Entity -import com.rtbishop.look4sat.domain.predict.OrbitalData +import com.rtbishop.look4sat.model.OrbitalData @Entity(tableName = "entries", primaryKeys = ["catnum"]) data class SatEntry(@Embedded val data: OrbitalData, var comment: String? = null) diff --git a/app/src/main/java/com/rtbishop/look4sat/injection/AppModule.kt b/app/src/main/java/com/rtbishop/look4sat/injection/AppModule.kt deleted file mode 100644 index e832d430..00000000 --- a/app/src/main/java/com/rtbishop/look4sat/injection/AppModule.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Look4Sat. Amateur radio satellite tracker and pass predictor. - * Copyright (C) 2019-2022 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.injection - -import android.bluetooth.BluetoothManager -import android.content.Context -import android.content.SharedPreferences -import android.hardware.SensorManager -import android.location.LocationManager -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object AppModule { - - @Provides - @Singleton - fun provideBluetoothManager(@ApplicationContext context: Context): BluetoothManager { - return context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager - } - - @Provides - @Singleton - fun provideLocationManager(@ApplicationContext context: Context): LocationManager { - return context.getSystemService(Context.LOCATION_SERVICE) as LocationManager - } - - @Provides - @Singleton - fun provideSensorManager(@ApplicationContext context: Context): SensorManager { - return context.getSystemService(Context.SENSOR_SERVICE) as SensorManager - } - - @Provides - @Singleton - fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences { - return context.getSharedPreferences("default", Context.MODE_PRIVATE) - } -} diff --git a/app/src/main/java/com/rtbishop/look4sat/injection/BaseModule.kt b/app/src/main/java/com/rtbishop/look4sat/injection/BaseModule.kt deleted file mode 100644 index e4534b9b..00000000 --- a/app/src/main/java/com/rtbishop/look4sat/injection/BaseModule.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Look4Sat. Amateur radio satellite tracker and pass predictor. - * Copyright (C) 2019-2022 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.injection - -import android.bluetooth.BluetoothManager -import android.content.Context -import androidx.room.Room -import com.rtbishop.look4sat.domain.IDataRepository -import com.rtbishop.look4sat.domain.ILocationManager -import com.rtbishop.look4sat.domain.ISatelliteManager -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.data.DataRepository -import com.rtbishop.look4sat.domain.predict.SatelliteManager -import com.rtbishop.look4sat.framework.LocationManager -import com.rtbishop.look4sat.framework.SettingsManager -import com.rtbishop.look4sat.framework.data.FileDataSource -import com.rtbishop.look4sat.framework.data.LocalDatabase -import com.rtbishop.look4sat.framework.data.LocalEntrySource -import com.rtbishop.look4sat.framework.data.LocalRadioSource -import com.rtbishop.look4sat.framework.data.MIGRATION_1_2 -import com.rtbishop.look4sat.framework.data.RemoteDataSource -import com.rtbishop.look4sat.presentation.radarScreen.BTReporter -import com.rtbishop.look4sat.utility.DataParser -import com.rtbishop.look4sat.utility.DataReporter -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import okhttp3.OkHttpClient - -@Module -@InstallIn(SingletonComponent::class) -object BaseModule { - - @Provides - @Singleton - fun provideDataRepository( - @ApplicationContext context: Context, - settings: ISettingsManager - ): IDataRepository { - val db = Room.databaseBuilder(context, LocalDatabase::class.java, "Look4SatDb") - .addMigrations(MIGRATION_1_2).fallbackToDestructiveMigration().build() - val parser = DataParser(Dispatchers.Default) - val fileSource = FileDataSource(context.contentResolver, Dispatchers.IO) - val entries = LocalEntrySource(db.entriesDao()) - val radios = LocalRadioSource(db.radiosDao()) - val remoteSource = RemoteDataSource(OkHttpClient.Builder().build(), Dispatchers.IO) - val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default) - return DataRepository(parser, fileSource, entries, radios, remoteSource, scope, settings) - } - - @Provides - @Singleton - fun provideDataReporter(): DataReporter = DataReporter(CoroutineScope(Dispatchers.IO)) - - @Provides - @Singleton - fun provideBTReporter(manager: BluetoothManager): BTReporter { - return BTReporter(manager, CoroutineScope(Dispatchers.IO)) - } - - @Provides - @Singleton - fun provideLocationManager(manager: LocationManager): ILocationManager = manager - - @Provides - @Singleton - fun provideSatelliteManager(): ISatelliteManager = SatelliteManager(Dispatchers.Default) - - @Provides - @Singleton - fun provideSettingsManager(manager: SettingsManager): ISettingsManager = manager -} diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/MainScreen.kt similarity index 57% rename from app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/MainScreen.kt index 49495583..20e69fdb 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/MainActivity.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/MainScreen.kt @@ -1,29 +1,5 @@ -/* - * Look4Sat. Amateur radio satellite tracker and pass predictor. - * Copyright (C) 2019-2022 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.presentation -import android.annotation.SuppressLint -import android.content.Context -import android.content.pm.ActivityInfo -import android.content.res.Configuration -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -32,7 +8,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp -import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.navigation.NavController import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost @@ -41,31 +16,11 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.presentation.entriesScreen.EntriesScreen -import com.rtbishop.look4sat.presentation.mapScreen.MapScreen -import com.rtbishop.look4sat.presentation.passesScreen.PassesScreen -import com.rtbishop.look4sat.presentation.radarScreen.RadarScreen -import com.rtbishop.look4sat.presentation.settingsScreen.SettingsScreen -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class MainActivity : ComponentActivity() { - - @SuppressLint("SourceLockedOrientationActivity") - override fun onCreate(savedInstanceState: Bundle?) { - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - installSplashScreen() - super.onCreate(savedInstanceState) - setContent { MainTheme { MainScreen() } } - } - - override fun attachBaseContext(newBase: Context?) { - val newConfig = Configuration(newBase?.resources?.configuration) - newConfig.fontScale = 1.0f - applyOverrideConfiguration(newConfig) - super.attachBaseContext(newBase) - } -} +import com.rtbishop.look4sat.presentation.entries.EntriesScreen +import com.rtbishop.look4sat.presentation.map.MapScreen +import com.rtbishop.look4sat.presentation.passes.PassesScreen +import com.rtbishop.look4sat.presentation.radar.RadarScreen +import com.rtbishop.look4sat.presentation.settings.SettingsScreen sealed class Screen(var title: String, var icon: Int, var route: String) { object Entries : Screen("Entries", R.drawable.ic_entries, "entries") @@ -77,7 +32,7 @@ sealed class Screen(var title: String, var icon: Int, var route: String) { @OptIn(ExperimentalMaterial3Api::class) @Composable -private fun MainScreen(navController: NavHostController = rememberNavController()) { +fun MainScreen(navController: NavHostController = rememberNavController()) { Scaffold(bottomBar = { MainNavBar(navController = navController) }) { innerPadding -> Box(modifier = Modifier.padding(innerPadding)) { MainNavGraph(navController) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/FilterDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/FilterDialog.kt similarity index 98% rename from app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/FilterDialog.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/FilterDialog.kt index 707ae20c..786e5e05 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/FilterDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/FilterDialog.kt @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.passesScreen +package com.rtbishop.look4sat.presentation.dialogs import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/LocatorDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/LocatorDialog.kt similarity index 97% rename from app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/LocatorDialog.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/LocatorDialog.kt index 3aba5728..51263f82 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/LocatorDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/LocatorDialog.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.settingsScreen +package com.rtbishop.look4sat.presentation.dialogs import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/ModesDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/ModesDialog.kt similarity index 98% rename from app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/ModesDialog.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/ModesDialog.kt index ef1b121b..bec1a3ef 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/ModesDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/ModesDialog.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.passesScreen +package com.rtbishop.look4sat.presentation.dialogs import androidx.compose.foundation.background import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/PositionDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/PositionDialog.kt similarity index 98% rename from app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/PositionDialog.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/PositionDialog.kt index de725cfb..2b5de5dc 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/PositionDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/PositionDialog.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.settingsScreen +package com.rtbishop.look4sat.presentation.dialogs import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/TypesDialog.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/TypesDialog.kt similarity index 97% rename from app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/TypesDialog.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/TypesDialog.kt index 66d05400..11d0bf39 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/TypesDialog.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/dialogs/TypesDialog.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.entriesScreen +package com.rtbishop.look4sat.presentation.dialogs import androidx.compose.foundation.background import androidx.compose.foundation.clickable diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesScreen.kt similarity index 97% rename from app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesScreen.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesScreen.kt index 82b60b5d..9ebd186c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesScreen.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.entriesScreen +package com.rtbishop.look4sat.presentation.entries import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background @@ -28,11 +28,12 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.model.SatItem -import com.rtbishop.look4sat.presentation.Screen +import com.rtbishop.look4sat.model.DataState +import com.rtbishop.look4sat.model.SatItem import com.rtbishop.look4sat.presentation.CardLoadingIndicator import com.rtbishop.look4sat.presentation.MainTheme +import com.rtbishop.look4sat.presentation.Screen +import com.rtbishop.look4sat.presentation.dialogs.TypesDialog import com.rtbishop.look4sat.presentation.onClick @Composable diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesViewModel.kt similarity index 87% rename from app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesViewModel.kt index 92e40d99..817597f5 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entries/EntriesViewModel.kt @@ -15,15 +15,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.entriesScreen +package com.rtbishop.look4sat.presentation.entries import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ILocationSource import com.rtbishop.look4sat.domain.ISatelliteManager -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.model.SatItem +import com.rtbishop.look4sat.domain.ISettingsSource +import com.rtbishop.look4sat.model.DataState +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.SatItem import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.delay @@ -37,7 +39,8 @@ import javax.inject.Inject class EntriesViewModel @Inject constructor( private val satelliteManager: ISatelliteManager, private val repository: IDataRepository, - private val settings: ISettingsManager + private val settings: ISettingsSource, + private val locationSource: ILocationSource ) : ViewModel() { private val satType = MutableStateFlow("All") @@ -78,11 +81,12 @@ class EntriesViewModel @Inject constructor( settings.saveEntriesSelection(newSelection) val selectedIds = settings.loadEntriesSelection() val satellites = repository.getEntriesWithIds(selectedIds) - val stationPos = settings.loadStationPosition() + val stationPos = locationSource.stationPosition.value + val geoPos = GeoPos(stationPos.latitude, stationPos.longitude) val timeRef = System.currentTimeMillis() val hoursAhead = settings.getHoursAhead() val minElev = settings.getMinElevation() - satelliteManager.calculatePasses(satellites, stationPos, timeRef, hoursAhead, minElev) + satelliteManager.calculatePasses(satellites, geoPos, timeRef, hoursAhead, minElev) } fun updateSelection(catNums: List, isSelected: Boolean) { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapData.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/map/MapData.kt similarity index 91% rename from app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapData.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/map/MapData.kt index 4b2c06c2..02e20ca9 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapData.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/map/MapData.kt @@ -15,9 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.mapScreen +package com.rtbishop.look4sat.presentation.map -import com.rtbishop.look4sat.domain.predict.GeoPos +import com.rtbishop.look4sat.model.GeoPos data class MapData( val catNum: Int, diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/map/MapScreen.kt similarity index 96% rename from app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapScreen.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/map/MapScreen.kt index d804318a..2c82c362 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/map/MapScreen.kt @@ -1,5 +1,6 @@ -package com.rtbishop.look4sat.presentation.mapScreen +package com.rtbishop.look4sat.presentation.map +import android.content.Context import android.graphics.* import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable @@ -22,9 +23,9 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.domain.predict.SatPos -import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.domain.Satellite +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.SatPos import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.util.GeoPoint @@ -60,7 +61,8 @@ private val labelRect = Rect() @Composable fun MapScreen(viewModel: MapViewModel = hiltViewModel()) { val context = LocalContext.current - Configuration.getInstance().load(context, viewModel.getPreferences()) + val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE) + Configuration.getInstance().load(context, preferences) viewModel.selectDefaultSatellite(-1) val stationPos = viewModel.stationPos.collectAsState(initial = null) val positions = viewModel.positions.collectAsState(initial = null) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/map/MapViewModel.kt similarity index 93% rename from app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/map/MapViewModel.kt index 7070d237..dbe07bc8 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/map/MapViewModel.kt @@ -15,17 +15,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.mapScreen +package com.rtbishop.look4sat.presentation.map -import android.content.SharedPreferences import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.rtbishop.look4sat.domain.IDataRepository -import com.rtbishop.look4sat.domain.ISatelliteManager -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.domain.predict.SatPos -import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.domain.* +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.SatPos import com.rtbishop.look4sat.utility.QthConverter import com.rtbishop.look4sat.utility.toDegrees import com.rtbishop.look4sat.utility.toTimerString @@ -42,13 +38,14 @@ import kotlin.math.min @HiltViewModel class MapViewModel @Inject constructor( - private val preferences: SharedPreferences, private val repository: IDataRepository, private val satelliteManager: ISatelliteManager, - private val settings: ISettingsManager + private val settings: ISettingsSource, + private val locationSource: ILocationSource ) : ViewModel() { - private val stationPosition = settings.loadStationPosition() + private val stationPosNew = locationSource.stationPosition.value + private val stationPosition = GeoPos(stationPosNew.latitude, stationPosNew.longitude) private var allPasses = satelliteManager.getPasses() private var allSatellites = listOf() private var dataUpdateJob: Job? = null @@ -73,8 +70,6 @@ class MapViewModel @Inject constructor( private val _positions = MutableSharedFlow>() val positions: SharedFlow> = _positions - fun getPreferences() = preferences - fun scrollSelection(decrement: Boolean) { if (allSatellites.isNotEmpty()) { val index = allSatellites.indexOf(selectedSatellite) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt similarity index 96% rename from app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesScreen.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt index 9f216c6e..011ae921 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesScreen.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.passesScreen +package com.rtbishop.look4sat.presentation.passes import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background @@ -23,12 +23,12 @@ import androidx.compose.ui.unit.* import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.predict.NearEarthSat -import com.rtbishop.look4sat.domain.predict.OrbitalData -import com.rtbishop.look4sat.domain.predict.SatPass -import com.rtbishop.look4sat.presentation.Screen -import com.rtbishop.look4sat.presentation.MainTheme +import com.rtbishop.look4sat.domain.NearEarthSat +import com.rtbishop.look4sat.model.DataState +import com.rtbishop.look4sat.model.OrbitalData +import com.rtbishop.look4sat.model.SatPass +import com.rtbishop.look4sat.presentation.* +import com.rtbishop.look4sat.presentation.dialogs.FilterDialog import com.rtbishop.look4sat.presentation.pullRefresh.PullRefreshIndicator import com.rtbishop.look4sat.presentation.pullRefresh.PullRefreshState import com.rtbishop.look4sat.presentation.pullRefresh.pullRefresh diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt similarity index 88% rename from app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesViewModel.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt index 908b44d7..dda0663d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passes/PassesViewModel.kt @@ -15,15 +15,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.passesScreen +package com.rtbishop.look4sat.presentation.passes import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.rtbishop.look4sat.domain.IDataRepository +import com.rtbishop.look4sat.domain.ILocationSource import com.rtbishop.look4sat.domain.ISatelliteManager -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.predict.SatPass +import com.rtbishop.look4sat.domain.ISettingsSource +import com.rtbishop.look4sat.model.DataState +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.SatPass import com.rtbishop.look4sat.utility.toTimerString import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.* @@ -35,7 +37,8 @@ import javax.inject.Inject class PassesViewModel @Inject constructor( private val satelliteManager: ISatelliteManager, private val repository: IDataRepository, - private val settings: ISettingsManager + private val settings: ISettingsSource, + private val locationSource: ILocationSource ) : ViewModel() { private val _passes = MutableStateFlow>>(DataState.Loading) @@ -105,11 +108,12 @@ class PassesViewModel @Inject constructor( selection?.let { items -> settings.saveEntriesSelection(items) } settings.setHoursAhead(hoursAhead) settings.setMinElevation(minElevation) - val stationPos = settings.loadStationPosition() + val stationPos = locationSource.stationPosition.value + val geoPos = GeoPos(stationPos.latitude, stationPos.longitude) val selectedIds = settings.loadEntriesSelection() val satellites = repository.getEntriesWithIds(selectedIds) satelliteManager.calculatePasses( - satellites, stationPos, timeRef, hoursAhead, minElevation + satellites, geoPos, timeRef, hoursAhead, minElevation ) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarData.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarData.kt similarity index 89% rename from app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarData.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarData.kt index 807510a7..c68123b6 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarData.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarData.kt @@ -15,8 +15,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.radarScreen +package com.rtbishop.look4sat.presentation.radar -import com.rtbishop.look4sat.domain.predict.SatPos +import com.rtbishop.look4sat.model.SatPos data class RadarData(val satPos: SatPos, val satTrack: List = emptyList()) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt similarity index 88% rename from app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarScreen.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt index b8422118..aa8e3e6b 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarScreen.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.radarScreen +package com.rtbishop.look4sat.presentation.radar import androidx.compose.foundation.background import androidx.compose.foundation.layout.* @@ -18,15 +18,12 @@ import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.rtbishop.look4sat.R -import com.rtbishop.look4sat.domain.model.SatRadio +import com.rtbishop.look4sat.model.SatRadio @Composable fun RadarScreen(navController: NavController) { val viewModel: RadarViewModel = hiltViewModel() val currentPass = viewModel.getPass().collectAsState(null) - val radarData = viewModel.radarData.collectAsState() - val transmitters = viewModel.transmitters.collectAsState() - val orientation = viewModel.orientation.collectAsState() Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) { ElevatedCard(modifier = Modifier.height(52.dp)) { @@ -62,20 +59,18 @@ fun RadarScreen(navController: NavController) { ElevatedCard(modifier = Modifier .fillMaxSize() .weight(1f)) { - radarData.value?.let { data -> - orientation.value?.let { triple -> - RadarViewCompose( - item = data.satPos, - items = data.satTrack, - orientation = triple - ) - } + viewModel.radarData.value?.let { data -> + RadarViewCompose( + item = data.satPos, + items = data.satTrack, + azimElev = viewModel.orientation.value + ) } } ElevatedCard(modifier = Modifier .fillMaxSize() .weight(1f)) { - TransmittersList(transmitters = transmitters.value) + TransmittersList(transmitters = viewModel.transmitters.value) } } } @@ -161,15 +156,9 @@ private fun TransmitterItem(radio: SatRadio) { // setShowAim(viewModel.getUseCompass()) // setScanning(viewModel.getShowSweep()) // } -// radarCard.addView(radarView) // viewModel.radarData.observe(viewLifecycleOwner) { passData -> -// radarView?.setPosition(passData.satPos) -// radarView?.setPositions(passData.satTrack) // setPassText(pass, passData.satPos) // } -// viewModel.orientation.observe(viewLifecycleOwner) { value -> -// radarView?.setOrientation(value.first, value.second, value.third) -// } // } // } //} diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarView.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarView.kt similarity index 94% rename from app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarView.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarView.kt index 8daccc91..3f257337 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarView.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarView.kt @@ -1,6 +1,6 @@ @file:OptIn(ExperimentalTextApi::class) -package com.rtbishop.look4sat.presentation.radarScreen +package com.rtbishop.look4sat.presentation.radar import androidx.compose.animation.core.* import androidx.compose.foundation.Canvas @@ -14,14 +14,14 @@ import androidx.compose.ui.graphics.* import androidx.compose.ui.graphics.drawscope.* import androidx.compose.ui.text.* import androidx.compose.ui.unit.sp -import com.rtbishop.look4sat.domain.predict.PI_2 -import com.rtbishop.look4sat.domain.predict.SatPos +import com.rtbishop.look4sat.domain.PI_2 +import com.rtbishop.look4sat.model.SatPos import com.rtbishop.look4sat.utility.toRadians import kotlin.math.cos import kotlin.math.sin @Composable -fun RadarViewCompose(item: SatPos, items: List, orientation: Triple) { +fun RadarViewCompose(item: SatPos, items: List, azimElev: Pair) { val radarColor = Color(0xFFDCDCDC) val primaryColor = Color(0xFFFFE082) val secondaryColor = Color(0xFFDC0000) @@ -41,14 +41,14 @@ fun RadarViewCompose(item: SatPos, items: List, orientation: Triple 0) drawPosition(item, radius, animScale.value, primaryColor) - drawAim(orientation.first, orientation.second, radius, strokeWidth, secondaryColor) + drawAim(azimElev.first, azimElev.second, radius, strokeWidth, secondaryColor) } sweepDegrees.value = (sweepDegrees.value + 360 / 12.0f / 60) % 360 } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarViewModel.kt similarity index 67% rename from app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarViewModel.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarViewModel.kt index 01c8c7c3..ff842e49 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radar/RadarViewModel.kt @@ -15,29 +15,26 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.radarScreen +package com.rtbishop.look4sat.presentation.radar import android.hardware.GeomagneticField import android.util.Log +import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.rtbishop.look4sat.domain.IDataRepository -import com.rtbishop.look4sat.domain.ISatelliteManager -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.model.SatRadio -import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.domain.predict.SatPass -import com.rtbishop.look4sat.domain.predict.SatPos -import com.rtbishop.look4sat.domain.predict.Satellite -import com.rtbishop.look4sat.framework.OrientationManager -import com.rtbishop.look4sat.utility.DataReporter +import com.rtbishop.look4sat.domain.* +import com.rtbishop.look4sat.framework.BluetoothReporter +import com.rtbishop.look4sat.framework.NetworkReporter +import com.rtbishop.look4sat.framework.OrientationSource +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.SatPass +import com.rtbishop.look4sat.model.SatPos +import com.rtbishop.look4sat.model.SatRadio import com.rtbishop.look4sat.utility.round import com.rtbishop.look4sat.utility.toDegrees import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.isActive import kotlinx.coroutines.launch @@ -46,28 +43,34 @@ import javax.inject.Inject @HiltViewModel class RadarViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, - private val orientationManager: OrientationManager, - private val reporter: DataReporter, - private val btReporter: BTReporter, + private val orientationSource: OrientationSource, + private val reporter: NetworkReporter, + private val bluetoothReporter: BluetoothReporter, private val satManager: ISatelliteManager, private val repository: IDataRepository, - private val settings: ISettingsManager -) : ViewModel(), OrientationManager.OrientationListener { + private val settings: ISettingsSource, + private val locationSource: ILocationSource +) : ViewModel() { - private val stationPos = settings.loadStationPosition() - private val _passData = MutableStateFlow(null) - private val _transmitters = MutableStateFlow>(emptyList()) - private val _orientation = MutableStateFlow?>(null) - val radarData: StateFlow = _passData - val transmitters: StateFlow> = _transmitters - val orientation: StateFlow?> = _orientation + private val stationPos = locationSource.stationPosition.value.toGeoPos() + private val magDeclination = getMagDeclination(stationPos) + val transmitters = mutableStateOf>(emptyList()) + val radarData = mutableStateOf(null) + val orientation = mutableStateOf(orientationSource.orientation.value) init { - enableSensor() + if (settings.isSensorEnabled()) { + viewModelScope.launch { + orientationSource.startListening() + orientationSource.orientation.collect { data -> + orientation.value = Pair(data.first + magDeclination, data.second) + } + } + } } override fun onCleared() { - disableSensor() + orientationSource.stopListening() super.onCleared() } @@ -94,22 +97,10 @@ class RadarViewModel @Inject constructor( } } - fun enableSensor() { - if (settings.isSensorEnabled()) orientationManager.startListening(this) - } - - fun disableSensor() { - if (settings.isSensorEnabled()) orientationManager.stopListening() - } - fun getUseCompass(): Boolean = settings.isSensorEnabled() fun getShowSweep(): Boolean = settings.isSweepEnabled() - override fun onOrientationChanged(azimuth: Float, pitch: Float, roll: Float) { - _orientation.value = Triple(azimuth + getMagDeclination(stationPos), pitch, roll) - } - private fun getMagDeclination(geoPos: GeoPos, time: Long = System.currentTimeMillis()): Float { val latitude = geoPos.lat.toFloat() val longitude = geoPos.lon.toFloat() @@ -129,7 +120,7 @@ class RadarViewModel @Inject constructor( val elevation = satPos.elevation.toDegrees().round(1) reporter.reportRotation(server, port, azimuth, elevation) } - _passData.value = RadarData(satPos, track) + radarData.value = RadarData(satPos, track) } } @@ -137,14 +128,14 @@ class RadarViewModel @Inject constructor( viewModelScope.launch { if (settings.getBTEnabled()) { val btDevice = settings.getBTDeviceAddr() - if (btReporter.isConnected()) { + if (bluetoothReporter.isConnected()) { val format = settings.getBTFormat() val azimuth = satPos.azimuth.toDegrees().round(0).toInt() val elevation = satPos.elevation.toDegrees().round(0).toInt() - btReporter.reportRotation(format, azimuth, elevation) - } else if (!btReporter.isConnecting()) { + bluetoothReporter.reportRotation(format, azimuth, elevation) + } else if (!bluetoothReporter.isConnecting()) { Log.i("BTReporter", "BTReporter: Attempting to connect...") - btReporter.connectBTDevice(btDevice) + bluetoothReporter.connectBTDevice(btDevice) } } } @@ -154,7 +145,7 @@ class RadarViewModel @Inject constructor( viewModelScope.launch { delay(125) val list = satManager.processRadios(satellite, stationPos, radios, time) - _transmitters.value = list + transmitters.value = list } } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsScreen.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt similarity index 98% rename from app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsScreen.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt index 4d16dc80..6c00cc1c 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsScreen.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreen.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.settingsScreen +package com.rtbishop.look4sat.presentation.settings import android.Manifest import android.os.Build @@ -26,6 +26,8 @@ import com.rtbishop.look4sat.BuildConfig import com.rtbishop.look4sat.R import com.rtbishop.look4sat.presentation.CardButton import com.rtbishop.look4sat.presentation.MainTheme +import com.rtbishop.look4sat.presentation.dialogs.LocatorDialog +import com.rtbishop.look4sat.presentation.dialogs.PositionDialog import com.rtbishop.look4sat.presentation.gotoUrl import com.rtbishop.look4sat.presentation.showToast @@ -57,8 +59,8 @@ fun SettingsScreen(navController: NavController) { val locationPermFine = Manifest.permission.ACCESS_FINE_LOCATION val locationRequest = rememberLauncherForActivityResult(locationContract) { permissions -> when { - permissions[locationPermFine] == true -> viewModel.locationSettings.value.setGpsLoc - permissions[locationPermCoarse] == true -> viewModel.locationSettings.value.setGpsLoc + permissions[locationPermFine] == true -> viewModel.locationSettings.value.setGpsLoc() + permissions[locationPermCoarse] == true -> viewModel.locationSettings.value.setGpsLoc() else -> showToast(context, locationError) } } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsScreenState.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreenState.kt similarity index 93% rename from app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsScreenState.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreenState.kt index c325fc2b..c80ca3e1 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsScreenState.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsScreenState.kt @@ -1,4 +1,4 @@ -package com.rtbishop.look4sat.presentation.settingsScreen +package com.rtbishop.look4sat.presentation.settings data class LocationSettings( val getUpdating: Boolean, diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsViewModel.kt similarity index 81% rename from app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt rename to app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsViewModel.kt index f451170a..e6c1875f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settings/SettingsViewModel.kt @@ -15,15 +15,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.presentation.settingsScreen +package com.rtbishop.look4sat.presentation.settings import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.rtbishop.look4sat.domain.IDataRepository -import com.rtbishop.look4sat.domain.ILocationManager -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.model.DataState +import com.rtbishop.look4sat.domain.ILocationSource +import com.rtbishop.look4sat.domain.ISettingsSource +import com.rtbishop.look4sat.model.DataState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch @@ -31,21 +31,20 @@ import javax.inject.Inject @HiltViewModel class SettingsViewModel @Inject constructor( - private val locationManager: ILocationManager, + private val locationSource: ILocationSource, private val repository: IDataRepository, - private val settings: ISettingsManager + private val settings: ISettingsSource ) : ViewModel() { private val defaultLocationSettings = LocationSettings(false, - settings.getLastUpdateTime(), - locationManager.getStationPosition().lat, - locationManager.getStationPosition().lon, - settings.loadStationLocator(), - { locationManager.setPositionFromGps() }, - { lat, lon -> locationManager.setStationPosition(lat, lon) }, - { locationManager.setPositionFromQth(it) }) - var locationSettings = mutableStateOf(defaultLocationSettings) - private set + locationSource.stationPosition.value.timestamp, + locationSource.stationPosition.value.latitude, + locationSource.stationPosition.value.longitude, + locationSource.stationPosition.value.qthLocator, + { locationSource.setGpsPosition() }, + { lat, lon -> locationSource.setGeoPosition(lat, lon) }, + { locationSource.setQthPosition(it) }) + val locationSettings = mutableStateOf(defaultLocationSettings) private val defaultDataSettings = DataSettings(false, settings.getLastUpdateTime(), @@ -54,8 +53,7 @@ class SettingsViewModel @Inject constructor( { repository.updateFromWeb() }, { repository.updateFromFile(it) }, { repository.clearAllData() }) - var dataSettings = mutableStateOf(defaultDataSettings) - private set + val dataSettings = mutableStateOf(defaultDataSettings) private val defaultOtherSettings = OtherSettings(settings.isUtcEnabled(), settings.isUpdateEnabled(), @@ -65,8 +63,7 @@ class SettingsViewModel @Inject constructor( { setUpdate(it) }, { setSweep(it) }, { setSensor(it) }) - var otherSettings = mutableStateOf(defaultOtherSettings) - private set + val otherSettings = mutableStateOf(defaultOtherSettings) init { viewModelScope.launch { @@ -81,9 +78,7 @@ class SettingsViewModel @Inject constructor( combine(repository.getEntriesTotal(), repository.getRadiosTotal()) { sats, radios -> dataSettings.value = dataSettings.value.copy(getSatellites = sats, getRadios = radios) - }.collect { - - } + }.collect {} } } diff --git a/base/src/main/java/com/rtbishop/look4sat/utility/DataParser.kt b/base/src/main/java/com/rtbishop/look4sat/data/DataParser.kt similarity index 76% rename from base/src/main/java/com/rtbishop/look4sat/utility/DataParser.kt rename to base/src/main/java/com/rtbishop/look4sat/data/DataParser.kt index 46815954..4ecd5f4a 100644 --- a/base/src/main/java/com/rtbishop/look4sat/utility/DataParser.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/DataParser.kt @@ -15,50 +15,52 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.utility +package com.rtbishop.look4sat.data -import com.rtbishop.look4sat.domain.model.SatRadio -import com.rtbishop.look4sat.domain.predict.OrbitalData -import java.io.InputStream -import kotlin.math.pow +import com.rtbishop.look4sat.model.OrbitalData +import com.rtbishop.look4sat.model.SatRadio 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 defaultDispatcher: CoroutineDispatcher) { - suspend fun parseCSVStream(csvStream: InputStream): List = withContext(defaultDispatcher) { - val parsedItems = mutableListOf() - csvStream.bufferedReader().useLines { lines -> - lines.forEachIndexed { index, line -> - if (index != 0) { - val values = line.split(",") - parseCSV(values)?.let { tle -> parsedItems.add(tle) } + suspend fun parseCSVStream(csvStream: InputStream): List = + withContext(defaultDispatcher) { + val parsedItems = mutableListOf() + csvStream.bufferedReader().useLines { lines -> + lines.forEachIndexed { index, line -> + if (index != 0) { + val values = line.split(",") + parseCSV(values)?.let { tle -> parsedItems.add(tle) } + } } } + return@withContext parsedItems } - return@withContext parsedItems - } - suspend fun parseTLEStream(tleStream: InputStream): List = withContext(defaultDispatcher) { - val tleStrings = mutableListOf(String(), String(), String()) - val parsedItems = mutableListOf() - var lineIndex = 0 - tleStream.bufferedReader().forEachLine { line -> - tleStrings[lineIndex] = line - if (lineIndex < 2) { - lineIndex++ - } else { - val isLineOneValid = tleStrings[1].substring(0, 1) == "1" - val isLineTwoValid = tleStrings[2].substring(0, 1) == "2" - if (!isLineOneValid && !isLineTwoValid) return@forEachLine - parseTLE(tleStrings)?.let { tle -> parsedItems.add(tle) } - lineIndex = 0 + suspend fun parseTLEStream(tleStream: InputStream): List = + withContext(defaultDispatcher) { + val tleStrings = mutableListOf(String(), String(), String()) + val parsedItems = mutableListOf() + var lineIndex = 0 + tleStream.bufferedReader().forEachLine { line -> + tleStrings[lineIndex] = line + if (lineIndex < 2) { + lineIndex++ + } else { + val isLineOneValid = tleStrings[1].substring(0, 1) == "1" + val isLineTwoValid = tleStrings[2].substring(0, 1) == "2" + if (!isLineOneValid && !isLineTwoValid) return@forEachLine + parseTLE(tleStrings)?.let { tle -> parsedItems.add(tle) } + lineIndex = 0 + } } + return@withContext parsedItems } - return@withContext parsedItems - } suspend fun parseJSONStream(jsonStream: InputStream): List { return withContext(defaultDispatcher) { @@ -76,10 +78,6 @@ class DataParser(private val defaultDispatcher: CoroutineDispatcher) { } } - fun isLeapYear(year: Int): Boolean { - return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0) - } - private fun parseCSV(values: List): OrbitalData? { try { val name = values[0] @@ -122,8 +120,8 @@ class DataParser(private val defaultDispatcher: CoroutineDispatcher) { 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()) + 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 @@ -155,10 +153,8 @@ class DataParser(private val defaultDispatcher: CoroutineDispatcher) { val daysArray = arrayOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) var dayOfYear = dayOfMonth // If leap year increment Feb days - if (isLeapYear(year)) daysArray[1]++ - for (i in 0 until month - 1) { - dayOfYear += daysArray[i] - } + if (((year / 4 == 0) && (year / 100 != 0)) || (year / 400 == 0)) daysArray[1]++ + for (i in 0 until month - 1) { dayOfYear += daysArray[i] } return dayOfYear } } diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/data/DataRepository.kt b/base/src/main/java/com/rtbishop/look4sat/data/DataRepository.kt similarity index 90% rename from base/src/main/java/com/rtbishop/look4sat/domain/data/DataRepository.kt rename to base/src/main/java/com/rtbishop/look4sat/data/DataRepository.kt index 9471f3f7..c498b0e3 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/data/DataRepository.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/DataRepository.kt @@ -15,13 +15,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.data +package com.rtbishop.look4sat.data import com.rtbishop.look4sat.domain.IDataRepository -import com.rtbishop.look4sat.domain.ISettingsManager -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.model.SatEntry -import com.rtbishop.look4sat.utility.DataParser +import com.rtbishop.look4sat.domain.ISettingsSource +import com.rtbishop.look4sat.model.DataState +import com.rtbishop.look4sat.model.SatEntry import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -30,16 +29,16 @@ import java.util.zip.ZipInputStream class DataRepository( private val dataParser: DataParser, - private val fileSource: IFileDataSource, - private val entrySource: ILocalEntrySource, - private val radioSource: ILocalRadioSource, - private val remoteSource: IRemoteDataSource, + private val fileSource: IFileSource, + private val entrySource: IEntriesStorage, + private val radioSource: IRadiosStorage, + private val remoteSource: INetworkSource, private val repositoryScope: CoroutineScope, - private val settingsManager: ISettingsManager + private val settingsManager: ISettingsSource ) : IDataRepository { private val exceptionHandler = CoroutineExceptionHandler { _, exception -> - _updateState.value = DataState.Error(exception.message) + _updateState.value = DataState.Exception(exception.message) } private val updateStateDelay = 875L private val _updateState = MutableStateFlow>(DataState.Handled) diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalEntrySource.kt b/base/src/main/java/com/rtbishop/look4sat/data/IEntriesStorage.kt similarity index 82% rename from base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalEntrySource.kt rename to base/src/main/java/com/rtbishop/look4sat/data/IEntriesStorage.kt index a9692d8c..3d5f7fb0 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalEntrySource.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/IEntriesStorage.kt @@ -15,14 +15,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.data +package com.rtbishop.look4sat.data -import com.rtbishop.look4sat.domain.model.SatEntry -import com.rtbishop.look4sat.domain.model.SatItem -import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.domain.Satellite +import com.rtbishop.look4sat.model.SatEntry +import com.rtbishop.look4sat.model.SatItem import kotlinx.coroutines.flow.Flow -interface ILocalEntrySource { +interface IEntriesStorage { fun getEntriesTotal(): Flow diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/data/IFileDataSource.kt b/base/src/main/java/com/rtbishop/look4sat/data/IFileSource.kt similarity index 92% rename from base/src/main/java/com/rtbishop/look4sat/domain/data/IFileDataSource.kt rename to base/src/main/java/com/rtbishop/look4sat/data/IFileSource.kt index 51b4d912..3fac9a66 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/data/IFileDataSource.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/IFileSource.kt @@ -15,11 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.data +package com.rtbishop.look4sat.data import java.io.InputStream -interface IFileDataSource { +interface IFileSource { suspend fun getDataStream(uri: String): InputStream? } diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/data/IRemoteDataSource.kt b/base/src/main/java/com/rtbishop/look4sat/data/INetworkSource.kt similarity index 93% rename from base/src/main/java/com/rtbishop/look4sat/domain/data/IRemoteDataSource.kt rename to base/src/main/java/com/rtbishop/look4sat/data/INetworkSource.kt index aa8cb71e..4f30ca68 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/data/IRemoteDataSource.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/INetworkSource.kt @@ -15,11 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.data +package com.rtbishop.look4sat.data import java.io.InputStream -interface IRemoteDataSource { +interface INetworkSource { val radioApi: String get() = "https://db.satnogs.org/api/transmitters/?format=json&status=active" diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalRadioSource.kt b/base/src/main/java/com/rtbishop/look4sat/data/IRadiosStorage.kt similarity index 89% rename from base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalRadioSource.kt rename to base/src/main/java/com/rtbishop/look4sat/data/IRadiosStorage.kt index 8418ef01..7ffc42e3 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/data/ILocalRadioSource.kt +++ b/base/src/main/java/com/rtbishop/look4sat/data/IRadiosStorage.kt @@ -15,12 +15,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.data +package com.rtbishop.look4sat.data -import com.rtbishop.look4sat.domain.model.SatRadio +import com.rtbishop.look4sat.model.SatRadio import kotlinx.coroutines.flow.Flow -interface ILocalRadioSource { +interface IRadiosStorage { fun getRadiosTotal(): Flow diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt b/base/src/main/java/com/rtbishop/look4sat/domain/DeepSpaceSat.kt similarity index 99% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/DeepSpaceSat.kt index a425e9a2..c6a40a85 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/DeepSpaceSat.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/DeepSpaceSat.kt @@ -15,8 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.domain +import com.rtbishop.look4sat.model.OrbitalData import kotlin.math.* class DeepSpaceSat(data: OrbitalData) : Satellite(data) { diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt b/base/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt index caacbcae..9cabd0de 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt @@ -17,10 +17,9 @@ */ package com.rtbishop.look4sat.domain -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.model.SatItem -import com.rtbishop.look4sat.domain.model.SatRadio -import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.model.DataState +import com.rtbishop.look4sat.model.SatItem +import com.rtbishop.look4sat.model.SatRadio import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/ILocationManager.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ILocationManager.kt deleted file mode 100644 index 55493384..00000000 --- a/base/src/main/java/com/rtbishop/look4sat/domain/ILocationManager.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Look4Sat. Amateur radio satellite tracker and pass predictor. - * Copyright (C) 2019-2022 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 - -import com.rtbishop.look4sat.domain.model.DataState -import com.rtbishop.look4sat.domain.predict.GeoPos -import kotlinx.coroutines.flow.SharedFlow - -interface ILocationManager { - - val stationPosition: SharedFlow> - - fun getStationLocator(): String - - fun getStationPosition(): GeoPos - - fun setStationPosition(latitude: Double, longitude: Double) - - fun setPositionFromGps() - - fun setPositionFromNet() - - fun setPositionFromQth(locator: String) - - fun setPositionHandled() -} diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/ILocationSource.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ILocationSource.kt new file mode 100644 index 00000000..6182247f --- /dev/null +++ b/base/src/main/java/com/rtbishop/look4sat/domain/ILocationSource.kt @@ -0,0 +1,32 @@ +/* + * Look4Sat. Amateur radio satellite tracker and pass predictor. + * Copyright (C) 2019-2022 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 + +import com.rtbishop.look4sat.model.StationPos +import kotlinx.coroutines.flow.StateFlow + +interface ILocationSource { + + val stationPosition: StateFlow + + fun setGpsPosition(): Boolean + + fun setGeoPosition(latitude: Double, longitude: Double): Boolean + + fun setQthPosition(locator: String): Boolean +} diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/ISatelliteManager.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ISatelliteManager.kt index 25d2c75c..370b4335 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/ISatelliteManager.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/ISatelliteManager.kt @@ -1,10 +1,9 @@ package com.rtbishop.look4sat.domain -import com.rtbishop.look4sat.domain.model.SatRadio -import com.rtbishop.look4sat.domain.predict.GeoPos -import com.rtbishop.look4sat.domain.predict.SatPass -import com.rtbishop.look4sat.domain.predict.SatPos -import com.rtbishop.look4sat.domain.predict.Satellite +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.SatPass +import com.rtbishop.look4sat.model.SatPos +import com.rtbishop.look4sat.model.SatRadio import kotlinx.coroutines.flow.SharedFlow interface ISatelliteManager { diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsSource.kt similarity index 94% rename from base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/ISettingsSource.kt index 13105b94..4c4c05e7 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsManager.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/ISettingsSource.kt @@ -17,9 +17,9 @@ */ package com.rtbishop.look4sat.domain -import com.rtbishop.look4sat.domain.predict.GeoPos +import com.rtbishop.look4sat.model.StationPos -interface ISettingsManager { +interface ISettingsSource { val sourcesMap: Map get() = mapOf( @@ -51,13 +51,9 @@ interface ISettingsManager { "Amsat" to "https://amsat.org/tle/current/nasabare.txt" ) - fun loadStationLocator(): String + fun loadStationPosition(): StationPos - fun saveStationLocator(locator: String) - - fun loadStationPosition(): GeoPos - - fun saveStationPosition(position: GeoPos) + fun saveStationPosition(stationPos: StationPos) fun getHoursAhead(): Int diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt b/base/src/main/java/com/rtbishop/look4sat/domain/NearEarthSat.kt similarity index 99% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/NearEarthSat.kt index e195c602..9f16df3b 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/NearEarthSat.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/NearEarthSat.kt @@ -15,8 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.domain +import com.rtbishop.look4sat.model.OrbitalData import kotlin.math.* class NearEarthSat(data: OrbitalData) : Satellite(data) { diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt b/base/src/main/java/com/rtbishop/look4sat/domain/Satellite.kt similarity index 98% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/Satellite.kt index 4743441e..828c60be 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/Satellite.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/Satellite.kt @@ -15,8 +15,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.domain +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.OrbitalData +import com.rtbishop.look4sat.model.SatPos import kotlin.math.* const val ASTRONOMICAL_UNIT = 1.49597870691E8 diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatelliteManager.kt b/base/src/main/java/com/rtbishop/look4sat/domain/SatelliteManager.kt similarity index 97% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/SatelliteManager.kt rename to base/src/main/java/com/rtbishop/look4sat/domain/SatelliteManager.kt index 3295a5f0..2b0fb687 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatelliteManager.kt +++ b/base/src/main/java/com/rtbishop/look4sat/domain/SatelliteManager.kt @@ -15,10 +15,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.domain -import com.rtbishop.look4sat.domain.ISatelliteManager -import com.rtbishop.look4sat.domain.model.SatRadio +import com.rtbishop.look4sat.model.GeoPos +import com.rtbishop.look4sat.model.SatPass +import com.rtbishop.look4sat.model.SatPos +import com.rtbishop.look4sat.model.SatRadio import com.rtbishop.look4sat.utility.round import com.rtbishop.look4sat.utility.toDegrees import kotlinx.coroutines.CoroutineDispatcher diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/model/DataState.kt b/base/src/main/java/com/rtbishop/look4sat/model/DataState.kt similarity index 85% rename from base/src/main/java/com/rtbishop/look4sat/domain/model/DataState.kt rename to base/src/main/java/com/rtbishop/look4sat/model/DataState.kt index 8307c48e..125daa75 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/model/DataState.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/DataState.kt @@ -15,11 +15,12 @@ * 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 +package com.rtbishop.look4sat.model sealed class DataState { data class Success(val data: T) : DataState() - data class Error(val message: String?) : DataState() + data class Error(val resId: Int?) : DataState() + data class Exception(val message: String?) : DataState() object Handled : DataState() object Loading : DataState() } diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/GeoPos.kt b/base/src/main/java/com/rtbishop/look4sat/model/GeoPos.kt similarity index 95% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/GeoPos.kt rename to base/src/main/java/com/rtbishop/look4sat/model/GeoPos.kt index c21889e5..8ed8f19c 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/GeoPos.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/GeoPos.kt @@ -15,6 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.model data class GeoPos(val lat: Double, val lon: Double, val alt: Double = 0.0, val name: String? = null) diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt b/base/src/main/java/com/rtbishop/look4sat/model/OrbitalData.kt similarity index 95% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt rename to base/src/main/java/com/rtbishop/look4sat/model/OrbitalData.kt index 9a05da11..0b179633 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/OrbitalData.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/OrbitalData.kt @@ -15,7 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.model + +import com.rtbishop.look4sat.domain.* data class OrbitalData( val name: String, diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt b/base/src/main/java/com/rtbishop/look4sat/model/SatEntry.kt similarity index 89% rename from base/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt rename to base/src/main/java/com/rtbishop/look4sat/model/SatEntry.kt index 6c0580c7..4c4fac3b 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/model/SatEntry.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/SatEntry.kt @@ -15,8 +15,6 @@ * 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.domain.predict.OrbitalData +package com.rtbishop.look4sat.model data class SatEntry(val data: OrbitalData, var comment: String? = null) diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt b/base/src/main/java/com/rtbishop/look4sat/model/SatItem.kt similarity index 95% rename from base/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt rename to base/src/main/java/com/rtbishop/look4sat/model/SatItem.kt index 2cc20db6..4c68f3fa 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/model/SatItem.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/SatItem.kt @@ -15,7 +15,7 @@ * 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 +package com.rtbishop.look4sat.model data class SatItem( val catnum: Int, diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPass.kt b/base/src/main/java/com/rtbishop/look4sat/model/SatPass.kt similarity index 93% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPass.kt rename to base/src/main/java/com/rtbishop/look4sat/model/SatPass.kt index f939fce4..d5573a91 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPass.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/SatPass.kt @@ -15,7 +15,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.model + +import com.rtbishop.look4sat.domain.Satellite data class SatPass( val aosTime: Long = 0L, diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt b/base/src/main/java/com/rtbishop/look4sat/model/SatPos.kt similarity index 91% rename from base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt rename to base/src/main/java/com/rtbishop/look4sat/model/SatPos.kt index fd40a870..36ca0c3b 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/predict/SatPos.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/SatPos.kt @@ -15,8 +15,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.rtbishop.look4sat.domain.predict +package com.rtbishop.look4sat.model +import com.rtbishop.look4sat.domain.DEG2RAD +import com.rtbishop.look4sat.domain.EARTH_RADIUS +import com.rtbishop.look4sat.domain.RAD2DEG +import com.rtbishop.look4sat.domain.SPEED_OF_LIGHT import kotlin.math.* data class SatPos( diff --git a/base/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt b/base/src/main/java/com/rtbishop/look4sat/model/SatRadio.kt similarity index 96% rename from base/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt rename to base/src/main/java/com/rtbishop/look4sat/model/SatRadio.kt index 250e42d4..734aacad 100644 --- a/base/src/main/java/com/rtbishop/look4sat/domain/model/SatRadio.kt +++ b/base/src/main/java/com/rtbishop/look4sat/model/SatRadio.kt @@ -15,7 +15,7 @@ * 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 +package com.rtbishop.look4sat.model data class SatRadio( val uuid: String, diff --git a/base/src/main/java/com/rtbishop/look4sat/model/StationPos.kt b/base/src/main/java/com/rtbishop/look4sat/model/StationPos.kt new file mode 100644 index 00000000..3151c93f --- /dev/null +++ b/base/src/main/java/com/rtbishop/look4sat/model/StationPos.kt @@ -0,0 +1,7 @@ +package com.rtbishop.look4sat.model + +data class StationPos( + val latitude: Double, val longitude: Double, val qthLocator: String, val timestamp: Long +) { + fun toGeoPos(): GeoPos = GeoPos(latitude, longitude) +} diff --git a/base/src/main/java/com/rtbishop/look4sat/utility/Extensions.kt b/base/src/main/java/com/rtbishop/look4sat/utility/Extensions.kt index 7b698008..cc9453d1 100644 --- a/base/src/main/java/com/rtbishop/look4sat/utility/Extensions.kt +++ b/base/src/main/java/com/rtbishop/look4sat/utility/Extensions.kt @@ -17,8 +17,8 @@ */ package com.rtbishop.look4sat.utility -import com.rtbishop.look4sat.domain.predict.DEG2RAD -import com.rtbishop.look4sat.domain.predict.RAD2DEG +import com.rtbishop.look4sat.domain.DEG2RAD +import com.rtbishop.look4sat.domain.RAD2DEG import java.util.concurrent.TimeUnit fun Long.toTimerString(): String { @@ -64,7 +64,7 @@ fun Double.toRadians(): Double = this * DEG2RAD //} fun String.isValidIPv4(): Boolean { - val ip4 = "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\\.(?!\$)|\$)){4}\$" + val ip4 = "^((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])(\\.(?!\$)|\$)){4}\$" return this.matches(ip4.toRegex()) } diff --git a/base/src/main/java/com/rtbishop/look4sat/utility/QthConverter.kt b/base/src/main/java/com/rtbishop/look4sat/utility/QthConverter.kt index 6c1782c9..650f50f3 100644 --- a/base/src/main/java/com/rtbishop/look4sat/utility/QthConverter.kt +++ b/base/src/main/java/com/rtbishop/look4sat/utility/QthConverter.kt @@ -17,7 +17,7 @@ */ package com.rtbishop.look4sat.utility -import com.rtbishop.look4sat.domain.predict.GeoPos +import com.rtbishop.look4sat.model.GeoPos object QthConverter { @@ -35,27 +35,27 @@ object QthConverter { return GeoPos(latitude, longitude) } - fun positionToQth(lat: Double, lon: Double): String? { - if (!isValidPosition(lat, lon)) return null - val tempLon = if (lon > 180.0) lon - 180 else lon + fun positionToQth(latitude: Double, longitude: Double): String? { + if (!isValidPosition(latitude, longitude)) return null + val tempLon = if (longitude > 180.0) longitude - 180 else longitude val upper = "ABCDEFGHIJKLMNOPQRSTUVWX" val lower = "abcdefghijklmnopqrstuvwx" - val longitude = tempLon + 180 - val latitude = lat + 90 - val lonFirst = upper[(longitude / 20).toInt()] - val latFirst = upper[(latitude / 10).toInt()] - val lonSecond = ((longitude / 2) % 10).toInt().toString() - val latSecond = (latitude % 10).toInt().toString() - val lonThird = lower[((longitude % 2) * 12).toInt()] - val latThird = lower[((latitude % 1) * 24).toInt()] + val newLongitude = tempLon + 180 + val newLatitude = latitude + 90 + val lonFirst = upper[(newLongitude / 20).toInt()] + val latFirst = upper[(newLatitude / 10).toInt()] + val lonSecond = ((newLongitude / 2) % 10).toInt().toString() + val latSecond = (newLatitude % 10).toInt().toString() + val lonThird = lower[((newLongitude % 2) * 12).toInt()] + val latThird = lower[((newLatitude % 1) * 24).toInt()] return "$lonFirst$latFirst$lonSecond$latSecond$lonThird$latThird" } - fun isValidPosition(lat: Double, lon: Double): Boolean { + private fun isValidPosition(lat: Double, lon: Double): Boolean { return (lat >= -90.0 && lat <= 90.0) && (lon >= -180.0 && lon <= 360.0) } private fun isValidLocator(locator: String): Boolean { - return locator.matches("[a-xA-X][a-xA-X][0-9][0-9][a-xA-X][a-xA-X]".toRegex()) + return locator.matches("[a-xA-X][a-xA-X]\\d\\d[a-xA-X][a-xA-X]".toRegex()) } } diff --git a/base/src/test/java/com/rtbishop/look4sat/DataParserTest.kt b/base/src/test/java/com/rtbishop/look4sat/DataParserTest.kt index c7048343..c49833e6 100644 --- a/base/src/test/java/com/rtbishop/look4sat/DataParserTest.kt +++ b/base/src/test/java/com/rtbishop/look4sat/DataParserTest.kt @@ -17,7 +17,7 @@ */ package com.rtbishop.look4sat -import com.rtbishop.look4sat.utility.DataParser +import com.rtbishop.look4sat.data.DataParser import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.runTest