|
7 | 7 | //! (PD) on the OSDP bus. It can send commands to and receive events from PDs.
|
8 | 8 |
|
9 | 9 | use crate::{
|
10 |
| - file::OsdpFileOps, OsdpCommand, OsdpError, OsdpEvent, OsdpFlag, PdCapability, PdId, PdInfo, |
| 10 | + file::OsdpFileOps, Channel, OsdpCommand, OsdpError, OsdpEvent, OsdpFlag, PdCapability, PdId, |
| 11 | + PdInfoBuilder, |
11 | 12 | };
|
12 | 13 | use alloc::{boxed::Box, vec::Vec};
|
13 | 14 | use core::ffi::c_void;
|
@@ -64,27 +65,58 @@ fn cp_setup(info: Vec<crate::OsdpPdInfoHandle>) -> Result<*mut c_void> {
|
64 | 65 | }
|
65 | 66 | }
|
66 | 67 |
|
67 |
| -/// OSDP CP device context. |
68 |
| -#[derive(Debug)] |
69 |
| -pub struct ControlPanel { |
70 |
| - ctx: *mut core::ffi::c_void, |
| 68 | +/// Builder for creating a new `ControlPanel`. |
| 69 | +#[derive(Debug, Default)] |
| 70 | +pub struct ControlPanelBuilder { |
| 71 | + channel_pds: Vec<(Box<dyn Channel>, Vec<PdInfoBuilder>)>, |
71 | 72 | }
|
72 | 73 |
|
73 |
| -unsafe impl Send for ControlPanel {} |
| 74 | +impl ControlPanelBuilder { |
| 75 | + /// Create a new instance of [`ControlPanelBuilder`]. |
| 76 | + pub const fn new() -> Self { |
| 77 | + Self { |
| 78 | + channel_pds: Vec::new(), |
| 79 | + } |
| 80 | + } |
74 | 81 |
|
75 |
| -impl ControlPanel { |
76 |
| - /// Create a new CP context for the list of PDs described by the [`PdInfo`] vector. |
77 |
| - pub fn new(pd_info: Vec<PdInfo>) -> Result<Self> { |
78 |
| - if pd_info.len() > 126 { |
| 82 | + /// Add a new PDs and their shared channel to the CP. |
| 83 | + pub fn add_channel(mut self, channel: Box<dyn Channel>, pd_info: Vec<PdInfoBuilder>) -> Self { |
| 84 | + self.channel_pds.push((channel, pd_info)); |
| 85 | + self |
| 86 | + } |
| 87 | + |
| 88 | + /// Build the [`ControlPanel`] instance. |
| 89 | + pub fn build(self) -> Result<ControlPanel> { |
| 90 | + if self.channel_pds.len() > 126 { |
79 | 91 | return Err(OsdpError::PdInfo("max PD count exceeded"));
|
80 | 92 | }
|
81 |
| - let info: Vec<crate::OsdpPdInfoHandle> = pd_info.into_iter().map(|i| i.into()).collect(); |
| 93 | + let info: Vec<crate::OsdpPdInfoHandle> = self |
| 94 | + .channel_pds |
| 95 | + .into_iter() |
| 96 | + .map(|(channel, pd_info)| { |
| 97 | + let channel: libosdp_sys::osdp_channel = channel.into(); |
| 98 | + pd_info |
| 99 | + .into_iter() |
| 100 | + .map(move |pd| pd.channel(channel).build().into()) |
| 101 | + }) |
| 102 | + .flatten() |
| 103 | + .collect(); |
82 | 104 | unsafe { libosdp_sys::osdp_set_log_callback(Some(log_handler)) };
|
83 |
| - Ok(Self { |
| 105 | + Ok(ControlPanel { |
84 | 106 | ctx: cp_setup(info)?,
|
85 | 107 | })
|
86 | 108 | }
|
| 109 | +} |
| 110 | + |
| 111 | +/// OSDP CP device context. |
| 112 | +#[derive(Debug)] |
| 113 | +pub struct ControlPanel { |
| 114 | + ctx: *mut core::ffi::c_void, |
| 115 | +} |
87 | 116 |
|
| 117 | +unsafe impl Send for ControlPanel {} |
| 118 | + |
| 119 | +impl ControlPanel { |
88 | 120 | /// The application must call this method periodically to refresh the
|
89 | 121 | /// underlying LibOSDP state. To meet the OSDP timing guarantees, this
|
90 | 122 | /// function must be called at least once every 50ms. This method does not
|
|
0 commit comments