kopia lustrzana https://github.com/rt-bishop/Look4Sat
Implemented Clean architecture, removed redundant dependencies
rodzic
53fcf4790a
commit
e9a6471b6d
|
@ -32,12 +32,6 @@ android {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
all {
|
||||
exclude module: "commons-logging"
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -68,7 +62,6 @@ dependencies {
|
|||
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
|
||||
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
|
||||
|
||||
implementation "com.github.davidmoten:predict4java:$predict4java_version"
|
||||
implementation "org.osmdroid:osmdroid-android:$osmdroid_version"
|
||||
implementation "com.jakewharton.timber:timber:$timber_version"
|
||||
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "53fa623fc55b279c50d33e6263866a89",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "entries",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`tle` TEXT NOT NULL, `catNum` INTEGER NOT NULL, `name` TEXT NOT NULL, `isSelected` INTEGER NOT NULL, PRIMARY KEY(`catNum`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "tle",
|
||||
"columnName": "tle",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "catNum",
|
||||
"columnName": "catNum",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isSelected",
|
||||
"columnName": "isSelected",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"catNum"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "transmitters",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uuid` TEXT NOT NULL, `info` TEXT NOT NULL, `isAlive` INTEGER NOT NULL, `downlink` INTEGER, `uplink` INTEGER, `mode` TEXT, `isInverted` INTEGER NOT NULL, `catNum` INTEGER NOT NULL, PRIMARY KEY(`uuid`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "uuid",
|
||||
"columnName": "uuid",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "info",
|
||||
"columnName": "info",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isAlive",
|
||||
"columnName": "isAlive",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "downlink",
|
||||
"columnName": "downlink",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "uplink",
|
||||
"columnName": "uplink",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "mode",
|
||||
"columnName": "mode",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "isInverted",
|
||||
"columnName": "isInverted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "catNum",
|
||||
"columnName": "catNum",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"uuid"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '53fa623fc55b279c50d33e6263866a89')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.api
|
||||
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Streaming
|
||||
import retrofit2.http.Url
|
||||
|
||||
interface SatelliteService {
|
||||
|
||||
@Streaming
|
||||
@GET
|
||||
suspend fun fetchFileByUrl(@Url url: String): Response<ResponseBody>
|
||||
|
||||
@GET("transmitters/")
|
||||
suspend fun fetchTransmitters(): List<SatTrans>
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.database
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.github.amsacode.predict4java.SatelliteFactory
|
||||
import com.github.amsacode.predict4java.TLE
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
|
||||
object RoomConverters {
|
||||
|
||||
private lateinit var tleAdapter: JsonAdapter<TLE>
|
||||
|
||||
fun initialize(moshi: Moshi) {
|
||||
tleAdapter = moshi.adapter(TLE::class.java)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TypeConverter
|
||||
fun tleToString(tle: TLE): String {
|
||||
return tleAdapter.toJson(tle)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TypeConverter
|
||||
fun tleFromString(string: String): TLE? {
|
||||
return tleAdapter.fromJson(string)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@TypeConverter
|
||||
fun satFromString(string: String): Satellite? {
|
||||
val tle = tleAdapter.fromJson(string)
|
||||
return SatelliteFactory.createSatellite(tle)
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.database
|
||||
|
||||
import androidx.room.*
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.rtbishop.look4sat.data.model.SatEntry
|
||||
import com.rtbishop.look4sat.data.model.SatItem
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface SatelliteDao {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT catNum, name, isSelected FROM entries ORDER BY name ASC")
|
||||
fun getSatItems(): Flow<List<SatItem>>
|
||||
|
||||
@Query("SELECT * FROM transmitters WHERE catNum = :catNum")
|
||||
fun getSatTransmitters(catNum: Int): Flow<List<SatTrans>>
|
||||
|
||||
@Query("SELECT tle FROM entries WHERE isSelected = 1")
|
||||
suspend fun getSelectedSatellites(): List<Satellite>
|
||||
|
||||
@Query("SELECT catNum FROM entries WHERE isSelected = 1")
|
||||
suspend fun getSelectedCatNums(): List<Int>
|
||||
|
||||
@Transaction
|
||||
suspend fun updateEntries(entries: List<SatEntry>) {
|
||||
val selectedCatNums = getSelectedCatNums()
|
||||
insertEntries(entries)
|
||||
restoreEntriesSelection(selectedCatNums, true)
|
||||
}
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertEntries(entries: List<SatEntry>)
|
||||
|
||||
@Transaction
|
||||
suspend fun restoreEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
clearEntriesSelection()
|
||||
catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) }
|
||||
}
|
||||
|
||||
@Query("UPDATE entries SET isSelected = 0")
|
||||
suspend fun clearEntriesSelection()
|
||||
|
||||
@Query("UPDATE entries SET isSelected = :isSelected WHERE catNum = :catNum")
|
||||
suspend fun updateEntrySelection(catNum: Int, isSelected: Boolean)
|
||||
|
||||
@Transaction
|
||||
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
catNums.forEach { catNum -> updateEntrySelection(catNum, isSelected) }
|
||||
}
|
||||
|
||||
@Transaction
|
||||
suspend fun updateTransmitters(transmitters: List<SatTrans>) {
|
||||
deleteTransmitters()
|
||||
insertTransmitters(transmitters)
|
||||
}
|
||||
|
||||
@Query("DELETE from transmitters")
|
||||
suspend fun deleteTransmitters()
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertTransmitters(transmitters: List<SatTrans>)
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.database
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.rtbishop.look4sat.data.model.SatEntry
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
|
||||
@Database(entities = [SatEntry::class, SatTrans::class], version = 3)
|
||||
@TypeConverters(RoomConverters::class)
|
||||
abstract class SatelliteDb : RoomDatabase() {
|
||||
|
||||
abstract fun satelliteDao(): SatelliteDao
|
||||
}
|
||||
|
||||
val MIGRATION_1_2 = object : Migration(1, 2) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("DROP TABLE sources")
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_2_3 = object : Migration(2, 3) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL("CREATE TABLE trans_backup (uuid TEXT NOT NULL, info TEXT NOT NULL, isAlive INTEGER NOT NULL, downlink INTEGER, uplink INTEGER, mode TEXT, isInverted INTEGER NOT NULL, catNum INTEGER NOT NULL, PRIMARY KEY(uuid))")
|
||||
database.execSQL("INSERT INTO trans_backup (uuid, info, isAlive, downlink, uplink, mode, isInverted, catNum) SELECT uuid, description, isAlive, downlinkLow, uplinkLow, mode, isInverted, catNum FROM transmitters")
|
||||
database.execSQL("DROP TABLE transmitters")
|
||||
database.execSQL("ALTER TABLE trans_backup RENAME TO transmitters")
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
sealed class Result<out T : Any> {
|
||||
data class Success<out T : Any>(val data: T) : Result<T>()
|
||||
data class Error(val exception: Throwable) : Result<Nothing>()
|
||||
object InProgress : Result<Nothing>()
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.github.amsacode.predict4java.TLE
|
||||
|
||||
@Entity(tableName = "entries")
|
||||
data class SatEntry(
|
||||
val tle: TLE,
|
||||
var isSelected: Boolean = false,
|
||||
@PrimaryKey val catNum: Int = tle.catnum,
|
||||
val name: String = tle.name
|
||||
)
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
import androidx.room.Relation
|
||||
|
||||
data class SatItem(
|
||||
val catNum: Int,
|
||||
val name: String,
|
||||
var isSelected: Boolean,
|
||||
@Relation(
|
||||
parentColumn = "catNum",
|
||||
entity = SatTrans::class,
|
||||
entityColumn = "catNum",
|
||||
projection = ["mode"]
|
||||
)
|
||||
val modes: List<String>
|
||||
)
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
import com.rtbishop.look4sat.utility.PassPredictor
|
||||
import java.util.*
|
||||
|
||||
data class SatPass(
|
||||
val catNum: Int,
|
||||
val name: String,
|
||||
val isDeepSpace: Boolean,
|
||||
private val aosTime: Long,
|
||||
val aosAzimuth: Double,
|
||||
private val losTime: Long,
|
||||
val losAzimuth: Double,
|
||||
private val tcaTime: Long,
|
||||
val tcaAzimuth: Double,
|
||||
val altitude: Double,
|
||||
val maxElevation: Double,
|
||||
val predictor: PassPredictor,
|
||||
var progress: Int = 0
|
||||
) {
|
||||
val aosDate: Date
|
||||
get() = Date(aosTime)
|
||||
|
||||
val losDate: Date
|
||||
get() = Date(losTime)
|
||||
|
||||
val tcaDate: Date
|
||||
get() = Date(tcaTime)
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.squareup.moshi.Json
|
||||
|
||||
@Entity(tableName = "transmitters")
|
||||
data class SatTrans(
|
||||
@PrimaryKey @field:Json(name = "uuid") val uuid: String,
|
||||
@field:Json(name = "description") val info: String,
|
||||
@field:Json(name = "alive") val isAlive: Boolean,
|
||||
@field:Json(name = "downlink_low") var downlink: Long?,
|
||||
@field:Json(name = "uplink_low") var uplink: Long?,
|
||||
@field:Json(name = "mode") val mode: String?,
|
||||
@field:Json(name = "invert") val isInverted: Boolean,
|
||||
@field:Json(name = "norad_cat_id") val catNum: Int
|
||||
)
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
import com.github.amsacode.predict4java.Position
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import org.osmdroid.views.overlay.Overlay
|
||||
|
||||
data class SelectedSat(
|
||||
val pass: Satellite,
|
||||
val catNum: Int,
|
||||
val name: String,
|
||||
val range: Double,
|
||||
val altitude: Double,
|
||||
val velocity: Double,
|
||||
val qthLoc: String,
|
||||
val osmPos: Position,
|
||||
val footprint: Overlay,
|
||||
val groundTrack: Overlay
|
||||
)
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.model
|
||||
|
||||
class TleSource(var url: String = String())
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.data.repository
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.github.amsacode.predict4java.TLE
|
||||
import com.rtbishop.look4sat.data.api.SatelliteService
|
||||
import com.rtbishop.look4sat.data.database.SatelliteDao
|
||||
import com.rtbishop.look4sat.data.model.SatEntry
|
||||
import com.rtbishop.look4sat.data.model.SatItem
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import com.rtbishop.look4sat.data.model.TleSource
|
||||
import com.rtbishop.look4sat.di.IoDispatcher
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.InputStream
|
||||
import java.util.zip.ZipInputStream
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class SatelliteRepo @Inject constructor(
|
||||
private val resolver: ContentResolver,
|
||||
private val satelliteDao: SatelliteDao,
|
||||
private val satelliteService: SatelliteService,
|
||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||
) {
|
||||
|
||||
fun getSatItems(): Flow<List<SatItem>> {
|
||||
return satelliteDao.getSatItems()
|
||||
}
|
||||
|
||||
fun getSatTransmitters(catNum: Int): Flow<List<SatTrans>> {
|
||||
return satelliteDao.getSatTransmitters(catNum)
|
||||
}
|
||||
|
||||
suspend fun getSelectedSatellites(): List<Satellite> {
|
||||
return satelliteDao.getSelectedSatellites()
|
||||
}
|
||||
|
||||
suspend fun importSatDataFromFile(uri: Uri) {
|
||||
runCatching {
|
||||
resolver.openInputStream(uri)?.use { stream ->
|
||||
val entries = importEntriesFromStreams(listOf(stream))
|
||||
satelliteDao.updateEntries(entries)
|
||||
}
|
||||
}.onFailure { throw it }
|
||||
}
|
||||
|
||||
suspend fun importSatDataFromWeb(sources: List<TleSource>) {
|
||||
coroutineScope {
|
||||
launch { importEntriesFromSources(sources) }
|
||||
launch { importTransmitters() }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
satelliteDao.updateEntriesSelection(catNums, isSelected)
|
||||
}
|
||||
|
||||
private suspend fun importEntriesFromSources(sources: List<TleSource>) {
|
||||
val streams = getStreamsForSources(sources)
|
||||
val entries = importEntriesFromStreams(streams)
|
||||
satelliteDao.updateEntries(entries)
|
||||
}
|
||||
|
||||
private suspend fun importTransmitters() {
|
||||
val transmitters = satelliteService.fetchTransmitters().filter { it.isAlive }
|
||||
satelliteDao.updateTransmitters(transmitters)
|
||||
}
|
||||
|
||||
private suspend fun getStreamsForSources(sources: List<TleSource>): List<InputStream> {
|
||||
val streams = mutableListOf<InputStream>()
|
||||
sources.forEach { tleSource ->
|
||||
satelliteService.fetchFileByUrl(tleSource.url).body()?.byteStream()?.let { stream ->
|
||||
if (tleSource.url.contains(".zip", true)) {
|
||||
streams.add(getZipStream(stream))
|
||||
} else {
|
||||
streams.add(stream)
|
||||
}
|
||||
}
|
||||
}
|
||||
return streams
|
||||
}
|
||||
|
||||
private suspend fun getZipStream(inputStream: InputStream): InputStream {
|
||||
var stream: InputStream
|
||||
withContext(ioDispatcher) {
|
||||
ZipInputStream(inputStream).apply {
|
||||
nextEntry
|
||||
stream = this
|
||||
}
|
||||
}
|
||||
return stream
|
||||
}
|
||||
|
||||
private suspend fun importEntriesFromStreams(streams: List<InputStream>): List<SatEntry> {
|
||||
val importedEntries = mutableListOf<SatEntry>()
|
||||
withContext(ioDispatcher) {
|
||||
streams.forEach { stream ->
|
||||
val entries = TLE.importSat(stream).map { tle -> SatEntry(tle) }
|
||||
importedEntries.addAll(entries)
|
||||
}
|
||||
}
|
||||
return importedEntries
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.rtbishop.look4sat.di
|
||||
|
||||
import com.rtbishop.look4sat.domain.SatelliteRepo
|
||||
import com.rtbishop.look4sat.interactors.*
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object InteractorsModule {
|
||||
|
||||
@Provides
|
||||
fun provideGetSatItemsUseCase(satelliteRepo: SatelliteRepo): GetSatItems {
|
||||
return GetSatItems(satelliteRepo)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideGetSelectedSatellitesUseCase(satelliteRepo: SatelliteRepo): GetSelectedSatellites {
|
||||
return GetSelectedSatellites(satelliteRepo)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideGetTransmittersForSatUseCase(satelliteRepo: SatelliteRepo): GetTransmittersForSat {
|
||||
return GetTransmittersForSat(satelliteRepo)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideImportDataFromFileUseCase(satelliteRepo: SatelliteRepo): ImportDataFromFile {
|
||||
return ImportDataFromFile(satelliteRepo)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideImportDataFromWebUseCase(satelliteRepo: SatelliteRepo): ImportDataFromWeb {
|
||||
return ImportDataFromWeb(satelliteRepo)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideUpdateEntriesSelectionUseCase(satelliteRepo: SatelliteRepo): UpdateEntriesSelection {
|
||||
return UpdateEntriesSelection(satelliteRepo)
|
||||
}
|
||||
}
|
|
@ -19,29 +19,55 @@ package com.rtbishop.look4sat.di
|
|||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import com.rtbishop.look4sat.data.database.*
|
||||
import com.rtbishop.look4sat.data.DefaultSatelliteRepo
|
||||
import com.rtbishop.look4sat.data.LocalDataSource
|
||||
import com.rtbishop.look4sat.data.RemoteDataSource
|
||||
import com.rtbishop.look4sat.domain.SatelliteRepo
|
||||
import com.rtbishop.look4sat.framework.db.RoomConverters
|
||||
import com.rtbishop.look4sat.framework.db.RoomDataSource
|
||||
import com.rtbishop.look4sat.framework.db.SatelliteDao
|
||||
import com.rtbishop.look4sat.framework.db.SatelliteDb
|
||||
import com.squareup.moshi.Moshi
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object RepositoryModule {
|
||||
|
||||
object LocalSourceModule {
|
||||
|
||||
@Provides
|
||||
fun provideLocalDataSource(satelliteDao: SatelliteDao): LocalDataSource {
|
||||
return RoomDataSource(satelliteDao)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDefaultRepository(
|
||||
localSource: LocalDataSource,
|
||||
remoteSource: RemoteDataSource,
|
||||
@IoDispatcher ioDispatcher: CoroutineDispatcher
|
||||
): SatelliteRepo {
|
||||
return DefaultSatelliteRepo(localSource, remoteSource, ioDispatcher)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideMoshi(): Moshi {
|
||||
return Moshi.Builder().build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideSatDataDao(db: SatelliteDb): SatelliteDao {
|
||||
return db.satelliteDao()
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
fun provideSatelliteDb(@ApplicationContext context: Context, moshi: Moshi): SatelliteDb {
|
||||
RoomConverters.initialize(moshi)
|
||||
return Room.databaseBuilder(context, SatelliteDb::class.java, "satDb")
|
||||
.addMigrations(MIGRATION_1_2)
|
||||
.addMigrations(MIGRATION_2_3)
|
||||
.build()
|
||||
return Room.databaseBuilder(context, SatelliteDb::class.java, "SatelliteDb").build()
|
||||
}
|
||||
}
|
|
@ -17,8 +17,9 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.di
|
||||
|
||||
import com.rtbishop.look4sat.data.api.SatelliteService
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.rtbishop.look4sat.data.RemoteDataSource
|
||||
import com.rtbishop.look4sat.framework.api.NetworkDataSource
|
||||
import com.rtbishop.look4sat.framework.api.SatelliteService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
|
@ -28,13 +29,13 @@ import retrofit2.converter.moshi.MoshiConverterFactory
|
|||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object NetworkModule {
|
||||
|
||||
object RemoteSourceModule {
|
||||
|
||||
@Provides
|
||||
fun provideMoshi(): Moshi {
|
||||
return Moshi.Builder().build()
|
||||
fun provideRemoteDataSource(satelliteService: SatelliteService): RemoteDataSource {
|
||||
return NetworkDataSource(satelliteService)
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
fun provideSatDataService(): SatelliteService {
|
||||
return Retrofit.Builder()
|
|
@ -4,14 +4,14 @@ import com.rtbishop.look4sat.data.RemoteDataSource
|
|||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import java.io.InputStream
|
||||
|
||||
class RetrofitDataSource(private val satelliteService: SatelliteService) : RemoteDataSource {
|
||||
class NetworkDataSource(private val api: SatelliteService) : RemoteDataSource {
|
||||
|
||||
override suspend fun fetchFileStream(url: String): InputStream? {
|
||||
return satelliteService.fetchFileByUrl(url).body()?.byteStream()
|
||||
return api.fetchFileByUrl(url).body()?.byteStream()
|
||||
}
|
||||
|
||||
override suspend fun fetchTransmitters(): List<SatTrans> {
|
||||
return satelliteService.fetchTransmitters().map { trans ->
|
||||
return api.fetchTransmitters().map { trans ->
|
||||
SatTrans(
|
||||
trans.uuid, trans.info, trans.isAlive, trans.downlink,
|
||||
trans.uplink, trans.mode, trans.isInverted, trans.catNum
|
|
@ -18,8 +18,8 @@
|
|||
package com.rtbishop.look4sat.framework.db
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.rtbishop.look4sat.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.predict4kotlin.TLE
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.TLE
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.rtbishop.look4sat.data.LocalDataSource
|
|||
import com.rtbishop.look4sat.domain.model.SatEntry
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import com.rtbishop.look4sat.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.utility.DataMapper
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
@ -38,4 +38,4 @@ class RoomDataSource(private val satelliteDao: SatelliteDao) : LocalDataSource {
|
|||
val satTransList = DataMapper.domainTransListToSatTransList(satelliteTrans)
|
||||
satelliteDao.updateTransmitters(satTransList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import androidx.room.*
|
|||
import com.rtbishop.look4sat.framework.model.SatEntry
|
||||
import com.rtbishop.look4sat.framework.model.SatItem
|
||||
import com.rtbishop.look4sat.framework.model.SatTrans
|
||||
import com.rtbishop.look4sat.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
|
|
|
@ -19,7 +19,7 @@ package com.rtbishop.look4sat.framework.model
|
|||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.rtbishop.look4sat.predict4kotlin.TLE
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.TLE
|
||||
|
||||
@Entity(tableName = "entries")
|
||||
data class SatEntry(
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.framework.model
|
||||
|
||||
import com.rtbishop.look4sat.utility.PassPredictor
|
||||
import java.util.*
|
||||
|
||||
data class SatPass(
|
||||
val catNum: Int,
|
||||
val name: String,
|
||||
val isDeepSpace: Boolean,
|
||||
private val aosTime: Long,
|
||||
val aosAzimuth: Double,
|
||||
private val losTime: Long,
|
||||
val losAzimuth: Double,
|
||||
private val tcaTime: Long,
|
||||
val tcaAzimuth: Double,
|
||||
val altitude: Double,
|
||||
val maxElevation: Double,
|
||||
val predictor: PassPredictor,
|
||||
var progress: Int = 0
|
||||
) {
|
||||
val aosDate: Date
|
||||
get() = Date(aosTime)
|
||||
|
||||
val losDate: Date
|
||||
get() = Date(losTime)
|
||||
|
||||
val tcaDate: Date
|
||||
get() = Date(tcaTime)
|
||||
}
|
|
@ -17,8 +17,8 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.framework.model
|
||||
|
||||
import com.github.amsacode.predict4java.Position
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Position
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import org.osmdroid.views.overlay.Overlay
|
||||
|
||||
data class SelectedSat(
|
||||
|
|
|
@ -22,8 +22,8 @@ import android.view.ViewGroup
|
|||
import androidx.recyclerview.widget.AsyncListDiffer
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.rtbishop.look4sat.data.model.SatItem
|
||||
import com.rtbishop.look4sat.databinding.SatItemBinding
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
|
||||
class EntriesAdapter : RecyclerView.Adapter<EntriesAdapter.SatItemHolder>() {
|
||||
|
||||
|
|
|
@ -27,10 +27,10 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.Result
|
||||
import com.rtbishop.look4sat.data.model.SatItem
|
||||
import com.rtbishop.look4sat.data.model.TleSource
|
||||
import com.rtbishop.look4sat.framework.model.Result
|
||||
import com.rtbishop.look4sat.databinding.FragmentEntriesBinding
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.framework.model.TleSource
|
||||
import com.rtbishop.look4sat.utility.RecyclerDivider
|
||||
import com.rtbishop.look4sat.utility.getNavResult
|
||||
import com.rtbishop.look4sat.utility.navigateSafe
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.presentation.entriesScreen
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.widget.SearchView
|
||||
|
@ -24,10 +25,13 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.lifecycle.*
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.Result
|
||||
import com.rtbishop.look4sat.data.model.SatItem
|
||||
import com.rtbishop.look4sat.data.model.TleSource
|
||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.framework.model.Result
|
||||
import com.rtbishop.look4sat.framework.model.TleSource
|
||||
import com.rtbishop.look4sat.interactors.GetSatItems
|
||||
import com.rtbishop.look4sat.interactors.ImportDataFromFile
|
||||
import com.rtbishop.look4sat.interactors.ImportDataFromWeb
|
||||
import com.rtbishop.look4sat.interactors.UpdateEntriesSelection
|
||||
import com.rtbishop.look4sat.utility.PrefsManager
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
|
@ -40,13 +44,17 @@ import kotlin.system.measureTimeMillis
|
|||
@HiltViewModel
|
||||
class EntriesViewModel @Inject constructor(
|
||||
private val prefsManager: PrefsManager,
|
||||
private val satelliteRepo: SatelliteRepo
|
||||
private val resolver: ContentResolver,
|
||||
private val getSatItems: GetSatItems,
|
||||
private val importDataFromFile: ImportDataFromFile,
|
||||
private val importDataFromWeb: ImportDataFromWeb,
|
||||
private val updateEntriesSelection: UpdateEntriesSelection,
|
||||
) : ViewModel(), EntriesAdapter.EntriesClickListener, SearchView.OnQueryTextListener {
|
||||
|
||||
private val transModes = MutableLiveData(prefsManager.loadModesSelection())
|
||||
private val currentQuery = MutableLiveData(String())
|
||||
private val itemsWithModes = transModes.switchMap { modes ->
|
||||
liveData { satelliteRepo.getSatItems().collect { emit(filterByModes(it, modes)) } }
|
||||
liveData { getSatItems().collect { emit(filterByModes(it, modes)) } }
|
||||
}
|
||||
private val itemsWithQuery = currentQuery.switchMap { query ->
|
||||
itemsWithModes.map { items -> Result.Success(filterByQuery(items, query)) }
|
||||
|
@ -60,11 +68,11 @@ class EntriesViewModel @Inject constructor(
|
|||
fun importSatDataFromFile(uri: Uri) {
|
||||
viewModelScope.launch {
|
||||
_satData.value = Result.InProgress
|
||||
try {
|
||||
satelliteRepo.importSatDataFromFile(uri)
|
||||
} catch (exception: Exception) {
|
||||
_satData.value = Result.Error(exception)
|
||||
}
|
||||
runCatching {
|
||||
resolver.openInputStream(uri)?.use { stream ->
|
||||
importDataFromFile(stream)
|
||||
}
|
||||
}.onFailure { _satData.value = Result.Error(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,9 +84,10 @@ class EntriesViewModel @Inject constructor(
|
|||
val updateMillis = measureTimeMillis {
|
||||
try {
|
||||
prefsManager.saveTleSources(satSources)
|
||||
satelliteRepo.importSatDataFromWeb(satSources)
|
||||
importDataFromWeb(satSources.map { it.url })
|
||||
} catch (exception: Exception) {
|
||||
_satData.value = Result.Error(exception)
|
||||
Timber.d(exception)
|
||||
}
|
||||
}
|
||||
Timber.d("Update from WEB took $updateMillis ms")
|
||||
|
@ -133,7 +142,7 @@ class EntriesViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
|
||||
viewModelScope.launch { satelliteRepo.updateEntriesSelection(catNums, isSelected) }
|
||||
viewModelScope.launch { updateEntriesSelection(catNums, isSelected) }
|
||||
}
|
||||
|
||||
private fun filterByModes(items: List<SatItem>, modes: List<String>): List<SatItem> {
|
||||
|
|
|
@ -25,11 +25,11 @@ import android.view.View
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.github.amsacode.predict4java.Position
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.SelectedSat
|
||||
import com.rtbishop.look4sat.databinding.FragmentMapBinding
|
||||
import com.rtbishop.look4sat.framework.model.SelectedSat
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Position
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.utility.PrefsManager
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import org.osmdroid.config.Configuration
|
||||
|
|
|
@ -20,11 +20,11 @@ package com.rtbishop.look4sat.presentation.mapScreen
|
|||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import androidx.lifecycle.*
|
||||
import com.github.amsacode.predict4java.Position
|
||||
import com.github.amsacode.predict4java.SatPos
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.rtbishop.look4sat.data.model.SelectedSat
|
||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||
import com.rtbishop.look4sat.framework.model.SelectedSat
|
||||
import com.rtbishop.look4sat.interactors.GetSelectedSatellites
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Position
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPos
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.utility.*
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
|
@ -39,9 +39,9 @@ import javax.inject.Inject
|
|||
|
||||
@HiltViewModel
|
||||
class MapViewModel @Inject constructor(
|
||||
prefsManager: PrefsManager,
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val qthConverter: QthConverter
|
||||
private val getSelectedSatellites: GetSelectedSatellites,
|
||||
private val qthConverter: QthConverter,
|
||||
prefsManager: PrefsManager
|
||||
) : ViewModel() {
|
||||
|
||||
private val dateNow = Date()
|
||||
|
@ -71,12 +71,12 @@ class MapViewModel @Inject constructor(
|
|||
fun getSatMarkers(): LiveData<Map<Satellite, Position>> = _satMarkers
|
||||
|
||||
val stationPosition = liveData {
|
||||
emit(Position(gsp.latitude.toOsmLat(), gsp.longitude.toOsmLon()))
|
||||
emit(Position(gsp.lat.toOsmLat(), gsp.lon.toOsmLon()))
|
||||
}
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
val satellites = satelliteRepo.getSelectedSatellites()
|
||||
val satellites = getSelectedSatellites()
|
||||
if (satellites.isNotEmpty()) {
|
||||
filteredSats = satellites
|
||||
selectedSat = satellites.first()
|
||||
|
@ -171,18 +171,18 @@ class MapViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun getSatFootprint(satPos: SatPos): Overlay {
|
||||
val rangePoints = mutableListOf<GeoPoint>()
|
||||
satPos.rangeCircle.forEach {
|
||||
val points = mutableListOf<GeoPoint>()
|
||||
satPos.getRangeCircle().forEach {
|
||||
val osmPos = Position(it.lat.toOsmLat(), it.lon.toOsmLon())
|
||||
rangePoints.add(GeoPoint(osmPos.lat, osmPos.lon))
|
||||
points.add(GeoPoint(osmPos.lat, osmPos.lon))
|
||||
}
|
||||
return Polygon().apply {
|
||||
fillPaint.set(footprintPaint)
|
||||
outlinePaint.set(footprintPaint)
|
||||
try {
|
||||
points = rangePoints
|
||||
this.points = points
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Timber.d("RangeCircle: ${satPos.rangeCircle}, RangePoints: $rangePoints")
|
||||
Timber.d("RangeCircle: ${satPos.getRangeCircle()}, RangePoints: $points")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ import androidx.recyclerview.widget.AsyncListDiffer
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.databinding.ItemPassGeoBinding
|
||||
import com.rtbishop.look4sat.databinding.ItemPassLeoBinding
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.Result
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.framework.model.Result
|
||||
import com.rtbishop.look4sat.databinding.FragmentPassesBinding
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import com.rtbishop.look4sat.utility.RecyclerDivider
|
||||
import com.rtbishop.look4sat.utility.formatForTimer
|
||||
import com.rtbishop.look4sat.utility.navigateSafe
|
||||
|
|
|
@ -21,10 +21,10 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.rtbishop.look4sat.data.model.Result
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.framework.model.Result
|
||||
import com.rtbishop.look4sat.utility.PassesRepo
|
||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||
import com.rtbishop.look4sat.interactors.GetSelectedSatellites
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import com.rtbishop.look4sat.utility.PrefsManager
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
|
@ -33,9 +33,9 @@ import javax.inject.Inject
|
|||
|
||||
@HiltViewModel
|
||||
class PassesViewModel @Inject constructor(
|
||||
private val prefsManager: PrefsManager,
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val passesRepo: PassesRepo
|
||||
private val getSelectedSatellites: GetSelectedSatellites,
|
||||
private val passesRepo: PassesRepo,
|
||||
private val prefsManager: PrefsManager
|
||||
) : ViewModel() {
|
||||
|
||||
private val _passes = MutableLiveData<Result<List<SatPass>>>(Result.InProgress)
|
||||
|
@ -45,7 +45,7 @@ class PassesViewModel @Inject constructor(
|
|||
init {
|
||||
viewModelScope.launch {
|
||||
_passes.postValue(Result.InProgress)
|
||||
passesRepo.triggerCalculation(satelliteRepo.getSelectedSatellites())
|
||||
passesRepo.triggerCalculation(getSelectedSatellites())
|
||||
}
|
||||
viewModelScope.launch {
|
||||
passesRepo.passes.collect { passes ->
|
||||
|
@ -59,7 +59,7 @@ class PassesViewModel @Inject constructor(
|
|||
viewModelScope.launch {
|
||||
_passes.postValue(Result.InProgress)
|
||||
passesProcessing?.cancelAndJoin()
|
||||
passesRepo.forceCalculation(satelliteRepo.getSelectedSatellites())
|
||||
passesRepo.forceCalculation(getSelectedSatellites())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ import androidx.navigation.fragment.findNavController
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.databinding.FragmentPolarBinding
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import com.rtbishop.look4sat.utility.RecyclerDivider
|
||||
import com.rtbishop.look4sat.utility.formatForTimer
|
||||
import com.rtbishop.look4sat.utility.navigateSafe
|
||||
|
|
|
@ -25,7 +25,7 @@ import android.graphics.Path
|
|||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import java.util.*
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
package com.rtbishop.look4sat.presentation.polarScreen
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import com.rtbishop.look4sat.utility.PassesRepo
|
||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||
import com.rtbishop.look4sat.di.IoDispatcher
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import com.rtbishop.look4sat.interactors.GetTransmittersForSat
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import com.rtbishop.look4sat.utility.OrientationProvider
|
||||
import com.rtbishop.look4sat.utility.PrefsManager
|
||||
import com.rtbishop.look4sat.utility.round
|
||||
|
@ -39,7 +39,7 @@ class PolarViewModel @Inject constructor(
|
|||
private val orientationProvider: OrientationProvider,
|
||||
private val prefsManager: PrefsManager,
|
||||
private val passesRepo: PassesRepo,
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val getTransmittersForSat: GetTransmittersForSat,
|
||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||
) : ViewModel(), OrientationProvider.OrientationListener {
|
||||
|
||||
|
@ -98,7 +98,7 @@ class PolarViewModel @Inject constructor(
|
|||
|
||||
private fun processTransmitters(satPass: SatPass) {
|
||||
viewModelScope.launch {
|
||||
satelliteRepo.getSatTransmitters(satPass.catNum).collect { transList ->
|
||||
getTransmittersForSat(satPass.catNum).collect { transList ->
|
||||
while (isActive) {
|
||||
val timeNow = Date()
|
||||
val copiedList = transList.map { it.copy() }
|
||||
|
|
|
@ -23,8 +23,8 @@ import androidx.recyclerview.widget.AsyncListDiffer
|
|||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.rtbishop.look4sat.R
|
||||
import com.rtbishop.look4sat.data.model.SatTrans
|
||||
import com.rtbishop.look4sat.databinding.ItemTransBinding
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import java.util.*
|
||||
|
||||
class TransAdapter : RecyclerView.Adapter<TransAdapter.TransHolder>() {
|
||||
|
|
|
@ -103,7 +103,7 @@ class PrefsFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private fun setPositionFromQth(qthString: String): Boolean {
|
||||
qthConverter.qthToLocation(qthString)?.let { gsp ->
|
||||
prefsManager.setStationPosition(gsp.latitude, gsp.longitude, gsp.heightAMSL)
|
||||
prefsManager.setStationPosition(gsp.lat, gsp.lon, gsp.alt)
|
||||
showSnack(getString(R.string.pref_pos_success))
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ import android.view.LayoutInflater
|
|||
import android.view.ViewGroup
|
||||
import androidx.core.widget.doOnTextChanged
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.rtbishop.look4sat.data.model.TleSource
|
||||
import com.rtbishop.look4sat.databinding.ItemTleSourceBinding
|
||||
import com.rtbishop.look4sat.framework.model.TleSource
|
||||
|
||||
class SourcesAdapter(private val sources: MutableList<TleSource> = mutableListOf()) :
|
||||
RecyclerView.Adapter<SourcesAdapter.TleSourceHolder>() {
|
||||
|
|
|
@ -26,8 +26,6 @@ import androidx.navigation.NavController
|
|||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.Navigator
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.github.amsacode.predict4java.GroundStationPosition
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
@ -64,10 +62,6 @@ fun Double.getOrbitalVelocity(): Double {
|
|||
return sqrt(earthG * earthM / radius) / 1000
|
||||
}
|
||||
|
||||
fun Satellite.getPredictor(stationPosition: GroundStationPosition): PassPredictor {
|
||||
return PassPredictor(this, stationPosition)
|
||||
}
|
||||
|
||||
fun NavController.navigateSafe(
|
||||
@IdRes resId: Int,
|
||||
args: Bundle? = null,
|
||||
|
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
* Look4Sat. Amateur radio satellite tracker and pass predictor.
|
||||
* Copyright (C) 2019-2021 Arty Bishop (bishop.arty@gmail.com)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.utility
|
||||
|
||||
import com.github.amsacode.predict4java.GroundStationPosition
|
||||
import com.github.amsacode.predict4java.SatPos
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import java.util.*
|
||||
|
||||
class PassPredictor(private val satellite: Satellite, private val qth: GroundStationPosition) {
|
||||
|
||||
private val oneQuarterOrbitMin = (24.0 * 60.0 / satellite.tle.meanmo / 4.0).toInt()
|
||||
private val speedOfLight = 2.99792458E8
|
||||
|
||||
fun getDownlinkFreq(freq: Long, date: Date): Long {
|
||||
val rangeRate = getSatPos(date).rangeRate
|
||||
return (freq.toDouble() * (speedOfLight - rangeRate * 1000.0) / speedOfLight).toLong()
|
||||
}
|
||||
|
||||
fun getUplinkFreq(freq: Long, date: Date): Long {
|
||||
val rangeRate = getSatPos(date).rangeRate
|
||||
return (freq.toDouble() * (speedOfLight + rangeRate * 1000.0) / speedOfLight).toLong()
|
||||
}
|
||||
|
||||
fun getSatPos(date: Date): SatPos {
|
||||
return satellite.getPosition(qth, date)
|
||||
}
|
||||
|
||||
fun getPositions(refDate: Date, stepSec: Int, minBefore: Int, orbits: Double): List<SatPos> {
|
||||
val positions = mutableListOf<SatPos>()
|
||||
val orbitalPeriod = 24 * 60 / satellite.tle.meanmo
|
||||
val endDate = Date(refDate.time + (orbitalPeriod * orbits * 60L * 1000L).toLong())
|
||||
val startDate = Date(refDate.time - minBefore * 60L * 1000L)
|
||||
var currentDate = startDate
|
||||
while (currentDate.before(endDate)) {
|
||||
positions.add(getSatPos(currentDate))
|
||||
currentDate = Date(currentDate.time + stepSec * 1000)
|
||||
}
|
||||
return positions
|
||||
}
|
||||
|
||||
fun getPasses(refDate: Date, hoursAhead: Int, windBack: Boolean): List<SatPass> {
|
||||
val passes = mutableListOf<SatPass>()
|
||||
val endDate = Date(refDate.time + hoursAhead * 60L * 60L * 1000L)
|
||||
var startDate = refDate
|
||||
var shouldWindBack = windBack
|
||||
var lastAosDate: Date
|
||||
var count = 0
|
||||
if (satellite.willBeSeen(qth)) {
|
||||
if (satellite.tle.isDeepspace) {
|
||||
passes.add(nextDeepSpacePass(refDate))
|
||||
} else {
|
||||
do {
|
||||
if (count > 0) shouldWindBack = false
|
||||
val pass = nextNearEarthPass(startDate, shouldWindBack)
|
||||
lastAosDate = pass.aosDate
|
||||
passes.add(pass)
|
||||
startDate =
|
||||
Date(pass.losDate.time + (oneQuarterOrbitMin * 3) * 60L * 1000L)
|
||||
count++
|
||||
} while (lastAosDate < endDate)
|
||||
}
|
||||
}
|
||||
return passes
|
||||
}
|
||||
|
||||
private fun nextDeepSpacePass(refDate: Date): SatPass {
|
||||
val satPos = getSatPos(refDate)
|
||||
val id = satellite.tle.catnum
|
||||
val name = satellite.tle.name
|
||||
val isDeep = satellite.tle.isDeepspace
|
||||
val aos = Date(refDate.time - 24 * 60L * 60L * 1000L).time
|
||||
val los = Date(refDate.time + 24 * 60L * 60L * 1000L).time
|
||||
val tca = Date((aos + los) / 2).time
|
||||
val az = Math.toDegrees(satPos.azimuth)
|
||||
val elev = Math.toDegrees(satPos.elevation)
|
||||
val alt = satPos.altitude
|
||||
return SatPass(id, name, isDeep, aos, az, los, az, tca, az, alt, elev, this)
|
||||
}
|
||||
|
||||
private fun nextNearEarthPass(refDate: Date, windBack: Boolean = false): SatPass {
|
||||
val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
|
||||
clear()
|
||||
timeInMillis = refDate.time
|
||||
}
|
||||
val id = satellite.tle.catnum
|
||||
val name = satellite.tle.name
|
||||
val isDeep = satellite.tle.isDeepspace
|
||||
|
||||
var elevation: Double
|
||||
var maxElevation = 0.0
|
||||
var alt = 0.0
|
||||
var tcaAz = 0.0
|
||||
|
||||
// wind back time 1/4 of an orbit
|
||||
if (windBack) calendar.add(Calendar.MINUTE, -oneQuarterOrbitMin)
|
||||
var satPos = getSatPos(calendar.time)
|
||||
|
||||
if (satPos.elevation > 0.0) {
|
||||
// move forward in 30 second intervals until the sat goes below the horizon
|
||||
do {
|
||||
calendar.add(Calendar.SECOND, 30)
|
||||
satPos = getSatPos(calendar.time)
|
||||
} while (satPos.elevation > 0.0)
|
||||
// move forward 3/4 of an orbit
|
||||
calendar.add(Calendar.MINUTE, oneQuarterOrbitMin * 3)
|
||||
}
|
||||
|
||||
// find the next time sat comes above the horizon
|
||||
do {
|
||||
calendar.add(Calendar.SECOND, 60)
|
||||
satPos = getSatPos(calendar.time)
|
||||
elevation = satPos.elevation
|
||||
if (elevation > maxElevation) {
|
||||
maxElevation = elevation
|
||||
alt = satPos.altitude
|
||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
||||
}
|
||||
} while (satPos.elevation < 0.0)
|
||||
|
||||
// refine to 3 seconds
|
||||
calendar.add(Calendar.SECOND, -60)
|
||||
do {
|
||||
calendar.add(Calendar.SECOND, 3)
|
||||
satPos = getSatPos(calendar.time)
|
||||
elevation = satPos.elevation
|
||||
if (elevation > maxElevation) {
|
||||
maxElevation = elevation
|
||||
alt = satPos.altitude
|
||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
||||
}
|
||||
} while (satPos.elevation < 0.0)
|
||||
|
||||
val aos = satPos.time.time
|
||||
val aosAz = Math.toDegrees(satPos.azimuth)
|
||||
|
||||
// find when sat goes below
|
||||
do {
|
||||
calendar.add(Calendar.SECOND, 30)
|
||||
satPos = getSatPos(calendar.time)
|
||||
elevation = satPos.elevation
|
||||
if (elevation > maxElevation) {
|
||||
maxElevation = elevation
|
||||
alt = satPos.altitude
|
||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
||||
}
|
||||
} while (satPos.elevation > 0.0)
|
||||
|
||||
// refine to 3 seconds
|
||||
calendar.add(Calendar.SECOND, -30)
|
||||
do {
|
||||
calendar.add(Calendar.SECOND, 3)
|
||||
satPos = getSatPos(calendar.time)
|
||||
elevation = satPos.elevation
|
||||
if (elevation > maxElevation) {
|
||||
maxElevation = elevation
|
||||
alt = satPos.altitude
|
||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
||||
}
|
||||
} while (satPos.elevation > 0.0)
|
||||
|
||||
val los = satPos.time.time
|
||||
val losAz = Math.toDegrees(satPos.azimuth)
|
||||
val tca = Date((aos + los) / 2).time
|
||||
val elev = Math.toDegrees(maxElevation)
|
||||
return SatPass(id, name, isDeep, aos, aosAz, los, losAz, tca, tcaAz, alt, elev, this)
|
||||
}
|
||||
}
|
|
@ -17,9 +17,9 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.utility
|
||||
|
||||
import com.github.amsacode.predict4java.Satellite
|
||||
import com.rtbishop.look4sat.data.model.SatPass
|
||||
import com.rtbishop.look4sat.di.DefaultDispatcher
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.SatPass
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
|
|
|
@ -20,8 +20,8 @@ package com.rtbishop.look4sat.utility
|
|||
import android.content.SharedPreferences
|
||||
import android.hardware.GeomagneticField
|
||||
import androidx.core.content.edit
|
||||
import com.github.amsacode.predict4java.GroundStationPosition
|
||||
import com.rtbishop.look4sat.data.model.TleSource
|
||||
import com.rtbishop.look4sat.framework.model.TleSource
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.GroundPos
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.Types
|
||||
import javax.inject.Inject
|
||||
|
@ -60,12 +60,12 @@ class PrefsManager @Inject constructor(val preferences: SharedPreferences, moshi
|
|||
return preferences.getInt(keyMinElevation, 16).toDouble()
|
||||
}
|
||||
|
||||
fun getStationPosition(): GroundStationPosition {
|
||||
fun getStationPosition(): GroundPos {
|
||||
val defaultGSP = "0.0"
|
||||
val latitude = preferences.getString(keyLatitude, null) ?: defaultGSP
|
||||
val longitude = preferences.getString(keyLongitude, null) ?: defaultGSP
|
||||
val altitude = preferences.getString(keyAltitude, null) ?: defaultGSP
|
||||
return GroundStationPosition(latitude.toDouble(), longitude.toDouble(), altitude.toDouble())
|
||||
return GroundPos(latitude.toDouble(), longitude.toDouble(), altitude.toDouble())
|
||||
}
|
||||
|
||||
fun setStationPosition(latitude: Double, longitude: Double, altitude: Double) {
|
||||
|
@ -78,9 +78,9 @@ class PrefsManager @Inject constructor(val preferences: SharedPreferences, moshi
|
|||
|
||||
fun getMagDeclination(): Float {
|
||||
val stationPosition = getStationPosition()
|
||||
val lat = stationPosition.latitude.toFloat()
|
||||
val lon = stationPosition.longitude.toFloat()
|
||||
val alt = stationPosition.heightAMSL.toFloat()
|
||||
val lat = stationPosition.lat.toFloat()
|
||||
val lon = stationPosition.lon.toFloat()
|
||||
val alt = stationPosition.alt.toFloat()
|
||||
return GeomagneticField(lat, lon, alt, System.currentTimeMillis()).declination
|
||||
}
|
||||
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
*/
|
||||
package com.rtbishop.look4sat.utility
|
||||
|
||||
import com.github.amsacode.predict4java.GroundStationPosition
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.GroundPos
|
||||
import javax.inject.Inject
|
||||
|
||||
class QthConverter @Inject constructor() {
|
||||
|
||||
fun qthToLocation(qthString: String): GroundStationPosition? {
|
||||
fun qthToLocation(qthString: String): GroundPos? {
|
||||
val trimmedQth = qthString.take(6)
|
||||
if (!isValidQTH(trimmedQth)) return null
|
||||
val lonFirst = (trimmedQth[0].toUpperCase().toInt() - 65) * 20
|
||||
|
@ -33,7 +33,7 @@ class QthConverter @Inject constructor() {
|
|||
val latThird = (((trimmedQth[5].toLowerCase().toInt() - 97) / 24.0) + (1.0 / 48.0)) - 90
|
||||
val longitude = (lonFirst + lonSecond + lonThird).round(4)
|
||||
val latitude = (latFirst + latSecond + latThird).round(4)
|
||||
return GroundStationPosition(latitude, longitude, 0.0)
|
||||
return GroundPos(latitude, longitude, 0.0)
|
||||
}
|
||||
|
||||
fun locationToQTH(lat: Double, lon: Double): String? {
|
||||
|
|
|
@ -2,7 +2,7 @@ buildscript {
|
|||
ext {
|
||||
gradle_version = '4.1.3'
|
||||
kotlin_version = '1.4.32'
|
||||
coroutines_version = '1.4.1'
|
||||
coroutines_version = '1.4.3'
|
||||
material_version = '1.3.0'
|
||||
constraint_layout_version = '2.0.4'
|
||||
lifecycle_version = '2.3.1'
|
||||
|
@ -11,7 +11,6 @@ buildscript {
|
|||
room_version = '2.3.0'
|
||||
hilt_version = '2.33-beta'
|
||||
retrofit_version = '2.9.0'
|
||||
predict4java_version = '1.3.1'
|
||||
osmdroid_version = '6.1.10'
|
||||
timber_version = '4.7.1'
|
||||
junit_version = '4.13.2'
|
||||
|
|
|
@ -11,4 +11,7 @@ java {
|
|||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
}
|
||||
|
||||
testImplementation "junit:junit:$junit_version"
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_test_version"
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.rtbishop.look4sat.domain.SatelliteRepo
|
|||
import com.rtbishop.look4sat.domain.model.SatEntry
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import com.rtbishop.look4sat.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -32,15 +32,13 @@ class DefaultSatelliteRepo(
|
|||
}
|
||||
|
||||
override suspend fun importDataFromFile(stream: InputStream) = withContext(ioDispatcher) {
|
||||
val entries = mutableListOf<SatEntry>()
|
||||
val tleList = Satellite.importTLE(stream)
|
||||
tleList.forEach { tle -> entries.add(SatEntry(tle)) }
|
||||
val entries = Satellite.importTLE(stream).map { tle -> SatEntry(tle) }
|
||||
localSource.updateEntries(entries)
|
||||
}
|
||||
|
||||
override suspend fun importDataFromWeb(sources: List<String>) {
|
||||
coroutineScope {
|
||||
launch {
|
||||
launch(ioDispatcher) {
|
||||
val entries = mutableListOf<SatEntry>()
|
||||
val streams = mutableListOf<InputStream>()
|
||||
sources.forEach { source ->
|
||||
|
@ -59,7 +57,7 @@ class DefaultSatelliteRepo(
|
|||
}
|
||||
localSource.updateEntries(entries)
|
||||
}
|
||||
launch {
|
||||
launch(ioDispatcher) {
|
||||
val transmitters = remoteSource.fetchTransmitters().filter { it.isAlive }
|
||||
localSource.updateTransmitters(transmitters)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.rtbishop.look4sat.data
|
|||
import com.rtbishop.look4sat.domain.model.SatEntry
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import com.rtbishop.look4sat.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface LocalDataSource {
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.rtbishop.look4sat.domain
|
|||
|
||||
import com.rtbishop.look4sat.domain.model.SatItem
|
||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||
import com.rtbishop.look4sat.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.io.InputStream
|
||||
|
||||
|
@ -19,4 +19,4 @@ interface SatelliteRepo {
|
|||
suspend fun importDataFromWeb(sources: List<String>)
|
||||
|
||||
suspend fun updateEntriesSelection(catNums: List<Int>, isSelected: Boolean)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.rtbishop.look4sat.domain.model
|
||||
|
||||
import com.rtbishop.look4sat.predict4kotlin.TLE
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.TLE
|
||||
|
||||
data class SatEntry(
|
||||
val tle: TLE,
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
import kotlin.math.*
|
||||
|
|
@ -15,6 +15,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
data class GroundPos(val lat: Double, val lon: Double, val alt: Double, val name: String = "base")
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
import kotlin.math.*
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
import java.util.*
|
||||
|
|
@ -15,6 +15,6 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
data class Position(val lat: Double, val lon: Double)
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
import java.util.*
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
import java.util.*
|
||||
import kotlin.math.*
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
|
@ -15,7 +15,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.rtbishop.look4sat.predict4kotlin
|
||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||
|
||||
data class TLE(
|
||||
val name: String,
|
|
@ -9,4 +9,4 @@ class GetSatItems(private val satelliteRepo: SatelliteRepo) {
|
|||
operator fun invoke(): Flow<List<SatItem>> {
|
||||
return satelliteRepo.getSatItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.rtbishop.look4sat.interactors
|
||||
|
||||
import com.rtbishop.look4sat.domain.SatelliteRepo
|
||||
import com.rtbishop.look4sat.predict4kotlin.Satellite
|
||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||
|
||||
class GetSelectedSatellites(private val satelliteRepo: SatelliteRepo) {
|
||||
|
||||
suspend operator fun invoke(): List<Satellite> {
|
||||
return satelliteRepo.getSelectedSatellites()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,4 +9,4 @@ class GetTransmittersForSat(private val satelliteRepo: SatelliteRepo) {
|
|||
operator fun invoke(catNum: Int): Flow<List<SatTrans>> {
|
||||
return satelliteRepo.getTransmittersForSat(catNum)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,4 +8,4 @@ class ImportDataFromFile(private val satelliteRepo: SatelliteRepo) {
|
|||
suspend operator fun invoke(stream: InputStream) {
|
||||
satelliteRepo.importDataFromFile(stream)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ class ImportDataFromWeb(private val satelliteRepo: SatelliteRepo) {
|
|||
suspend operator fun invoke(sources: List<String>) {
|
||||
satelliteRepo.importDataFromWeb(sources)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ class UpdateEntriesSelection(private val satelliteRepo: SatelliteRepo) {
|
|||
suspend operator fun invoke(catNums: List<Int>, isSelected: Boolean) {
|
||||
satelliteRepo.updateEntriesSelection(catNums, isSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,4 +18,4 @@ android.useAndroidX=true
|
|||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
# Kotlin code style for this project: "official" or "obsolete":
|
||||
kotlin.code.style=official
|
||||
kotlin.code.style=official
|
||||
|
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||
|
|
Ładowanie…
Reference in New Issue