generic_camera/
server.rs

1/*!
2 * # Generic Camera Server
3 * This module contains the implementation of a generic camera server that can manage multiple cameras.
4 */
5use rand::{thread_rng, Rng};
6use refimage::GenericImageOwned;
7use std::collections::HashMap;
8
9use crate::AnyGenCam;
10#[allow(unused_imports)]
11use crate::GenCam;
12use crate::GenCamCtrl;
13use crate::GenCamDescriptor;
14use crate::GenCamError;
15use crate::GenCamResult;
16use crate::GenCamRoi;
17use crate::GenCamState;
18use crate::Property;
19use crate::PropertyValue;
20use serde::{Deserialize, Serialize};
21
22/// The result of a generic camera server call.
23pub type GenSrvOutput = GenCamResult<GenSrvValue>;
24
25/// The Ok variant of a generic camera server call.
26#[derive(Clone, Debug, Serialize, Deserialize)]
27pub enum GenSrvValue {
28    /// No return value.
29    Unit,
30    /// Camera information in a [`GenCamDescriptor`].
31    Info(GenCamDescriptor),
32    /// A single [`PropertyValue`].
33    Property {
34        /// The value of the property.
35        value: PropertyValue,
36        /// The auto setting of the property, if applicable.
37        auto: Option<bool>,
38    },
39    /// A captured image from the camera.
40    Image(GenericImageOwned),
41    /// Region of interest defined on the camera.
42    Roi(GenCamRoi),
43    /// The current state of the camera.
44    State(GenCamState),
45    /// A list of properties available on the camera.
46    PropertyList(HashMap<GenCamCtrl, Property>),
47}
48
49impl From<()> for GenSrvValue {
50    fn from(_: ()) -> Self {
51        GenSrvValue::Unit
52    }
53}
54
55impl From<&GenCamDescriptor> for GenSrvValue {
56    fn from(info: &GenCamDescriptor) -> Self {
57        GenSrvValue::Info(info.clone())
58    }
59}
60
61impl From<GenCamDescriptor> for GenSrvValue {
62    fn from(info: GenCamDescriptor) -> Self {
63        GenSrvValue::Info(info)
64    }
65}
66
67impl From<(PropertyValue, bool)> for GenSrvValue {
68    fn from(value: (PropertyValue, bool)) -> Self {
69        let (value, auto) = value;
70        GenSrvValue::Property {
71            value,
72            auto: Some(auto),
73        }
74    }
75}
76
77impl From<(&PropertyValue, bool)> for GenSrvValue {
78    fn from(value: (&PropertyValue, bool)) -> Self {
79        let (value, auto) = value;
80        GenSrvValue::Property {
81            value: value.clone(),
82            auto: Some(auto),
83        }
84    }
85}
86
87impl From<PropertyValue> for GenSrvValue {
88    fn from(value: PropertyValue) -> Self {
89        GenSrvValue::Property { value, auto: None }
90    }
91}
92
93impl From<GenericImageOwned> for GenSrvValue {
94    fn from(image: GenericImageOwned) -> Self {
95        GenSrvValue::Image(image)
96    }
97}
98
99impl From<GenCamRoi> for GenSrvValue {
100    fn from(roi: GenCamRoi) -> Self {
101        GenSrvValue::Roi(roi)
102    }
103}
104
105impl From<GenCamState> for GenSrvValue {
106    fn from(state: GenCamState) -> Self {
107        GenSrvValue::State(state)
108    }
109}
110
111impl From<HashMap<GenCamCtrl, Property>> for GenSrvValue {
112    fn from(properties: HashMap<GenCamCtrl, Property>) -> Self {
113        GenSrvValue::PropertyList(properties)
114    }
115}
116
117/// The possible calls that can be made to a generic camera server.
118#[derive(Clone, Debug, Serialize, Deserialize)]
119pub enum GenSrvCmd {
120    /// Get the vendor of the camera. Calls the [`GenCam::vendor`] method.
121    Vendor,
122    /// Check if the camera is ready. Calls the [`GenCam::camera_ready`] method.
123    CameraReady,
124    /// Get the name of the camera. Calls the [`GenCam::camera_name`] method.
125    CameraName,
126    /// Get the camera info. Calls the [`GenCam::info`] method.
127    Info,
128    /// List all properties available on the camera. Calls the [`GenCam::list_properties`] method.
129    ListProperties,
130    /// Get a specific property from the camera. Calls the [`GenCam::get_property`] method.
131    GetProperty(GenCamCtrl),
132    /// Set a specific property on the camera. Calls the [`GenCam::set_property`] method.
133    SetProperty(GenCamCtrl, PropertyValue, bool),
134    /// Cancel a capture in progress. Calls the [`GenCam::cancel_capture`] method.
135    CancelCapture,
136    /// Check if the camera is currently capturing. Calls the [`GenCam::is_capturing`] method.
137    IsCapturing,
138    /// Capture an image from the camera. Calls the [`GenCam::capture`] method.
139    Capture,
140    /// Start an exposure on the camera. Calls the [`GenCam::start_exposure`] method.
141    StartExposure,
142    /// Download an image from the camera. Calls the [`GenCam::download_image`] method.
143    DownloadImage,
144    /// Check if an image is ready to be downloaded. Calls the [`GenCam::image_ready`] method.
145    ImageReady,
146    /// Get the current state of the camera. Calls the [`GenCam::camera_state`] method.
147    CameraState,
148    /// Set the region of interest on the camera. Calls the [`GenCam::set_roi`] method.
149    SetRoi(GenCamRoi),
150    /// Get the current region of interest. Calls the [`GenCam::get_roi`] method.
151    GetRoi,
152}
153
154/// A generic camera server that can manage multiple cameras.
155///
156/// Once a camera is added to the server, it can be accessed by its assigned ID.
157///
158/// # Examples
159/// ```rust,ignore
160/// use generic_camera::server::GenCamServer;
161/// use generic_camera::GenCam;
162///
163/// let mut server = GenCamServer::default();
164/// let id = server.add_camera(...);
165/// ```
166#[derive(Debug, Default)]
167pub struct GenCamServer {
168    cameras: HashMap<u32, AnyGenCam>,
169    infos: HashMap<u32, GenCamDescriptor>,
170}
171
172impl GenCamServer {
173    /// Add a camera to the server and return the camera's assigned ID.
174    pub fn add_camera(&mut self, camera: AnyGenCam) -> GenCamResult<u32> {
175        let id = thread_rng().gen();
176        let info = camera.info()?.clone();
177        self.cameras.insert(id, camera);
178        self.infos.insert(id, info);
179        Ok(id)
180    }
181
182    /// Get a reference to a camera by its ID.
183    pub fn get_camera(&self, id: u32) -> Option<&AnyGenCam> {
184        self.cameras.get(&id)
185    }
186
187    /// Get a mutable reference to a camera by its ID.
188    pub fn get_camera_mut(&mut self, id: u32) -> Option<&mut AnyGenCam> {
189        self.cameras.get_mut(&id)
190    }
191
192    /// Remove a camera from the server by its ID.
193    pub fn remove_camera(&mut self, id: u32) -> Option<AnyGenCam> {
194        self.cameras.remove(&id)
195    }
196
197    /// Get the number of cameras currently connected to the server.
198    pub fn num_cameras(&self) -> usize {
199        self.cameras.len()
200    }
201
202    /// Get the camera information map.
203    pub fn list_cameras(&self) -> &HashMap<u32, GenCamDescriptor> {
204        &self.infos
205    }
206
207    /// Execute a client call on a camera by its ID.
208    pub fn execute_fn(&mut self, id: u32, sig: GenSrvCmd) -> GenCamResult<GenSrvValue> {
209        let Some(camera) = self.get_camera_mut(id) else {
210            return Err(GenCamError::InvalidId(id as _));
211        };
212        use GenSrvCmd::*;
213        let res = match sig {
214            Vendor => {
215                let vendor = camera.vendor();
216                PropertyValue::EnumStr(vendor.to_string()).into()
217            }
218            CameraReady => {
219                let ready = camera.camera_ready();
220                PropertyValue::Bool(ready).into()
221            }
222            CameraName => {
223                let name = camera.camera_name();
224                PropertyValue::EnumStr(name.to_string()).into()
225            }
226            Info => {
227                let info = camera.info()?.clone();
228                info.into()
229            }
230            ListProperties => {
231                let properties = camera.list_properties();
232                GenSrvValue::PropertyList(properties.clone())
233            }
234            GetProperty(ctrl) => camera.get_property(ctrl)?.into(),
235            SetProperty(ctrl, value, auto) => camera.set_property(ctrl, &value, auto)?.into(),
236            CancelCapture => camera.cancel_capture()?.into(),
237            IsCapturing => PropertyValue::Bool(camera.is_capturing()).into(),
238            Capture => GenSrvValue::Image(camera.capture()?.into()),
239            StartExposure => camera.start_exposure()?.into(),
240            DownloadImage => GenSrvValue::Image(camera.download_image()?.into()),
241            ImageReady => PropertyValue::Bool(camera.image_ready()?).into(),
242            CameraState => camera.camera_state()?.into(),
243            SetRoi(roi) => (*camera.set_roi(&roi)?).into(),
244            GetRoi => (*camera.get_roi()).into(),
245        };
246        Ok(res)
247    }
248}