Skip to content

Commit

Permalink
[api][desktop]: Add Rotator on Sequencer
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed Jun 7, 2024
1 parent 9ec66ec commit 302c7ab
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.camera.CameraEvent
import nebulosa.indi.device.camera.FrameType
import nebulosa.indi.device.guide.GuideOutput
import nebulosa.indi.device.mount.Mount
import nebulosa.log.loggerFor
import java.nio.file.Files
import java.time.Duration
Expand Down Expand Up @@ -64,7 +65,7 @@ data class DARVTask(
override fun execute(cancellationToken: CancellationToken) {
LOG.info("DARV started. camera={}, guideOutput={}, request={}", camera, guideOutput, request)

camera.snoop(listOf(guideOutput))
if (guideOutput is Mount) camera.snoop(camera.snoopedDevices.filter { it !is Mount } + guideOutput)

val task = SplitTask(listOf(cameraCaptureTask, Task.of(delayTask, forwardGuidePulseTask, backwardGuidePulseTask)), executor)
task.execute(cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ data class TPPATask(
rightAscension = mount?.rightAscension ?: 0.0
declination = mount?.declination ?: 0.0

camera.snoop(listOf(mount))
camera.snoop(camera.snoopedDevices.filter { it !is Mount } + mount)

cancellationToken.listenToPause(this)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ data class AutoFocusTask(
var numberOfAttempts = 0
val maximumFocusPoints = request.capture.exposureAmount * request.initialOffsetSteps * 10

// camera.snoop(listOf(focuser))
camera.snoop(camera.snoopedDevices.filter { it !is Focuser } + focuser)

while (!exited && !cancellationToken.isCancelled) {
numberOfAttempts++
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.filterwheel.FilterWheel
import nebulosa.indi.device.focuser.Focuser
import nebulosa.indi.device.mount.Mount
import nebulosa.indi.device.rotator.Rotator
import org.springframework.web.bind.annotation.*

@RestController
Expand All @@ -16,9 +17,9 @@ class SequencerController(
@PutMapping("{camera}/start")
fun start(
camera: Camera,
mount: Mount?, wheel: FilterWheel?, focuser: Focuser?,
mount: Mount?, wheel: FilterWheel?, focuser: Focuser?, rotator: Rotator?,
@RequestBody @Valid body: SequencePlanRequest,
) = sequencerService.start(camera, body, mount, wheel, focuser)
) = sequencerService.start(camera, body, mount, wheel, focuser, rotator)

@PutMapping("{camera}/stop")
fun stop(camera: Camera) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import nebulosa.indi.device.filterwheel.FilterWheelEvent
import nebulosa.indi.device.focuser.Focuser
import nebulosa.indi.device.focuser.FocuserEvent
import nebulosa.indi.device.mount.Mount
import nebulosa.indi.device.rotator.Rotator
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor
Expand Down Expand Up @@ -54,7 +55,7 @@ class SequencerExecutor(

fun execute(
camera: Camera, request: SequencePlanRequest,
mount: Mount? = null, wheel: FilterWheel? = null, focuser: Focuser? = null,
mount: Mount? = null, wheel: FilterWheel? = null, focuser: Focuser? = null, rotator: Rotator? = null,
) {
check(camera.connected) { "${camera.name} Camera is not connected" }
check(jobs.none { it.task.camera === camera }) { "${camera.name} Sequencer Job is already in progress" }
Expand All @@ -67,7 +68,11 @@ class SequencerExecutor(
check(jobs.none { it.task.focuser === focuser }) { "${camera.name} Sequencer Job is already in progress" }
}

val task = SequencerTask(camera, request, guider, mount, wheel, focuser, threadPoolTaskExecutor, calibrationFrameService)
if (rotator != null && rotator.connected) {
check(jobs.none { it.task.rotator === rotator }) { "${camera.name} Sequencer Job is already in progress" }
}

val task = SequencerTask(camera, request, guider, mount, wheel, focuser, rotator, threadPoolTaskExecutor, calibrationFrameService)
task.subscribe(this)

with(SequencerJob(task)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.filterwheel.FilterWheel
import nebulosa.indi.device.focuser.Focuser
import nebulosa.indi.device.mount.Mount
import nebulosa.indi.device.rotator.Rotator
import org.springframework.stereotype.Service
import java.nio.file.Path
import kotlin.io.path.exists
Expand All @@ -18,13 +19,13 @@ class SequencerService(
@Synchronized
fun start(
camera: Camera, request: SequencePlanRequest,
mount: Mount?, wheel: FilterWheel?, focuser: Focuser?,
mount: Mount?, wheel: FilterWheel?, focuser: Focuser?, rotator: Rotator?,
) {
val savePath = request.savePath
?.takeIf { "$it".isNotBlank() && it.exists() && it.isDirectory() }
?: Path.of("$sequencesPath", (System.currentTimeMillis() / 1000).toString())

sequencerExecutor.execute(camera, request.copy(savePath = savePath), mount, wheel, focuser)
sequencerExecutor.execute(camera, request.copy(savePath = savePath), mount, wheel, focuser, rotator)
}

@Synchronized
Expand Down
4 changes: 3 additions & 1 deletion api/src/main/kotlin/nebulosa/api/sequencer/SequencerTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import nebulosa.indi.device.filterwheel.FilterWheel
import nebulosa.indi.device.filterwheel.FilterWheelEvent
import nebulosa.indi.device.focuser.Focuser
import nebulosa.indi.device.mount.Mount
import nebulosa.indi.device.rotator.Rotator
import nebulosa.log.loggerFor
import java.time.Duration
import java.util.*
Expand All @@ -37,6 +38,7 @@ data class SequencerTask(
@JvmField val mount: Mount? = null,
@JvmField val wheel: FilterWheel? = null,
@JvmField val focuser: Focuser? = null,
@JvmField val rotator: Rotator? = null,
private val executor: Executor? = null,
private val calibrationFrameProvider: CalibrationFrameProvider? = null,
) : AbstractTask<MessageEvent>(), Consumer<Any>, CameraEventAware, WheelEventAware {
Expand Down Expand Up @@ -131,7 +133,7 @@ data class SequencerTask(
override fun execute(cancellationToken: CancellationToken) {
LOG.info("Sequencer started. camera={}, mount={}, wheel={}, focuser={}, plan={}", camera, mount, wheel, focuser, plan)

camera.snoop(listOf(mount, wheel, focuser))
camera.snoop(listOf(mount, wheel, focuser, rotator))

for (task in tasks) {
if (cancellationToken.isCancelled) break
Expand Down
11 changes: 4 additions & 7 deletions desktop/src/app/sequencer/sequencer.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,8 @@
<i *ngIf="plan.autoSubFolderMode === 'MIDNIGHT'" (click)="toggleAutoSubFolder()"
class="mdi mdi-weather-night text-blue-600 cursor-pointer" pTooltip="Auto sub folder: MIDNIGHT" tooltipPosition="bottom"
[positionTop]="8"></i>

<span class="p-float-label">
<input pInputText [disabled]="running" class="p-inputtext-sm border-0 w-full" [(ngModel)]="plan.savePath"
(ngModelChange)="savePlan()" />
<label>Path</label>
</span>
<p-button [disabled]="running" icon="mdi mdi-folder-open" size="small" (onClick)="chooseSavePath()" />
<neb-path-chooser key="SEQUENCER_SAVE_PATH" [directory]="true" [(path)]="plan.savePath" (pathChange)="savePlan()"
class="w-full" />
</div>
</div>
</p-tabPanel>
Expand Down Expand Up @@ -144,6 +139,8 @@
(deviceChange)="wheelChanged()" />
<neb-device-chooser title="FOCUSER" icon="mdi mdi-image-filter-center-focus" [devices]="focusers" [(device)]="focuser"
[hasNone]="true" (deviceChange)="focuserChanged()" />
<neb-device-chooser title="ROTATOR" icon="mdi mdi-rotate-right" [devices]="rotators" [(device)]="rotator"
[hasNone]="true" (deviceChange)="rotatorChanged()" />
</div>
</div>
<div class="grid mt-0">
Expand Down
74 changes: 43 additions & 31 deletions desktop/src/app/sequencer/sequencer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { JsonFile } from '../../shared/types/app.types'
import { Camera, CameraCaptureEvent, CameraStartCapture } from '../../shared/types/camera.types'
import { Focuser } from '../../shared/types/focuser.types'
import { Mount } from '../../shared/types/mount.types'
import { Rotator } from '../../shared/types/rotator.types'
import { EMPTY_SEQUENCE_PLAN, SEQUENCE_ENTRY_PROPERTIES, SequenceCaptureMode, SequenceEntryProperty, SequencePlan, SequencerEvent } from '../../shared/types/sequencer.types'
import { FilterWheel } from '../../shared/types/wheel.types'
import { deviceComparator } from '../../shared/utils/comparators'
Expand All @@ -34,11 +35,13 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable
mounts: Mount[] = []
wheels: FilterWheel[] = []
focusers: Focuser[] = []
rotators: Rotator[] = []

camera?: Camera
mount?: Mount
wheel?: FilterWheel
focuser?: Focuser
rotator?: Rotator

readonly captureModes: SequenceCaptureMode[] = ['FULLY', 'INTERLEAVED']
readonly plan = structuredClone(EMPTY_SEQUENCE_PLAN)
Expand Down Expand Up @@ -177,43 +180,53 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable
})

electron.on('CAMERA.UPDATED', event => {
ngZone.run(() => {
const camera = this.cameras.find(e => e.id === event.device.id)
const camera = this.cameras.find(e => e.id === event.device.id)

if (camera) {
if (camera) {
ngZone.run(() => {
Object.assign(camera, event.device)
}
})
})
}
})

electron.on('MOUNT.UPDATED', event => {
ngZone.run(() => {
const mount = this.mounts.find(e => e.id === event.device.id)
const mount = this.mounts.find(e => e.id === event.device.id)

if (mount) {
if (mount) {
ngZone.run(() => {
Object.assign(mount, event.device)
}
})
})
}
})

electron.on('WHEEL.UPDATED', event => {
ngZone.run(() => {
const wheel = this.wheels.find(e => e.id === event.device.id)
const wheel = this.wheels.find(e => e.id === event.device.id)

if (wheel) {
if (wheel) {
ngZone.run(() => {
Object.assign(wheel, event.device)
}
})
})
}
})

electron.on('FOCUSER.UPDATED', event => {
ngZone.run(() => {
const focuser = this.focusers.find(e => e.id === event.device.id)
const focuser = this.focusers.find(e => e.id === event.device.id)

if (focuser) {
if (focuser) {
ngZone.run(() => {
Object.assign(focuser, event.device)
}
})
})
}
})

electron.on('ROTATOR.UPDATED', event => {
const rotator = this.rotators.find(e => e.id === event.device.id)

if (rotator) {
ngZone.run(() => {
Object.assign(rotator, event.device)
})
}
})

electron.on('SEQUENCER.ELAPSED', event => {
Expand Down Expand Up @@ -246,6 +259,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable
this.mounts = (await this.api.mounts()).sort(deviceComparator)
this.wheels = (await this.api.wheels()).sort(deviceComparator)
this.focusers = (await this.api.focusers()).sort(deviceComparator)
this.rotators = (await this.api.rotators()).sort(deviceComparator)

this.loadSavedJsonFileFromPathOrAddDefault()

Expand All @@ -262,6 +276,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable
if (this.mount) this.api.mountListen(this.mount)
if (this.focuser) this.api.focuserListen(this.focuser)
if (this.wheel) this.api.wheelListen(this.wheel)
if (this.rotator) this.api.rotatorListen(this.rotator)
}

private enableOrDisableTopbarMenu(enable: boolean) {
Expand All @@ -272,6 +287,7 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable
const camera = this.camera ?? this.cameras[0]
// const wheel = this.wheel ?? this.wheels[0]
// const focuser = this.focuser ?? this.focusers[0]
// const rotator = this.rotator ?? this.rotators[0]

this.plan.entries.push({
enabled: true,
Expand Down Expand Up @@ -356,8 +372,9 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable

this.camera = this.cameras.find(e => e.name === this.plan.camera?.name) ?? this.cameras[0]
this.mount = this.mounts.find(e => e.name === this.plan.mount?.name) ?? this.mounts[0]
this.focuser = this.focusers.find(e => e.name === this.plan.focuser?.name) ?? this.focusers[0]
this.wheel = this.wheels.find(e => e.name === this.plan.wheel?.name) ?? this.wheels[0]
this.focuser = this.focusers.find(e => e.name === this.plan.focuser?.name) ?? this.focusers[0]
this.rotator = this.rotators.find(e => e.name === this.plan.rotator?.name) ?? this.rotators[0]

return plan.entries.length
}
Expand All @@ -377,16 +394,6 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable
}
}

async chooseSavePath() {
const defaultPath = this.plan.savePath
const path = await this.electron.openDirectory({ defaultPath })

if (path) {
this.plan.savePath = path
this.savePlan()
}
}

async showCameraDialog(entry: CameraStartCapture) {
if (await CameraComponent.showAsDialog(this.browserWindow, 'SEQUENCER', this.camera!, entry)) {
this.savePlan()
Expand Down Expand Up @@ -415,11 +422,16 @@ export class SequencerComponent implements AfterContentInit, OnDestroy, Pingable
this.ping()
}

rotatorChanged() {
this.ping()
}

savePlan() {
this.plan.camera = this.camera
this.plan.mount = this.mount
this.plan.wheel = this.wheel
this.plan.focuser = this.focuser
this.plan.rotator = this.rotator
this.storage.set(SEQUENCER_PLAN_KEY, this.plan)
this.savedPathWasModified = !!this.savedPath
}
Expand Down
2 changes: 2 additions & 0 deletions desktop/src/shared/types/sequencer.types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AutoSubFolderMode, Camera, CameraCaptureEvent, CameraStartCapture, Dither } from './camera.types'
import { Focuser } from './focuser.types'
import { Mount } from './mount.types'
import { Rotator } from './rotator.types'
import { FilterWheel } from './wheel.types'

export type SequenceCaptureMode = 'FULLY' | 'INTERLEAVED'
Expand Down Expand Up @@ -39,6 +40,7 @@ export interface SequencePlan {
mount?: Mount
wheel?: FilterWheel
focuser?: Focuser
rotator?: Rotator
}

export const EMPTY_SEQUENCE_PLAN: SequencePlan = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ data class PixInsightDetectStars(
@JvmField val stars: List<Star> = emptyList(),
) {

override fun toString() = "Output(success=$success, errorMessage=$errorMessage, stars=${stars.size})"

companion object {

@JvmStatic val FAILED = Output()
Expand Down

0 comments on commit 302c7ab

Please sign in to comment.