Skip to content

Commit

Permalink
Merge branch 'feature/sequencer' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed Dec 15, 2023
2 parents 8adef81 + 6398889 commit f7475ee
Show file tree
Hide file tree
Showing 200 changed files with 2,828 additions and 2,231 deletions.
9 changes: 6 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ updates:
directory: "/"
schedule:
interval: "monthly"
day: "friday"
open-pull-requests-limit: 16
target-branch: "dev"
commit-message:
Expand All @@ -28,6 +27,9 @@ updates:
okhttp:
patterns:
- "com.squareup.okhttp3*"
rx:
patterns:
- "io.reactivex.rxjava3*"
jackson:
patterns:
- "com.fasterxml.jackson*"
Expand All @@ -36,7 +38,6 @@ updates:
directory: "/desktop"
schedule:
interval: "monthly"
day: "friday"
open-pull-requests-limit: 64
target-branch: "dev"
commit-message:
Expand All @@ -45,12 +46,14 @@ updates:
angular:
patterns:
- "@angular*"
types:
patterns:
- "@types*"

- package-ecosystem: "npm"
directory: "/desktop/app"
schedule:
interval: "monthly"
day: "friday"
target-branch: "dev"
commit-message:
prefix: "[desktop]"
Expand Down
4 changes: 2 additions & 2 deletions api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ plugins {
dependencies {
implementation(project(":nebulosa-astap"))
implementation(project(":nebulosa-astrometrynet"))
implementation(project(":nebulosa-batch-processing"))
implementation(project(":nebulosa-common"))
implementation(project(":nebulosa-guiding-phd2"))
implementation(project(":nebulosa-hips2fits"))
Expand All @@ -31,8 +32,8 @@ dependencies {
implementation(libs.flyway)
implementation(libs.okhttp)
implementation(libs.oshi)
implementation(libs.rx)
implementation(libs.sqlite)
implementation(libs.hikari)
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.springframework.boot:spring-boot-starter-web") {
exclude(module = "spring-boot-starter-tomcat")
Expand All @@ -41,7 +42,6 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-websocket") {
exclude(module = "spring-boot-starter-tomcat")
}
implementation("org.springframework.boot:spring-boot-starter-batch")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-undertow")
implementation("org.hibernate.orm:hibernate-community-dialects")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package nebulosa.api.alignment.polar

import nebulosa.api.alignment.polar.darv.DARVStart
import nebulosa.api.beans.annotations.EntityBy
import nebulosa.api.alignment.polar.darv.DARVStartRequest
import nebulosa.api.beans.annotations.EntityParam
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guide.GuideOutput
import org.springframework.web.bind.annotation.PutMapping
Expand All @@ -17,14 +17,14 @@ class PolarAlignmentController(

@PutMapping("darv/{camera}/{guideOutput}/start")
fun darvStart(
@EntityBy camera: Camera, @EntityBy guideOutput: GuideOutput,
@RequestBody body: DARVStart,
@EntityParam camera: Camera, @EntityParam guideOutput: GuideOutput,
@RequestBody body: DARVStartRequest,
) {
polarAlignmentService.darvStart(camera, guideOutput, body)
}

@PutMapping("darv/{camera}/{guideOutput}/stop")
fun darvStop(@EntityBy camera: Camera, @EntityBy guideOutput: GuideOutput) {
fun darvStop(@EntityParam camera: Camera, @EntityParam guideOutput: GuideOutput) {
polarAlignmentService.darvStop(camera, guideOutput)
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package nebulosa.api.alignment.polar

import nebulosa.api.alignment.polar.darv.DARVPolarAlignmentExecutor
import nebulosa.api.alignment.polar.darv.DARVStart
import nebulosa.api.alignment.polar.darv.DARVExecutor
import nebulosa.api.alignment.polar.darv.DARVStartRequest
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guide.GuideOutput
import org.springframework.stereotype.Service

@Service
class PolarAlignmentService(
private val darvPolarAlignmentExecutor: DARVPolarAlignmentExecutor,
private val darvExecutor: DARVExecutor,
) {

fun darvStart(camera: Camera, guideOutput: GuideOutput, darvStart: DARVStart) {
fun darvStart(camera: Camera, guideOutput: GuideOutput, darvStartRequest: DARVStartRequest) {
check(camera.connected) { "camera not connected" }
check(guideOutput.connected) { "guide output not connected" }
darvPolarAlignmentExecutor.execute(darvStart.copy(camera = camera, guideOutput = guideOutput))
darvExecutor.execute(darvStartRequest.copy(camera = camera, guideOutput = guideOutput))
}

fun darvStop(camera: Camera, guideOutput: GuideOutput) {
darvPolarAlignmentExecutor.stop(camera, guideOutput)
darvExecutor.stop(camera, guideOutput)
}
}
25 changes: 25 additions & 0 deletions api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVEvent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package nebulosa.api.alignment.polar.darv

import nebulosa.api.messages.MessageEvent
import nebulosa.guiding.GuideDirection
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guide.GuideOutput
import java.time.Duration

sealed interface DARVEvent : MessageEvent {

val camera: Camera

val guideOutput: GuideOutput

val remainingTime: Duration

val progress: Double

val direction: GuideDirection?

val state: DARVState

override val eventName
get() = "DARV_POLAR_ALIGNMENT_ELAPSED"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package nebulosa.api.alignment.polar.darv

import io.reactivex.rxjava3.functions.Consumer
import nebulosa.api.messages.MessageEvent
import nebulosa.api.messages.MessageService
import nebulosa.batch.processing.JobExecution
import nebulosa.batch.processing.JobLauncher
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guide.GuideOutput
import nebulosa.log.loggerFor
import org.springframework.stereotype.Component
import java.util.*

/**
* @see <a href="https://www.cloudynights.com/articles/cat/articles/darv-drift-alignment-by-robert-vice-r2760">Reference</a>
*/
@Component
class DARVExecutor(
private val jobLauncher: JobLauncher,
private val messageService: MessageService,
) : Consumer<MessageEvent> {

private val jobExecutions = LinkedList<JobExecution>()

@Synchronized
fun execute(request: DARVStartRequest) {
val camera = requireNotNull(request.camera)
val guideOutput = requireNotNull(request.guideOutput)

check(!isRunning(camera, guideOutput)) { "DARV job is already running" }

LOG.info("starting DARV job. data={}", request)

with(DARVJob(request)) {
subscribe(this@DARVExecutor)
val jobExecution = jobLauncher.launch(this)
jobExecutions.add(jobExecution)
}
}

fun findJobExecution(camera: Camera, guideOutput: GuideOutput): JobExecution? {
for (i in jobExecutions.indices.reversed()) {
val jobExecution = jobExecutions[i]
val job = jobExecution.job as DARVJob

if (!jobExecution.isDone && job.camera === camera && job.guideOutput === guideOutput) {
return jobExecution
}
}

return null
}

@Synchronized
fun stop(camera: Camera, guideOutput: GuideOutput) {
val jobExecution = findJobExecution(camera, guideOutput) ?: return
jobLauncher.stop(jobExecution)
}

fun isRunning(camera: Camera, guideOutput: GuideOutput): Boolean {
return findJobExecution(camera, guideOutput) != null
}

override fun accept(event: MessageEvent) {
messageService.sendMessage(event)
}

companion object {

@JvmStatic private val LOG = loggerFor<DARVExecutor>()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nebulosa.api.alignment.polar.darv

import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guide.GuideOutput
import java.time.Duration

data class DARVFinished(
override val camera: Camera,
override val guideOutput: GuideOutput,
) : DARVEvent {

override val remainingTime = Duration.ZERO!!
override val progress = 0.0
override val state = DARVState.IDLE
override val direction = null
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nebulosa.api.alignment.polar.darv

import nebulosa.api.messages.MessageEvent
import nebulosa.guiding.GuideDirection
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guide.GuideOutput
import java.time.Duration

data class DARVGuidePulseElapsed(
override val camera: Camera,
override val guideOutput: GuideOutput,
override val remainingTime: Duration,
override val progress: Double,
override val direction: GuideDirection,
override val state: DARVState,
) : MessageEvent, DARVEvent
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nebulosa.api.alignment.polar.darv

import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.guide.GuideOutput
import java.time.Duration

data class DARVInitialPauseElapsed(
override val camera: Camera,
override val guideOutput: GuideOutput,
override val remainingTime: Duration,
override val progress: Double,
) : DARVEvent {

override val state = DARVState.INITIAL_PAUSE
override val direction = null
}
94 changes: 94 additions & 0 deletions api/src/main/kotlin/nebulosa/api/alignment/polar/darv/DARVJob.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package nebulosa.api.alignment.polar.darv

import io.reactivex.rxjava3.subjects.PublishSubject
import nebulosa.api.cameras.CameraCaptureListener
import nebulosa.api.cameras.CameraExposureFinished
import nebulosa.api.cameras.CameraExposureStep
import nebulosa.api.cameras.CameraStartCaptureRequest
import nebulosa.api.guiding.GuidePulseListener
import nebulosa.api.guiding.GuidePulseRequest
import nebulosa.api.guiding.GuidePulseStep
import nebulosa.api.messages.MessageEvent
import nebulosa.batch.processing.*
import nebulosa.batch.processing.delay.DelayStep
import nebulosa.batch.processing.delay.DelayStepListener
import nebulosa.common.concurrency.Incrementer
import java.nio.file.Files
import java.nio.file.Path
import java.time.Duration

data class DARVJob(
val request: DARVStartRequest,
) : SimpleJob(), PublishSubscribe<MessageEvent>, CameraCaptureListener, GuidePulseListener, DelayStepListener {

@JvmField val camera = requireNotNull(request.camera)
@JvmField val guideOutput = requireNotNull(request.guideOutput)
@JvmField val direction = if (request.reversed) request.direction.reversed else request.direction

@JvmField val cameraRequest = CameraStartCaptureRequest(
camera = camera,
exposureTime = request.exposureTime + request.initialPause,
savePath = Files.createTempDirectory("darv"),
)

override val id = "DARV.Job.${ID.increment()}"

override val subject = PublishSubject.create<MessageEvent>()

init {
val cameraExposureStep = CameraExposureStep(cameraRequest)
cameraExposureStep.registerCameraCaptureListener(this)

val initialPauseDelayStep = DelayStep(request.initialPause)
initialPauseDelayStep.registerDelayStepListener(this)

val guidePulseDuration = request.exposureTime.dividedBy(2L)
val forwardGuidePulseRequest = GuidePulseRequest(guideOutput, direction, guidePulseDuration)
val forwardGuidePulseStep = GuidePulseStep(forwardGuidePulseRequest)
forwardGuidePulseStep.registerGuidePulseListener(this)

val backwardGuidePulseRequest = GuidePulseRequest(guideOutput, direction.reversed, guidePulseDuration)
val backwardGuidePulseStep = GuidePulseStep(backwardGuidePulseRequest)
backwardGuidePulseStep.registerGuidePulseListener(this)

val guideFlow = SimpleFlowStep(initialPauseDelayStep, forwardGuidePulseStep, backwardGuidePulseStep)
add(SimpleSplitStep(cameraExposureStep, guideFlow))
}

override fun beforeJob(jobExecution: JobExecution) {
onNext(DARVStarted(camera, guideOutput, request.initialPause, direction))
}

override fun afterJob(jobExecution: JobExecution) {
onNext(DARVFinished(camera, guideOutput))
}

override fun onExposureFinished(step: CameraExposureStep, stepExecution: StepExecution) {
val savePath = stepExecution.context[CameraExposureStep.SAVE_PATH] as Path
onNext(CameraExposureFinished(step.camera, 1, 1, Duration.ZERO, 1.0, Duration.ZERO, savePath))
}

override fun onGuidePulseElapsed(step: GuidePulseStep, stepExecution: StepExecution) {
val direction = step.request.direction
val remainingTime = stepExecution.context[DelayStep.REMAINING_TIME] as Duration
val progress = stepExecution.context[DelayStep.PROGRESS] as Double
val state = if (direction == this.direction) DARVState.FORWARD else DARVState.BACKWARD
onNext(DARVGuidePulseElapsed(camera, guideOutput, remainingTime, progress, direction, state))
}

override fun onDelayElapsed(step: DelayStep, stepExecution: StepExecution) {
val remainingTime = stepExecution.context[DelayStep.REMAINING_TIME] as Duration
val progress = stepExecution.context[DelayStep.PROGRESS] as Double
onNext(DARVInitialPauseElapsed(camera, guideOutput, remainingTime, progress))
}

override fun stop(mayInterruptIfRunning: Boolean) {
super.stop(mayInterruptIfRunning)
close()
}

companion object {

@JvmStatic private val ID = Incrementer()
}
}

This file was deleted.

Loading

0 comments on commit f7475ee

Please sign in to comment.