1use embedded_hal::blocking::delay::DelayMs;
45use embedded_hal::blocking::spi::Transfer;
46
47use heapless::String;
48
49use super::gpio::EspControlInterface;
50use super::network::{
51 ConnectionState, Hostname, IpAddress, NetworkError, Port, Socket, TransportMode,
52};
53use super::protocol::{NinaProtocolHandler, ProtocolInterface};
54use super::wifi::Wifi;
55use super::{Error, ARRAY_LENGTH_PLACEHOLDER};
56
57const MAX_HOSTNAME_LENGTH: usize = 255;
58
59pub trait Connect<'a, S, B, C> {
63 fn connect<F: FnMut(&mut TcpClient<'a, B, C>), D: DelayMs<u16>>(
65 &mut self,
66 server: S,
67 port: Port,
68 mode: TransportMode,
69 delay: &mut D,
70 f: &mut F,
71 ) -> Result<(), Error>;
72}
73
74pub struct TcpClient<'a, B, C> {
77 pub(crate) protocol_handler: &'a mut NinaProtocolHandler<B, C>,
78 pub(crate) socket: Option<Socket>,
79 pub(crate) server_ip_address: Option<IpAddress>,
80 pub(crate) port: Port,
81 pub(crate) mode: TransportMode,
82 pub(crate) server_hostname: Option<String<MAX_HOSTNAME_LENGTH>>,
83}
84
85impl<'a, B, C> Connect<'a, IpAddress, B, C> for TcpClient<'a, B, C>
86where
87 B: Transfer<u8>,
88 C: EspControlInterface,
89{
90 fn connect<F: FnMut(&mut TcpClient<'a, B, C>), D: DelayMs<u16>>(
91 &mut self,
92 ip: IpAddress,
93 port: Port,
94 mode: TransportMode,
95 delay: &mut D,
96 f: &mut F,
97 ) -> Result<(), Error> {
98 let socket = self.get_socket()?;
99 self.socket = Some(socket);
100 self.server_ip_address = Some(ip);
101 self.server_hostname = Some(String::new());
102 self.port = port;
103 self.mode = mode;
104
105 self.connect_common(delay, f)
106 }
107}
108
109impl<'a, B, C> Connect<'a, Hostname<'_>, B, C> for TcpClient<'a, B, C>
110where
111 B: Transfer<u8>,
112 C: EspControlInterface,
113{
114 fn connect<F: FnMut(&mut TcpClient<'a, B, C>), D: DelayMs<u16>>(
115 &mut self,
116 server_hostname: Hostname,
117 port: Port,
118 mode: TransportMode,
119 delay: &mut D,
120 f: &mut F,
121 ) -> Result<(), Error> {
122 let socket = self.get_socket()?;
123 self.socket = Some(socket);
124 self.server_hostname = Some(server_hostname.into()); self.port = port;
126 self.mode = mode;
127
128 self.connect_common(delay, f)
129 }
130}
131
132impl<'a, B, C> TcpClient<'a, B, C>
133where
134 B: Transfer<u8>,
135 C: EspControlInterface,
136{
137 pub fn build(wifi: &'a mut Wifi<B, C>) -> Self {
139 Self {
140 protocol_handler: wifi.protocol_handler.get_mut(),
141 socket: None,
142 server_ip_address: None,
143 port: 0,
144 mode: TransportMode::Tcp,
145 server_hostname: Some(String::new()),
146 }
147 }
148
149 pub fn server_ip_address(&self) -> Option<IpAddress> {
152 self.server_ip_address
153 }
154
155 pub fn server_hostname(&self) -> &str {
158 self.server_hostname.as_ref().unwrap().as_str()
159 }
160
161 pub fn port(&self) -> Port {
164 self.port
165 }
166
167 pub fn mode(&self) -> TransportMode {
170 self.mode
171 }
172
173 pub fn get_socket(&mut self) -> Result<Socket, Error> {
175 self.protocol_handler.get_socket()
176 }
177
178 pub fn send_data(&mut self, data: &str) -> Result<[u8; ARRAY_LENGTH_PLACEHOLDER], Error> {
180 self.protocol_handler
181 .send_data(data, self.socket.unwrap_or_default())
182 }
183
184 fn connect_common<F: FnMut(&mut TcpClient<'a, B, C>), D: DelayMs<u16>>(
187 &mut self,
188 delay: &mut D,
189 mut f: F,
190 ) -> Result<(), Error> {
191 let socket = self.socket.unwrap_or_default();
192 let mode = self.mode;
193 let mut ip = self.server_ip_address.unwrap_or_default();
194 let hostname = self.server_hostname.as_ref().unwrap();
195 let port = self.port;
196
197 if !hostname.is_empty() {
198 ip = self
199 .protocol_handler
200 .resolve(hostname.as_str())
201 .unwrap_or_default();
202 }
203
204 self.protocol_handler
205 .start_client_tcp(socket, ip, port, &mode)?;
206
207 delay.delay_ms(250);
212
213 let mut retry_limit = 10_000;
214
215 while retry_limit > 0 {
216 match self.protocol_handler.get_client_state_tcp(socket) {
217 Ok(ConnectionState::Established) => {
218 f(self);
219
220 self.protocol_handler.stop_client_tcp(socket, &mode)?;
221
222 return Ok(());
223 }
224 Ok(_status) => {
225 delay.delay_ms(100);
226 retry_limit -= 1;
227 }
228 Err(error) => {
229 self.protocol_handler.stop_client_tcp(socket, &mode)?;
232
233 return Err(error);
234 }
235 }
236 }
237
238 self.protocol_handler.stop_client_tcp(socket, &mode)?;
239
240 Err(NetworkError::ConnectionTimeout.into())
241 }
242}