1use s7_comm::ItemRequest;
2use serde::{Deserialize, Serialize};
3
4use crate::Error;
5use std::ops::Deref;
6
7type S7Area = s7_comm::Area;
8#[derive(
10 Debug, Copy, Clone, Serialize, Deserialize,
11)]
12#[allow(dead_code)]
13pub enum Area {
14 ProcessInput(DataSizeType),
15 ProcessOutput(DataSizeType),
16 DataBausteine(u16, DataSizeType),
28 V(DataSizeType), }
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::DataBausteine(_, _) => {
92 S7Area::DataBlocks
93 }, }
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 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 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 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 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}