s7_client/client/
request_param.rs

1use s7_comm::ItemRequest;
2use serde::{Deserialize, Serialize};
3
4use crate::Error;
5use std::ops::Deref;
6
7type S7Area = s7_comm::Area;
8// Area ID
9#[derive(
10    Debug, Copy, Clone, Serialize, Deserialize,
11)]
12#[allow(dead_code)]
13pub enum Area {
14    ProcessInput(DataSizeType),
15    ProcessOutput(DataSizeType),
16    /// Merkers are address registers within the
17    /// CPU. The number of available flag
18    /// bytes depends on the respective CPU and
19    /// can be taken from the technical data.
20    /// You can use flag bits, flag bytes, flag
21    /// words or flag double words in a PLC
22    /// program.
23    // Merker,
24    /// German thing, means building blocks
25    /// This is your storage  : db number,
26    /// DataSizeType
27    DataBausteine(u16, DataSizeType),
28    V(DataSizeType), /* Counter,
29                      * Timer, */
30}
31
32impl Into<ItemRequest> for Area {
33    fn into(self) -> ItemRequest {
34        match &self {
35            Area::ProcessInput(ds) => {
36                ItemRequest::new(
37                    s7_comm::TransportSize::Byte,
38                    s7_comm::DbNumber::NotIn,
39                    S7Area::ProcessInput,
40                    ds.byte_addr(),
41                    ds.bit_addr(),
42                    ds.len(),
43                )
44            },
45            Area::ProcessOutput(ds) => {
46                ItemRequest::new(
47                    s7_comm::TransportSize::Byte,
48                    s7_comm::DbNumber::NotIn,
49                    S7Area::ProcessOutput,
50                    ds.byte_addr(),
51                    ds.bit_addr(),
52                    ds.len(),
53                )
54            },
55            Area::V(ds) => ItemRequest::new(
56                s7_comm::TransportSize::Byte,
57                s7_comm::DbNumber::DbNumber(1),
58                S7Area::DataBlocks,
59                ds.byte_addr(),
60                ds.bit_addr(),
61                ds.len(),
62            ),
63            Area::DataBausteine(
64                db_number,
65                ds,
66            ) => ItemRequest::new(
67                s7_comm::TransportSize::Byte,
68                s7_comm::DbNumber::DbNumber(
69                    *db_number,
70                ),
71                S7Area::DataBlocks,
72                ds.byte_addr(),
73                ds.bit_addr(),
74                ds.len(),
75            ),
76        }
77    }
78}
79
80impl Area {
81    pub fn area_data(&self) -> S7Area {
82        match &self {
83            Area::ProcessInput(_) => {
84                S7Area::ProcessInput
85            },
86            Area::ProcessOutput(_) => {
87                S7Area::ProcessOutput
88            },
89            Area::V(_) => S7Area::DataBlocks,
90            // Area::Merker => {0x83}
91            Area::DataBausteine(_, _) => {
92                S7Area::DataBlocks
93            }, /* Area::Counter => {0x1C}
94                * Area::Timer => {0x1D} */
95        }
96    }
97
98    pub fn db_number(&self) -> u16 {
99        match self {
100            Area::ProcessInput(_) => 0,
101            Area::ProcessOutput(_) => 0,
102            Area::V(_) => 1,
103            Area::DataBausteine(db_number, _) => {
104                *db_number
105            },
106        }
107    }
108}
109impl Deref for Area {
110    type Target = DataSizeType;
111
112    fn deref(&self) -> &Self::Target {
113        match self {
114            Area::ProcessInput(val) => val,
115            Area::ProcessOutput(val) => val,
116            Area::V(val) => val,
117            Area::DataBausteine(_, val) => val,
118        }
119    }
120}
121#[derive(
122    Debug, Copy, Clone, Serialize, Deserialize,
123)]
124#[repr(u8)]
125pub enum BitAddr {
126    Addr0 = 0,
127    Addr1 = 1,
128    Addr2 = 2,
129    Addr3 = 3,
130    Addr4 = 4,
131    Addr5 = 5,
132    Addr6 = 6,
133    Addr7 = 7,
134}
135impl TryFrom<u16> for BitAddr {
136    type Error = Error;
137
138    fn try_from(
139        value: u16,
140    ) -> Result<Self, Self::Error> {
141        match value {
142            0 => Ok(Self::Addr0),
143            1 => Ok(Self::Addr1),
144            2 => Ok(Self::Addr2),
145            3 => Ok(Self::Addr3),
146            4 => Ok(Self::Addr4),
147            5 => Ok(Self::Addr5),
148            6 => Ok(Self::Addr6),
149            7 => Ok(Self::Addr7),
150            val => {
151                Err(Error::InvalidBitAddr(val))
152            },
153        }
154    }
155}
156
157#[derive(
158    Debug, Copy, Clone, Serialize, Deserialize,
159)]
160pub enum DataSizeType {
161    Bit { addr: u16, bit_addr: BitAddr },
162    Byte { addr: u16, len: u16 },
163    Char { addr: u16, len: u16 },
164    Word { addr: u16, len: u16 },
165    Int { addr: u16, len: u16 },
166    DWord { addr: u16, len: u16 },
167    DInt { addr: u16, len: u16 },
168    Real { addr: u16, len: u16 },
169    Counter { addr: u16, len: u16 },
170    Timer { addr: u16, len: u16 },
171}
172impl DataSizeType {
173    /// 类型对应的字节长度
174    pub fn length(&self) -> u16 {
175        use DataSizeType::*;
176        match self {
177            Bit { .. }
178            | Byte { .. }
179            | Char { .. } => 1,
180            Word { .. }
181            | Int { .. }
182            | Counter { .. }
183            | Timer { .. } => 2,
184            DWord { .. }
185            | DInt { .. }
186            | Real { .. } => 4,
187        }
188    }
189
190    /// 位的偏移位置
191    pub fn bit_addr(&self) -> u8 {
192        use DataSizeType::*;
193        match self {
194            Bit { bit_addr, .. } => {
195                *bit_addr as u8
196            },
197            _ => 0x00,
198        }
199    }
200
201    /// 读取的单位长度
202    pub fn len(&self) -> u16 {
203        use DataSizeType::*;
204        match self {
205            Bit { .. } => 1u16,
206            Byte { len, .. } => *len,
207            Char { len, .. } => *len,
208            Word { len, .. } => *len,
209            Int { len, .. } => *len,
210            DWord { len, .. } => *len,
211            DInt { len, .. } => *len,
212            Real { len, .. } => *len,
213            Counter { len, .. } => *len,
214            Timer { len, .. } => *len,
215        }
216    }
217
218    /// 用于返回后的byte长度 = 读取长度 *
219    /// 单位字节数
220    pub fn byte_len(&self) -> usize {
221        (self.len() * self.length()) as usize
222    }
223
224    pub fn addr(&self) -> [u8; 3] {
225        use DataSizeType::*;
226        let byte_addr = match self {
227            Bit { addr, .. } => *addr,
228            Byte { addr, .. } => *addr,
229            Char { addr, .. } => *addr,
230            Word { addr, .. } => *addr,
231            Int { addr, .. } => *addr,
232            DWord { addr, .. } => *addr,
233            DInt { addr, .. } => *addr,
234            Real { addr, .. } => *addr,
235            Counter { addr, .. } => *addr,
236            Timer { addr, .. } => *addr,
237        };
238        let address = ((byte_addr as u32) << 3)
239            + self.bit_addr() as u32;
240        [
241            ((address & 0x00FF0000) >> 16) as u8,
242            ((address & 0x0000FF00) >> 8) as u8,
243            (address & 0x000000FF) as u8,
244        ]
245    }
246
247    pub fn byte_addr(&self) -> u16 {
248        use DataSizeType::*;
249        match self {
250            Bit { addr, .. } => *addr,
251            Byte { addr, .. } => *addr,
252            Char { addr, .. } => *addr,
253            Word { addr, .. } => *addr,
254            Int { addr, .. } => *addr,
255            DWord { addr, .. } => *addr,
256            DInt { addr, .. } => *addr,
257            Real { addr, .. } => *addr,
258            Counter { addr, .. } => *addr,
259            Timer { addr, .. } => *addr,
260        }
261    }
262
263    pub fn data(&self) -> u8 {
264        use DataSizeType::*;
265        match self {
266            Bit { .. } => 0x01,
267            Byte { .. } => 0x02,
268            Char { .. } => 0x03,
269            Word { .. } => 0x04,
270            Int { .. } => 0x05,
271            DWord { .. } => 0x06,
272            DInt { .. } => 0x07,
273            Real { .. } => 0x08,
274            Counter { .. } => 0x1C,
275            Timer { .. } => 0x1D,
276        }
277    }
278}