Skip to content

Commit

Permalink
[api][desktop]: Finish TPPA Job refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed Oct 7, 2024
1 parent 25f16d0 commit 3be0ea6
Show file tree
Hide file tree
Showing 16 changed files with 113 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ data class TPPAEvent(
@JvmField var azimuthErrorDirection: String = "",
@JvmField var altitudeErrorDirection: String = "",
@JvmField @field:JsonIgnoreProperties("camera") val capture: CameraCaptureEvent = CameraCaptureEvent(camera),
@JvmField var pausing: Boolean = false,
) : MessageEvent {

override val eventName = "TPPA.ELAPSED"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import nebulosa.api.beans.annotations.Subscriber
import nebulosa.api.cameras.CameraEventAware
import nebulosa.api.message.MessageEvent
import nebulosa.api.message.MessageService
import nebulosa.api.mounts.MountEventAware
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.camera.CameraEvent
import nebulosa.indi.device.mount.Mount
import nebulosa.indi.device.mount.MountEvent
import okhttp3.OkHttpClient
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
Expand All @@ -21,7 +23,7 @@ class TPPAExecutor(
private val messageService: MessageService,
private val httpClient: OkHttpClient,
private val threadPoolTaskExecutor: ThreadPoolTaskExecutor,
) : Consumer<MessageEvent>, CameraEventAware {
) : Consumer<MessageEvent>, CameraEventAware, MountEventAware {

private val jobs = ConcurrentHashMap.newKeySet<TPPAJob>(1)

Expand All @@ -34,6 +36,11 @@ class TPPAExecutor(
jobs.find { it.camera === event.device }?.handleCameraEvent(event)
}

@Subscribe(threadMode = ThreadMode.ASYNC)
override fun handleMountEvent(event: MountEvent) {
jobs.find { it.mount === event.device }?.handleMountEvent(event)
}

@Synchronized
fun execute(camera: Camera, mount: Mount, request: TPPAStartRequest) {
check(camera.connected) { "${camera.name} Camera is not connected" }
Expand Down
37 changes: 23 additions & 14 deletions api/src/main/kotlin/nebulosa/api/alignment/polar/tppa/TPPAJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ package nebulosa.api.alignment.polar.tppa

import nebulosa.alignment.polar.point.three.ThreePointPolarAlignment
import nebulosa.alignment.polar.point.three.ThreePointPolarAlignmentResult
import nebulosa.api.cameras.AutoSubFolderMode
import nebulosa.api.cameras.CameraEventAware
import nebulosa.api.cameras.CameraExposureEvent
import nebulosa.api.cameras.CameraExposureFinished
import nebulosa.api.cameras.CameraExposureTask
import nebulosa.api.cameras.*
import nebulosa.api.message.MessageEvent
import nebulosa.api.mounts.MountEventAware
import nebulosa.api.mounts.MountMoveRequest
Expand All @@ -20,8 +16,8 @@ import nebulosa.indi.device.mount.MountEvent
import nebulosa.job.manager.AbstractJob
import nebulosa.job.manager.Task
import nebulosa.job.manager.delay.DelayEvent
import nebulosa.job.manager.delay.DelayStarted
import nebulosa.job.manager.delay.DelayTask
import nebulosa.log.debug
import nebulosa.log.loggerFor
import nebulosa.math.Angle
import nebulosa.math.formatSignedDMS
Expand Down Expand Up @@ -127,24 +123,25 @@ data class TPPAJob(

override fun onPause(paused: Boolean) {
if (paused) {
status.pausing = true
status.state = TPPAState.PAUSING
status.send()
}

super.onPause(paused)
}

override fun beforePause(task: Task) {
status.pausing = false
status.state = TPPAState.PAUSED
status.send()
}

override fun accept(event: Any) {
status.capture.captureElapsedTime = stopwatch.elapsedMicroseconds

when (event) {
is CameraExposureEvent -> {
if (event is CameraExposureStarted) {
status.capture.captureElapsedTime = stopwatch.elapsedMicroseconds
}

status.capture.handleCameraExposureEvent(event)

if (event is CameraExposureFinished) {
Expand All @@ -154,10 +151,19 @@ data class TPPAJob(
status.send()
}
is DelayEvent -> {
if (event is DelayStarted) {
status.capture.captureElapsedTime = stopwatch.elapsedMicroseconds
}

status.capture.handleCameraDelayEvent(event)

if (event.task === settleDelayTask) {
status.state = TPPAState.SETTLING
status.send()
} else if (event.task === mountMoveTask.delayTask) {
status.state = TPPAState.SLEWING
}

status.send()
}
is ThreePointPolarAlignmentResult.NeedMoreMeasurement -> {
noSolutionAttempts = 0
Expand Down Expand Up @@ -198,7 +204,10 @@ data class TPPAJob(
else -> ""
}

LOG.debug { "TPPA aligned. azimuthError=${status.azimuthError.formatSignedDMS()}, altitudeError=${status.altitudeError.formatSignedDMS()}" }
LOG.debug(
"TPPA aligned. azimuthError={}, altitudeError={}",
status.azimuthError.formatSignedDMS(), status.altitudeError.formatSignedDMS()
)

status.state = TPPAState.COMPUTED
status.send()
Expand All @@ -207,7 +216,7 @@ data class TPPAJob(
}

override fun beforeStart() {
LOG.debug { "TPPA started. longitude=$longitude, latitude=$latitude, camera=$camera, mount=$mount, request=$request" }
LOG.debug("TPPA started. longitude={}, latitude={}, camera={}, mount={}, request={}", longitude, latitude, camera, mount, request)

status.rightAscension = mount.rightAscension
status.declination = mount.declination
Expand All @@ -216,7 +225,7 @@ data class TPPAJob(
}

override fun afterFinish() {
LOG.debug { "TPPA finished. camera=$camera, mount=$mount, request=$request" }
LOG.debug("TPPA finished. camera={}, mount={}, request={}", camera, mount, request)

stopwatch.stop()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ class BeanConfiguration {
@Bean
fun alpacaHttpClient(connectionPool: ConnectionPool) = OkHttpClient.Builder()
.connectionPool(connectionPool)
.readTimeout(60L, TimeUnit.SECONDS)
.writeTimeout(60L, TimeUnit.SECONDS)
.connectTimeout(60L, TimeUnit.SECONDS)
.callTimeout(60L, TimeUnit.SECONDS)
.readTimeout(90L, TimeUnit.SECONDS)
.writeTimeout(90L, TimeUnit.SECONDS)
.connectTimeout(90L, TimeUnit.SECONDS)
.callTimeout(90L, TimeUnit.SECONDS)
.build()

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ data class CameraCaptureEvent(

@Suppress("NOTHING_TO_INLINE")
private inline fun computeCaptureProgress() {
if (captureElapsedTime > 0L) {
if (captureElapsedTime > 0L && captureRemainingTime >= 0L) {
captureProgress = captureElapsedTime.toDouble() / (captureElapsedTime + captureRemainingTime)
}
}
Expand Down
8 changes: 8 additions & 0 deletions api/src/main/kotlin/nebulosa/api/mounts/MountTrackTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import nebulosa.indi.device.mount.MountEvent
import nebulosa.indi.device.mount.MountTrackingChanged
import nebulosa.job.manager.Job
import nebulosa.job.manager.Task
import nebulosa.log.loggerFor
import nebulosa.util.concurrency.latch.CountUpDownLatch

data class MountTrackTask(
Expand All @@ -23,9 +24,16 @@ data class MountTrackTask(

override fun run() {
if (mount.connected && mount.tracking != enabled) {
LOG.debug("Mount Track started. mount={}, enabled={}", mount, enabled)
trackingLatch.countUp()
mount.tracking(enabled)
trackingLatch.await()
LOG.debug("Mount Track finished. mount={}, enabled={}", mount, enabled)
}
}

companion object {

@JvmStatic private val LOG = loggerFor<MountTrackTask>()
}
}
51 changes: 39 additions & 12 deletions desktop/src/app/alignment/alignment.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
</div>
</div>
</div>
<div class="grid">
<div class="grid relative">
<div class="col-12">
<p-tabView [(activeIndex)]="tab">
<p-tabPanel header="TPPA">
Expand Down Expand Up @@ -262,19 +262,46 @@
[text]="true" />
</div>
</div>
<div class="grid mt-1">
<div class="col-12 flex-column justify-content-center text-sm overflow-y-auto max-h-8rem p-0">
<span>1. Locate a star near the south meridian and close to declination 0.</span>
<span>2. Start DARV and wait for routine to complete.</span>
<span>3. If you see V shaped track, adjust the Azimuth and repeat the step 2 till you get a line.</span>
<span>4. Locate a star in the eastern or western horizon and close to declination 0.</span>
<span>5. Start DARV and wait for routine to complete.</span>
<span>6. If you see V shaped track, adjust the Altitude and repeat the step 5 till you get a line.</span>
<span>7. Increase the drift time and repeat the step 1 to refine the alignment.</span>
</div>
</div>
</p-tabPanel>
</p-tabView>
</div>
<p-button
[text]="true"
severity="info"
icon="mdi mdi-information"
styleClass="absolute"
[style]="{ right: '8px', top: '5px' }"
(onClick)="tab === 0 ? tppaInfo.toggle($event) : darvInfo.toggle($event)" />

<p-overlayPanel
#tppaInfo
[focusOnShow]="false"
appendTo="body"
[style]="{ maxWidth: '91vw' }">
<div class="grid text-sm">
<div class="col-12 flex-column justify-content-center px-0">
<span>1. Choose step duration and speed so that the step size is at least 30 arcmin.</span>
<span>2. Start TPPA and wait for the azimuth/altitude errors to be displayed.</span>
<span>3. Repeatedly adjust the Azimuth/Altitude until their values get close to 0.</span>
</div>
</div>
</p-overlayPanel>
<p-overlayPanel
#darvInfo
[focusOnShow]="false"
appendTo="body"
[style]="{ maxWidth: '91vw' }">
<div class="grid text-sm">
<div class="col-12 flex-column justify-content-center px-0">
<span>1. Locate a star near the south meridian and close to declination 0.</span>
<span>2. Start DARV and wait for routine to complete.</span>
<span>3. If you see V shaped track, adjust the Azimuth and repeat the step 2 till you get a line.</span>
<span>4. Locate a star in the eastern or western horizon and close to declination 0.</span>
<span>5. Start DARV and wait for routine to complete.</span>
<span>6. If you see V shaped track, adjust the Altitude and repeat the step 5 till you get a line.</span>
<span>7. Increase the drift time and repeat the step 1 to refine the alignment.</span>
</div>
</div>
</p-overlayPanel>
</div>
</div>
2 changes: 1 addition & 1 deletion desktop/src/app/alignment/alignment.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ export class AlignmentComponent implements AfterViewInit, OnDestroy, Tickable {
this.method = 'DARV'
this.darvRequest.direction = direction
this.darvRequest.reversed = this.preference.darvHemisphere === 'SOUTHERN'
Object.assign(this.tppaRequest.plateSolver, this.preferenceService.settings.get().plateSolver[this.tppaRequest.plateSolver.type])

await this.openCameraImage()
await this.api.darvStart(this.camera, this.guideOutput, this.darvRequest)
Expand All @@ -290,6 +289,7 @@ export class AlignmentComponent implements AfterViewInit, OnDestroy, Tickable {
protected async tppaStart() {
if (this.camera?.id && this.mount?.id) {
this.method = 'TPPA'
Object.assign(this.tppaRequest.plateSolver, this.preferenceService.settings.get().plateSolver[this.tppaRequest.plateSolver.type])

await this.openCameraImage()
await this.api.tppaStart(this.camera, this.mount, this.tppaRequest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package nebulosa.alpaca.api

import com.fasterxml.jackson.annotation.JsonFormat
import com.fasterxml.jackson.annotation.JsonProperty
import java.time.LocalDateTime
import java.time.OffsetDateTime

data class DateTimeResponse(
@field:JsonProperty("ClientTransactionID") override val clientTransactionID: Int = 0,
@field:JsonProperty("ServerTransactionID") override val serverTransactionID: Int = 0,
@field:JsonProperty("ErrorNumber") override val errorNumber: Int = 0,
@field:JsonProperty("ErrorMessage") override val errorMessage: String = "",
@field:JsonProperty("Value") @field:JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS]")
override val value: LocalDateTime = LocalDateTime.now(),
) : AlpacaResponse<LocalDateTime>
@field:JsonProperty("Value") @field:JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSS][XXX]")
override val value: OffsetDateTime = OffsetDateTime.MIN,
) : AlpacaResponse<OffsetDateTime>
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import nebulosa.alpaca.api.AlpacaResponse
import nebulosa.alpaca.api.ConfiguredDevice
import nebulosa.alpaca.indi.client.AlpacaClient
import nebulosa.indi.device.*
import nebulosa.log.debug
import nebulosa.log.loggerFor
import nebulosa.time.SystemClock
import nebulosa.util.Resettable
import nebulosa.util.time.Stopwatch
import retrofit2.Call
Expand Down Expand Up @@ -90,20 +90,19 @@ abstract class ASCOMDevice : Device, Resettable {
val body = response.body()

return if (body == null) {
LOG.debug { "response has no body. device=%s, request=%s %s, response=%s".format(name, request.method, request.url, response) }
LOG.debug("response has no body. device={}, request={} {}, response={}", name, request.method, request.url, response)
null
} else if (body.errorNumber != 0) {
val message = body.errorMessage

if (message.isNotEmpty()) {
addMessageAndFireEvent("[%s]: %s".format(LocalDateTime.now(), message))
addMessageAndFireEvent("[%s]: %s".format(LocalDateTime.now(SystemClock), message))
}

LOG.debug {
"unsuccessful response. device=%s, request=%s %s, errorNumber=%s, message=%s".format(
name, request.method, request.url, body.errorNumber, body.errorMessage
)
}
LOG.debug(
"unsuccessful response. device={}, request={} {}, errorNumber={}, message={}",
name, request.method, request.url, body.errorNumber, body.errorMessage
)

null
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ data class ASCOMMount(

private fun processDateTime() {
service.utcDate(device.number).doRequest {
dateTime = it.value.atOffset(ZoneOffset.UTC)
dateTime = it.value
sender.fireOnEventReceived(MountTimeChanged(this))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ class NovaAstrometryNetService(

fun login(apiKey: String): Call<Session> {
return FormBody.Builder()
.add("request-json", jsonMapper.writeValueAsString(mapOf("apikey" to apiKey)))
.add("request-json", objectMapper.writeValueAsString(mapOf("apikey" to apiKey)))
.build()
.let(service::login)
}

fun uploadFromUrl(upload: Upload): Call<Submission> {
return FormBody.Builder()
.add("request-json", jsonMapper.writeValueAsString(upload))
.add("request-json", objectMapper.writeValueAsString(upload))
.build()
.let(service::uploadFromUrl)
}

fun uploadFromFile(path: Path, upload: Upload): Call<Submission> {
val requestJsonBody = jsonMapper.writeValueAsBytes(upload).toRequestBody(TEXT_PLAIN_MEDIA_TYPE)
val requestJsonBody = objectMapper.writeValueAsBytes(upload).toRequestBody(TEXT_PLAIN_MEDIA_TYPE)

val fileName = "%s.%s".format(UUID.randomUUID(), path.extension)
val fileBody = path.toFile().asRequestBody(OCTET_STREAM_MEDIA_TYPE)
Expand All @@ -54,7 +54,7 @@ class NovaAstrometryNetService(
}

fun uploadFromImage(image: Image, upload: Upload): Call<Submission> {
val requestJsonBody = jsonMapper.writeValueAsBytes(upload).toRequestBody(TEXT_PLAIN_MEDIA_TYPE)
val requestJsonBody = objectMapper.writeValueAsBytes(upload).toRequestBody(TEXT_PLAIN_MEDIA_TYPE)

val fileName = "%s.fits".format(UUID.randomUUID())
val fileBody = object : RequestBody() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import nebulosa.indi.protocol.DefVector.Companion.isNotReadOnly
import nebulosa.indi.protocol.Vector.Companion.isBusy
import nebulosa.math.*
import nebulosa.nova.position.ICRF
import nebulosa.time.SystemClock
import java.time.Duration
import java.time.OffsetDateTime
import java.time.ZoneOffset
Expand Down Expand Up @@ -56,7 +57,7 @@ internal open class INDIMount(
@Volatile final override var longitude = 0.0
@Volatile final override var latitude = 0.0
@Volatile final override var elevation = 0.0
@Volatile final override var dateTime = OffsetDateTime.now()!!
@Volatile final override var dateTime = OffsetDateTime.now(SystemClock)!!

override fun handleMessage(message: INDIProtocol) {
when (message) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class INDIXmlInputStream(source: InputStream) : INDIInputStream {
private fun parseDefSwitch(): DefSwitch {
val defSwitch = DefSwitch()
defSwitch.parseDefElement()
defSwitch.value = reader.elementText.trim().equals("On", true)
defSwitch.value = reader.elementText.contains("On", true)
return defSwitch
}

Expand Down
Loading

0 comments on commit 3be0ea6

Please sign in to comment.