diff --git a/api/src/main/kotlin/nebulosa/api/cameras/CameraController.kt b/api/src/main/kotlin/nebulosa/api/cameras/CameraController.kt
index 86c25dc79..7e64d19d7 100644
--- a/api/src/main/kotlin/nebulosa/api/cameras/CameraController.kt
+++ b/api/src/main/kotlin/nebulosa/api/cameras/CameraController.kt
@@ -6,6 +6,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.hibernate.validator.constraints.Range
import org.springframework.web.bind.annotation.*
@@ -39,8 +40,8 @@ class CameraController(
@PutMapping("{camera}/snoop")
fun snoop(
camera: Camera,
- mount: Mount?, wheel: FilterWheel?, focuser: Focuser?,
- ) = cameraService.snoop(camera, mount, wheel, focuser)
+ mount: Mount?, wheel: FilterWheel?, focuser: Focuser?, rotator: Rotator?
+ ) = cameraService.snoop(camera, mount, wheel, focuser, rotator)
@PutMapping("{camera}/cooler")
fun cooler(
diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts
index c4b775df8..0bf5944ec 100644
--- a/desktop/src/app/camera/camera.component.ts
+++ b/desktop/src/app/camera/camera.component.ts
@@ -10,9 +10,11 @@ import { BrowserWindowService } from '../../shared/services/browser-window.servi
import { ElectronService } from '../../shared/services/electron.service'
import { PreferenceService } from '../../shared/services/preference.service'
import { Camera, CameraDialogInput, CameraDialogMode, CameraPreference, CameraStartCapture, EMPTY_CAMERA, EMPTY_CAMERA_START_CAPTURE, ExposureMode, ExposureTimeUnit, FrameType, updateCameraStartCaptureFromCamera } from '../../shared/types/camera.types'
+import { Device } from '../../shared/types/device.types'
import { Focuser } from '../../shared/types/focuser.types'
import { Equipment } from '../../shared/types/home.types'
import { Mount } from '../../shared/types/mount.types'
+import { Rotator } from '../../shared/types/rotator.types'
import { FilterWheel } from '../../shared/types/wheel.types'
import { AppComponent } from '../app.component'
@@ -103,6 +105,11 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
label: 'Focuser',
menu: [],
},
+ {
+ icon: 'mdi mdi-rotate-right',
+ label: 'Rotator',
+ menu: [],
+ },
]
},
]
@@ -215,6 +222,14 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
}
})
+ electron.on('ROTATOR.UPDATED', event => {
+ if (event.device.id === this.equipment.rotator?.id) {
+ ngZone.run(() => {
+ Object.assign(this.equipment.rotator!, event.device)
+ })
+ }
+ })
+
electron.on('CALIBRATION.CHANGED', () => {
ngZone.run(() => this.loadCalibrationGroups())
})
@@ -289,23 +304,21 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
}
private async loadEquipment() {
- const mounts = await this.api.mounts()
- this.equipment.mount = mounts.find(e => e.name === this.equipment.mount?.name)
-
const buildStartTooltip = () => {
this.startTooltip =
`MOUNT: ${this.equipment.mount?.name ?? 'None'}
FILTER WHEEL: ${this.equipment.wheel?.name ?? 'None'}
- FOCUSER: ${this.equipment.focuser?.name ?? 'None'}`
+ FOCUSER: ${this.equipment.focuser?.name ?? 'None'}
+ ROTATOR: ${this.equipment.rotator?.name ?? 'None'}`
}
- const makeMountItem = (mount?: Mount) => {
+ const makeItem = (checked: boolean, command: () => void, device?: Device) => {
return {
- icon: mount ? 'mdi mdi-connection' : 'mdi mdi-close',
- label: mount?.name ?? 'None',
- checked: this.equipment.mount?.name === mount?.name,
+ icon: device ? 'mdi mdi-connection' : 'mdi mdi-close',
+ label: device?.name ?? 'None',
+ checked,
command: async (event: SlideMenuItemCommandEvent) => {
- this.equipment.mount = mount
+ command()
buildStartTooltip()
this.preference.equipmentForDevice(this.camera).set(this.equipment)
event.parent?.menu?.forEach(item => item.checked = item === event.item)
@@ -313,27 +326,28 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
}
}
+ // MOUNT
+
+ const mounts = await this.api.mounts()
+ this.equipment.mount = mounts.find(e => e.name === this.equipment.mount?.name)
+
+ const makeMountItem = (mount?: Mount) => {
+ return makeItem(this.equipment.mount?.name === mount?.name, () => this.equipment.mount = mount, mount)
+ }
+
this.cameraModel[1].menu![0].menu!.push(makeMountItem())
for (const mount of mounts) {
this.cameraModel[1].menu![0].menu!.push(makeMountItem(mount))
}
+ // FILTER WHEEL
+
const wheels = await this.api.wheels()
this.equipment.wheel = wheels.find(e => e.name === this.equipment.wheel?.name)
const makeWheelItem = (wheel?: FilterWheel) => {
- return {
- icon: wheel ? 'mdi mdi-connection' : 'mdi mdi-close',
- label: wheel?.name ?? 'None',
- checked: this.equipment.wheel?.name === wheel?.name,
- command: async (event: SlideMenuItemCommandEvent) => {
- this.equipment.wheel = wheel
- buildStartTooltip()
- this.preference.equipmentForDevice(this.camera).set(this.equipment)
- event.parent?.menu?.forEach(item => item.checked = item === event.item)
- },
- }
+ return makeItem(this.equipment.wheel?.name === wheel?.name, () => this.equipment.wheel = wheel, wheel)
}
this.cameraModel[1].menu![1].menu!.push(makeWheelItem())
@@ -342,21 +356,13 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
this.cameraModel[1].menu![1].menu!.push(makeWheelItem(wheel))
}
+ // FOCUSER
+
const focusers = await this.api.focusers()
this.equipment.focuser = focusers.find(e => e.name === this.equipment.focuser?.name)
const makeFocuserItem = (focuser?: Focuser) => {
- return {
- icon: focuser ? 'mdi mdi-connection' : 'mdi mdi-close',
- label: focuser?.name ?? 'None',
- checked: this.equipment.focuser?.name === focuser?.name,
- command: async (event: SlideMenuItemCommandEvent) => {
- this.equipment.focuser = focuser
- buildStartTooltip()
- this.preference.equipmentForDevice(this.camera).set(this.equipment)
- event.parent?.menu?.forEach(item => item.checked = item === event.item)
- },
- }
+ return makeItem(this.equipment.focuser?.name === focuser?.name, () => this.equipment.focuser = focuser, focuser)
}
this.cameraModel[1].menu![2].menu!.push(makeFocuserItem())
@@ -365,6 +371,21 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
this.cameraModel[1].menu![2].menu!.push(makeFocuserItem(focuser))
}
+ // ROTATOR
+
+ const rotators = await this.api.rotators()
+ this.equipment.rotator = rotators.find(e => e.name === this.equipment.rotator?.name)
+
+ const makeRotatorItem = (rotator?: Rotator) => {
+ return makeItem(this.equipment.rotator?.name === rotator?.name, () => this.equipment.rotator = rotator, rotator)
+ }
+
+ this.cameraModel[1].menu![3].menu!.push(makeRotatorItem())
+
+ for (const rotator of rotators) {
+ this.cameraModel[1].menu![3].menu!.push(makeRotatorItem(rotator))
+ }
+
buildStartTooltip()
}
diff --git a/desktop/src/app/rotator/rotator.component.ts b/desktop/src/app/rotator/rotator.component.ts
index d0bd81edd..20843f897 100644
--- a/desktop/src/app/rotator/rotator.component.ts
+++ b/desktop/src/app/rotator/rotator.component.ts
@@ -109,7 +109,7 @@ export class RotatorComponent implements AfterViewInit, OnDestroy {
}
private update() {
- if (!this.rotator.id) {
+ if (this.rotator.id) {
this.moving = this.rotator.moving
this.reversed = this.rotator.reversed
}
diff --git a/desktop/src/shared/services/api.service.ts b/desktop/src/shared/services/api.service.ts
index 737c8bede..426feeabc 100644
--- a/desktop/src/shared/services/api.service.ts
+++ b/desktop/src/shared/services/api.service.ts
@@ -70,8 +70,8 @@ export class ApiService {
// TODO: Rotator
cameraSnoop(camera: Camera, equipment: Equipment) {
- const { mount, wheel, focuser } = equipment
- const query = this.http.query({ mount: mount?.name, wheel: wheel?.name, focuser: focuser?.name })
+ const { mount, wheel, focuser, rotator } = equipment
+ const query = this.http.query({ mount: mount?.name, wheel: wheel?.name, focuser: focuser?.name, rotator: rotator?.name })
return this.http.put(`cameras/${camera.id}/snoop?${query}`)
}
diff --git a/desktop/src/shared/types/home.types.ts b/desktop/src/shared/types/home.types.ts
index c8f4a28d3..fd22c33fc 100644
--- a/desktop/src/shared/types/home.types.ts
+++ b/desktop/src/shared/types/home.types.ts
@@ -1,6 +1,7 @@
import { Camera } 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 HomeWindowType = 'CAMERA' | 'MOUNT' | 'GUIDER' | 'WHEEL' | 'FOCUSER' | 'DOME' | 'ROTATOR' | 'SWITCH' |
@@ -45,4 +46,5 @@ export interface Equipment {
mount?: Mount
focuser?: Focuser
wheel?: FilterWheel
+ rotator?: Rotator
}
diff --git a/nebulosa-alpaca-api/src/main/kotlin/nebulosa/alpaca/api/AlpacaRotatorService.kt b/nebulosa-alpaca-api/src/main/kotlin/nebulosa/alpaca/api/AlpacaRotatorService.kt
new file mode 100644
index 000000000..da6167647
--- /dev/null
+++ b/nebulosa-alpaca-api/src/main/kotlin/nebulosa/alpaca/api/AlpacaRotatorService.kt
@@ -0,0 +1,48 @@
+package nebulosa.alpaca.api
+
+import retrofit2.Call
+import retrofit2.http.*
+
+interface AlpacaRotatorService : AlpacaDeviceService {
+
+ @GET("api/v1/rotator/{id}/connected")
+ override fun isConnected(@Path("id") id: Int): Call
+
+ @FormUrlEncoded
+ @PUT("api/v1/rotator/{id}/connected")
+ override fun connect(@Path("id") id: Int, @Field("Connected") connected: Boolean): Call
+
+ @GET("api/v1/rotator/{id}/canreverse")
+ fun canReverse(@Path("id") id: Int): Call
+
+ @GET("api/v1/rotator/{id}/ismoving")
+ fun isMoving(@Path("id") id: Int): Call
+
+ @GET("api/v1/rotator/{id}/reverse")
+ fun isReversed(@Path("id") id: Int): Call
+
+ @GET("api/v1/rotator/{id}/position")
+ fun position(@Path("id") id: Int): Call
+
+ @GET("api/v1/rotator/{id}/stepsize")
+ fun stepSize(@Path("id") id: Int): Call
+
+ @FormUrlEncoded
+ @PUT("api/v1/rotator/{id}/reverse")
+ fun reverse(@Path("id") id: Int, @Field("Reverse") reverse: Boolean): Call
+
+ @PUT("api/v1/rotator/{id}/halt")
+ fun halt(@Path("id") id: Int): Call
+
+ @FormUrlEncoded
+ @PUT("api/v1/rotator/{id}/move")
+ fun move(@Path("id") id: Int, @Field("Position") position: Double): Call
+
+ @FormUrlEncoded
+ @PUT("api/v1/rotator/{id}/moveabsolute")
+ fun moveTo(@Path("id") id: Int, @Field("Position") position: Double): Call
+
+ @FormUrlEncoded
+ @PUT("api/v1/rotator/{id}/sync")
+ fun sync(@Path("id") id: Int, @Field("Position") position: Double): Call
+}
diff --git a/nebulosa-alpaca-api/src/main/kotlin/nebulosa/alpaca/api/AlpacaService.kt b/nebulosa-alpaca-api/src/main/kotlin/nebulosa/alpaca/api/AlpacaService.kt
index 94c180c0a..16e9b6bd0 100644
--- a/nebulosa-alpaca-api/src/main/kotlin/nebulosa/alpaca/api/AlpacaService.kt
+++ b/nebulosa-alpaca-api/src/main/kotlin/nebulosa/alpaca/api/AlpacaService.kt
@@ -24,4 +24,6 @@ class AlpacaService(
val filterWheel by lazy { retrofit.create() }
val focuser by lazy { retrofit.create() }
+
+ val rotator by lazy { retrofit.create() }
}
diff --git a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/client/AlpacaClient.kt b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/client/AlpacaClient.kt
index 91a135312..89eaaf687 100644
--- a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/client/AlpacaClient.kt
+++ b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/client/AlpacaClient.kt
@@ -5,6 +5,7 @@ import nebulosa.alpaca.api.DeviceType
import nebulosa.alpaca.indi.device.cameras.ASCOMCamera
import nebulosa.alpaca.indi.device.focusers.ASCOMFocuser
import nebulosa.alpaca.indi.device.mounts.ASCOMMount
+import nebulosa.alpaca.indi.device.rotators.ASCOMRotator
import nebulosa.alpaca.indi.device.wheels.ASCOMFilterWheel
import nebulosa.indi.device.AbstractINDIDeviceProvider
import nebulosa.indi.protocol.INDIProtocol
@@ -21,7 +22,7 @@ data class AlpacaClient(
override val id = UUID.randomUUID().toString()
- override fun sendMessageToServer(message: INDIProtocol) {}
+ override fun sendMessageToServer(message: INDIProtocol) = Unit
fun discovery() {
val response = service.management.configuredDevices().execute()
@@ -59,7 +60,13 @@ data class AlpacaClient(
}
}
}
- DeviceType.ROTATOR -> Unit
+ DeviceType.ROTATOR -> {
+ with(ASCOMRotator(device, service.rotator, this)) {
+ if (registerRotator(this)) {
+ initialize()
+ }
+ }
+ }
DeviceType.DOME -> Unit
DeviceType.SWITCH -> Unit
DeviceType.COVER_CALIBRATOR -> Unit
diff --git a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/ASCOMDevice.kt b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/ASCOMDevice.kt
index 1eec61374..6a58bb809 100644
--- a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/ASCOMDevice.kt
+++ b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/ASCOMDevice.kt
@@ -7,6 +7,7 @@ import nebulosa.alpaca.indi.client.AlpacaClient
import nebulosa.common.Resettable
import nebulosa.common.time.Stopwatch
import nebulosa.indi.device.*
+import nebulosa.log.debug
import nebulosa.log.loggerFor
import retrofit2.Call
import retrofit2.HttpException
@@ -84,23 +85,29 @@ abstract class ASCOMDevice : Device, Resettable {
protected fun > Call.doRequest(): T? {
try {
- val response = execute().body()
+ val request = request()
+ val response = execute()
+ val body = response.body()
- return if (response == null) {
- LOG.warn("response has no body. device={}, url={}", name, request().url)
+ return if (body == null) {
+ LOG.debug { "response has no body. device=%s, request=%s %s, response=%s".format(name, request.method, request.url, response) }
null
- } else if (response.errorNumber != 0) {
- val message = response.errorMessage
+ } else if (body.errorNumber != 0) {
+ val message = body.errorMessage
if (message.isNotEmpty()) {
addMessageAndFireEvent("[%s]: %s".format(LocalDateTime.now(), message))
}
- // LOG.warn("unsuccessful response. device={}, code={}, message={}", name, response.errorNumber, response.errorMessage)
+ LOG.debug {
+ "unsuccessful response. device=%s, request=%s %s, errorNumber=%s, message=%s".format(
+ name, request.method, request.url, body.errorNumber, body.errorMessage
+ )
+ }
null
} else {
- response
+ body
}
} catch (e: HttpException) {
LOG.error("unexpected response. device=$name", e)
diff --git a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt
index 90c54264b..4f7dce29e 100644
--- a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt
+++ b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/mounts/ASCOMMount.kt
@@ -224,9 +224,9 @@ data class ASCOMMount(
service.utcDate(device.number, dateTime.toInstant()).doRequest()
}
- override fun snoop(devices: Iterable) {}
+ override fun snoop(devices: Iterable) = Unit
- override fun handleMessage(message: INDIProtocol) {}
+ override fun handleMessage(message: INDIProtocol) = Unit
override fun onConnected() {
processCapabilities()
@@ -237,7 +237,7 @@ data class ASCOMMount(
equatorialSystem = service.equatorialSystem(device.number).doRequest()?.value ?: equatorialSystem
}
- override fun onDisconnected() {}
+ override fun onDisconnected() = Unit
override fun reset() {
super.reset()
diff --git a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/rotators/ASCOMRotator.kt b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/rotators/ASCOMRotator.kt
new file mode 100644
index 000000000..26e372fe6
--- /dev/null
+++ b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/rotators/ASCOMRotator.kt
@@ -0,0 +1,112 @@
+package nebulosa.alpaca.indi.device.rotators
+
+import nebulosa.alpaca.api.AlpacaRotatorService
+import nebulosa.alpaca.api.ConfiguredDevice
+import nebulosa.alpaca.indi.client.AlpacaClient
+import nebulosa.alpaca.indi.device.ASCOMDevice
+import nebulosa.indi.device.Device
+import nebulosa.indi.device.rotator.*
+import nebulosa.indi.protocol.INDIProtocol
+
+@Suppress("RedundantModalityModifier")
+data class ASCOMRotator(
+ override val device: ConfiguredDevice,
+ override val service: AlpacaRotatorService,
+ override val sender: AlpacaClient,
+) : ASCOMDevice(), Rotator {
+
+ @Volatile final override var angle = 0.0
+ @Volatile final override var minAngle = 0.0
+ @Volatile final override var maxAngle = 360.0
+ @Volatile final override var moving = false
+ @Volatile final override var canAbort = true
+ @Volatile final override var canHome = false
+ @Volatile final override var canSync = true
+ @Volatile final override var canReverse = false
+ @Volatile final override var reversed = false
+ @Volatile final override var hasBacklashCompensation = false
+ @Volatile final override var backslash = 0
+
+ override val snoopedDevices = emptyList()
+
+ override fun onConnected() {
+ processCapabilities()
+ processPosition()
+ }
+
+ override fun onDisconnected() = Unit
+
+ override fun refresh(elapsedTimeInSeconds: Long) {
+ super.refresh(elapsedTimeInSeconds)
+
+ if (connected) {
+ processPosition()
+ processMoving()
+ processReversed()
+ }
+ }
+
+ override fun snoop(devices: Iterable) = Unit
+
+ override fun moveRotator(angle: Double) {
+ service.moveTo(device.number, angle).doRequest()
+ }
+
+ override fun syncRotator(angle: Double) {
+ if (canSync) {
+ service.sync(device.number, angle).doRequest()
+ }
+ }
+
+ override fun homeRotator() = Unit
+
+ override fun reverseRotator(enable: Boolean) {
+ if (canReverse) {
+ service.reverse(device.number, enable).doRequest()
+ }
+ }
+
+ override fun abortRotator() {
+ if (canAbort) {
+ service.halt(device.number).doRequest()
+ }
+ }
+
+ override fun handleMessage(message: INDIProtocol) = Unit
+
+ private fun processCapabilities() {
+ service.canReverse(device.number).doRequest {
+ if (it.value != canReverse) {
+ canReverse = it.value
+ sender.fireOnEventReceived(RotatorCanReverseChanged(this))
+ }
+ }
+ }
+
+ private fun processPosition() {
+ service.position(device.number).doRequest {
+ if (it.value != angle) {
+ angle = it.value
+ sender.fireOnEventReceived(RotatorAngleChanged(this))
+ }
+ }
+ }
+
+ private fun processMoving() {
+ service.isMoving(device.number).doRequest {
+ if (it.value != moving) {
+ moving = it.value
+ sender.fireOnEventReceived(RotatorMovingChanged(this))
+ }
+ }
+ }
+
+ private fun processReversed() {
+ service.isReversed(device.number).doRequest {
+ if (it.value != reversed) {
+ reversed = it.value
+ sender.fireOnEventReceived(RotatorReversedChanged(this))
+ }
+ }
+ }
+}
diff --git a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/wheels/ASCOMFilterWheel.kt b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/wheels/ASCOMFilterWheel.kt
index dc2035dde..d327dcc32 100644
--- a/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/wheels/ASCOMFilterWheel.kt
+++ b/nebulosa-alpaca-indi/src/main/kotlin/nebulosa/alpaca/indi/device/wheels/ASCOMFilterWheel.kt
@@ -29,7 +29,7 @@ data class ASCOMFilterWheel(
processNames()
}
- override fun onDisconnected() {}
+ override fun onDisconnected() = Unit
override fun moveTo(position: Int) {
if (position in 1..count && position != this.position) {
@@ -55,9 +55,9 @@ data class ASCOMFilterWheel(
sender.fireOnEventReceived(FilterWheelNamesChanged(this))
}
- override fun snoop(devices: Iterable) {}
+ override fun snoop(devices: Iterable) = Unit
- override fun handleMessage(message: INDIProtocol) {}
+ override fun handleMessage(message: INDIProtocol) = Unit
private fun processPosition() {
service.position(device.number).doRequest {
diff --git a/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/IdentityGuideAlgorithm.kt b/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/IdentityGuideAlgorithm.kt
index 61e7d8a0c..f7fae575e 100644
--- a/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/IdentityGuideAlgorithm.kt
+++ b/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/IdentityGuideAlgorithm.kt
@@ -6,5 +6,5 @@ class IdentityGuideAlgorithm(override val axis: GuideAxis) : GuideAlgorithm {
override fun compute(input: Double) = input
- override fun reset() {}
+ override fun reset() = Unit
}
diff --git a/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/RandomDither.kt b/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/RandomDither.kt
index c24877604..e4fb17c55 100644
--- a/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/RandomDither.kt
+++ b/nebulosa-guiding-internal/src/main/kotlin/nebulosa/guiding/internal/RandomDither.kt
@@ -10,7 +10,7 @@ class RandomDither(private val random: Random = Random.Default) : Dither {
return doubleArrayOf(ra, dec)
}
- override fun reset() {}
+ override fun reset() = Unit
companion object {
diff --git a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/AbstractINDIDeviceProvider.kt b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/AbstractINDIDeviceProvider.kt
index 53e55e8b8..235b7e947 100644
--- a/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/AbstractINDIDeviceProvider.kt
+++ b/nebulosa-indi-device/src/main/kotlin/nebulosa/indi/device/AbstractINDIDeviceProvider.kt
@@ -198,35 +198,12 @@ abstract class AbstractINDIDeviceProvider : INDIDeviceProvider {
}
override fun close() {
- cameras().forEach {
- it.close()
- unregisterCamera(it)
- }
-
- mounts().forEach {
- it.close()
- unregisterMount(it)
- }
-
- wheels().forEach {
- it.close()
- unregisterFilterWheel(it)
- }
-
- focusers().forEach {
- it.close()
- unregisterFocuser(it)
- }
-
- rotators().forEach {
- it.close()
- unregisterRotator(it)
- }
-
- gps().forEach {
- it.close()
- unregisterGPS(it)
- }
+ cameras().onEach(Device::close).onEach(::unregisterCamera)
+ mounts().onEach(Device::close).onEach(::unregisterMount)
+ wheels().onEach(Device::close).onEach(::unregisterFilterWheel)
+ focusers().onEach(Device::close).onEach(::unregisterFocuser)
+ rotators().onEach(Device::close).onEach(::unregisterRotator)
+ gps().onEach(Device::close).onEach(::unregisterGPS)
cameras.clear()
mounts.clear()
diff --git a/nebulosa-skycatalog/src/main/kotlin/nebulosa/skycatalog/SkyCatalog.kt b/nebulosa-skycatalog/src/main/kotlin/nebulosa/skycatalog/SkyCatalog.kt
index dc52ca6fc..66b6f0157 100644
--- a/nebulosa-skycatalog/src/main/kotlin/nebulosa/skycatalog/SkyCatalog.kt
+++ b/nebulosa-skycatalog/src/main/kotlin/nebulosa/skycatalog/SkyCatalog.kt
@@ -39,7 +39,7 @@ abstract class SkyCatalog(estimatedSize: Int = 0) : Collection
return res
}
- protected fun notifyLoadFinished() {}
+ protected fun notifyLoadFinished() = Unit
override val size
get() = data.size