kopia lustrzana https://github.com/rt-bishop/Look4Sat
Added GeoConverter.kt and various minor fixes
rodzic
5f392304d3
commit
814a23e730
|
@ -9,6 +9,7 @@
|
||||||
android:name=".MainApplication"
|
android:name=".MainApplication"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
@ -16,7 +17,7 @@
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.Look4Sat.Main"
|
android:theme="@style/Theme.Look4Sat.Main"
|
||||||
tools:targetApi="31">
|
tools:targetApi="33">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
|
|
@ -11,7 +11,6 @@ import com.rtbishop.look4sat.data.database.MainDatabase
|
||||||
import com.rtbishop.look4sat.data.framework.BluetoothReporter
|
import com.rtbishop.look4sat.data.framework.BluetoothReporter
|
||||||
import com.rtbishop.look4sat.data.framework.NetworkReporter
|
import com.rtbishop.look4sat.data.framework.NetworkReporter
|
||||||
import com.rtbishop.look4sat.data.framework.SettingsRepo
|
import com.rtbishop.look4sat.data.framework.SettingsRepo
|
||||||
import com.rtbishop.look4sat.data.repository.DataParser
|
|
||||||
import com.rtbishop.look4sat.data.repository.DatabaseRepo
|
import com.rtbishop.look4sat.data.repository.DatabaseRepo
|
||||||
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
import com.rtbishop.look4sat.data.repository.SatelliteRepo
|
||||||
import com.rtbishop.look4sat.data.repository.SelectionRepo
|
import com.rtbishop.look4sat.data.repository.SelectionRepo
|
||||||
|
@ -22,20 +21,25 @@ import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
|
||||||
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
|
import com.rtbishop.look4sat.domain.repository.ISatelliteRepo
|
||||||
import com.rtbishop.look4sat.domain.repository.ISelectionRepo
|
import com.rtbishop.look4sat.domain.repository.ISelectionRepo
|
||||||
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||||
|
import com.rtbishop.look4sat.domain.source.IDataSource
|
||||||
import com.rtbishop.look4sat.domain.source.ISensorSource
|
import com.rtbishop.look4sat.domain.source.ISensorSource
|
||||||
|
import com.rtbishop.look4sat.domain.utility.DataParser
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import okhttp3.Cache
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.osmdroid.config.Configuration
|
import org.osmdroid.config.Configuration
|
||||||
|
|
||||||
class MainContainer(private val context: Context) {
|
class MainContainer(private val context: Context) {
|
||||||
|
|
||||||
private val database = Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb")
|
private val database =
|
||||||
.addMigrations(MIGRATION_1_2).fallbackToDestructiveMigration().build()
|
Room.databaseBuilder(context, MainDatabase::class.java, "Look4SatDb").addMigrations(MIGRATION_1_2)
|
||||||
|
.fallbackToDestructiveMigration().build()
|
||||||
private val localStorage = LocalStorage(database.storageDao())
|
private val localStorage = LocalStorage(database.storageDao())
|
||||||
private val mainHandler = CoroutineExceptionHandler { _, error -> println("Look4Sat: $error") }
|
private val mainHandler = CoroutineExceptionHandler { _, error -> println("Look4Sat: $error") }
|
||||||
|
private val remoteSource = provideRemoteSource()
|
||||||
val mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + mainHandler)
|
val mainScope = CoroutineScope(SupervisorJob() + Dispatchers.Default + mainHandler)
|
||||||
val settingsRepo = provideSettingsRepo()
|
val settingsRepo = provideSettingsRepo()
|
||||||
val databaseRepo = provideDatabaseRepo()
|
val databaseRepo = provideDatabaseRepo()
|
||||||
|
@ -57,11 +61,15 @@ class MainContainer(private val context: Context) {
|
||||||
return SensorSource(sensorManager, sensor)
|
return SensorSource(sensorManager, sensor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun provideRemoteSource(): IDataSource {
|
||||||
|
val cache = Cache(context.cacheDir, 1000 * 1000 * 10L)
|
||||||
|
val httpClient = OkHttpClient.Builder().cache(cache).build()
|
||||||
|
return DataSource(context.contentResolver, httpClient, Dispatchers.IO)
|
||||||
|
}
|
||||||
|
|
||||||
private fun provideDatabaseRepo(): IDatabaseRepo {
|
private fun provideDatabaseRepo(): IDatabaseRepo {
|
||||||
val httpClient = OkHttpClient.Builder().build()
|
|
||||||
val dataParser = DataParser(Dispatchers.Default)
|
val dataParser = DataParser(Dispatchers.Default)
|
||||||
val dataSource = DataSource(context.contentResolver, httpClient, Dispatchers.IO)
|
return DatabaseRepo(Dispatchers.Default, dataParser, remoteSource, localStorage, settingsRepo)
|
||||||
return DatabaseRepo(Dispatchers.Default, dataParser, dataSource, localStorage, settingsRepo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun provideSatelliteRepo(): ISatelliteRepo {
|
private fun provideSatelliteRepo(): ISatelliteRepo {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import com.rtbishop.look4sat.domain.repository.IDatabaseRepo
|
||||||
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
import com.rtbishop.look4sat.domain.repository.ISettingsRepo
|
||||||
import com.rtbishop.look4sat.domain.source.IDataSource
|
import com.rtbishop.look4sat.domain.source.IDataSource
|
||||||
import com.rtbishop.look4sat.domain.source.ILocalStorage
|
import com.rtbishop.look4sat.domain.source.ILocalStorage
|
||||||
|
import com.rtbishop.look4sat.domain.utility.DataParser
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.rtbishop.look4sat.data
|
||||||
|
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class ExampleUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
Assert.assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ kotlin {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
||||||
|
implementation("org.json:json:20230618")
|
||||||
|
|
||||||
testImplementation("junit:junit:4.13.2")
|
testImplementation("junit:junit:4.13.2")
|
||||||
testImplementation("io.mockk:mockk:1.13.5")
|
testImplementation("io.mockk:mockk:1.13.5")
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.data.repository
|
package com.rtbishop.look4sat.domain.utility
|
||||||
|
|
||||||
import com.rtbishop.look4sat.domain.model.SatRadio
|
import com.rtbishop.look4sat.domain.model.SatRadio
|
||||||
import com.rtbishop.look4sat.domain.predict.OrbitalData
|
import com.rtbishop.look4sat.domain.predict.OrbitalData
|
|
@ -17,8 +17,6 @@
|
||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.domain.utility
|
package com.rtbishop.look4sat.domain.utility
|
||||||
|
|
||||||
import com.rtbishop.look4sat.domain.predict.DEG2RAD
|
|
||||||
import com.rtbishop.look4sat.domain.predict.RAD2DEG
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
fun Long.toTimerString(): String {
|
fun Long.toTimerString(): String {
|
||||||
|
@ -41,10 +39,6 @@ fun Double.round(decimals: Int): Double {
|
||||||
return kotlin.math.round(this * multiplier) / multiplier
|
return kotlin.math.round(this * multiplier) / multiplier
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Double.toDegrees(): Double = this * RAD2DEG
|
|
||||||
|
|
||||||
fun Double.toRadians(): Double = this * DEG2RAD
|
|
||||||
|
|
||||||
//fun String.getHash(type: String = "SHA-256"): String {
|
//fun String.getHash(type: String = "SHA-256"): String {
|
||||||
// val hexChars = "0123456789ABCDEF"
|
// val hexChars = "0123456789ABCDEF"
|
||||||
// val bytes = MessageDigest.getInstance(type).digest(this.toByteArray())
|
// val bytes = MessageDigest.getInstance(type).digest(this.toByteArray())
|
||||||
|
@ -63,12 +57,12 @@ fun Double.toRadians(): Double = this * DEG2RAD
|
||||||
// return pattern.matcher(this).matches()
|
// return pattern.matcher(this).matches()
|
||||||
//}
|
//}
|
||||||
|
|
||||||
fun String.isValidIPv4(): Boolean {
|
//fun String.isValidIPv4(): Boolean {
|
||||||
val ip4 = "^((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|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())
|
// return this.matches(ip4.toRegex())
|
||||||
}
|
//}
|
||||||
|
|
||||||
fun String.isValidPort(): Boolean {
|
//fun String.isValidPort(): Boolean {
|
||||||
val port = "([1-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])"
|
// val port = "([1-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])"
|
||||||
return this.matches(port.toRegex()) && this.toInt() in 1024..65535
|
// return this.matches(port.toRegex()) && this.toInt() in 1024..65535
|
||||||
}
|
//}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.rtbishop.look4sat.domain.utility
|
||||||
|
|
||||||
|
import com.rtbishop.look4sat.domain.predict.DEG2RAD
|
||||||
|
import com.rtbishop.look4sat.domain.predict.PI
|
||||||
|
import com.rtbishop.look4sat.domain.predict.RAD2DEG
|
||||||
|
import kotlin.math.ln
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
private const val MIN_LATITUDE = -85.05112877980658
|
||||||
|
private const val MAX_LATITUDE = 85.05112877980658
|
||||||
|
private const val MIN_LONGITUDE = -180.0
|
||||||
|
private const val MAX_LONGITUDE = 180.0
|
||||||
|
|
||||||
|
fun Double.toDegrees(): Double = this * RAD2DEG
|
||||||
|
|
||||||
|
fun Double.toRadians(): Double = this * DEG2RAD
|
||||||
|
|
||||||
|
fun Double.latToY01(): Double {
|
||||||
|
val sinus = sin(clipLat(this) * PI / MAX_LONGITUDE)
|
||||||
|
return 0.5 - ln((1 + sinus) / (1 - sinus)) / (4 * PI)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Double.lonToX01(): Double {
|
||||||
|
return (clipLon(this) - MIN_LONGITUDE) / (MAX_LONGITUDE - MIN_LONGITUDE)
|
||||||
|
}
|
||||||
|
|
||||||
|
//fun Double.y01ToLat(): Double {
|
||||||
|
// return 90 - 360 * atan(exp((this - 0.5) * 2 * PI)) / PI
|
||||||
|
//}
|
||||||
|
|
||||||
|
//fun Double.x01ToLon(): Double {
|
||||||
|
// return MIN_LONGITUDE + (MAX_LONGITUDE - MIN_LONGITUDE) * this
|
||||||
|
//}
|
||||||
|
|
||||||
|
private fun clipLat(latitude: Double): Double {
|
||||||
|
return clip(latitude, MIN_LATITUDE, MAX_LATITUDE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clipLon(longitude: Double): Double {
|
||||||
|
var result = longitude
|
||||||
|
while (result < MIN_LONGITUDE) result += 360.0
|
||||||
|
while (result > MAX_LONGITUDE) result -= 360.0
|
||||||
|
return clip(result, MIN_LONGITUDE, MAX_LONGITUDE)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clip(currentValue: Double, minValue: Double, maxValue: Double): Double {
|
||||||
|
return min(max(currentValue, minValue), maxValue)
|
||||||
|
}
|
|
@ -15,9 +15,9 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.data
|
package com.rtbishop.look4sat.domain
|
||||||
|
|
||||||
import com.rtbishop.look4sat.data.repository.DataParser
|
import com.rtbishop.look4sat.domain.utility.DataParser
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
@ -49,12 +49,12 @@ class DataParserTest {
|
||||||
1 25544U 98067A 21320.51955234 .00001288 00000+0 31985-4 0 9990
|
1 25544U 98067A 21320.51955234 .00001288 00000+0 31985-4 0 9990
|
||||||
2 25544 51.6447 309.4881 0004694 203.6966 299.8876 15.48582035312205
|
2 25544 51.6447 309.4881 0004694 203.6966 299.8876 15.48582035312205
|
||||||
""".trimIndent().byteInputStream()
|
""".trimIndent().byteInputStream()
|
||||||
// private val validJSONStream = """
|
private val validJSONStream = """
|
||||||
// [{"uuid":"UzPz4gcsNBPKPKAFPmer7g","description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
[{"uuid":"UzPz4gcsNBPKPKAFPmer7g","description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
||||||
// """.trimIndent().byteInputStream()
|
""".trimIndent().byteInputStream()
|
||||||
// private val invalidJSONStream = """
|
private val invalidJSONStream = """
|
||||||
// [{"description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
[{"description":"Upper side band (drifting)","alive":true,"type":"Transmitter","uplink_low":null,"uplink_high":null,"uplink_drift":null,"downlink_low":136658500,"downlink_high":null,"downlink_drift":null,"mode":"USB","mode_id":9,"uplink_mode":null,"invert":false,"baud":null,"sat_id":"SCHX-0895-2361-9925-0309","norad_cat_id":965,"status":"active","updated":"2019-04-18T05:39:53.343316Z","citation":"CITATION NEEDED - https://xkcd.com/285/","service":"Unknown","coordination":"","coordination_url":""}]
|
||||||
// """.trimIndent().byteInputStream()
|
""".trimIndent().byteInputStream()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Given valid CSV stream returns valid data`() = runTest(testDispatcher) {
|
fun `Given valid CSV stream returns valid data`() = runTest(testDispatcher) {
|
||||||
|
@ -87,15 +87,15 @@ class DataParserTest {
|
||||||
assert(csvResult == tleResult)
|
assert(csvResult == tleResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
@Test
|
||||||
// fun `Given valid JSON stream returns valid data`() = runTest(testDispatcher) {
|
fun `Given valid JSON stream returns valid data`() = runTest(testDispatcher) {
|
||||||
// val parsedList = dataParser.parseJSONStream(validJSONStream)
|
val parsedList = dataParser.parseJSONStream(validJSONStream)
|
||||||
// assert(parsedList[0].downlink == 136658500L)
|
assert(parsedList[0].downlink == 136658500L)
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// @Test
|
@Test
|
||||||
// fun `Given invalid JSON stream returns empty list`() = runTest(testDispatcher) {
|
fun `Given invalid JSON stream returns empty list`() = runTest(testDispatcher) {
|
||||||
// val parsedList = dataParser.parseJSONStream(invalidJSONStream)
|
val parsedList = dataParser.parseJSONStream(invalidJSONStream)
|
||||||
// assert(parsedList.isEmpty())
|
assert(parsedList.isEmpty())
|
||||||
// }
|
}
|
||||||
}
|
}
|
Ładowanie…
Reference in New Issue