ascom_alpaca/api/camera/
mod.rs

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/// Camera Specific Methods.
17#[apply(rpc_trait)]
18pub trait Camera: Device + Send + Sync {
19    /// Returns the X offset of the Bayer matrix, as defined in SensorType.
20    #[http("bayeroffsetx", method = Get)]
21    async fn bayer_offset_x(&self) -> ASCOMResult<i32> {
22        Err(ASCOMError::NOT_IMPLEMENTED)
23    }
24
25    /// Returns the Y offset of the Bayer matrix, as defined in SensorType.
26    #[http("bayeroffsety", method = Get)]
27    async fn bayer_offset_y(&self) -> ASCOMResult<i32> {
28        Err(ASCOMError::NOT_IMPLEMENTED)
29    }
30
31    /// Returns the binning factor for the X axis.
32    #[http("binx", method = Get)]
33    async fn bin_x(&self) -> ASCOMResult<i32> {
34        Err(ASCOMError::NOT_IMPLEMENTED)
35    }
36
37    /// Sets the binning factor for the X axis.
38    #[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    /// Returns the binning factor for the Y axis.
44    #[http("biny", method = Get)]
45    async fn bin_y(&self) -> ASCOMResult<i32> {
46        Err(ASCOMError::NOT_IMPLEMENTED)
47    }
48
49    /// Sets the binning factor for the Y axis.
50    #[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    /// Returns the current camera operational state as an integer.
56    #[http("camerastate", method = Get, device_state = CameraState)]
57    async fn camera_state(&self) -> ASCOMResult<CameraState> {
58        Err(ASCOMError::NOT_IMPLEMENTED)
59    }
60
61    /// Returns the width of the CCD camera chip in unbinned pixels.
62    #[http("cameraxsize", method = Get)]
63    async fn camera_xsize(&self) -> ASCOMResult<i32> {
64        Err(ASCOMError::NOT_IMPLEMENTED)
65    }
66
67    /// Returns the height of the CCD camera chip in unbinned pixels.
68    #[http("cameraysize", method = Get)]
69    async fn camera_ysize(&self) -> ASCOMResult<i32> {
70        Err(ASCOMError::NOT_IMPLEMENTED)
71    }
72
73    /// Returns true if the camera can abort exposures; false if not.
74    #[http("canabortexposure", method = Get)]
75    async fn can_abort_exposure(&self) -> ASCOMResult<bool> {
76        Ok(false)
77    }
78
79    /// Returns a flag showing whether this camera supports asymmetric binning.
80    #[http("canasymmetricbin", method = Get)]
81    async fn can_asymmetric_bin(&self) -> ASCOMResult<bool> {
82        Ok(false)
83    }
84
85    /// Indicates whether the camera has a fast readout mode.
86    #[http("canfastreadout", method = Get)]
87    async fn can_fast_readout(&self) -> ASCOMResult<bool> {
88        Ok(false)
89    }
90
91    /// If true, the camera's cooler power setting can be read.
92    #[http("cangetcoolerpower", method = Get)]
93    async fn can_get_cooler_power(&self) -> ASCOMResult<bool> {
94        Ok(false)
95    }
96
97    /// Returns a flag indicating whether this camera supports pulse guiding.
98    #[http("canpulseguide", method = Get)]
99    async fn can_pulse_guide(&self) -> ASCOMResult<bool> {
100        Ok(false)
101    }
102
103    /// Returns a flag indicatig whether this camera supports setting the CCD temperature.
104    #[http("cansetccdtemperature", method = Get)]
105    async fn can_set_ccd_temperature(&self) -> ASCOMResult<bool> {
106        Ok(false)
107    }
108
109    /// Returns a flag indicating whether this camera can stop an exposure that is in progress.
110    #[http("canstopexposure", method = Get)]
111    async fn can_stop_exposure(&self) -> ASCOMResult<bool> {
112        Ok(false)
113    }
114
115    /// Returns the current CCD temperature in degrees Celsius.
116    #[http("ccdtemperature", method = Get, device_state = CCDTemperature)]
117    async fn ccd_temperature(&self) -> ASCOMResult<f64> {
118        Err(ASCOMError::NOT_IMPLEMENTED)
119    }
120
121    /// Returns the current cooler on/off state.
122    #[http("cooleron", method = Get)]
123    async fn cooler_on(&self) -> ASCOMResult<bool> {
124        Err(ASCOMError::NOT_IMPLEMENTED)
125    }
126
127    /// Turns on and off the camera cooler.
128    ///
129    /// True = cooler on, False = cooler off.
130    #[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    /// Returns the present cooler power level, in percent.
136    #[http("coolerpower", method = Get, device_state = CoolerPower)]
137    async fn cooler_power(&self) -> ASCOMResult<f64> {
138        Err(ASCOMError::NOT_IMPLEMENTED)
139    }
140
141    /// Returns the gain of the camera in photoelectrons per A/D unit.
142    #[http("electronsperadu", method = Get)]
143    async fn electrons_per_adu(&self) -> ASCOMResult<f64> {
144        Err(ASCOMError::NOT_IMPLEMENTED)
145    }
146
147    /// Returns the maximum exposure time in seconds supported by StartExposure.
148    #[http("exposuremax", method = Get)]
149    async fn exposure_max(&self) -> ASCOMResult<f64>;
150
151    /// Returns the minimium exposure time in seconds supported by StartExposure.
152    #[http("exposuremin", method = Get)]
153    async fn exposure_min(&self) -> ASCOMResult<f64>;
154
155    /// Returns the smallest increment in exposure time supported by StartExposure.
156    #[http("exposureresolution", method = Get)]
157    async fn exposure_resolution(&self) -> ASCOMResult<f64>;
158
159    /// Returns whenther Fast Readout Mode is enabled.
160    #[http("fastreadout", method = Get)]
161    async fn fast_readout(&self) -> ASCOMResult<bool> {
162        Err(ASCOMError::NOT_IMPLEMENTED)
163    }
164
165    /// Sets whether Fast Readout Mode is enabled.
166    #[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    /// Reports the full well capacity of the camera in electrons, at the current camera settings (binning, SetupDialog settings, etc.).
172    #[http("fullwellcapacity", method = Get)]
173    async fn full_well_capacity(&self) -> ASCOMResult<f64> {
174        Err(ASCOMError::NOT_IMPLEMENTED)
175    }
176
177    /// The camera's gain (GAIN VALUE MODE) OR the index of the selected camera gain description in the Gains array (GAINS INDEX MODE).
178    #[http("gain", method = Get)]
179    async fn gain(&self) -> ASCOMResult<i32> {
180        Err(ASCOMError::NOT_IMPLEMENTED)
181    }
182
183    /// The camera's gain (GAIN VALUE MODE) OR the index of the selected camera gain description in the Gains array (GAINS INDEX MODE).
184    #[http("gain", method = Put)]
185    async fn set_gain(&self, #[http("Gain")] gain: i32) -> ASCOMResult<()> {
186        Err(ASCOMError::NOT_IMPLEMENTED)
187    }
188
189    /// Returns the maximum value of Gain.
190    #[http("gainmax", method = Get)]
191    async fn gain_max(&self) -> ASCOMResult<i32> {
192        Err(ASCOMError::NOT_IMPLEMENTED)
193    }
194
195    /// Returns the minimum value of Gain.
196    #[http("gainmin", method = Get)]
197    async fn gain_min(&self) -> ASCOMResult<i32> {
198        Err(ASCOMError::NOT_IMPLEMENTED)
199    }
200
201    /// Returns the Gains supported by the camera.
202    #[http("gains", method = Get)]
203    async fn gains(&self) -> ASCOMResult<Vec<String>> {
204        Err(ASCOMError::NOT_IMPLEMENTED)
205    }
206
207    /// Returns a flag indicating whether this camera has a mechanical shutter.
208    #[http("hasshutter", method = Get)]
209    async fn has_shutter(&self) -> ASCOMResult<bool>;
210
211    /// Returns the current heat sink temperature (called "ambient temperature" by some manufacturers) in degrees Celsius.
212    #[http("heatsinktemperature", method = Get, device_state = HeatSinkTemperature)]
213    async fn heat_sink_temperature(&self) -> ASCOMResult<f64> {
214        Err(ASCOMError::NOT_IMPLEMENTED)
215    }
216
217    /// Returns an array of 32bit integers containing the pixel values from the last exposure.
218    ///
219    /// This call can return either a 2 dimension (monochrome images) or 3 dimension (colour or multi-plane images) array  of size `NumX * NumY` or `NumX * NumY * NumPlanes`. Where applicable, the size of `NumPlanes` has to be determined by inspection of the returned array.
220    #[http("imagearray", method = Get)]
221    async fn image_array(&self) -> ASCOMResult<ImageArray> {
222        Err(ASCOMError::NOT_IMPLEMENTED)
223    }
224
225    /// Returns a flag indicating whether the image is ready to be downloaded from the camera.
226    #[http("imageready", method = Get, device_state = ImageReady)]
227    async fn image_ready(&self) -> ASCOMResult<bool> {
228        Err(ASCOMError::NOT_IMPLEMENTED)
229    }
230
231    /// Returns a flag indicating whether the camera is currrently in a PulseGuide operation.
232    #[http("ispulseguiding", method = Get, device_state = IsPulseGuiding)]
233    async fn is_pulse_guiding(&self) -> ASCOMResult<bool> {
234        Err(ASCOMError::NOT_IMPLEMENTED)
235    }
236
237    /// Reports the actual exposure duration in seconds (i.e. shutter open time).
238    #[http("lastexposureduration", method = Get)]
239    async fn last_exposure_duration(&self) -> ASCOMResult<f64> {
240        Err(ASCOMError::NOT_IMPLEMENTED)
241    }
242
243    /// Reports the actual exposure start.
244    ///
245    /// The time must be UTC.
246    #[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    /// Reports the maximum ADU value the camera can produce.
252    #[http("maxadu", method = Get)]
253    async fn max_adu(&self) -> ASCOMResult<i32>;
254
255    /// Returns the maximum allowed binning for the X camera axis.
256    #[http("maxbinx", method = Get)]
257    async fn max_bin_x(&self) -> ASCOMResult<i32> {
258        Err(ASCOMError::NOT_IMPLEMENTED)
259    }
260
261    /// Returns the maximum allowed binning for the Y camera axis.
262    #[http("maxbiny", method = Get)]
263    async fn max_bin_y(&self) -> ASCOMResult<i32> {
264        Err(ASCOMError::NOT_IMPLEMENTED)
265    }
266
267    /// Returns the current subframe width in binned pixels.
268    #[http("numx", method = Get)]
269    async fn num_x(&self) -> ASCOMResult<i32> {
270        Err(ASCOMError::NOT_IMPLEMENTED)
271    }
272
273    /// Sets the current subframe width in binned pixels.
274    #[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    /// Returns the current subframe height in binned pixels.
280    #[http("numy", method = Get)]
281    async fn num_y(&self) -> ASCOMResult<i32> {
282        Err(ASCOMError::NOT_IMPLEMENTED)
283    }
284
285    /// Sets the current subframe height in binned pixels.
286    #[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    /// Returns the camera's offset (OFFSET VALUE MODE) OR the index of the selected camera offset description in the offsets array (OFFSETS INDEX MODE).
292    #[http("offset", method = Get)]
293    async fn offset(&self) -> ASCOMResult<i32> {
294        Err(ASCOMError::NOT_IMPLEMENTED)
295    }
296
297    /// Sets the camera's offset (OFFSET VALUE MODE) OR the index of the selected camera offset description in the offsets array (OFFSETS INDEX MODE).
298    #[http("offset", method = Put)]
299    async fn set_offset(&self, #[http("Offset")] offset: i32) -> ASCOMResult<()> {
300        Err(ASCOMError::NOT_IMPLEMENTED)
301    }
302
303    /// Returns the maximum value of offset.
304    #[http("offsetmax", method = Get)]
305    async fn offset_max(&self) -> ASCOMResult<i32> {
306        Err(ASCOMError::NOT_IMPLEMENTED)
307    }
308
309    /// Returns the Minimum value of offset.
310    #[http("offsetmin", method = Get)]
311    async fn offset_min(&self) -> ASCOMResult<i32> {
312        Err(ASCOMError::NOT_IMPLEMENTED)
313    }
314
315    /// Returns the offsets supported by the camera.
316    #[http("offsets", method = Get)]
317    async fn offsets(&self) -> ASCOMResult<Vec<String>> {
318        Err(ASCOMError::NOT_IMPLEMENTED)
319    }
320
321    /// Returns the percentage of the current operation that is complete.
322    ///
323    /// If valid, returns an integer between 0 and 100, where 0 indicates 0% progress (function just started) and 100 indicates 100% progress (i.e. completion).
324    #[http("percentcompleted", method = Get, device_state = PercentCompleted)]
325    async fn percent_completed(&self) -> ASCOMResult<i32> {
326        Err(ASCOMError::NOT_IMPLEMENTED)
327    }
328
329    /// Returns the width of the CCD chip pixels in microns.
330    #[http("pixelsizex", method = Get)]
331    async fn pixel_size_x(&self) -> ASCOMResult<f64>;
332
333    /// Returns the Height of the CCD chip pixels in microns.
334    #[http("pixelsizey", method = Get)]
335    async fn pixel_size_y(&self) -> ASCOMResult<f64>;
336
337    /// ReadoutMode is an index into the array ReadoutModes and returns the desired readout mode for the camera.
338    ///
339    /// Defaults to 0 if not set.
340    #[http("readoutmode", method = Get)]
341    async fn readout_mode(&self) -> ASCOMResult<i32> {
342        Err(ASCOMError::NOT_IMPLEMENTED)
343    }
344
345    /// Sets the ReadoutMode as an index into the array ReadoutModes.
346    #[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    /// This property provides an array of strings, each of which describes an available readout mode of the camera.
352    ///
353    /// At least one string must be present in the list.
354    #[http("readoutmodes", method = Get)]
355    async fn readout_modes(&self) -> ASCOMResult<Vec<String>> {
356        Err(ASCOMError::NOT_IMPLEMENTED)
357    }
358
359    /// The name of the sensor used within the camera.
360    #[http("sensorname", method = Get)]
361    async fn sensor_name(&self) -> ASCOMResult<String> {
362        Err(ASCOMError::NOT_IMPLEMENTED)
363    }
364
365    /// Returns a value indicating whether the sensor is monochrome, or what Bayer matrix it encodes.
366    #[http("sensortype", method = Get)]
367    async fn sensor_type(&self) -> ASCOMResult<SensorType> {
368        Err(ASCOMError::NOT_IMPLEMENTED)
369    }
370
371    /// Returns the current camera cooler setpoint in degrees Celsius.
372    #[http("setccdtemperature", method = Get)]
373    async fn set_ccd_temperature(&self) -> ASCOMResult<f64> {
374        Err(ASCOMError::NOT_IMPLEMENTED)
375    }
376
377    /// Set's the camera's cooler setpoint in degrees Celsius.
378    #[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    /// Returns the current subframe start position for the X axis (0 based) in binned pixels.
388    #[http("startx", method = Get)]
389    async fn start_x(&self) -> ASCOMResult<i32>;
390
391    /// Sets the current subframe X axis start position in binned pixels.
392    #[http("startx", method = Put)]
393    async fn set_start_x(&self, #[http("StartX")] start_x: i32) -> ASCOMResult<()>;
394
395    /// Returns the current subframe start position for the Y axis (0 based) in binned pixels.
396    #[http("starty", method = Get)]
397    async fn start_y(&self) -> ASCOMResult<i32>;
398
399    /// Sets the current subframe Y axis start position in binned pixels.
400    #[http("starty", method = Put)]
401    async fn set_start_y(&self, #[http("StartY")] start_y: i32) -> ASCOMResult<()>;
402
403    /// The Camera's sub exposure duration in seconds.
404    ///
405    /// _ICameraV3 and later._
406    #[http("subexposureduration", method = Get)]
407    async fn sub_exposure_duration(&self) -> ASCOMResult<f64> {
408        Err(ASCOMError::NOT_IMPLEMENTED)
409    }
410
411    /// Sets image sub exposure duration in seconds.
412    ///
413    /// _ICameraV3 and later._
414    #[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    /// Aborts the current exposure, if any, and returns the camera to Idle state.
424    #[http("abortexposure", method = Put)]
425    async fn abort_exposure(&self) -> ASCOMResult<()> {
426        Err(ASCOMError::NOT_IMPLEMENTED)
427    }
428
429    /// Activates the Camera's mount control sytem to instruct the mount to move in a particular direction for a given period of time.
430    #[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    /// Starts an exposure.
442    ///
443    /// Use ImageReady to check when the exposure is complete.
444    #[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    /// Stops the current exposure, if any.
454    ///
455    /// If an exposure is in progress, the readout process is initiated. Ignored if readout is already in process.
456    #[http("stopexposure", method = Put)]
457    async fn stop_exposure(&self) -> ASCOMResult<()> {
458        Err(ASCOMError::NOT_IMPLEMENTED)
459    }
460
461    /// This method returns the version of the ASCOM device interface contract to which this device complies.
462    ///
463    /// Only one interface version is current at a moment in time and all new devices should be built to the latest interface version. Applications can choose which device interface versions they support and it is in their interest to support  previous versions as well as the current version to ensure thay can use the largest number of devices.
464    #[http("interfaceversion", method = Get)]
465    async fn interface_version(&self) -> ASCOMResult<i32> {
466        Ok(4_i32)
467    }
468}
469
470convenience_props!(Camera {
471    /// Returns the X and Y offsets of the Bayer matrix, as defined in SensorType.
472    bayer_offset(bayer_offset_x, bayer_offset_y): [i32; 2],
473
474    /// Returns the binning factors for the X and Y axes.
475    #[
476        /// Sets the binning factors for the X and Y axes.
477        set
478    ]
479    bin(bin_x, bin_y): [i32; 2],
480
481    /// Returns the width and height of the CCD camera chip in unbinned pixels.
482    camera_size(camera_xsize, camera_ysize): [i32; 2],
483
484    /// Returns the exposure time range in seconds supported by StartExposure.
485    exposure_range(exposure_min, exposure_max): RangeInclusive<f64>,
486
487    /// Returns the supported gain range.
488    gain_range(gain_min, gain_max): RangeInclusive<i32>,
489
490    /// Returns the maximum allowed binning for the X and Y camera axes.
491    max_bin(max_bin_x, max_bin_y): [i32; 2],
492
493    /// Returns the current subframe width and height in binned pixels.
494    #[
495        /// Sets the current subframe width and height in binned pixels.
496        set
497    ]
498    num(num_x, num_y): [i32; 2],
499
500    /// Returns the supported offset range.
501    offset_range(offset_min, offset_max): RangeInclusive<i32>,
502
503    /// Returns the width and height of the CCD chip pixels in microns.
504    pixel_size(pixel_size_x, pixel_size_y): [f64; 2],
505
506    /// Returns the current subframe start position for the X and Y axes (0 based) in binned pixels.
507    start(start_x, start_y): [i32; 2],
508});
509
510/// Camera gain mode.
511///
512/// See [ASCOM docs](https://ascom-standards.org/newdocs/camera.html#Camera.Gain) for more details on gain modes.
513#[cfg(feature = "client")]
514#[derive(Debug, Clone, PartialEq, Eq)]
515pub enum GainMode {
516    /// A range of valid Gain values.
517    Range(RangeInclusive<i32>),
518    /// A list of valid Gain values.
519    List(Vec<String>),
520}
521
522#[cfg(feature = "client")]
523impl dyn Camera {
524    /// Return the camera gain mode with valid Gain values, or `None` if Gain is not supported.
525    ///
526    /// This is a convenience method for clients aggregating following properties:
527    /// - [`gain_min`](Camera::gain_min)
528    /// - [`gain_max`](Camera::gain_max)
529    /// - [`gains`](Camera::gains)
530    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        // Try to get the gain list first.
539        Ok(match if_implemented(self.gains().await)? {
540            Some(gains) => Some(GainMode::List(gains)),
541            None => {
542                // If gain list is not supported, we fall back to the gain range.
543                if_implemented(self.gain_range().await)?.map(GainMode::Range)
544            }
545        })
546    }
547}
548
549/// Camera state.
550#[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    /// At idle state, available to start exposure.
564    Idle = 0,
565
566    /// Exposure started but waiting (for shutter, trigger, filter wheel, etc.).
567    Waiting = 1,
568
569    /// Exposure currently in progress.
570    Exposing = 2,
571
572    /// Sensor array is being read out (digitized).
573    Reading = 3,
574
575    /// Downloading data to host.
576    Download = 4,
577
578    /// Camera error condition serious enough to prevent further operations.
579    Error = 5,
580}
581
582/// The type of sensor in the camera.
583#[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    /// Single-plane monochrome sensor.
597    Monochrome = 0,
598
599    /// Multiple-plane color sensor.
600    Color = 1,
601
602    /// Single-plane Bayer matrix RGGB sensor.
603    RGGB = 2,
604
605    /// Single-plane Bayer matrix CMYG sensor.
606    CMYG = 3,
607
608    /// Single-plane Bayer matrix CMYG2 sensor.
609    CMYG2 = 4,
610
611    /// Single-plane Bayer matrix LRGB sensor.
612    LRGB = 5,
613}