sim7020/at_command/
http.rs

1use crate::at_command::{AtRequest, AtResponse, BufferType};
2use crate::AtError;
3use at_commands::builder::CommandBuilder;
4use at_commands::parser::CommandParser;
5
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7#[derive(Debug)]
8pub struct HttpClient {
9    pub client_id: u8,
10}
11
12pub struct HttpSession<'a> {
13    pub client_id: u8,
14    pub successful: bool,
15    pub host: &'a str,
16}
17
18/// create a HTTP or HTTPS session
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub struct GetHttpSessions {}
21
22impl AtRequest for GetHttpSessions {
23    type Response = ();
24
25    fn get_command<'a>(&'a self, buffer: &'a mut BufferType) -> Result<&'a [u8], usize> {
26        let cmd = CommandBuilder::create_query(buffer, true)
27            .named(b"+CHTTPCREATE")
28            .finish();
29        cmd
30    }
31
32    fn parse_response(&self, data: &[u8]) -> Result<AtResponse, AtError> {
33        let connections = CommandParser::parse(data)
34            .expect_identifier(b"\r\n+CHTTPCREATE: ")
35            .expect_int_parameter()
36            .expect_int_parameter()
37            .expect_raw_string()
38            .expect_identifier(b"\r\n+CHTTPCREATE: ")
39            .expect_int_parameter()
40            .expect_int_parameter()
41            .expect_raw_string()
42            .expect_identifier(b"\r\n+CHTTPCREATE: ")
43            .expect_int_parameter()
44            .expect_int_parameter()
45            .expect_raw_string()
46            .expect_identifier(b"\r\n+CHTTPCREATE: ")
47            .expect_int_parameter()
48            .expect_int_parameter()
49            .expect_raw_string()
50            .finish()?;
51        let (cid0, state0, _, cid1, state1, _, cid2, state2, _, cid3, state3, _) = connections;
52        Ok(AtResponse::HttpSessions(
53            cid0 as u8,
54            state0 != 0,
55            cid1 as u8,
56            state1 != 0,
57            cid2 as u8,
58            state2 != 0,
59            cid3 as u8,
60            state3 != 0,
61        ))
62    }
63}
64
65/// create a HTTP or HTTPS session
66#[cfg_attr(feature = "defmt", derive(defmt::Format))]
67pub struct CreateHttpSession<'a> {
68    pub host: &'a str,
69    pub user: Option<&'a str>,
70    pub password: Option<&'a str>,
71}
72
73impl AtRequest for CreateHttpSession<'_> {
74    type Response = Result<(), AtError>;
75
76    fn get_command<'a>(&'a self, buffer: &'a mut BufferType) -> Result<&'a [u8], usize> {
77        at_commands::builder::CommandBuilder::create_set(buffer, true)
78            .named("+CHTTPCREATE")
79            .with_string_parameter(self.host)
80            // todo: optional parameters need to be fixed
81            // .with_optional_string_parameter(self.user)
82            // .with_optional_string_parameter(self.password)
83            .finish()
84    }
85
86    fn parse_response(&self, data: &[u8]) -> Result<AtResponse, AtError> {
87        let (client_id,) = at_commands::parser::CommandParser::parse(data)
88            .expect_identifier(b"\r\n+CHTTPCREATE: ")
89            .expect_int_parameter()
90            .expect_identifier(b"\r\n\r\nOK\r\n")
91            .finish()?;
92        Ok(AtResponse::HTTPSessionCreated(client_id as u8))
93    }
94}
95
96/// Connect to a server using http or https
97#[cfg_attr(feature = "defmt", derive(defmt::Format))]
98pub struct HttpConnect {
99    pub client_id: u8,
100}
101
102impl AtRequest for HttpConnect {
103    type Response = Result<(), AtError>;
104
105    fn get_command<'a>(&'a self, buffer: &'a mut BufferType) -> Result<&'a [u8], usize> {
106        at_commands::builder::CommandBuilder::create_set(buffer, true)
107            .named("+CHTTPCON")
108            .with_int_parameter(self.client_id)
109            .finish()
110    }
111}
112
113/// Disconnect from a server
114#[cfg_attr(feature = "defmt", derive(defmt::Format))]
115pub struct HttpDisconnect {
116    pub client_id: u8,
117}
118
119impl AtRequest for HttpDisconnect {
120    type Response = Result<(), AtError>;
121
122    fn get_command<'a>(&'a self, buffer: &'a mut BufferType) -> Result<&'a [u8], usize> {
123        at_commands::builder::CommandBuilder::create_set(buffer, true)
124            .named("+CHTTPDISCON")
125            .with_int_parameter(self.client_id)
126            .finish()
127    }
128}
129
130/// Connect to a server using http or https
131#[cfg_attr(feature = "defmt", derive(defmt::Format))]
132pub struct HttpDestroy {
133    pub client_id: u8,
134}
135
136impl AtRequest for HttpDestroy {
137    type Response = Result<(), AtError>;
138
139    fn get_command<'a>(&'a self, buffer: &'a mut BufferType) -> Result<&'a [u8], usize> {
140        at_commands::builder::CommandBuilder::create_set(buffer, true)
141            .named("+CHTTPDESTROY")
142            .with_int_parameter(self.client_id)
143            .finish()
144    }
145}
146
147#[cfg_attr(feature = "defmt", derive(defmt::Format))]
148#[repr(u8)]
149pub enum HttpMethod {
150    GET = 0,
151    POST = 1,
152    PUT = 2,
153    DELETE = 3,
154}
155
156/// customer_header: The string converted from customer header hex data
157/// content_type: A string indicate the content type of the content, if the method is not POST and PUT, it must be empty.
158/// content_string: The string converted from content hex data.
159#[cfg_attr(feature = "defmt", derive(defmt::Format))]
160pub struct HttpSend<'a> {
161    pub client_id: u8,
162    pub method: HttpMethod,
163    pub path: &'a str,
164}
165
166impl AtRequest for HttpSend<'_> {
167    type Response = Result<(), AtError>;
168
169    fn get_command<'a>(&'a self, buffer: &'a mut BufferType) -> Result<&'a [u8], usize> {
170        let method: u8 = match self.method {
171            HttpMethod::GET => 0,
172            HttpMethod::POST => 1,
173            HttpMethod::PUT => 2,
174            HttpMethod::DELETE => 3,
175        };
176
177        at_commands::builder::CommandBuilder::create_set(buffer, true)
178            .named("+CHTTPSEND")
179            .with_int_parameter(self.client_id)
180            .with_int_parameter(method)
181            .with_string_parameter(self.path)
182            // .with_optional_string_parameter(self.customer_header)
183            // .with_optional_string_parameter(self.content_type)
184            // .with_optional_string_parameter(self.content_string)
185            .finish()
186    }
187}