esp8266_wifi_serial/
softap.rs

1use core::{fmt::Debug, format_args};
2
3use embedded_hal::serial;
4use serde::{Deserialize, Serialize};
5use simple_clock::SimpleClock;
6
7use crate::{Error, Module, NetworkSession};
8
9/// WiFi modes that supported by this module.
10#[repr(u8)]
11#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, Eq)]
12pub enum WifiMode {
13    /// Open network mode without any encryption.
14    Open = 0,
15    /// WPA PSK encryption mode.
16    WpaPsk = 2,
17    /// WPA2 PSK encryption mode.
18    Wpa2Psk = 3,
19    /// Both WPA PSK and WPA2 PSK encryption modes.
20    WpaWpa2Psk = 4,
21}
22
23/// Software access point configuration parameters.
24#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize, Eq)]
25pub struct SoftApConfig<'a> {
26    /// Access point SSID.
27    pub ssid: &'a str,
28    /// Access point password.
29    ///
30    /// This field will be ignored if WiFi mode is open.
31    pub password: &'a str,
32    /// Channel number.
33    pub channel: u8,
34    /// WiFi mode.
35    pub mode: WifiMode,
36}
37
38impl<'a> SoftApConfig<'a> {
39    /// Creates a software access point with the configuration parameters and establishes
40    /// a new WiFi session.
41    pub fn start<Rx, Tx, C, const N: usize>(
42        self,
43        mut module: Module<Rx, Tx, C, N>,
44    ) -> crate::Result<NetworkSession<Rx, Tx, C, N>>
45    where
46        Rx: serial::Read<u8> + 'static,
47        Tx: serial::Write<u8> + 'static,
48        C: SimpleClock,
49    {
50        self.init(&mut module)?;
51        Ok(NetworkSession::new(module))
52    }
53
54    fn init<Rx, Tx, C, const N: usize>(
55        &self,
56        module: &mut Module<Rx, Tx, C, N>,
57    ) -> crate::Result<()>
58    where
59        Rx: serial::Read<u8> + 'static,
60        Tx: serial::Write<u8> + 'static,
61        C: SimpleClock,
62    {
63        // Enable SoftAP+Station mode.
64        module
65            .send_at_command("AT+CWMODE=3")?
66            .expect("Malformed command");
67
68        // Enable multiple connections.
69        module
70            .send_at_command("AT+CIPMUX=1")?
71            .expect("Malformed command");
72
73        // Start SoftAP.
74        module
75            .send_at_command(format_args!(
76                "AT+CWSAP=\"{}\",\"{}\",{},{}",
77                self.ssid, self.password, self.channel, self.mode as u8,
78            ))?
79            .expect("Malformed command");
80
81        Ok(())
82    }
83}
84
85/// Configuration parameters describe a connection to the existing access point.
86#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
87pub struct JoinApConfig<'a> {
88    /// Access point SSID.
89    pub ssid: &'a str,
90    /// Access point password.
91    pub password: &'a str,
92}
93
94impl<'a> JoinApConfig<'a> {
95    /// Joins to the existing access point and establishing a new WiFi session.
96    pub fn join<Rx, Tx, C, const N: usize>(
97        self,
98        mut module: Module<Rx, Tx, C, N>,
99    ) -> crate::Result<NetworkSession<Rx, Tx, C, N>>
100    where
101        Rx: serial::Read<u8> + 'static,
102        Tx: serial::Write<u8> + 'static,
103        C: SimpleClock,
104    {
105        self.init(&mut module)?;
106        Ok(NetworkSession::new(module))
107    }
108
109    fn init<Rx, Tx, C, const N: usize>(
110        &self,
111        module: &mut Module<Rx, Tx, C, N>,
112    ) -> crate::Result<()>
113    where
114        Rx: serial::Read<u8> + 'static,
115        Tx: serial::Write<u8> + 'static,
116        C: SimpleClock,
117    {
118        // Enable Station mode.
119        module
120            .send_at_command("AT+CWMODE=1")?
121            .expect("Malformed command");
122
123        // Enable multiple connections.
124        module
125            .send_at_command("AT+CIPMUX=1")?
126            .expect("Malformed command");
127
128        // Join the given access point.
129        module
130            .send_at_command(format_args!(
131                "AT+CWJAP=\"{}\",\"{}\"",
132                self.ssid, self.password,
133            ))?
134            .map_err(|_| Error::JoinApError)?;
135
136        Ok(())
137    }
138}