Skip to content

Commit

Permalink
[api][desktop]: Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed Oct 9, 2024
1 parent 700d087 commit 20bfed7
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 75 deletions.
8 changes: 7 additions & 1 deletion api/src/main/kotlin/nebulosa/api/Nebulosa.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nebulosa.api

import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.jsonMapper
import com.github.rvesse.airline.annotations.Command
Expand All @@ -16,6 +17,7 @@ import org.koin.core.context.startKoin
import java.nio.file.Path
import java.time.LocalDate
import java.time.LocalTime
import java.util.concurrent.ConcurrentHashMap

@Command(name = "nebulosa")
class Nebulosa : Runnable, AutoCloseable {
Expand Down Expand Up @@ -63,8 +65,11 @@ class Nebulosa : Runnable, AutoCloseable {

private data object LocationConverter : (String) -> Location? {

private val CACHED_LOCATION = ConcurrentHashMap<String, Location>(4)

override fun invoke(value: String): Location? {
return if (value.isBlank()) null else OBJECT_MAPPER.readValue(value, Location::class.java)
return if (value.isBlank()) null
else CACHED_LOCATION.computeIfAbsent(value) { OBJECT_MAPPER.readValue(value, Location::class.java) }
}
}

Expand Down Expand Up @@ -92,6 +97,7 @@ class Nebulosa : Runnable, AutoCloseable {
addModule(DeviceModule())
disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
}
}
}
4 changes: 3 additions & 1 deletion api/src/main/kotlin/nebulosa/api/atlas/Location.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package nebulosa.api.atlas

import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import nebulosa.api.beans.converters.angle.DegreesDeserializer
Expand All @@ -18,5 +19,6 @@ data class Location(
@JvmField val offsetInMinutes: Int = 0,
) : GeographicCoordinate, TimeZonedInSeconds {

override val offsetInSeconds = offsetInMinutes * 60
override val offsetInSeconds
@JsonIgnore get() = offsetInMinutes * 60
}
16 changes: 9 additions & 7 deletions api/src/main/kotlin/nebulosa/api/atlas/SkyAtlasController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SkyAtlasController(
app.get("sky-atlas/planets/{code}/position", ::positionOfPlanet)
app.get("sky-atlas/planets/{code}/altitude-points", ::altitudePointsOfPlanet)
app.get("sky-atlas/minor-planets", ::searchMinorPlanet)
app.get("sky-atlas/close-approaches", ::closeApproachesForMinorPlanets)
app.get("sky-atlas/minor-planets/close-approaches", ::closeApproachesForMinorPlanets)
app.get("sky-atlas/sky-objects", ::searchSkyObject)
app.get("sky-atlas/sky-objects/types", ::skyObjectTypes)
app.get("sky-atlas/sky-objects/{id}/position", ::positionOfSkyObject)
Expand Down Expand Up @@ -72,12 +72,12 @@ class SkyAtlasController(
ctx.json(skyAtlasService.altitudePointsOfMoon(location, dateTime, stepSize, fast))
}

private fun positionOfPlanet(ctx: Context): BodyPosition {
private fun positionOfPlanet(ctx: Context) {
val code = ctx.pathParam("code")
val location = ctx.location()
val dateTime = LocalDateTime.of(ctx.localDate(), ctx.localTime())
val fast = ctx.queryParamAsBoolean("fast").getOrDefault(false)
return skyAtlasService.positionOfPlanet(location, code, dateTime, fast)
ctx.json(skyAtlasService.positionOfPlanet(location, code, dateTime, fast))
}

private fun altitudePointsOfPlanet(ctx: Context) {
Expand All @@ -89,9 +89,9 @@ class SkyAtlasController(
ctx.json(skyAtlasService.altitudePointsOfPlanet(location, code, dateTime, stepSize, fast))
}

private fun searchMinorPlanet(ctx: Context): MinorPlanet {
private fun searchMinorPlanet(ctx: Context) {
val text = ctx.queryParamAsString("text").notBlank().get()
return skyAtlasService.searchMinorPlanet(text)
ctx.json(skyAtlasService.searchMinorPlanet(text))
}

private fun closeApproachesForMinorPlanets(ctx: Context) {
Expand All @@ -116,7 +116,7 @@ class SkyAtlasController(
ctx.json(skyAtlasService.altitudePointsOfSkyObject(location, id, dateTime, stepSize))
}

private fun searchSkyObject(ctx: Context): List<SimbadEntity> {
private fun searchSkyObject(ctx: Context) {
val text = ctx.queryParamAsString("text").getOrDefault("")
val rightAscension = ctx.queryParamAsString("rightAscension").getOrDefault("")
val declination = ctx.queryParamAsString("declination").getOrDefault("")
Expand All @@ -127,10 +127,12 @@ class SkyAtlasController(
val type = ctx.queryParamAsString("type").allowNullable().get()?.let(SkyObjectType::valueOf)
val id = ctx.queryParamAsLong("id").getOrDefault(0L)

return skyAtlasService.searchSkyObject(
val result = skyAtlasService.searchSkyObject(
text, rightAscension.hours, declination.deg, radius.deg,
constellation, magnitudeMin, magnitudeMax, type, id,
)

ctx.json(result)
}

private fun skyObjectTypes(ctx: Context) {
Expand Down
4 changes: 2 additions & 2 deletions api/src/main/kotlin/nebulosa/api/image/ImageController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class ImageController(
val path = ctx.queryParamAsPath("path").exists().get()
val request = ctx.bodyAsClass<AnnotateImageRequest>()
val location = ctx.locationOrNull()
imageService.annotations(path, request, location)
ctx.json(imageService.annotations(path, request, location))
}

private fun coordinateInterpolation(ctx: Context) {
Expand All @@ -57,7 +57,7 @@ class ImageController(
private fun histogram(ctx: Context) {
val path = ctx.queryParamAsPath("path").exists().get()
val bitLength = ctx.queryParamAsInt("bitLength").range(8..16).getOrDefault(16)
imageService.histogram(path, bitLength)
ctx.json(imageService.histogram(path, bitLength))
}

private fun fovCameras(ctx: Context) {
Expand Down
24 changes: 15 additions & 9 deletions api/src/main/kotlin/nebulosa/api/image/ImageService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,14 @@ class ImageService(
val rightAscension = it[1].hours.takeIf(Angle::isFinite) ?: return@forEach
val declination = it[2].deg.takeIf(Angle::isFinite) ?: return@forEach
val (x, y) = wcs.skyToPix(rightAscension, declination)
val magnitude = it[6].replace(INVALID_MAG_CHARS, "").toDoubleOrNull() ?: SkyObject.UNKNOWN_MAGNITUDE
val minorPlanet = ImageAnnotation.MinorPlanet(0L, it[0], rightAscension, declination, magnitude)
val annotation = ImageAnnotation(x, y, minorPlanet = minorPlanet)
annotations.add(annotation)
count++

if (x >= 0 && y >= 0 && x < image.width && y < image.height) {
val magnitude = it[6].replace(INVALID_MAG_CHARS, "").toDoubleOrNull() ?: SkyObject.UNKNOWN_MAGNITUDE
val minorPlanet = ImageAnnotation.MinorPlanet(0L, it[0], rightAscension, declination, magnitude)
val annotation = ImageAnnotation(x, y, minorPlanet = minorPlanet)
annotations.add(annotation)
count++
}
}
}

Expand Down Expand Up @@ -255,10 +258,13 @@ class ImageService(
val astrometric = barycentric.observe(entry).equatorial()

val (x, y) = wcs.skyToPix(astrometric.longitude.normalized, astrometric.latitude)
val annotation = if (entry.type.classification == ClassificationType.STAR) ImageAnnotation(x, y, star = StarDSO(entry))
else ImageAnnotation(x, y, dso = StarDSO(entry))
annotations.add(annotation)
count++

if (x >= 0 && y >= 0 && x < image.width && y < image.height) {
val annotation = if (entry.type.classification == ClassificationType.STAR) ImageAnnotation(x, y, star = StarDSO(entry))
else ImageAnnotation(x, y, dso = StarDSO(entry))
annotations.add(annotation)
count++
}
}

LOG.info("found {} stars/DSOs", count)
Expand Down
52 changes: 26 additions & 26 deletions api/src/main/kotlin/nebulosa/api/mounts/MountController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,29 @@ class MountController(

init {
app.get("mounts", ::mounts)
app.get("mount/{id}", ::mount)
app.put("mount/{id}/connect", ::connect)
app.put("mount/{id}/disconnect", ::disconnect)
app.put("mount/{id}/tracking", ::tracking)
app.put("mount/{id}/sync", ::sync)
app.put("mount/{id}/slew", ::slew)
app.put("mount/{id}/goto", ::goTo)
app.put("mount/{id}/home", ::home)
app.put("mount/{id}/abort", ::abort)
app.put("mount/{id}/track-mode", ::trackMode)
app.put("mount/{id}/slew-rate", ::slewRate)
app.put("mount/{id}/move", ::move)
app.put("mount/{id}/park", ::park)
app.put("mount/{id}/unpark", ::unpark)
app.put("mount/{id}/coordinates", ::coordinates)
app.put("mount/{id}/datetime", ::dateTime)
app.get("mount/{id}/location", ::location)
app.get("mount/{id}/location/{type}", ::celestialLocation)
app.put("mount/{id}/point-here", ::pointMountHere)
app.get("mount/{id}/remote-control", ::remoteControlList)
app.put("mount/{id}/remote-control/start", ::remoteControlStart)
app.put("mount/{id}/remote-control/stop", ::remoteControlStop)
app.put("mount/{id}/listen", ::listen)
app.get("mounts/{id}", ::mount)
app.put("mounts/{id}/connect", ::connect)
app.put("mounts/{id}/disconnect", ::disconnect)
app.put("mounts/{id}/tracking", ::tracking)
app.put("mounts/{id}/sync", ::sync)
app.put("mounts/{id}/slew", ::slew)
app.put("mounts/{id}/goto", ::goTo)
app.put("mounts/{id}/home", ::home)
app.put("mounts/{id}/abort", ::abort)
app.put("mounts/{id}/track-mode", ::trackMode)
app.put("mounts/{id}/slew-rate", ::slewRate)
app.put("mounts/{id}/move", ::move)
app.put("mounts/{id}/park", ::park)
app.put("mounts/{id}/unpark", ::unpark)
app.put("mounts/{id}/coordinates", ::coordinates)
app.put("mounts/{id}/datetime", ::dateTime)
app.get("mounts/{id}/location", ::location)
app.get("mounts/{id}/location/{type}", ::celestialLocation)
app.put("mounts/{id}/point-here", ::pointMountHere)
app.get("mounts/{id}/remote-control", ::remoteControlList)
app.put("mounts/{id}/remote-control/start", ::remoteControlStart)
app.put("mounts/{id}/remote-control/stop", ::remoteControlStop)
app.put("mounts/{id}/listen", ::listen)
}

private fun mounts(ctx: Context) {
Expand Down Expand Up @@ -125,7 +125,7 @@ class MountController(
private fun slewRate(ctx: Context) {
val id = ctx.pathParam("id")
val mount = connectionService.mount(id) ?: return
val rate = ctx.queryParamAsString("mode").notBlank().get()
val rate = ctx.queryParamAsString("rate").notBlank().get()
mountService.slewRate(mount, mount.slewRates.first { it.name == rate })
}

Expand Down Expand Up @@ -208,7 +208,7 @@ class MountController(
private fun remoteControlStart(ctx: Context) {
val id = ctx.pathParam("id")
val mount = connectionService.mount(id) ?: return
val protocol = ctx.queryParamAsString("procotol").notBlank().get().let(MountRemoteControlProtocol::valueOf)
val protocol = ctx.queryParamAsString("protocol").notBlank().get().let(MountRemoteControlProtocol::valueOf)
val host = ctx.queryParamAsString("host").getOrDefault("0.0.0.0")
val port = ctx.queryParamAsInt("port").positive().getOrDefault(10001)
mountService.remoteControlStart(mount, protocol, host, port)
Expand All @@ -217,7 +217,7 @@ class MountController(
private fun remoteControlStop(ctx: Context) {
val id = ctx.pathParam("id")
val mount = connectionService.mount(id) ?: return
val protocol = ctx.queryParamAsString("procotol").notBlank().get().let(MountRemoteControlProtocol::valueOf)
val protocol = ctx.queryParamAsString("protocol").notBlank().get().let(MountRemoteControlProtocol::valueOf)
mountService.remoteControlStop(mount, protocol)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class PlateSolverController(
private fun start(ctx: Context) {
val path = ctx.queryParamAsPath("path").exists().get()
val solver = ctx.bodyValidator<PlateSolverRequest>().validate().get()
plateSolverService.solveImage(solver, path)
ctx.json(plateSolverService.solveImage(solver, path))
}

@Suppress("UNUSED_PARAMETER")
Expand Down
8 changes: 4 additions & 4 deletions desktop/app/window.manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,16 @@ export class WindowManager {
}
}

private createWebSocket(host: string, port: number, appWindow: ApplicationWindow) {
private createWebSocket(host: string, port: number, connected: (webSocket: WebSocket) => void) {
const webSocket = new WebSocket(`ws://${host}:${port}/ws`)

const reconnect = () => {
setTimeout(() => this.createWebSocket(host, port, appWindow), 2000)
setTimeout(() => this.createWebSocket(host, port, connected), 2000)
}

webSocket.on('open', () => {
console.info('Web Socket connected')
appWindow.webSocket = webSocket
connected(webSocket)
})

webSocket.on('message', (data: Buffer) => {
Expand Down Expand Up @@ -254,7 +254,7 @@ export class WindowManager {
const open: OpenWindow = { id: 'home', path: 'home', preference: {} }
const appWindow = await this.createWindow(open)

this.createWebSocket(host, port, appWindow)
this.createWebSocket(host, port, (webSocket) => (appWindow.webSocket = webSocket))

appWindow.apiProcess = apiProcess
}
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/app/filterwheel/filterwheel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy, Tickab

const offset = nextFocusOffset - currentFocusOffset

if (this.focuser && offset !== 0) {
if (this.focuser?.connected && offset !== 0) {
if (offset < 0) await this.api.focuserMoveIn(this.focuser, -offset)
else await this.api.focuserMoveOut(this.focuser, offset)
}
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/app/mount/mount.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@
severity="danger"
pTooltip="Stop"
tooltipPosition="bottom"
(onClick)="stopRemoteControl(item.type)" />
(onClick)="stopRemoteControl(item.protocol)" />
</div>
</div>
</ng-template>
Expand Down
18 changes: 3 additions & 15 deletions desktop/src/shared/interceptors/confirmation.interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { Observable, finalize } from 'rxjs'
import { Observable } from 'rxjs'
import { ConfirmationService } from '../services/confirmation.service'
import { IdempotencyKeyInterceptor } from './idempotency-key.interceptor'

Expand All @@ -17,20 +17,8 @@ export class ConfirmationInterceptor implements HttpInterceptor {
if (idempotencyKey) {
this.confirmationService.register(idempotencyKey)
}

const res = next.handle(req)

if (idempotencyKey) {
return res.pipe(
finalize(() => {
this.confirmationService.unregister(idempotencyKey)
}),
)
}

return res
} else {
return next.handle(req)
}

return next.handle(req)
}
}
9 changes: 2 additions & 7 deletions desktop/src/shared/services/confirmation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@ import { ApiService } from './api.service'

@Injectable({ providedIn: 'root' })
export class ConfirmationService {
private readonly keys = new Map<string, string>()
private readonly keys = new Set<string>()

constructor(
private readonly angularService: AngularService,
private readonly api: ApiService,
) {}

register(key: string) {
this.keys.set(key, '')
}

unregister(key: string) {
this.keys.delete(key)
this.keys.add(key)
}

has(key: string) {
Expand All @@ -28,6 +24,5 @@ export class ConfirmationService {
async processConfirmationEvent(event: ConfirmationEvent) {
const response = await this.angularService.confirm(event.message)
await this.api.confirm(event.idempotencyKey, response === ConfirmEventType.ACCEPT)
this.unregister(event.idempotencyKey)
}
}

0 comments on commit 20bfed7

Please sign in to comment.