Skip to content

Commit

Permalink
[api][desktop]: Focuser
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed Jul 27, 2023
1 parent 63a8b99 commit 58469dc
Show file tree
Hide file tree
Showing 23 changed files with 614 additions and 64 deletions.
19 changes: 10 additions & 9 deletions api/src/main/kotlin/nebulosa/api/controllers/CameraController.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package nebulosa.api.controllers

import jakarta.validation.Valid
import jakarta.validation.constraints.NotBlank
import nebulosa.api.data.requests.CameraStartCaptureRequest
import nebulosa.api.data.responses.CameraResponse
import nebulosa.api.services.CameraService
import org.hibernate.validator.constraints.Range
import org.springframework.web.bind.annotation.*
import java.util.*

@RestController
class CameraController(
Expand All @@ -18,42 +19,42 @@ class CameraController(
}

@GetMapping("camera")
fun camera(@RequestParam name: String): CameraResponse {
fun camera(@RequestParam @Valid @NotBlank name: String): CameraResponse {
return cameraService[name]
}

@PostMapping("cameraConnect")
fun connect(@RequestParam name: String) {
fun connect(@RequestParam @Valid @NotBlank name: String) {
cameraService.connect(name)
}

@PostMapping("cameraDisconnect")
fun disconnect(@RequestParam name: String) {
fun disconnect(@RequestParam @Valid @NotBlank name: String) {
cameraService.disconnect(name)
}

@GetMapping("cameraIsCapturing")
fun isCapturing(@RequestParam name: String): Boolean {
fun isCapturing(@RequestParam @Valid @NotBlank name: String): Boolean {
return cameraService.isCapturing(name)
}

@PostMapping("cameraSetpointTemperature")
fun setpointTemperature(@RequestParam name: String, @RequestParam temperature: Double) {
fun setpointTemperature(@RequestParam @Valid @NotBlank name: String, @RequestParam @Valid @Range(min = -50, max = 50) temperature: Double) {
cameraService.setpointTemperature(name, temperature)
}

@PostMapping("cameraCooler")
fun cooler(@RequestParam name: String, @RequestParam value: Boolean) {
fun cooler(@RequestParam @Valid @NotBlank name: String, @RequestParam value: Boolean) {
cameraService.cooler(name, value)
}

@PostMapping("cameraStartCapture")
fun startCapture(@RequestParam name: String, @RequestBody @Valid body: CameraStartCaptureRequest) {
fun startCapture(@RequestParam @Valid @NotBlank name: String, @RequestBody @Valid body: CameraStartCaptureRequest) {
cameraService.startCapture(name, body)
}

@PostMapping("cameraAbortCapture")
fun abortCapture(@RequestParam name: String) {
fun abortCapture(@RequestParam @Valid @NotBlank name: String) {
cameraService.abortCapture(name)
}
}
74 changes: 74 additions & 0 deletions api/src/main/kotlin/nebulosa/api/controllers/FocuserController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package nebulosa.api.controllers

import jakarta.validation.Valid
import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.PositiveOrZero
import nebulosa.api.data.responses.FocuserResponse
import nebulosa.api.services.FocuserService
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
class FocuserController(
private val focuserService: FocuserService,
) {

@GetMapping("attachedFocusers")
fun attachedFocusers(): List<FocuserResponse> {
return focuserService.attachedFocusers()
}

@GetMapping("focuser")
fun focuser(@RequestParam @Valid @NotBlank name: String): FocuserResponse {
return focuserService[name]
}

@PostMapping("focuserConnect")
fun connect(@RequestParam @Valid @NotBlank name: String) {
focuserService.connect(name)
}

@PostMapping("focuserDisconnect")
fun disconnect(@RequestParam @Valid @NotBlank name: String) {
focuserService.disconnect(name)
}

@PostMapping("focuserMoveIn")
fun moveIn(
@RequestParam @Valid @NotBlank name: String,
@RequestParam @Valid @PositiveOrZero steps: Int,
) {
focuserService.moveIn(name, steps)
}

@PostMapping("focuserMoveOut")
fun moveOut(
@RequestParam @Valid @NotBlank name: String,
@RequestParam @Valid @PositiveOrZero steps: Int,
) {
focuserService.moveOut(name, steps)
}

@PostMapping("focuserMoveTo")
fun moveTo(
@RequestParam @Valid @NotBlank name: String,
@RequestParam @Valid @PositiveOrZero steps: Int,
) {
focuserService.moveTo(name, steps)
}

@PostMapping("focuserAbort")
fun abort(@RequestParam @Valid @NotBlank name: String) {
focuserService.abort(name)
}

@PostMapping("focuserSyncTo")
fun syncTo(
@RequestParam @Valid @NotBlank name: String,
@RequestParam @Valid @PositiveOrZero steps: Int,
) {
focuserService.syncTo(name, steps)
}
}
38 changes: 38 additions & 0 deletions api/src/main/kotlin/nebulosa/api/data/responses/FocuserResponse.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package nebulosa.api.data.responses

import nebulosa.indi.device.focuser.Focuser

data class FocuserResponse(
val name: String,
val connected: Boolean,
val moving: Boolean,
val position: Int,
val canAbsoluteMove: Boolean,
val canRelativeMove: Boolean,
val canAbort: Boolean,
val canReverse: Boolean,
val reverse: Boolean,
val canSync: Boolean,
val hasBackslash: Boolean,
val maxPosition: Int,
val hasThermometer: Boolean,
val temperature: Double,
) {

constructor(focuser: Focuser) : this(
focuser.name,
focuser.connected,
focuser.moving,
focuser.position,
focuser.canAbsoluteMove,
focuser.canRelativeMove,
focuser.canAbort,
focuser.canReverse,
focuser.reverse,
focuser.canSync,
focuser.hasBackslash,
focuser.maxPosition,
focuser.hasThermometer,
focuser.temperature,
)
}
12 changes: 6 additions & 6 deletions api/src/main/kotlin/nebulosa/api/services/CameraService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ class CameraService(
}

operator fun get(name: String): CameraResponse {
val camera = equipmentService.camera(name)!!
val camera = requireNotNull(equipmentService.camera(name))
return CameraResponse(camera)
}

fun connect(name: String) {
val camera = equipmentService.camera(name)!!
val camera = requireNotNull(equipmentService.camera(name))
camera.connect()
}

fun disconnect(name: String) {
val camera = equipmentService.camera(name)!!
val camera = requireNotNull(equipmentService.camera(name))
camera.disconnect()
}

Expand All @@ -81,20 +81,20 @@ class CameraService(
}

fun setpointTemperature(name: String, temperature: Double) {
val camera = equipmentService.camera(name)!!
val camera = requireNotNull(equipmentService.camera(name))
camera.temperature(temperature)
}

fun cooler(name: String, enable: Boolean) {
val camera = equipmentService.camera(name)!!
val camera = requireNotNull(equipmentService.camera(name))
camera.cooler(enable)
}

@Synchronized
fun startCapture(name: String, data: CameraStartCaptureRequest) {
if (isCapturing(name)) return

val camera = equipmentService.camera(name)!!
val camera = requireNotNull(equipmentService.camera(name))
val savePath = data.savePath?.ifBlank { null }?.let(Path::of)
?.takeIf { it.exists() && it.isDirectory() }
?: Path.of("$capturesDirectory", name).createDirectories()
Expand Down
16 changes: 15 additions & 1 deletion api/src/main/kotlin/nebulosa/api/services/EquipmentService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import nebulosa.indi.device.DeviceEventHandler
import nebulosa.indi.device.camera.Camera
import nebulosa.indi.device.camera.CameraAttached
import nebulosa.indi.device.camera.CameraDetached
import nebulosa.indi.device.focuser.Focuser
import nebulosa.indi.device.focuser.FocuserAttached
import nebulosa.indi.device.focuser.FocuserDetached
import org.greenrobot.eventbus.EventBus
import org.springframework.stereotype.Service
import java.util.*
Expand All @@ -14,12 +17,15 @@ import java.util.*
class EquipmentService(private val eventBus: EventBus) : DeviceEventHandler {

private val cameras = ArrayList<Camera>(2)
private val focusers = ArrayList<Focuser>(2)

@Synchronized
override fun onEventReceived(event: DeviceEvent<*>) {
when (event) {
is CameraAttached -> cameras.add(event.device)
is CameraDetached -> cameras.remove(event.device)
is FocuserAttached -> focusers.add(event.device)
is FocuserDetached -> focusers.remove(event.device)
}

eventBus.post(event)
Expand All @@ -33,7 +39,15 @@ class EquipmentService(private val eventBus: EventBus) : DeviceEventHandler {
return cameras.firstOrNull { it.name == name }
}

fun focusers(): List<Focuser> {
return Collections.unmodifiableList(focusers)
}

fun focuser(name: String): Focuser? {
return focusers.firstOrNull { it.name == name }
}

operator fun get(name: String): Device? {
return camera(name)
return camera(name) ?: focuser(name)
}
}
78 changes: 78 additions & 0 deletions api/src/main/kotlin/nebulosa/api/services/FocuserService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package nebulosa.api.services

import jakarta.annotation.PostConstruct
import nebulosa.api.data.responses.FocuserResponse
import nebulosa.indi.device.PropertyChangedEvent
import nebulosa.indi.device.focuser.FocuserAttached
import nebulosa.indi.device.focuser.FocuserDetached
import nebulosa.indi.device.focuser.FocuserEvent
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.springframework.stereotype.Service

@Service
class FocuserService(
private val equipmentService: EquipmentService,
private val webSocketService: WebSocketService,
private val eventBus: EventBus,
) {

@PostConstruct
private fun initialize() {
eventBus.register(this)
}

@Subscribe(threadMode = ThreadMode.ASYNC)
fun onFocuserEvent(event: FocuserEvent) {
when (event) {
is PropertyChangedEvent -> webSocketService.sendFocuserUpdated(event.device!!)
is FocuserAttached -> webSocketService.sendFocuserAttached(event.device)
is FocuserDetached -> webSocketService.sendFocuserDetached(event.device)
}
}

fun attachedFocusers(): List<FocuserResponse> {
return equipmentService.focusers().map(::FocuserResponse)
}

operator fun get(name: String): FocuserResponse {
val focuser = requireNotNull(equipmentService.focuser(name))
return FocuserResponse(focuser)
}

fun connect(name: String) {
val focuser = requireNotNull(equipmentService.focuser(name))
focuser.connect()
}

fun disconnect(name: String) {
val focuser = requireNotNull(equipmentService.focuser(name))
focuser.disconnect()
}

fun moveIn(name: String, steps: Int) {
val focuser = requireNotNull(equipmentService.focuser(name))
focuser.moveFocusIn(steps)
}

fun moveOut(name: String, steps: Int) {
val focuser = requireNotNull(equipmentService.focuser(name))
focuser.moveFocusOut(steps)
}

fun moveTo(name: String, steps: Int) {
val focuser = requireNotNull(equipmentService.focuser(name))
focuser.moveFocusTo(steps)
}

fun abort(name: String) {
val focuser = requireNotNull(equipmentService.focuser(name))
focuser.abortFocus()
}

fun syncTo(name: String, steps: Int) {
val focuser = requireNotNull(equipmentService.focuser(name))
focuser.syncFocusTo(steps)
}
}
Loading

0 comments on commit 58469dc

Please sign in to comment.