Skip to content

Commit

Permalink
Merge branch 'dev' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed Aug 26, 2023
2 parents b156e79 + 0346f38 commit 87d5881
Show file tree
Hide file tree
Showing 60 changed files with 963 additions and 289 deletions.
2 changes: 1 addition & 1 deletion api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import org.springframework.boot.gradle.tasks.bundling.BootJar

plugins {
kotlin("jvm")
id("org.springframework.boot") version "3.1.2"
id("org.springframework.boot") version "3.1.3"
id("io.spring.dependency-management") version "1.1.3"
kotlin("plugin.spring")
kotlin("kapt")
Expand Down
71 changes: 69 additions & 2 deletions api/objectbox-models/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -557,10 +557,77 @@
}
],
"relations": []
},
{
"id": "7:8968304416388002032",
"lastPropertyId": "5:7830389679541367505",
"name": "TLEEntity",
"properties": [
{
"id": "1:1418769500440679099",
"name": "id",
"type": 6,
"flags": 129
},
{
"id": "2:7290811067773705137",
"name": "source",
"indexId": "14:9187059019963520245",
"type": 6,
"flags": 8
},
{
"id": "3:2719054692725905613",
"name": "name",
"type": 9
},
{
"id": "4:7447454692522974010",
"name": "tle",
"type": 9
}
],
"relations": []
},
{
"id": "8:3715657608088091992",
"lastPropertyId": "5:6338712844528940250",
"name": "TLESourceEntity",
"properties": [
{
"id": "1:1484675797823198018",
"name": "id",
"type": 6,
"flags": 1
},
{
"id": "2:3112508440451107751",
"name": "url",
"indexId": "15:6936188058417201855",
"type": 9,
"flags": 2048
},
{
"id": "3:6679808789215869090",
"name": "updatedAt",
"type": 6
},
{
"id": "4:3330731028661288545",
"name": "enabled",
"type": 1
},
{
"id": "5:6338712844528940250",
"name": "deletable",
"type": 1
}
],
"relations": []
}
],
"lastEntityId": "6:2301362482019052453",
"lastIndexId": "13:1450764334546729064",
"lastEntityId": "8:3715657608088091992",
"lastIndexId": "15:6936188058417201855",
"lastRelationId": "0:0",
"lastSequenceId": "0:0",
"modelVersion": 5,
Expand Down
37 changes: 34 additions & 3 deletions api/src/main/kotlin/nebulosa/api/controllers/AtlasController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import jakarta.validation.Valid
import jakarta.validation.constraints.Min
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Positive
import nebulosa.api.data.entities.DeepSkyObjectEntity
import nebulosa.api.data.entities.LocationEntity
import nebulosa.api.data.entities.StarEntity
import nebulosa.api.data.entities.*
import nebulosa.api.data.responses.BodyPositionResponse
import nebulosa.api.data.responses.MinorPlanetResponse
import nebulosa.api.data.responses.TwilightResponse
Expand Down Expand Up @@ -120,6 +118,28 @@ class AtlasController(
return atlasService.positionOfDSO(locationRepository.withId(location)!!, deepSkyObjectRepository.withId(dso)!!, (date + time).noSeconds())
}

@GetMapping("positionOfSatellite")
fun positionOfSatellite(
@RequestParam location: Long,
@RequestParam @Valid @NotBlank tle: String,
@DateTimeFormat(pattern = "yyyy-MM-dd") @RequestParam(required = false) date: LocalDate?,
@DateTimeFormat(pattern = "HH:mm") @RequestParam(required = false) time: LocalTime?,
): BodyPositionResponse {
return atlasService.positionOfSatellite(locationRepository.withId(location)!!, tle, (date + time).noSeconds())
}

@GetMapping("searchSatellites")
fun searchSatellites(
@RequestParam(required = false, defaultValue = "") text: String,
): List<TLEEntity> {
return atlasService.searchSatellites(text)
}

@GetMapping("satelliteSources")
fun satelliteSources(): List<TLESourceEntity> {
return atlasService.satelliteSources()
}

@GetMapping("twilight")
fun twilight(
@RequestParam location: Long,
Expand Down Expand Up @@ -178,6 +198,17 @@ class AtlasController(
.altitudePointsOfDSO(locationRepository.withId(location)!!, deepSkyObjectRepository.withId(dso)!!, date.orNow(), stepSize)
}

@GetMapping("altitudePointsOfSatellite")
fun altitudePointsOfSatellite(
@RequestParam location: Long,
@RequestParam @Valid @NotBlank tle: String,
@DateTimeFormat(pattern = "yyyy-MM-dd") @RequestParam(required = false) date: LocalDate?,
@RequestParam(required = false, defaultValue = "1") stepSize: Int,
): List<DoubleArray> {
return atlasService
.altitudePointsOfSatellite(locationRepository.withId(location)!!, tle, date.orNow(), stepSize)
}

@GetMapping("searchMinorPlanet")
fun searchMinorPlanet(@RequestParam @Valid @NotBlank text: String): MinorPlanetResponse {
return atlasService.searchMinorPlanet(text)
Expand Down
26 changes: 26 additions & 0 deletions api/src/main/kotlin/nebulosa/api/data/entities/TLEEntity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package nebulosa.api.data.entities

import com.fasterxml.jackson.annotation.JsonIgnore
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import io.objectbox.annotation.Index

@Entity
data class TLEEntity(
@Id(assignable = true) var id: Long = 0L,
@JsonIgnore @Index var source: Long = 0L,
var name: String = "",
var tle: String = "",
) {

companion object {

@JvmStatic
fun from(source: TLESourceEntity, lines: List<String>): TLEEntity {
val name = lines[0]
val id = lines[1].substring(2..6).toLong()
val tle = lines.joinToString("\n")
return TLEEntity(id, source.id, name, tle)
}
}
}
14 changes: 14 additions & 0 deletions api/src/main/kotlin/nebulosa/api/data/entities/TLESourceEntity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package nebulosa.api.data.entities

import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import io.objectbox.annotation.Index

@Entity
data class TLESourceEntity(
@Id var id: Long = 0L,
@Index var url: String = "",
var updatedAt: Long = 0,
var enabled: Boolean = true,
var deletable: Boolean = false,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package nebulosa.api.data.serializers

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.ser.std.StdSerializer
import nebulosa.guiding.GuidePoint
import nebulosa.guiding.Guider
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Component

@Component
@Qualifier("serializer")
class GuiderSerializer : StdSerializer<Guider>(Guider::class.java) {

override fun serialize(
guider: Guider,
gen: JsonGenerator,
provider: SerializerProvider,
) {
gen.writeStartObject()
gen.writeFieldName("lockPosition")
gen.writeGuidePoint(guider.lockPosition)
gen.writeFieldName("primaryStar")
gen.writeGuidePoint(guider.primaryStar)
gen.writeNumberField("searchRegion", guider.searchRegion)
gen.writeBooleanField("looping", guider.isLooping)
gen.writeBooleanField("calibrating", guider.isCalibrating)
gen.writeBooleanField("guiding", guider.isGuiding)
gen.writeEndObject()
}

companion object {

@JvmStatic
private fun JsonGenerator.writeGuidePoint(point: GuidePoint) {
writeStartObject()
writeNumberField("x", point.x)
writeNumberField("y", point.y)
writeBooleanField("valid", point.valid)
writeEndObject()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ sealed class BoxRepository<T : Any> : Iterable<T> {

fun save(entity: T) = box.put(entity)

fun saveAll(entities: Collection<T>) = box.put(entities)

fun delete(id: Long) = box.remove(id)

fun delete(entity: T) = box.remove(entity)
Expand Down
123 changes: 123 additions & 0 deletions api/src/main/kotlin/nebulosa/api/repositories/TLERepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package nebulosa.api.repositories

import io.objectbox.BoxStore
import io.objectbox.query.QueryBuilder.StringOrder.CASE_INSENSITIVE
import jakarta.annotation.PostConstruct
import nebulosa.api.data.entities.TLEEntity
import nebulosa.api.data.entities.TLEEntity_
import nebulosa.api.data.entities.TLESourceEntity
import nebulosa.log.loggerFor
import okhttp3.OkHttpClient
import okhttp3.Request
import org.springframework.stereotype.Service
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutorService
import java.util.function.Supplier

@Service
class TLERepository(
boxStore: BoxStore,
private val tleSourceRepository: TLESourceRepository,
private val systemExecutorService: ExecutorService,
private val okHttpClient: OkHttpClient,
) : BoxRepository<TLEEntity>() {

override val box = boxStore.boxFor(TLEEntity::class.java)!!

fun sources() = tleSourceRepository.all()

fun withSources(source: TLESourceEntity): List<TLEEntity> = box.query()
.equal(TLEEntity_.source, source.id)
.build()
.find()

fun withName(name: String): List<TLEEntity> = box.query()
.let { if (name.isBlank()) it else it.contains(TLEEntity_.name, name, CASE_INSENSITIVE) }
.order(TLEEntity_.name)
.build()
.find()

fun deleteWithSource(source: TLESourceEntity) = box.query()
.equal(TLEEntity_.source, source.id)
.build()
.remove()

@PostConstruct
fun updateIfOld() {
val currentTime = System.currentTimeMillis()

for (source in sources()) {
if (source.enabled && currentTime - source.updatedAt >= TLE_UPDATE_INTERVAL) {
deleteWithSource(source)

CompletableFuture
.supplyAsync(TLEUpdater(source), systemExecutorService)
.whenComplete { entities, e ->
e?.printStackTrace()

if (!entities.isNullOrEmpty()) {
saveAll(entities)

source.updatedAt = System.currentTimeMillis()
tleSourceRepository.save(source)

LOG.info("updated {} satellites from {}", entities.size, source.url)
}
}
} else if (!source.enabled) {
deleteWithSource(source)
}
}
}

private inner class TLEUpdater(private val source: TLESourceEntity) : Supplier<List<TLEEntity>> {

override fun get(): List<TLEEntity> {
val request = Request.Builder()
.get()
.url(source.url)
.build()

return okHttpClient.newCall(request)
.execute().use {
if (it.isSuccessful) {
source.parseTLEFile(it.body.byteStream())
} else {
emptyList()
}
}
}
}

companion object {

const val TLE_UPDATE_INTERVAL = 1000L * 60 * 60 * 72 // 72 hours in ms

@JvmStatic private val LOG = loggerFor<TLERepository>()

@JvmStatic
internal fun TLESourceEntity.parseTLEFile(data: ByteArray): List<TLEEntity> {
return parseTLEFile(ByteArrayInputStream(data))
}

@JvmStatic
internal fun TLESourceEntity.parseTLEFile(data: InputStream): List<TLEEntity> {
val entities = ArrayList<TLEEntity>(128)
val lines = ArrayList<String>(3)

for (line in data.bufferedReader().lines()) {
lines.add(line)

if (lines.size == 3) {
val tle = TLEEntity.from(this, lines)
lines.clear()
entities.add(tle)
}
}

return entities
}
}
}
Loading

0 comments on commit 87d5881

Please sign in to comment.