Skip to content

Commit 3f3f8b2

Browse files
committed
Add random_mac feature
- Implement random_mac feature to generate a random MAC address on startup. - Use `cargo run --features random_mac` to enable the random MAC address functionality. - This feature facilitates logging out of the BUPT-portal for debugging and development purposes. Signed-off-by: YouXam <[email protected]>
1 parent 6e0dcfc commit 3f3f8b2

File tree

5 files changed

+114
-13
lines changed

5 files changed

+114
-13
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ alloc = ["esp-idf-svc/alloc"]
2727
nightly = ["esp-idf-svc/nightly"]
2828
experimental = ["esp-idf-svc/experimental"]
2929
embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"]
30+
random_mac = ["rand"]
3031

3132
[dependencies]
3233
log = { version = "0.4", default-features = false }
@@ -41,6 +42,7 @@ embedded-svc = "0.27.1"
4142
urlencoding = "2.1.3"
4243
include_dir = "0.7.3"
4344
serde_json = "1.0.117"
45+
rand = { version = "0.8.5", optional = true }
4446

4547
[patch.crates-io]
4648
esp-idf-svc = { git = "https://github.com/YouXam/esp-idf-svc.git", branch = "fix-http-error-handling" }

frontend/src/components/Login.tsx

Lines changed: 72 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,69 @@
11
import Loading from "../assets/loading.svg"
2-
import { useState } from "preact/hooks"
2+
import { useState, useRef } from "preact/hooks"
33

44
export default function Component() {
55
const [loading, setLoading] = useState(false)
6+
const usernameRef = useRef(null)
7+
const passwordRef = useRef(null)
8+
const [errorMsg, setErrorMsg] = useState('')
9+
const [loggedIn, setLoggedIn] = useState(false)
10+
11+
async function submit(e) {
12+
e.preventDefault()
13+
setLoading(true)
14+
try {
15+
const response = await fetch('/login', {
16+
method: 'POST',
17+
headers: {
18+
'Content-Type': 'application/x-www-form-urlencoded'
19+
},
20+
body: `username=${encodeURIComponent(usernameRef.current.value)}&password=${encodeURIComponent(passwordRef.current.value)}`
21+
})
22+
const result = await response.json()
23+
if (result.code) {
24+
setErrorMsg(result.message)
25+
} else {
26+
setLoggedIn(true)
27+
}
28+
} catch (error) {
29+
console.error(error)
30+
setErrorMsg('连接失败: ' + error.message)
31+
} finally {
32+
setLoading(false)
33+
}
34+
}
35+
36+
if (loggedIn) {
37+
return (
38+
<div className="min-h-[75vh] flex flex-col items-center justify-center px-4 py-12">
39+
<div className="w-full max-w-md space-y-8">
40+
<div className="text-center">
41+
<svg
42+
className="mx-auto h-24 w-24 text-green-500"
43+
fill="none"
44+
stroke="currentColor"
45+
viewBox="0 0 24 24"
46+
xmlns="http://www.w3.org/2000/svg"
47+
>
48+
<path
49+
strokeLinecap="round"
50+
strokeLinejoin="round"
51+
strokeWidth="2"
52+
d="M5 13l4 4L19 7"
53+
></path>
54+
</svg>
55+
<h1 className="text-2xl font-bold tracking-tight text-gray-900 dark:text-gray-50">
56+
登录成功
57+
</h1>
58+
<p className="mt-2 text-xs text-gray-600 dark:text-gray-400">
59+
现在您可以断开 BYR-pet Wi-Fi 连接
60+
</p>
61+
</div>
62+
</div>
63+
</div>
64+
)
65+
}
66+
667
return (
768
<>
869
<div className="min-h-[75vh] flex flex-col items-center justify-center px-4 py-12">
@@ -15,8 +76,11 @@ export default function Component() {
1576
输入学号和校园网密码以连接 BUPT-portal
1677
</p>
1778
</div>
18-
<form className="space-y-6" action="/login" method="post">
79+
<div className="space-y-6">
1980
<div>
81+
{errorMsg && (<div className="text-red-500 dark:text-red-400 text-center text-sm mb-4">
82+
{errorMsg}
83+
</div>)}
2084
<label
2185
htmlFor="username"
2286
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
@@ -31,6 +95,7 @@ export default function Component() {
3195
className="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-50 dark:placeholder-gray-500"
3296
type="text"
3397
name="username"
98+
ref={usernameRef}
3499
/>
35100
</div>
36101
</div>
@@ -49,24 +114,24 @@ export default function Component() {
49114
className="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-50 dark:placeholder-gray-500"
50115
type="password"
51116
name="password"
117+
ref={passwordRef}
52118
/>
53119
</div>
54120
</div>
55121
<div>
56122
<button
57123
type="submit"
58124
disabled={loading}
125+
onClick={submit}
59126
className="flex w-full justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-indigo-500 dark:hover:bg-indigo-600 dark:focus:ring-indigo-600 disabled:opacity-50 disabled:cursor-not-allowed"
60127
>
61-
{ loading && <img src={Loading} className="w-5 h-5 mr-2 animate-spin" alt="loading" /> }
62-
{ loading ? "登录中..." : "连接 BUPT-portal" }
128+
{loading && <img src={Loading} className="w-5 h-5 mr-2 animate-spin" alt="loading" />}
129+
{loading ? "登录中..." : errorMsg ? "重试" : "连接 BUPT-portal"}
63130
</button>
64131
</div>
65-
</form>
132+
</div>
66133
</div>
67134
</div>
68135
</>
69-
70-
71136
)
72137
}

src/net/bupt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ fn auth(account: BuptAccount, cookie: String) -> Result<()> {
120120
})
121121
},
122122
);
123-
fatal!("BUPT-portal authentication failed: {}", reason)
123+
fatal!("BUPT-portal 认证失败: {}", reason)
124124
}
125125
},
126126
_ => fatal!("unexpected status code: {}", response.status()),

src/net/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,19 @@ fn connect_wifi_with_config(
2727
NetConfig::NormalWifi(wifi) => (AuthMethod::WPA2Personal, wifi.ssid, wifi.password),
2828
};
2929
let mut esp_wifi = EspWifi::new(modem, sysloop.clone(), Some(nvs))?;
30+
31+
#[cfg(feature = "random_mac")]
32+
{
33+
use esp_idf_svc::wifi::WifiDeviceId;
34+
let mac = generate_random_mac();
35+
log::info!("Generated random MAC: {:02X?}", mac);
36+
esp_wifi.set_mac(WifiDeviceId::Sta, mac)?;
37+
log::info!(
38+
"Set MAC address to {:02X?}",
39+
esp_wifi.get_mac(WifiDeviceId::Sta)?
40+
);
41+
}
42+
3043
let mut wifi = BlockingWifi::wrap(&mut esp_wifi, sysloop)?;
3144

3245
wifi.set_configuration(&Configuration::Client(ClientConfiguration {
@@ -113,6 +126,17 @@ enum NetConfig {
113126
NormalWifi(Wifi),
114127
}
115128

129+
#[cfg(feature = "random_mac")]
130+
pub fn generate_random_mac() -> [u8; 6] {
131+
use rand::Rng;
132+
let mut rng = rand::thread_rng();
133+
let mut mac = [0u8; 6];
134+
rng.fill(&mut mac);
135+
mac[0] &= 0xFE;
136+
mac[0] &= 0xFD;
137+
mac
138+
}
139+
116140
pub fn connect() -> Result<Box<EspWifi<'static>>> {
117141
set_target_level("wifi", log::LevelFilter::Warn)?;
118142
set_target_level("wifi_init", log::LevelFilter::Warn)?;

src/net/provisioning.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,20 @@ use embedded_svc::http::Headers;
1313
use esp_idf_hal::delay;
1414
use esp_idf_svc::{
1515
eventloop::EspSystemEventLoop,
16+
hal::prelude::Peripherals,
1617
http::{
1718
server::{EspHttpConnection, EspHttpServer, Request},
1819
Method,
1920
},
2021
io::Write,
22+
ipv4::{self, RouterConfiguration},
2123
ipv4::{Mask, Subnet},
24+
netif::{EspNetif, NetifConfiguration, NetifStack},
2225
nvs::EspDefaultNvsPartition,
2326
wifi::{
2427
self, AccessPointConfiguration, AuthMethod, BlockingWifi, ClientConfiguration, EspWifi,
2528
},
2629
};
27-
use esp_idf_svc::{
28-
hal::prelude::Peripherals,
29-
ipv4::{self, RouterConfiguration},
30-
netif::{EspNetif, NetifConfiguration, NetifStack},
31-
};
3230

3331
use include_dir::{include_dir, Dir};
3432

@@ -218,6 +216,18 @@ fn setup_ap() -> anyhow::Result<Box<EspWifi<'static>>> {
218216
custom_mac: None,
219217
})?)?;
220218

219+
#[cfg(feature = "random_mac")]
220+
{
221+
use esp_idf_svc::wifi::WifiDeviceId;
222+
let mac = super::generate_random_mac();
223+
log::info!("Generated random MAC: {:02X?}", mac);
224+
esp_wifi.set_mac(WifiDeviceId::Sta, mac)?;
225+
log::info!(
226+
"Set MAC address to {:02X?}",
227+
esp_wifi.get_mac(WifiDeviceId::Sta)?
228+
);
229+
}
230+
221231
let mut wifi = BlockingWifi::wrap(&mut esp_wifi, sys_loop)?;
222232

223233
let wifi_configuration = wifi::Configuration::Mixed(

0 commit comments

Comments
 (0)