From 524a7916291a2c7da719dcb408190ae404d1e8ae Mon Sep 17 00:00:00 2001 From: Arty Bishop Date: Tue, 16 Nov 2021 17:19:50 +0000 Subject: [PATCH] Matched CSV and TLE parsed epoch and eccentricity data --- app/src/main/res/xml/preference.xml | 2 +- build.gradle | 2 +- .../rtbishop/look4sat/domain/DataParser.kt | 37 ++++++++++++------- .../com/rtbishop/look4sat/DataParserTest.kt | 25 ++++++++----- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml index 910e472c..fce8b99c 100644 --- a/app/src/main/res/xml/preference.xml +++ b/app/src/main/res/xml/preference.xml @@ -18,7 +18,7 @@ app:iconSpaceReserved="false"> = withContext(parserDispatcher) { val parsedItems = mutableListOf() csvStream.bufferedReader().useLines { lines -> @@ -84,14 +79,16 @@ class DataParser(private val parserDispatcher: CoroutineDispatcher) { private fun parseCSV(values: List): TLE? { try { val name = values[0] - calendar.time = simpleDateFormat.parse(values[2]) ?: Date() - val year = calendar.get(Calendar.YEAR).toString().substring(2, 4) - val day = calendar.get(Calendar.DAY_OF_YEAR) - val hours = calendar.get(Calendar.HOUR_OF_DAY) - val minutes = calendar.get(Calendar.MINUTE) - val seconds = calendar.get(Calendar.SECOND) - val fraction = ((hours * 60 * 60 + minutes * 60 + seconds) / 86400.0).toString() - val epoch = "$year$day${fraction.substring(1, fraction.length)}".toDouble() + val year = values[2].substring(0, 4) + val month = values[2].substring(5, 7) + val dayOfMonth = values[2].substring(8, 10) + val day = getDayOfYear(year.toInt(), month.toInt(), dayOfMonth.toInt()) + val hour = values[2].substring(11, 13).toInt() * 3600000000 // microseconds in one hour + val min = values[2].substring(14, 16).toInt() * 60000000 // microseconds in one minute + val sec = values[2].substring(17, 19).toInt() * 1000000 // microseconds in one second + val microsec = values[2].substring(20, 26).toInt() + val frac = ((hour + min + sec + microsec) / 86400000000.0).toString() + val epoch = "${year.substring(2)}$day${frac.substring(1)}".toDouble() val meanmo = values[3].toDouble() val eccn = values[4].toDouble() val incl = values[5].toDouble() @@ -114,7 +111,7 @@ class DataParser(private val parserDispatcher: CoroutineDispatcher) { val name: String = tle[0].trim() val epoch: Double = tle[1].substring(18, 32).toDouble() val meanmo: Double = tle[2].substring(52, 63).toDouble() - val eccn: Double = 1.0e-07 * tle[2].substring(26, 33).toDouble() + val eccn: Double = tle[2].substring(26, 33).toDouble() / 10000000.0 val incl: Double = tle[2].substring(8, 16).toDouble() val raan: Double = tle[2].substring(17, 25).toDouble() val argper: Double = tle[2].substring(34, 42).toDouble() @@ -147,4 +144,16 @@ class DataParser(private val parserDispatcher: CoroutineDispatcher) { return null } } + + private fun getDayOfYear(year: Int, month: Int, dayOfMonth: Int): Int { + if (month == 1) return dayOfMonth + val daysArray = arrayOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + var dayOfYear = dayOfMonth + // If leap year increment Feb days + if (((year / 4 == 0) && (year / 100 != 0)) || (year / 400 == 0)) daysArray[1]++ + for (i in 0 until month - 1) { + dayOfYear += daysArray[i] + } + return dayOfYear + } } diff --git a/core/src/test/java/com/rtbishop/look4sat/DataParserTest.kt b/core/src/test/java/com/rtbishop/look4sat/DataParserTest.kt index 15c2508e..f471033b 100644 --- a/core/src/test/java/com/rtbishop/look4sat/DataParserTest.kt +++ b/core/src/test/java/com/rtbishop/look4sat/DataParserTest.kt @@ -29,20 +29,20 @@ class DataParserTest { private val dataParser = DataParser(TestCoroutineDispatcher()) private val validCSVStream = """ OBJECT_NAME,OBJECT_ID,EPOCH,MEAN_MOTION,ECCENTRICITY,INCLINATION,RA_OF_ASC_NODE,ARG_OF_PERICENTER,MEAN_ANOMALY,EPHEMERIS_TYPE,CLASSIFICATION_TYPE,NORAD_CAT_ID,ELEMENT_SET_NO,REV_AT_EPOCH,BSTAR,MEAN_MOTION_DOT,MEAN_MOTION_DDOT - CALSPHERE 1,1964-063C,2021-10-23T03:34:39.713664,13.73605115,.0026891,90.1713,36.6548,20.0176,64.9795,0,U,900,999,83808,.30972E-3,.299E-5,0 + ISS (ZARYA),1998-067A,2021-11-16T12:28:09.322176,15.48582035,.0004694,51.6447,309.4881,203.6966,299.8876,0,U,25544,999,31220,.31985E-4,.1288E-4,0 """.trimIndent().byteInputStream() private val invalidCSVStream = """ - CALSPHERE 1,1964-063C,2021-10-23T03:34:39.713664,13.73605115,.0026891,90.1713,36.6548,20.0176,64.9795,0,U,900,999,83808,.30972E-3,.299E-5,0 + ISS (ZARYA),1998-067A,2021-11-16T12:28:09.322176,15.48582035,.0004694,51.6447,309.4881,203.6966,299.8876,0,U,25544,999,31220,.31985E-4,.1288E-4,0 OBJECT_NAME,OBJECT_ID,EPOCH,MEAN_MOTION,ECCENTRICITY,INCLINATION,RA_OF_ASC_NODE,ARG_OF_PERICENTER,MEAN_ANOMALY,EPHEMERIS_TYPE,CLASSIFICATION_TYPE,NORAD_CAT_ID,ELEMENT_SET_NO,REV_AT_EPOCH,BSTAR,MEAN_MOTION_DOT,MEAN_MOTION_DDOT """.trimIndent().byteInputStream() private val validTLEStream = """ ISS (ZARYA) - 1 25544U 98067A 21255.21005818 -.00120443 00000-0 -22592-2 0 9998 - 2 25544 51.6451 272.4173 0002526 27.1693 64.4213 15.48396490302085 + 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 """.trimIndent().byteInputStream() private val invalidTLEStream = """ - 1 25544U 98067A 21255.21005818 -.00120443 00000-0 -22592-2 0 9998 - 2 25544 51.6451 272.4173 0002526 27.1693 64.4213 15.48396490302085 + 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 """.trimIndent().byteInputStream() 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":""}] @@ -54,7 +54,7 @@ class DataParserTest { @Test fun `Given valid CSV stream returns valid data`() = runBlockingTest { val parsedList = dataParser.parseCSVStream(validCSVStream) - assert(parsedList[0].catnum == 900) + assert(parsedList[0].epoch == 21320.51955234) } @Test @@ -66,7 +66,7 @@ class DataParserTest { @Test fun `Given valid TLE stream returns valid data`() = runBlockingTest { val parsedList = dataParser.parseTLEStream(validTLEStream) - assert(parsedList[0].catnum == 25544) + assert(parsedList[0].epoch == 21320.51955234) } @Test @@ -75,10 +75,17 @@ class DataParserTest { assert(parsedList.isEmpty()) } + @Test + fun `Given valid data streams parsed results match`() = runBlockingTest { + val csvResult = dataParser.parseCSVStream(validCSVStream) + val tleResult = dataParser.parseTLEStream(validTLEStream) + assert(csvResult == tleResult) + } + @Test fun `Given valid JSON stream returns valid data`() = runBlockingTest { val parsedList = dataParser.parseJSONStream(validJSONStream) - assert(parsedList[0].catnum == 965) + assert(parsedList[0].downlink == 136658500L) } @Test