1use crate::classes::{DcPowerSupply, Dmm, FunctionGenerator};
2use instrument_core::connect::ConnectOptions;
3use instrument_core::diagnostics::{CommsObserver, DeviceHealth, Diagnostics};
4use instrument_core::error::Result;
5use instrument_core::kind::InstrumentKind;
6use instrument_core::session::{
7 ensure_kind_supported, InstrumentSession, SessionOpener, SessionPool,
8};
9use instrument_core::DiscoveredDevice;
10use std::sync::{Arc, Mutex};
11
12#[derive(Clone)]
14pub struct DeviceRef {
15 pub(crate) device: DiscoveredDevice,
16 pub(crate) opener: Arc<dyn SessionOpener>,
17 pub(crate) connect_options: ConnectOptions,
18 pub(crate) health: Arc<Mutex<DeviceHealth>>,
19 pub(crate) observer: Option<Arc<dyn CommsObserver>>,
20}
21
22impl DeviceRef {
23 pub fn discovered(&self) -> &DiscoveredDevice {
24 &self.device
25 }
26
27 pub fn address(&self) -> &instrument_core::ResourceAddress {
28 &self.device.address
29 }
30
31 pub fn supported_kinds(&self) -> &[InstrumentKind] {
32 &self.device.supported_kinds
33 }
34
35 pub fn connect_options(&self) -> &ConnectOptions {
36 &self.connect_options
37 }
38
39 pub fn health(&self) -> DeviceHealth {
40 self.health.lock().unwrap().clone()
41 }
42
43 pub fn with_connect_options(mut self, opts: ConnectOptions) -> Self {
44 self.connect_options = opts;
45 self
46 }
47
48 fn diagnostics(&self) -> Diagnostics {
49 let mut diag = Diagnostics::new(&self.device.address.raw).with_health(self.health.clone());
50 if let Some(observer) = &self.observer {
51 diag = diag.with_observer(observer.clone());
52 }
53 diag
54 }
55
56 pub fn open_session(&self) -> Result<InstrumentSession> {
58 let transport = self
59 .opener
60 .open(&self.device.address, &self.connect_options)?;
61 InstrumentSession::new_with_diagnostics(
62 self.device.address.clone(),
63 transport,
64 self.connect_options.clone(),
65 self.device.identity.clone(),
66 Some(self.diagnostics()),
67 )
68 }
69
70 pub fn session_pool(&self) -> Result<SessionPool> {
71 Ok(SessionPool::new(self.open_session()?))
72 }
73
74 pub fn open_dmm(&self) -> Result<Dmm> {
75 ensure_kind_supported(
76 &self.device.address,
77 InstrumentKind::Dmm,
78 &self.device.supported_kinds,
79 )?;
80 Ok(Dmm::new(self.open_session()?))
81 }
82
83 pub fn open_dc_power_supply(&self) -> Result<DcPowerSupply> {
84 ensure_kind_supported(
85 &self.device.address,
86 InstrumentKind::DcPowerSupply,
87 &self.device.supported_kinds,
88 )?;
89 Ok(DcPowerSupply::new(self.open_session()?))
90 }
91
92 pub fn open_function_generator(&self) -> Result<FunctionGenerator> {
93 ensure_kind_supported(
94 &self.device.address,
95 InstrumentKind::FunctionGenerator,
96 &self.device.supported_kinds,
97 )?;
98 Ok(FunctionGenerator::new(self.open_session()?))
99 }
100
101 pub fn open_untyped(&self) -> Result<InstrumentSession> {
102 self.open_session()
103 }
104}