diff --git a/desktop/src/app/camera/camera.component.ts b/desktop/src/app/camera/camera.component.ts
index 1632366d9..6638ffa5f 100644
--- a/desktop/src/app/camera/camera.component.ts
+++ b/desktop/src/app/camera/camera.component.ts
@@ -179,7 +179,6 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
}
readonly wait = {
- duration: 0,
remainingTime: 0,
progress: 0,
}
@@ -229,8 +228,6 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
) {
app.title = 'Camera'
- api.startListening('CAMERA')
-
electron.on('CAMERA_UPDATED', event => {
if (event.device.name === this.camera?.name) {
ngZone.run(() => {
@@ -240,16 +237,10 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
}
})
- electron.on('CAMERA_CAPTURE_STARTED', event => {
- if (event.camera.name === this.camera?.name) {
+ electron.on('CAMERA_DETACHED', event => {
+ if (event.device.name === this.camera?.name) {
ngZone.run(() => {
- this.capture.looping = event.looping
- this.capture.amount = event.exposureAmount
- this.capture.elapsedTime = 0
- this.capture.remainingTime = event.estimatedTime
- this.capture.progress = event.progress
- this.capturing = true
- this.waiting = false
+ this.connected = false
})
}
})
@@ -257,61 +248,27 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
electron.on('CAMERA_CAPTURE_ELAPSED', event => {
if (event.camera.name === this.camera?.name) {
ngZone.run(() => {
- this.capture.elapsedTime = event.elapsedTime
- this.capture.remainingTime = event.remainingTime
- this.capture.progress = event.progress
- })
- }
- })
-
- electron.on('CAMERA_CAPTURE_WAITING', event => {
- if (event.camera.name === this.camera?.name) {
- ngZone.run(() => {
- this.wait.duration = event.waitDuration
- this.wait.remainingTime = event.remainingTime
- this.wait.progress = event.progress
- this.capturing = false
- this.waiting = true
- })
- }
- })
-
- electron.on('CAMERA_CAPTURE_FINISHED', event => {
- if (event.camera.name === this.camera?.name) {
- ngZone.run(() => {
- this.capturing = false
- this.waiting = false
- })
- }
- })
-
- electron.on('CAMERA_EXPOSURE_STARTED', event => {
- if (event.camera.name === this.camera?.name) {
- ngZone.run(() => {
- this.exposure.remainingTime = event.remainingTime
- this.exposure.progress = event.progress
+ this.capture.elapsedTime = event.captureElapsedTime
+ this.capture.remainingTime = event.captureRemainingTime
+ this.capture.progress = event.captureProgress
+ this.exposure.remainingTime = event.exposureRemainingTime
+ this.exposure.progress = event.exposureProgress
this.exposure.count = event.exposureCount
- this.capturing = true
- this.waiting = false
- })
- }
- })
- electron.on('CAMERA_EXPOSURE_ELAPSED', event => {
- if (event.camera.name === this.camera?.name) {
- ngZone.run(() => {
- this.exposure.remainingTime = event.remainingTime
- this.exposure.progress = event.progress
- this.exposure.count = event.exposureCount
- })
- }
- })
-
- electron.on('CAMERA_EXPOSURE_FINISHED', event => {
- if (event.camera.name === this.camera?.name) {
- ngZone.run(() => {
- this.exposure.remainingTime = event.remainingTime
- this.exposure.progress = event.progress
+ if (event.state === 'WAITING') {
+ this.wait.remainingTime = event.waitRemainingTime
+ this.wait.progress = event.waitProgress
+ this.waiting = true
+ } else if (event.state === 'CAPTURE_STARTED') {
+ this.capture.looping = event.exposureAmount <= 0
+ this.capture.amount = event.exposureAmount
+ this.capturing = true
+ } else if (event.state === 'CAPTURE_FINISHED') {
+ this.capturing = false
+ this.waiting = false
+ } else if (event.state === 'EXPOSURE_STARTED') {
+ this.waiting = false
+ }
})
}
})
@@ -326,7 +283,6 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
@HostListener('window:unload')
ngOnDestroy() {
- this.api.stopListening('CAMERA')
this.abortCapture()
}
@@ -339,7 +295,7 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
const camera = await this.api.camera(this.camera.name)
Object.assign(this.camera, camera)
- await this.loadPreference()
+ this.loadPreference()
this.update()
} else {
this.app.subTitle = ''
@@ -425,18 +381,20 @@ export class CameraComponent implements AfterContentInit, OnDestroy {
}
private updateExposureUnit(unit: ExposureTimeUnit) {
- const a = CameraComponent.exposureUnitFactor(this.exposureTimeUnit)
- const b = CameraComponent.exposureUnitFactor(unit)
- const exposureTime = Math.trunc(this.exposureTime * b / a)
- const exposureTimeMin = Math.trunc(this.camera!.exposureMin * b / 60000000)
- const exposureTimeMax = Math.trunc(this.camera!.exposureMax * b / 60000000)
- this.exposureTimeMax = Math.max(1, exposureTimeMax)
- this.exposureTimeMin = Math.max(1, exposureTimeMin)
- this.exposureTime = Math.max(this.exposureTimeMin, Math.min(exposureTime, this.exposureTimeMax))
- this.exposureTimeUnit = unit
+ if (this.camera!.exposureMax) {
+ const a = CameraComponent.exposureUnitFactor(this.exposureTimeUnit)
+ const b = CameraComponent.exposureUnitFactor(unit)
+ const exposureTime = Math.trunc(this.exposureTime * b / a)
+ const exposureTimeMin = Math.trunc(this.camera!.exposureMin * b / 60000000)
+ const exposureTimeMax = Math.trunc(this.camera!.exposureMax * b / 60000000)
+ this.exposureTimeMax = Math.max(1, exposureTimeMax)
+ this.exposureTimeMin = Math.max(1, exposureTimeMin)
+ this.exposureTime = Math.max(this.exposureTimeMin, Math.min(exposureTime, this.exposureTimeMax))
+ this.exposureTimeUnit = unit
+ }
}
- private async update() {
+ private update() {
if (this.camera) {
this.connected = this.camera.connected
diff --git a/desktop/src/app/filterwheel/filterwheel.component.ts b/desktop/src/app/filterwheel/filterwheel.component.ts
index 1ec686822..c49045abd 100644
--- a/desktop/src/app/filterwheel/filterwheel.component.ts
+++ b/desktop/src/app/filterwheel/filterwheel.component.ts
@@ -64,6 +64,14 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy {
}
})
+ electron.on('WHEEL_DETACHED', event => {
+ if (event.device.name === this.wheel?.name) {
+ ngZone.run(() => {
+ this.connected = false
+ })
+ }
+ })
+
this.subscription = this.filterChangedPublisher
.pipe(throttleTime(1500))
.subscribe((filter) => {
@@ -127,7 +135,7 @@ export class FilterWheelComponent implements AfterContentInit, OnDestroy {
this.filterChangedPublisher.next(filter)
}
- private async update() {
+ private update() {
if (!this.wheel) {
return
}
diff --git a/desktop/src/app/focuser/focuser.component.ts b/desktop/src/app/focuser/focuser.component.ts
index 666b8fd6a..0f59124ce 100644
--- a/desktop/src/app/focuser/focuser.component.ts
+++ b/desktop/src/app/focuser/focuser.component.ts
@@ -55,6 +55,14 @@ export class FocuserComponent implements AfterViewInit, OnDestroy {
})
}
})
+
+ electron.on('FOCUSER_DETACHED', event => {
+ if (event.device.name === this.focuser?.name) {
+ ngZone.run(() => {
+ this.connected = false
+ })
+ }
+ })
}
async ngAfterViewInit() {
@@ -120,7 +128,7 @@ export class FocuserComponent implements AfterViewInit, OnDestroy {
this.api.focuserAbort(this.focuser!)
}
- private async update() {
+ private update() {
if (!this.focuser) {
return
}
diff --git a/desktop/src/app/guider/guider.component.ts b/desktop/src/app/guider/guider.component.ts
index e0d3b88a6..0f00c93a2 100644
--- a/desktop/src/app/guider/guider.component.ts
+++ b/desktop/src/app/guider/guider.component.ts
@@ -220,8 +220,6 @@ export class GuiderComponent implements AfterViewInit, OnDestroy {
) {
title.setTitle('Guider')
- api.startListening('GUIDING')
-
electron.on('GUIDE_OUTPUT_UPDATED', event => {
if (event.device.name === this.guideOutput?.name) {
ngZone.run(() => {
@@ -304,9 +302,7 @@ export class GuiderComponent implements AfterViewInit, OnDestroy {
}
@HostListener('window:unload')
- ngOnDestroy() {
- this.api.stopListening('GUIDING')
- }
+ ngOnDestroy() { }
private processGuiderStatus(event: Guider) {
this.connected = event.connected
diff --git a/desktop/src/app/home/home.component.ts b/desktop/src/app/home/home.component.ts
index 41f75c781..67f3d3aaa 100644
--- a/desktop/src/app/home/home.component.ts
+++ b/desktop/src/app/home/home.component.ts
@@ -1,4 +1,5 @@
import { AfterContentInit, Component, HostListener, NgZone, OnDestroy, ViewChild } from '@angular/core'
+import path from 'path'
import { MenuItem, MessageService } from 'primeng/api'
import { DeviceMenuComponent } from '../../shared/components/devicemenu/devicemenu.component'
import { DialogMenuComponent } from '../../shared/components/dialogmenu/dialogmenu.component'
@@ -7,6 +8,7 @@ import { BrowserWindowService } from '../../shared/services/browser-window.servi
import { ElectronService } from '../../shared/services/electron.service'
import { LocalStorageService } from '../../shared/services/local-storage.service'
import { Camera, Device, FilterWheel, Focuser, HomeWindowType, Mount } from '../../shared/types'
+import { compareDevice } from '../../shared/utils/comparators'
import { AppComponent } from '../app.component'
type MappedDevice = {
@@ -227,7 +229,7 @@ export class HomeComponent implements AfterContentInit, OnDestroy {
if (devices.length === 0) return
if (devices.length === 1) return this.openDeviceWindow(type, devices[0] as any)
- for (const device of devices) {
+ for (const device of [...devices].sort(compareDevice)) {
this.deviceModel.push({
icon: 'mdi mdi-connection',
label: device.name,
@@ -259,10 +261,12 @@ export class HomeComponent implements AfterContentInit, OnDestroy {
private async openImage(force: boolean = false) {
if (force || this.cameras.length === 0) {
- const path = await this.electron.openFITS()
+ const defaultPath = this.storage.get('home.image.directory', '')
+ const fitsPath = await this.electron.openFITS({ defaultPath })
- if (path) {
- this.browserWindow.openImage({ path, source: 'PATH' })
+ if (fitsPath) {
+ this.storage.set('home.image.directory', path.dirname(fitsPath))
+ this.browserWindow.openImage({ path: fitsPath, source: 'PATH' })
}
} else {
const camera = await this.imageMenu.show(this.cameras)
@@ -313,7 +317,9 @@ export class HomeComponent implements AfterContentInit, OnDestroy {
this.connected = await this.api.connectionStatus()
} catch {
this.connected = false
+ }
+ if (!this.connected) {
this.cameras = []
this.mounts = []
this.focusers = []
diff --git a/desktop/src/app/image/image.component.ts b/desktop/src/app/image/image.component.ts
index 95649657b..db7c88d8a 100644
--- a/desktop/src/app/image/image.component.ts
+++ b/desktop/src/app/image/image.component.ts
@@ -357,8 +357,8 @@ export class ImageComponent implements AfterViewInit, OnDestroy {
) {
app.title = 'Image'
- electron.on('CAMERA_EXPOSURE_FINISHED', async (event) => {
- if (event.camera.name === this.imageData.camera?.name) {
+ electron.on('CAMERA_CAPTURE_ELAPSED', async (event) => {
+ if (event.state === 'EXPOSURE_FINISHED' && event.camera.name === this.imageData.camera?.name) {
await this.closeImage()
ngZone.run(() => {
diff --git a/desktop/src/app/indi/indi.component.html b/desktop/src/app/indi/indi.component.html
index 8d27baf9c..0bfb1d811 100644
--- a/desktop/src/app/indi/indi.component.html
+++ b/desktop/src/app/indi/indi.component.html
@@ -2,7 +2,7 @@
-
@@ -18,7 +18,7 @@
diff --git a/desktop/src/app/indi/indi.component.scss b/desktop/src/app/indi/indi.component.scss
index 232c4e990..7746ea400 100644
--- a/desktop/src/app/indi/indi.component.scss
+++ b/desktop/src/app/indi/indi.component.scss
@@ -1,8 +1,16 @@
+:host {
+ ::ng-deep {
+ .p-listbox-list-wrapper {
+ max-height: calc(100vh - 175px) !important;
+ }
+ }
+}
+
.properties {
- height: calc(100vh - 80px);
+ height: calc(100vh - 100px);
overflow-y: auto;
}
.properties::-webkit-scrollbar {
display: none;
-}
+}
\ No newline at end of file
diff --git a/desktop/src/app/indi/indi.component.ts b/desktop/src/app/indi/indi.component.ts
index 057e361b1..cd38566f0 100644
--- a/desktop/src/app/indi/indi.component.ts
+++ b/desktop/src/app/indi/indi.component.ts
@@ -4,6 +4,7 @@ import { MenuItem } from 'primeng/api'
import { ApiService } from '../../shared/services/api.service'
import { ElectronService } from '../../shared/services/electron.service'
import { Device, INDIProperty, INDIPropertyItem, INDISendProperty } from '../../shared/types'
+import { compareDevice, compareText } from '../../shared/utils/comparators'
import { AppComponent } from '../app.component'
@Component({
@@ -31,8 +32,6 @@ export class INDIComponent implements AfterViewInit, OnDestroy {
) {
app.title = 'INDI'
- this.api.startListening('INDI')
-
electron.on('DEVICE_PROPERTY_CHANGED', event => {
ngZone.run(() => {
this.addOrUpdateProperty(event.property!)
@@ -62,7 +61,11 @@ export class INDIComponent implements AfterViewInit, OnDestroy {
async ngAfterViewInit() {
this.route.queryParams.subscribe(e => {
- this.device = JSON.parse(decodeURIComponent(e.data)) as Device
+ const device = JSON.parse(decodeURIComponent(e.data))
+
+ if ("name" in device && device.name) {
+ this.device = device
+ }
})
this.devices = [
@@ -70,17 +73,28 @@ export class INDIComponent implements AfterViewInit, OnDestroy {
...await this.api.mounts(),
...await this.api.focusers(),
...await this.api.wheels(),
- ]
+ ].sort(compareDevice)
+
+ this.device = this.devices[0]
}
@HostListener('window:unload')
ngOnDestroy() {
- this.api.stopListening('INDI')
+ if (this.device) {
+ this.api.indiStopListening(this.device)
+ }
}
- async deviceChanged() {
+ async deviceChanged(device: Device) {
+ if (this.device) {
+ this.api.indiStopListening(this.device)
+ }
+
+ this.device = device
+
this.updateProperties()
- this.messages = await this.api.indiLog(this.device!)
+ this.api.indiStartListening(device)
+ this.messages = await this.api.indiLog(device)
}
changeGroup(group: string) {
@@ -89,7 +103,7 @@ export class INDIComponent implements AfterViewInit, OnDestroy {
}
send(property: INDISendProperty) {
- this.api.sendIndiProperty(this.device!, property)
+ this.api.indiSendProperty(this.device!, property)
}
private updateGroups() {
@@ -116,7 +130,7 @@ export class INDIComponent implements AfterViewInit, OnDestroy {
if (this.groups.length === 0 || groupsChanged) {
this.groups = Array.from(groups)
- .sort((a, b) => a.localeCompare(b))
+ .sort(compareText)
.map(e =>