use rand::{thread_rng, Rng};
use refimage::GenericImageOwned;
use std::collections::HashMap;
use crate::AnyGenCam;
#[allow(unused_imports)]
use crate::GenCam;
use crate::GenCamCtrl;
use crate::GenCamDescriptor;
use crate::GenCamError;
use crate::GenCamResult;
use crate::GenCamRoi;
use crate::GenCamState;
use crate::Property;
use crate::PropertyValue;
use serde::{Deserialize, Serialize};
pub type GenSrvOutput = GenCamResult<GenSrvValue>;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum GenSrvValue {
Unit,
Info(GenCamDescriptor),
Property {
value: PropertyValue,
auto: Option<bool>,
},
Image(GenericImageOwned),
Roi(GenCamRoi),
State(GenCamState),
PropertyList(HashMap<GenCamCtrl, Property>),
}
impl From<()> for GenSrvValue {
fn from(_: ()) -> Self {
GenSrvValue::Unit
}
}
impl From<&GenCamDescriptor> for GenSrvValue {
fn from(info: &GenCamDescriptor) -> Self {
GenSrvValue::Info(info.clone())
}
}
impl From<GenCamDescriptor> for GenSrvValue {
fn from(info: GenCamDescriptor) -> Self {
GenSrvValue::Info(info)
}
}
impl From<(PropertyValue, bool)> for GenSrvValue {
fn from(value: (PropertyValue, bool)) -> Self {
let (value, auto) = value;
GenSrvValue::Property {
value,
auto: Some(auto),
}
}
}
impl From<(&PropertyValue, bool)> for GenSrvValue {
fn from(value: (&PropertyValue, bool)) -> Self {
let (value, auto) = value;
GenSrvValue::Property {
value: value.clone(),
auto: Some(auto),
}
}
}
impl From<PropertyValue> for GenSrvValue {
fn from(value: PropertyValue) -> Self {
GenSrvValue::Property { value, auto: None }
}
}
impl From<GenericImageOwned> for GenSrvValue {
fn from(image: GenericImageOwned) -> Self {
GenSrvValue::Image(image)
}
}
impl From<GenCamRoi> for GenSrvValue {
fn from(roi: GenCamRoi) -> Self {
GenSrvValue::Roi(roi)
}
}
impl From<GenCamState> for GenSrvValue {
fn from(state: GenCamState) -> Self {
GenSrvValue::State(state)
}
}
impl From<HashMap<GenCamCtrl, Property>> for GenSrvValue {
fn from(properties: HashMap<GenCamCtrl, Property>) -> Self {
GenSrvValue::PropertyList(properties)
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum GenSrvCmd {
Vendor,
CameraReady,
CameraName,
Info,
ListProperties,
GetProperty(GenCamCtrl),
SetProperty(GenCamCtrl, PropertyValue, bool),
CancelCapture,
IsCapturing,
Capture,
StartExposure,
DownloadImage,
ImageReady,
CameraState,
SetRoi(GenCamRoi),
GetRoi,
}
#[derive(Debug, Default)]
pub struct GenCamServer {
cameras: HashMap<u32, AnyGenCam>,
infos: HashMap<u32, GenCamDescriptor>,
}
impl GenCamServer {
pub fn add_camera(&mut self, camera: AnyGenCam) -> GenCamResult<u32> {
let id = thread_rng().gen();
let info = camera.info()?.clone();
self.cameras.insert(id, camera);
self.infos.insert(id, info);
Ok(id)
}
pub fn get_camera(&self, id: u32) -> Option<&AnyGenCam> {
self.cameras.get(&id)
}
pub fn get_camera_mut(&mut self, id: u32) -> Option<&mut AnyGenCam> {
self.cameras.get_mut(&id)
}
pub fn remove_camera(&mut self, id: u32) -> Option<AnyGenCam> {
self.cameras.remove(&id)
}
pub fn num_cameras(&self) -> usize {
self.cameras.len()
}
pub fn list_cameras(&self) -> &HashMap<u32, GenCamDescriptor> {
&self.infos
}
pub fn execute_fn(&mut self, id: u32, sig: GenSrvCmd) -> GenCamResult<GenSrvValue> {
let Some(camera) = self.get_camera_mut(id) else {
return Err(GenCamError::InvalidId(id as _));
};
use GenSrvCmd::*;
let res = match sig {
Vendor => {
let vendor = camera.vendor();
PropertyValue::EnumStr(vendor.to_string()).into()
}
CameraReady => {
let ready = camera.camera_ready();
PropertyValue::Bool(ready).into()
}
CameraName => {
let name = camera.camera_name();
PropertyValue::EnumStr(name.to_string()).into()
}
Info => {
let info = camera.info()?.clone();
info.into()
}
ListProperties => {
let properties = camera.list_properties();
GenSrvValue::PropertyList(properties.clone())
}
GetProperty(ctrl) => camera.get_property(ctrl)?.into(),
SetProperty(ctrl, value, auto) => camera.set_property(ctrl, &value, auto)?.into(),
CancelCapture => camera.cancel_capture()?.into(),
IsCapturing => PropertyValue::Bool(camera.is_capturing()).into(),
Capture => GenSrvValue::Image(camera.capture()?.into()),
StartExposure => camera.start_exposure()?.into(),
DownloadImage => GenSrvValue::Image(camera.download_image()?.into()),
ImageReady => PropertyValue::Bool(camera.image_ready()?).into(),
CameraState => camera.camera_state()?.into(),
SetRoi(roi) => (*camera.set_roi(&roi)?).into(),
GetRoi => (*camera.get_roi()).into(),
};
Ok(res)
}
}