Skip to content

Commit

Permalink
[api][desktop]: Allow Camera snoop rotators
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagohm committed May 20, 2024
1 parent d500bc0 commit 53507e6
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 40 deletions.
5 changes: 3 additions & 2 deletions api/src/main/kotlin/nebulosa/api/cameras/CameraController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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.*

Expand Down Expand Up @@ -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(
Expand Down
83 changes: 52 additions & 31 deletions desktop/src/app/camera/camera.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -103,6 +105,11 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
label: 'Focuser',
menu: [],
},
{
icon: 'mdi mdi-rotate-right',
label: 'Rotator',
menu: [],
},
]
},
]
Expand Down Expand Up @@ -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())
})
Expand Down Expand Up @@ -289,51 +304,50 @@ 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 =
`<b>MOUNT</b>: ${this.equipment.mount?.name ?? 'None'}
<b>FILTER WHEEL</b>: ${this.equipment.wheel?.name ?? 'None'}
<b>FOCUSER</b>: ${this.equipment.focuser?.name ?? 'None'}`
<b>FOCUSER</b>: ${this.equipment.focuser?.name ?? 'None'}
<b>ROTATOR</b>: ${this.equipment.rotator?.name ?? 'None'}`
}

const makeMountItem = (mount?: Mount) => {
const makeItem = (checked: boolean, command: () => void, device?: Device) => {
return <ExtendedMenuItem>{
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)
},
}
}

// 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 <ExtendedMenuItem>{
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())
Expand All @@ -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 <ExtendedMenuItem>{
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())
Expand All @@ -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()
}

Expand Down
4 changes: 2 additions & 2 deletions desktop/src/shared/services/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void>(`cameras/${camera.id}/snoop?${query}`)
}

Expand Down
2 changes: 2 additions & 0 deletions desktop/src/shared/types/home.types.ts
Original file line number Diff line number Diff line change
@@ -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' |
Expand Down Expand Up @@ -45,4 +46,5 @@ export interface Equipment {
mount?: Mount
focuser?: Focuser
wheel?: FilterWheel
rotator?: Rotator
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -89,7 +90,7 @@ abstract class ASCOMDevice : Device, Resettable {
val body = response.body()

return if (body == null) {
LOG.warn("response has no body. device={}, request={} {}, response={}", name, request.method, request.url, response.code())
LOG.debug { "response has no body. device=%s, request=%s %s, response=%s".format(name, request.method, request.url, response) }
null
} else if (body.errorNumber != 0) {
val message = body.errorMessage
Expand All @@ -98,10 +99,11 @@ abstract class ASCOMDevice : Device, Resettable {
addMessageAndFireEvent("[%s]: %s".format(LocalDateTime.now(), message))
}

LOG.warn(
"unsuccessful response. device={}, request={} {}, errorNumber={}, message={}",
name, request.method, request.url, body.errorNumber, body.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 {
Expand Down

0 comments on commit 53507e6

Please sign in to comment.