1mod image_array;
2pub use image_array::*;
3
4pub use super::camera_telescope_shared::GuideDirection;
5
6use super::Device;
7use super::time_repr::{Fits, TimeRepr};
8use crate::{ASCOMError, ASCOMResult};
9use macro_rules_attribute::apply;
10use num_enum::{IntoPrimitive, TryFromPrimitive};
11use serde_repr::{Deserialize_repr, Serialize_repr};
12#[cfg(feature = "client")]
13use std::ops::RangeInclusive;
14use std::time::SystemTime;
15
16#[apply(rpc_trait)]
18pub trait Camera: Device + Send + Sync {
19 #[http("bayeroffsetx", method = Get)]
21 async fn bayer_offset_x(&self) -> ASCOMResult<i32> {
22 Err(ASCOMError::NOT_IMPLEMENTED)
23 }
24
25 #[http("bayeroffsety", method = Get)]
27 async fn bayer_offset_y(&self) -> ASCOMResult<i32> {
28 Err(ASCOMError::NOT_IMPLEMENTED)
29 }
30
31 #[http("binx", method = Get)]
33 async fn bin_x(&self) -> ASCOMResult<i32> {
34 Err(ASCOMError::NOT_IMPLEMENTED)
35 }
36
37 #[http("binx", method = Put)]
39 async fn set_bin_x(&self, #[http("BinX")] bin_x: i32) -> ASCOMResult<()> {
40 Err(ASCOMError::NOT_IMPLEMENTED)
41 }
42
43 #[http("biny", method = Get)]
45 async fn bin_y(&self) -> ASCOMResult<i32> {
46 Err(ASCOMError::NOT_IMPLEMENTED)
47 }
48
49 #[http("biny", method = Put)]
51 async fn set_bin_y(&self, #[http("BinY")] bin_y: i32) -> ASCOMResult<()> {
52 Err(ASCOMError::NOT_IMPLEMENTED)
53 }
54
55 #[http("camerastate", method = Get, device_state = CameraState)]
57 async fn camera_state(&self) -> ASCOMResult<CameraState> {
58 Err(ASCOMError::NOT_IMPLEMENTED)
59 }
60
61 #[http("cameraxsize", method = Get)]
63 async fn camera_xsize(&self) -> ASCOMResult<i32> {
64 Err(ASCOMError::NOT_IMPLEMENTED)
65 }
66
67 #[http("cameraysize", method = Get)]
69 async fn camera_ysize(&self) -> ASCOMResult<i32> {
70 Err(ASCOMError::NOT_IMPLEMENTED)
71 }
72
73 #[http("canabortexposure", method = Get)]
75 async fn can_abort_exposure(&self) -> ASCOMResult<bool> {
76 Ok(false)
77 }
78
79 #[http("canasymmetricbin", method = Get)]
81 async fn can_asymmetric_bin(&self) -> ASCOMResult<bool> {
82 Ok(false)
83 }
84
85 #[http("canfastreadout", method = Get)]
87 async fn can_fast_readout(&self) -> ASCOMResult<bool> {
88 Ok(false)
89 }
90
91 #[http("cangetcoolerpower", method = Get)]
93 async fn can_get_cooler_power(&self) -> ASCOMResult<bool> {
94 Ok(false)
95 }
96
97 #[http("canpulseguide", method = Get)]
99 async fn can_pulse_guide(&self) -> ASCOMResult<bool> {
100 Ok(false)
101 }
102
103 #[http("cansetccdtemperature", method = Get)]
105 async fn can_set_ccd_temperature(&self) -> ASCOMResult<bool> {
106 Ok(false)
107 }
108
109 #[http("canstopexposure", method = Get)]
111 async fn can_stop_exposure(&self) -> ASCOMResult<bool> {
112 Ok(false)
113 }
114
115 #[http("ccdtemperature", method = Get, device_state = CCDTemperature)]
117 async fn ccd_temperature(&self) -> ASCOMResult<f64> {
118 Err(ASCOMError::NOT_IMPLEMENTED)
119 }
120
121 #[http("cooleron", method = Get)]
123 async fn cooler_on(&self) -> ASCOMResult<bool> {
124 Err(ASCOMError::NOT_IMPLEMENTED)
125 }
126
127 #[http("cooleron", method = Put)]
131 async fn set_cooler_on(&self, #[http("CoolerOn")] cooler_on: bool) -> ASCOMResult<()> {
132 Err(ASCOMError::NOT_IMPLEMENTED)
133 }
134
135 #[http("coolerpower", method = Get, device_state = CoolerPower)]
137 async fn cooler_power(&self) -> ASCOMResult<f64> {
138 Err(ASCOMError::NOT_IMPLEMENTED)
139 }
140
141 #[http("electronsperadu", method = Get)]
143 async fn electrons_per_adu(&self) -> ASCOMResult<f64> {
144 Err(ASCOMError::NOT_IMPLEMENTED)
145 }
146
147 #[http("exposuremax", method = Get)]
149 async fn exposure_max(&self) -> ASCOMResult<f64>;
150
151 #[http("exposuremin", method = Get)]
153 async fn exposure_min(&self) -> ASCOMResult<f64>;
154
155 #[http("exposureresolution", method = Get)]
157 async fn exposure_resolution(&self) -> ASCOMResult<f64>;
158
159 #[http("fastreadout", method = Get)]
161 async fn fast_readout(&self) -> ASCOMResult<bool> {
162 Err(ASCOMError::NOT_IMPLEMENTED)
163 }
164
165 #[http("fastreadout", method = Put)]
167 async fn set_fast_readout(&self, #[http("FastReadout")] fast_readout: bool) -> ASCOMResult<()> {
168 Err(ASCOMError::NOT_IMPLEMENTED)
169 }
170
171 #[http("fullwellcapacity", method = Get)]
173 async fn full_well_capacity(&self) -> ASCOMResult<f64> {
174 Err(ASCOMError::NOT_IMPLEMENTED)
175 }
176
177 #[http("gain", method = Get)]
179 async fn gain(&self) -> ASCOMResult<i32> {
180 Err(ASCOMError::NOT_IMPLEMENTED)
181 }
182
183 #[http("gain", method = Put)]
185 async fn set_gain(&self, #[http("Gain")] gain: i32) -> ASCOMResult<()> {
186 Err(ASCOMError::NOT_IMPLEMENTED)
187 }
188
189 #[http("gainmax", method = Get)]
191 async fn gain_max(&self) -> ASCOMResult<i32> {
192 Err(ASCOMError::NOT_IMPLEMENTED)
193 }
194
195 #[http("gainmin", method = Get)]
197 async fn gain_min(&self) -> ASCOMResult<i32> {
198 Err(ASCOMError::NOT_IMPLEMENTED)
199 }
200
201 #[http("gains", method = Get)]
203 async fn gains(&self) -> ASCOMResult<Vec<String>> {
204 Err(ASCOMError::NOT_IMPLEMENTED)
205 }
206
207 #[http("hasshutter", method = Get)]
209 async fn has_shutter(&self) -> ASCOMResult<bool>;
210
211 #[http("heatsinktemperature", method = Get, device_state = HeatSinkTemperature)]
213 async fn heat_sink_temperature(&self) -> ASCOMResult<f64> {
214 Err(ASCOMError::NOT_IMPLEMENTED)
215 }
216
217 #[http("imagearray", method = Get)]
221 async fn image_array(&self) -> ASCOMResult<ImageArray> {
222 Err(ASCOMError::NOT_IMPLEMENTED)
223 }
224
225 #[http("imageready", method = Get, device_state = ImageReady)]
227 async fn image_ready(&self) -> ASCOMResult<bool> {
228 Err(ASCOMError::NOT_IMPLEMENTED)
229 }
230
231 #[http("ispulseguiding", method = Get, device_state = IsPulseGuiding)]
233 async fn is_pulse_guiding(&self) -> ASCOMResult<bool> {
234 Err(ASCOMError::NOT_IMPLEMENTED)
235 }
236
237 #[http("lastexposureduration", method = Get)]
239 async fn last_exposure_duration(&self) -> ASCOMResult<f64> {
240 Err(ASCOMError::NOT_IMPLEMENTED)
241 }
242
243 #[http("lastexposurestarttime", method = Get, via = TimeRepr<Fits>)]
247 async fn last_exposure_start_time(&self) -> ASCOMResult<SystemTime> {
248 Err(ASCOMError::NOT_IMPLEMENTED)
249 }
250
251 #[http("maxadu", method = Get)]
253 async fn max_adu(&self) -> ASCOMResult<i32>;
254
255 #[http("maxbinx", method = Get)]
257 async fn max_bin_x(&self) -> ASCOMResult<i32> {
258 Err(ASCOMError::NOT_IMPLEMENTED)
259 }
260
261 #[http("maxbiny", method = Get)]
263 async fn max_bin_y(&self) -> ASCOMResult<i32> {
264 Err(ASCOMError::NOT_IMPLEMENTED)
265 }
266
267 #[http("numx", method = Get)]
269 async fn num_x(&self) -> ASCOMResult<i32> {
270 Err(ASCOMError::NOT_IMPLEMENTED)
271 }
272
273 #[http("numx", method = Put)]
275 async fn set_num_x(&self, #[http("NumX")] num_x: i32) -> ASCOMResult<()> {
276 Err(ASCOMError::NOT_IMPLEMENTED)
277 }
278
279 #[http("numy", method = Get)]
281 async fn num_y(&self) -> ASCOMResult<i32> {
282 Err(ASCOMError::NOT_IMPLEMENTED)
283 }
284
285 #[http("numy", method = Put)]
287 async fn set_num_y(&self, #[http("NumY")] num_y: i32) -> ASCOMResult<()> {
288 Err(ASCOMError::NOT_IMPLEMENTED)
289 }
290
291 #[http("offset", method = Get)]
293 async fn offset(&self) -> ASCOMResult<i32> {
294 Err(ASCOMError::NOT_IMPLEMENTED)
295 }
296
297 #[http("offset", method = Put)]
299 async fn set_offset(&self, #[http("Offset")] offset: i32) -> ASCOMResult<()> {
300 Err(ASCOMError::NOT_IMPLEMENTED)
301 }
302
303 #[http("offsetmax", method = Get)]
305 async fn offset_max(&self) -> ASCOMResult<i32> {
306 Err(ASCOMError::NOT_IMPLEMENTED)
307 }
308
309 #[http("offsetmin", method = Get)]
311 async fn offset_min(&self) -> ASCOMResult<i32> {
312 Err(ASCOMError::NOT_IMPLEMENTED)
313 }
314
315 #[http("offsets", method = Get)]
317 async fn offsets(&self) -> ASCOMResult<Vec<String>> {
318 Err(ASCOMError::NOT_IMPLEMENTED)
319 }
320
321 #[http("percentcompleted", method = Get, device_state = PercentCompleted)]
325 async fn percent_completed(&self) -> ASCOMResult<i32> {
326 Err(ASCOMError::NOT_IMPLEMENTED)
327 }
328
329 #[http("pixelsizex", method = Get)]
331 async fn pixel_size_x(&self) -> ASCOMResult<f64>;
332
333 #[http("pixelsizey", method = Get)]
335 async fn pixel_size_y(&self) -> ASCOMResult<f64>;
336
337 #[http("readoutmode", method = Get)]
341 async fn readout_mode(&self) -> ASCOMResult<i32> {
342 Err(ASCOMError::NOT_IMPLEMENTED)
343 }
344
345 #[http("readoutmode", method = Put)]
347 async fn set_readout_mode(&self, #[http("ReadoutMode")] readout_mode: i32) -> ASCOMResult<()> {
348 Err(ASCOMError::NOT_IMPLEMENTED)
349 }
350
351 #[http("readoutmodes", method = Get)]
355 async fn readout_modes(&self) -> ASCOMResult<Vec<String>> {
356 Err(ASCOMError::NOT_IMPLEMENTED)
357 }
358
359 #[http("sensorname", method = Get)]
361 async fn sensor_name(&self) -> ASCOMResult<String> {
362 Err(ASCOMError::NOT_IMPLEMENTED)
363 }
364
365 #[http("sensortype", method = Get)]
367 async fn sensor_type(&self) -> ASCOMResult<SensorType> {
368 Err(ASCOMError::NOT_IMPLEMENTED)
369 }
370
371 #[http("setccdtemperature", method = Get)]
373 async fn set_ccd_temperature(&self) -> ASCOMResult<f64> {
374 Err(ASCOMError::NOT_IMPLEMENTED)
375 }
376
377 #[http("setccdtemperature", method = Put)]
379 async fn set_set_ccd_temperature(
380 &self,
381
382 #[http("SetCCDTemperature")] set_ccd_temperature: f64,
383 ) -> ASCOMResult<()> {
384 Err(ASCOMError::NOT_IMPLEMENTED)
385 }
386
387 #[http("startx", method = Get)]
389 async fn start_x(&self) -> ASCOMResult<i32>;
390
391 #[http("startx", method = Put)]
393 async fn set_start_x(&self, #[http("StartX")] start_x: i32) -> ASCOMResult<()>;
394
395 #[http("starty", method = Get)]
397 async fn start_y(&self) -> ASCOMResult<i32>;
398
399 #[http("starty", method = Put)]
401 async fn set_start_y(&self, #[http("StartY")] start_y: i32) -> ASCOMResult<()>;
402
403 #[http("subexposureduration", method = Get)]
407 async fn sub_exposure_duration(&self) -> ASCOMResult<f64> {
408 Err(ASCOMError::NOT_IMPLEMENTED)
409 }
410
411 #[http("subexposureduration", method = Put)]
415 async fn set_sub_exposure_duration(
416 &self,
417
418 #[http("SubExposureDuration")] sub_exposure_duration: f64,
419 ) -> ASCOMResult<()> {
420 Err(ASCOMError::NOT_IMPLEMENTED)
421 }
422
423 #[http("abortexposure", method = Put)]
425 async fn abort_exposure(&self) -> ASCOMResult<()> {
426 Err(ASCOMError::NOT_IMPLEMENTED)
427 }
428
429 #[http("pulseguide", method = Put)]
431 async fn pulse_guide(
432 &self,
433
434 #[http("Direction")] direction: GuideDirection,
435
436 #[http("Duration")] duration: i32,
437 ) -> ASCOMResult<()> {
438 Err(ASCOMError::NOT_IMPLEMENTED)
439 }
440
441 #[http("startexposure", method = Put)]
445 async fn start_exposure(
446 &self,
447
448 #[http("Duration")] duration: f64,
449
450 #[http("Light")] light: bool,
451 ) -> ASCOMResult<()>;
452
453 #[http("stopexposure", method = Put)]
457 async fn stop_exposure(&self) -> ASCOMResult<()> {
458 Err(ASCOMError::NOT_IMPLEMENTED)
459 }
460
461 #[http("interfaceversion", method = Get)]
465 async fn interface_version(&self) -> ASCOMResult<i32> {
466 Ok(4_i32)
467 }
468}
469
470convenience_props!(Camera {
471 bayer_offset(bayer_offset_x, bayer_offset_y): [i32; 2],
473
474 #[
476 set
478 ]
479 bin(bin_x, bin_y): [i32; 2],
480
481 camera_size(camera_xsize, camera_ysize): [i32; 2],
483
484 exposure_range(exposure_min, exposure_max): RangeInclusive<f64>,
486
487 gain_range(gain_min, gain_max): RangeInclusive<i32>,
489
490 max_bin(max_bin_x, max_bin_y): [i32; 2],
492
493 #[
495 set
497 ]
498 num(num_x, num_y): [i32; 2],
499
500 offset_range(offset_min, offset_max): RangeInclusive<i32>,
502
503 pixel_size(pixel_size_x, pixel_size_y): [f64; 2],
505
506 start(start_x, start_y): [i32; 2],
508});
509
510#[cfg(feature = "client")]
514#[derive(Debug, Clone, PartialEq, Eq)]
515pub enum GainMode {
516 Range(RangeInclusive<i32>),
518 List(Vec<String>),
520}
521
522#[cfg(feature = "client")]
523impl dyn Camera {
524 pub async fn gain_mode(&self) -> ASCOMResult<Option<GainMode>> {
531 fn if_implemented<T>(res: ASCOMResult<T>) -> ASCOMResult<Option<T>> {
532 match res {
533 Err(err) if err.code == crate::ASCOMErrorCode::NOT_IMPLEMENTED => Ok(None),
534 _ => res.map(Some),
535 }
536 }
537
538 Ok(match if_implemented(self.gains().await)? {
540 Some(gains) => Some(GainMode::List(gains)),
541 None => {
542 if_implemented(self.gain_range().await)?.map(GainMode::Range)
544 }
545 })
546 }
547}
548
549#[derive(
551 Debug,
552 PartialEq,
553 Eq,
554 Clone,
555 Copy,
556 Serialize_repr,
557 Deserialize_repr,
558 TryFromPrimitive,
559 IntoPrimitive,
560)]
561#[repr(i32)]
562pub enum CameraState {
563 Idle = 0,
565
566 Waiting = 1,
568
569 Exposing = 2,
571
572 Reading = 3,
574
575 Download = 4,
577
578 Error = 5,
580}
581
582#[derive(
584 Debug,
585 PartialEq,
586 Eq,
587 Clone,
588 Copy,
589 Serialize_repr,
590 Deserialize_repr,
591 TryFromPrimitive,
592 IntoPrimitive,
593)]
594#[repr(i32)]
595pub enum SensorType {
596 Monochrome = 0,
598
599 Color = 1,
601
602 RGGB = 2,
604
605 CMYG = 3,
607
608 CMYG2 = 4,
610
611 LRGB = 5,
613}