pull/30/head
parent
c39391f4a0
commit
e617b4f283
@ -0,0 +1,144 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
require '_test_env.php'; |
||||||
|
|
||||||
|
$prod = defined('STDIN'); |
||||||
|
$root = $prod ? '' : ('http://' . ESP_IP); |
||||||
|
|
||||||
|
$menu = [ |
||||||
|
'home' => [ $prod ? '/status' : '/page_status.php', 'Home' ], |
||||||
|
'wifi' => [ $prod ? '/wifi' : '/page_wifi.php', 'WiFi config' ], |
||||||
|
'about' => [ $prod ? '/about' : '/page_about.php', 'About' ], |
||||||
|
]; |
||||||
|
|
||||||
|
$appname = 'Current Analyser'; |
||||||
|
|
||||||
|
function e($s) { |
||||||
|
return htmlspecialchars($s, ENT_HTML5|ENT_QUOTES); |
||||||
|
} |
||||||
|
|
||||||
|
?><!doctype html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
||||||
|
|
||||||
|
<title><?= e($menu[$page][1]) ?> - <?= e($appname) ?></title>
|
||||||
|
|
||||||
|
<link href="/css/app.css" rel="stylesheet"> |
||||||
|
<script src="/js/all.js"></script> |
||||||
|
<script> |
||||||
|
// server root (or URL) - used for local development with remote AJAX calls |
||||||
|
// (this needs CORS working on the target - which I added to esp-httpd) |
||||||
|
var _root = <?= json_encode($root) ?>;
|
||||||
|
</script> |
||||||
|
</head> |
||||||
|
<body class="page-<?=$page?>">
|
||||||
|
<div id="outer"> |
||||||
|
<nav id="menu"> |
||||||
|
<div id="brand" onclick="$('#menu').toggleClass('expanded')"><?= e($appname) ?></div>
|
||||||
|
<?php |
||||||
|
// generate the menu |
||||||
|
foreach($menu as $k => $m) { |
||||||
|
$sel = ($page == $k) ? ' class="selected"' : ''; |
||||||
|
$text = e($m[1]); |
||||||
|
$url = e($m[0]); |
||||||
|
echo "<a href=\"$url\"$sel>$text</a>"; |
||||||
|
} |
||||||
|
?> |
||||||
|
</nav> |
||||||
|
<div id="content"> |
||||||
|
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!doctype html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta name="viewport" content="width=device-width,shrink-to-fit=no,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0"> |
||||||
|
|
||||||
|
<title>WiFi Settings - ESP8266 Remote Terminal</title> |
||||||
|
|
||||||
|
<link rel="stylesheet" href="/css/app.css"> |
||||||
|
<script src="/js/app.js"></script> |
||||||
|
</head> |
||||||
|
<body class="page-wifi"> |
||||||
|
|
||||||
|
<img src="/img/loader.gif" alt="Loading…" id="loader"> |
||||||
|
|
||||||
|
<h1 onclick="location.href='/'">WiFi settings</h1> |
||||||
|
|
||||||
|
<div class="Box" id="wificonfbox"> |
||||||
|
<table> |
||||||
|
<tr> |
||||||
|
<th>WiFi mode</th> |
||||||
|
<td id="opmodebox">%WiFiMode%</td> |
||||||
|
</tr> |
||||||
|
<tr class="x-hide-noip x-hide-2"> |
||||||
|
<th>IP</th> |
||||||
|
<td>%StaIP%</td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<th>Switch to</th> |
||||||
|
<td id="modeswitch"></td> |
||||||
|
</tr> |
||||||
|
<tr class="x-hide-1"> |
||||||
|
<th><label for="channel">AP channel</label></th> |
||||||
|
<td> |
||||||
|
<form action="/wifi/setchannel" method="GET"> |
||||||
|
<input name="ch" id="channel" type="number" step=1 min=1 max=14 value="%WiFiChannel%"><!-- |
||||||
|
--><input type="submit" value="Set" class="narrow btn-green x-hide-3"> |
||||||
|
</form> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
<tr class="x-hide-1"> |
||||||
|
<th><label for="channel">AP name</label></th> |
||||||
|
<td> |
||||||
|
<form action="/wifi/setname" method="GET"> |
||||||
|
<input name="name" type="text" value="%APName%"><!-- |
||||||
|
--><input type="submit" value="Set" class="narrow btn-green"> |
||||||
|
</form> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
<tr><td colspan=2 style="white-space: normal;"> |
||||||
|
<p>Some changes require a reboot, dropping connection. It can take a while to re-connect.</p> |
||||||
|
<p> |
||||||
|
<b>If you lose access</b>, hold the BOOT button for 2 seconds (the Tx LED starts blinking) to re-enable AP mode. |
||||||
|
If that fails, hold the BOOT button for over 5 seconds (rapid Tx LED flashing) to perform a factory reset. |
||||||
|
<p> |
||||||
|
</td></tr> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="Box" id="ap-box"> |
||||||
|
<h2>Select AP to join</h2> |
||||||
|
<div id="ap-loader" class="x-hide-2">Scanning<span class="anim-dots">.</span></div> |
||||||
|
<div id="ap-noscan" class="x-hide-1 x-hide-3">Can't scan in AP-only mode.</div> |
||||||
|
<div id="ap-list" style="display:none"></div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<nav id="botnav"> |
||||||
|
<a href="/">Terminal</a><!-- |
||||||
|
--><a href="/help">Help</a><!-- |
||||||
|
--><a href="/about">About</a> |
||||||
|
</nav> |
||||||
|
|
||||||
|
<div class="Modal hidden" id="psk-modal"> |
||||||
|
<div class="Dialog"> |
||||||
|
<form action="/wifi/connect" method="post" id="conn-form"> |
||||||
|
<input type="hidden" id="conn-essid" name="essid"><!-- |
||||||
|
--><label for="conn-passwd">Password:</label><!-- |
||||||
|
--><input type="password" id="conn-passwd" name="passwd"><!-- |
||||||
|
--><input type="submit" value="Connect!"> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<script> |
||||||
|
_root = window.location.host; |
||||||
|
wifiInit({staSSID: '%StaSSID%', staIP: '%StaIP%', mode: '%WiFiModeNum%'}); |
||||||
|
</script> |
||||||
|
</body> |
||||||
|
</html> |
@ -1 +1 @@ |
|||||||
Subproject commit 03003ea591a272df50159ba52f84ca84c5cad78e |
Subproject commit 38c6c91f50e5a5cfba8df8309a95e814695accba |
@ -0,0 +1,654 @@ |
|||||||
|
/*
|
||||||
|
Cgi/template routines for the /wifi url. |
||||||
|
*/ |
||||||
|
|
||||||
|
/*
|
||||||
|
* ---------------------------------------------------------------------------- |
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42): |
||||||
|
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||||
|
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||||
|
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||||
|
* ---------------------------------------------------------------------------- |
||||||
|
* |
||||||
|
* File adapted and improved by Ondřej Hruška <ondra@ondrovo.com> |
||||||
|
*/ |
||||||
|
|
||||||
|
// TODO convert to work with WiFi Manager
|
||||||
|
// TODO make changes write to wificonf and apply when a different CGI is run (/wifi/apply or something)
|
||||||
|
// TODO (connection will trigger this immediately, with some delayto show the connecting page. Then polling cna proceed as usual)
|
||||||
|
|
||||||
|
#include <esp8266.h> |
||||||
|
#include "cgi_wifi.h" |
||||||
|
|
||||||
|
/** WiFi access point data */ |
||||||
|
typedef struct { |
||||||
|
char ssid[32]; |
||||||
|
char bssid[8]; |
||||||
|
int channel; |
||||||
|
char rssi; |
||||||
|
char enc; |
||||||
|
} ApData; |
||||||
|
|
||||||
|
/** Scan result type */ |
||||||
|
typedef struct { |
||||||
|
char scanInProgress; //if 1, don't access the underlying stuff from the webpage.
|
||||||
|
ApData **apData; |
||||||
|
int noAps; |
||||||
|
} ScanResultData; |
||||||
|
|
||||||
|
/** Static scan status storage. */ |
||||||
|
static ScanResultData cgiWifiAps; |
||||||
|
|
||||||
|
/** Progress of connection to AP enum */ |
||||||
|
typedef enum { |
||||||
|
CONNTRY_IDLE = 0, |
||||||
|
CONNTRY_WORKING = 1, |
||||||
|
CONNTRY_SUCCESS = 2, |
||||||
|
CONNTRY_FAIL = 3, |
||||||
|
} ConnTry; |
||||||
|
|
||||||
|
/** Connection result var */ |
||||||
|
static ConnTry connTryStatus = CONNTRY_IDLE; |
||||||
|
|
||||||
|
/** Connection to AP periodic check timer */ |
||||||
|
static os_timer_t staCheckTimer; |
||||||
|
|
||||||
|
/** reset_later() timer */ |
||||||
|
static ETSTimer resetTmr; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for reset_later() |
||||||
|
*/ |
||||||
|
static void ICACHE_FLASH_ATTR resetTmrCb(void *arg) |
||||||
|
{ |
||||||
|
system_restart(); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a reset |
||||||
|
* @param ms reset delay (milliseconds) |
||||||
|
*/ |
||||||
|
static void ICACHE_FLASH_ATTR reset_later(int ms) |
||||||
|
{ |
||||||
|
os_timer_disarm(&resetTmr); |
||||||
|
os_timer_setfn(&resetTmr, resetTmrCb, NULL); |
||||||
|
os_timer_arm(&resetTmr, ms, false); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate approximate signal strength % from RSSI |
||||||
|
*/ |
||||||
|
int ICACHE_FLASH_ATTR rssi2perc(int rssi) |
||||||
|
{ |
||||||
|
int r; |
||||||
|
|
||||||
|
if (rssi > 200) |
||||||
|
r = 100; |
||||||
|
else if (rssi < 100) |
||||||
|
r = 0; |
||||||
|
else |
||||||
|
r = 100 - 2 * (200 - rssi); // approx.
|
||||||
|
|
||||||
|
if (r > 100) r = 100; |
||||||
|
if (r < 0) r = 0; |
||||||
|
|
||||||
|
return r; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert Auth type to string |
||||||
|
*/ |
||||||
|
const ICACHE_FLASH_ATTR char *auth2str(AUTH_MODE auth) |
||||||
|
{ |
||||||
|
switch (auth) { |
||||||
|
case AUTH_OPEN: |
||||||
|
return "Open"; |
||||||
|
case AUTH_WEP: |
||||||
|
return "WEP"; |
||||||
|
case AUTH_WPA_PSK: |
||||||
|
return "WPA"; |
||||||
|
case AUTH_WPA2_PSK: |
||||||
|
return "WPA2"; |
||||||
|
case AUTH_WPA_WPA2_PSK: |
||||||
|
return "WPA/WPA2"; |
||||||
|
default: |
||||||
|
return "Unknown"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert WiFi opmode to string |
||||||
|
*/ |
||||||
|
const ICACHE_FLASH_ATTR char *opmode2str(WIFI_MODE opmode) |
||||||
|
{ |
||||||
|
switch (opmode) { |
||||||
|
case NULL_MODE: |
||||||
|
return "Disabled"; |
||||||
|
case STATION_MODE: |
||||||
|
return "Client"; |
||||||
|
case SOFTAP_MODE: |
||||||
|
return "AP only"; |
||||||
|
case STATIONAP_MODE: |
||||||
|
return "Client+AP"; |
||||||
|
default: |
||||||
|
return "Unknown"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback the code calls when a wlan ap scan is done. Basically stores the result in |
||||||
|
* the static cgiWifiAps struct. |
||||||
|
* |
||||||
|
* @param arg - a pointer to {struct bss_info}, which is a linked list of the found APs |
||||||
|
* @param status - OK if the scan succeeded |
||||||
|
*/ |
||||||
|
void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) |
||||||
|
{ |
||||||
|
int n; |
||||||
|
struct bss_info *bss_link = (struct bss_info *) arg; |
||||||
|
dbg("wifiScanDoneCb %d", status); |
||||||
|
if (status != OK) { |
||||||
|
cgiWifiAps.scanInProgress = 0; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// Clear prev ap data if needed.
|
||||||
|
if (cgiWifiAps.apData != NULL) { |
||||||
|
for (n = 0; n < cgiWifiAps.noAps; n++) free(cgiWifiAps.apData[n]); |
||||||
|
free(cgiWifiAps.apData); |
||||||
|
} |
||||||
|
|
||||||
|
// Count amount of access points found.
|
||||||
|
n = 0; |
||||||
|
while (bss_link != NULL) { |
||||||
|
bss_link = bss_link->next.stqe_next; |
||||||
|
n++; |
||||||
|
} |
||||||
|
// Allocate memory for access point data
|
||||||
|
cgiWifiAps.apData = (ApData **) malloc(sizeof(ApData *) * n); |
||||||
|
if (cgiWifiAps.apData == NULL) { |
||||||
|
error("Out of memory allocating apData"); |
||||||
|
return; |
||||||
|
} |
||||||
|
cgiWifiAps.noAps = n; |
||||||
|
info("Scan done: found %d APs", n); |
||||||
|
|
||||||
|
// Copy access point data to the static struct
|
||||||
|
n = 0; |
||||||
|
bss_link = (struct bss_info *) arg; |
||||||
|
while (bss_link != NULL) { |
||||||
|
if (n >= cgiWifiAps.noAps) { |
||||||
|
// This means the bss_link changed under our nose. Shouldn't happen!
|
||||||
|
// Break because otherwise we will write in unallocated memory.
|
||||||
|
error("Huh? I have more than the allocated %d aps!", cgiWifiAps.noAps); |
||||||
|
break; |
||||||
|
} |
||||||
|
// Save the ap data.
|
||||||
|
cgiWifiAps.apData[n] = (ApData *) malloc(sizeof(ApData)); |
||||||
|
if (cgiWifiAps.apData[n] == NULL) { |
||||||
|
error("Can't allocate mem for ap buff."); |
||||||
|
cgiWifiAps.scanInProgress = 0; |
||||||
|
return; |
||||||
|
} |
||||||
|
cgiWifiAps.apData[n]->rssi = bss_link->rssi; |
||||||
|
cgiWifiAps.apData[n]->channel = bss_link->channel; |
||||||
|
cgiWifiAps.apData[n]->enc = bss_link->authmode; |
||||||
|
strncpy(cgiWifiAps.apData[n]->ssid, (char *) bss_link->ssid, 32); |
||||||
|
strncpy(cgiWifiAps.apData[n]->bssid, (char *) bss_link->bssid, 6); |
||||||
|
|
||||||
|
bss_link = bss_link->next.stqe_next; |
||||||
|
n++; |
||||||
|
} |
||||||
|
// We're done.
|
||||||
|
cgiWifiAps.scanInProgress = 0; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Routine to start a WiFi access point scan. |
||||||
|
*/ |
||||||
|
static void ICACHE_FLASH_ATTR wifiStartScan(void) |
||||||
|
{ |
||||||
|
if (cgiWifiAps.scanInProgress) return; |
||||||
|
cgiWifiAps.scanInProgress = 1; |
||||||
|
wifi_station_scan(NULL, wifiScanDoneCb); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a |
||||||
|
* scan for access points and if available will return the result of an earlier scan. |
||||||
|
* The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl. |
||||||
|
*/ |
||||||
|
httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) |
||||||
|
{ |
||||||
|
int pos = (int) connData->cgiData; |
||||||
|
int len; |
||||||
|
char buff[256]; |
||||||
|
|
||||||
|
// 2nd and following runs of the function via MORE:
|
||||||
|
if (!cgiWifiAps.scanInProgress && pos != 0) { |
||||||
|
// Fill in json code for an access point
|
||||||
|
if (pos - 1 < cgiWifiAps.noAps) { |
||||||
|
int rssi = cgiWifiAps.apData[pos - 1]->rssi; |
||||||
|
|
||||||
|
len = sprintf(buff, "{\"essid\": \"%s\", \"bssid\": \"" |
||||||
|
MACSTR |
||||||
|
"\", \"rssi\": %d, \"rssi_perc\": %d, \"enc\": %d, \"channel\": %d}%s", |
||||||
|
cgiWifiAps.apData[pos - 1]->ssid, |
||||||
|
MAC2STR(cgiWifiAps.apData[pos - 1]->bssid), |
||||||
|
rssi, |
||||||
|
rssi2perc(rssi), |
||||||
|
cgiWifiAps.apData[pos - 1]->enc, |
||||||
|
cgiWifiAps.apData[pos - 1]->channel, |
||||||
|
(pos - 1 == cgiWifiAps.noAps - 1) ? "\n " : ",\n "); //<-terminator
|
||||||
|
|
||||||
|
httpdSend(connData, buff, len); |
||||||
|
} |
||||||
|
pos++; |
||||||
|
if ((pos - 1) >= cgiWifiAps.noAps) { |
||||||
|
len = sprintf(buff, " ]\n }\n}"); // terminate the whole object
|
||||||
|
httpdSend(connData, buff, len); |
||||||
|
// Also start a new scan.
|
||||||
|
wifiStartScan(); |
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
else { |
||||||
|
connData->cgiData = (void *) pos; |
||||||
|
return HTTPD_CGI_MORE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// First run of the function
|
||||||
|
httpdStartResponse(connData, 200); |
||||||
|
httpdHeader(connData, "Content-Type", "application/json"); |
||||||
|
httpdEndHeaders(connData); |
||||||
|
|
||||||
|
if (cgiWifiAps.scanInProgress == 1) { |
||||||
|
// We're still scanning. Tell Javascript code that.
|
||||||
|
len = sprintf(buff, "{\n \"result\": {\n \"inProgress\": 1\n }\n}"); |
||||||
|
httpdSend(connData, buff, len); |
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
else { |
||||||
|
// We have a scan result. Pass it on.
|
||||||
|
len = sprintf(buff, "{\n \"result\": {\n \"inProgress\": 0,\n \"APs\": [\n "); |
||||||
|
httpdSend(connData, buff, len); |
||||||
|
if (cgiWifiAps.apData == NULL) cgiWifiAps.noAps = 0; |
||||||
|
connData->cgiData = (void *) 1; |
||||||
|
return HTTPD_CGI_MORE; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** Temp store for new ap info. */ |
||||||
|
static struct station_config stconf; |
||||||
|
|
||||||
|
/**
|
||||||
|
* This routine is ran some time after a connection attempt to an access point. If |
||||||
|
* the connect succeeds, this gets the module in STA-only mode. |
||||||
|
*/ |
||||||
|
static void ICACHE_FLASH_ATTR staCheckConnStatus(void *arg) |
||||||
|
{ |
||||||
|
int x = wifi_station_get_connect_status(); |
||||||
|
if (x == STATION_GOT_IP) { |
||||||
|
info("Connected to AP."); |
||||||
|
connTryStatus = CONNTRY_SUCCESS; |
||||||
|
|
||||||
|
// This would enter STA only mode, but that kills the browser page if using STA+AP.
|
||||||
|
// Instead we stay in the current mode and let the user switch manually.
|
||||||
|
|
||||||
|
//wifi_set_opmode(STATION_MODE);
|
||||||
|
//system_restart();
|
||||||
|
} |
||||||
|
else { |
||||||
|
connTryStatus = CONNTRY_FAIL; |
||||||
|
error("Connection failed."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually connect to a station. This routine is timed because I had problems |
||||||
|
* with immediate connections earlier. It probably was something else that caused it, |
||||||
|
* but I can't be arsed to put the code back :P |
||||||
|
*/ |
||||||
|
static void ICACHE_FLASH_ATTR cgiWiFiConnect_do(void *arg) |
||||||
|
{ |
||||||
|
int x; |
||||||
|
dbg("Try to connect to AP..."); |
||||||
|
|
||||||
|
wifi_station_disconnect(); |
||||||
|
wifi_station_set_config(&stconf); |
||||||
|
wifi_station_connect(); |
||||||
|
|
||||||
|
x = wifi_get_opmode(); |
||||||
|
connTryStatus = CONNTRY_WORKING; |
||||||
|
if (x != STATION_MODE) { |
||||||
|
//Schedule check
|
||||||
|
os_timer_disarm(&staCheckTimer); |
||||||
|
os_timer_setfn(&staCheckTimer, staCheckConnStatus, NULL); |
||||||
|
os_timer_arm(&staCheckTimer, 15000, 0); //time out after 15 secs of trying to connect
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* This cgi uses the routines above to connect to a specific access point with the |
||||||
|
* given ESSID using the given password. |
||||||
|
* |
||||||
|
* Args: |
||||||
|
* - essid = SSID to connect to |
||||||
|
* - passwd = password to connect with |
||||||
|
*/ |
||||||
|
httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) |
||||||
|
{ |
||||||
|
char essid[128]; |
||||||
|
char passwd[128]; |
||||||
|
static os_timer_t reassTimer; |
||||||
|
|
||||||
|
if (connData->conn == NULL) { |
||||||
|
//Connection aborted. Clean up.
|
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
|
||||||
|
int ssilen = httpdFindArg(connData->post->buff, "essid", essid, sizeof(essid)); |
||||||
|
int passlen = httpdFindArg(connData->post->buff, "passwd", passwd, sizeof(passwd)); |
||||||
|
|
||||||
|
if (ssilen == -1 || passlen == -1) { |
||||||
|
error("Not rx needed args!"); |
||||||
|
httpdRedirect(connData, "/wifi"); |
||||||
|
} |
||||||
|
else { |
||||||
|
strncpy((char *) stconf.ssid, essid, 32); |
||||||
|
strncpy((char *) stconf.password, passwd, 64); |
||||||
|
info("Try to connect to AP %s pw %s", essid, passwd); |
||||||
|
|
||||||
|
//Schedule disconnect/connect
|
||||||
|
os_timer_disarm(&reassTimer); |
||||||
|
os_timer_setfn(&reassTimer, cgiWiFiConnect_do, NULL); |
||||||
|
// redirect & start connecting a little bit later
|
||||||
|
os_timer_arm(&reassTimer, 2000, 0); // was 500, increased so the connecting page has time to load
|
||||||
|
|
||||||
|
connTryStatus = CONNTRY_IDLE; |
||||||
|
httpdRedirect(connData, "/wifi/connecting"); |
||||||
|
} |
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Cgi to get connection status. |
||||||
|
* |
||||||
|
* This endpoint returns JSON with keys: |
||||||
|
* - status = 'idle', 'working' or 'fail', |
||||||
|
* - ip = IP address, after connection succeeds |
||||||
|
*/ |
||||||
|
httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) |
||||||
|
{ |
||||||
|
char buff[100]; |
||||||
|
int len; |
||||||
|
struct ip_info info; |
||||||
|
int st = wifi_station_get_connect_status(); |
||||||
|
|
||||||
|
httpdStartResponse(connData, 200); |
||||||
|
httpdHeader(connData, "Content-Type", "application/json"); |
||||||
|
httpdEndHeaders(connData); |
||||||
|
|
||||||
|
if (connTryStatus == CONNTRY_IDLE) { |
||||||
|
len = sprintf(buff, "{\"status\": \"idle\"}"); |
||||||
|
} |
||||||
|
else if (connTryStatus == CONNTRY_WORKING || connTryStatus == CONNTRY_SUCCESS) { |
||||||
|
if (st == STATION_GOT_IP) { |
||||||
|
wifi_get_ip_info(STATION_IF, &info); |
||||||
|
len = sprintf(buff, "{\"status\": \"success\", \"ip\": \"" |
||||||
|
IPSTR |
||||||
|
"\"}", GOOD_IP2STR(info.ip.addr)); |
||||||
|
os_timer_disarm(&staCheckTimer); |
||||||
|
os_timer_setfn(&staCheckTimer, staCheckConnStatus, NULL); |
||||||
|
os_timer_arm(&staCheckTimer, 1000, 0); |
||||||
|
} else { |
||||||
|
len = sprintf(buff, "{\"status\": \"working\"}"); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
len = sprintf(buff, "{\"status\": \"fail\"}"); |
||||||
|
} |
||||||
|
|
||||||
|
httpdSend(connData, buff, len); |
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Universal CGI endpoint to set WiFi params. |
||||||
|
* Note that some may cause a (delayed) restart. |
||||||
|
* |
||||||
|
* Args: |
||||||
|
* - ap_ch = channel 1-14 |
||||||
|
* - ap_ssid = SSID name for AP mode |
||||||
|
* - opmode = WiFi mode (resets device) |
||||||
|
* - hostname = set client hostname |
||||||
|
* - tpw = set transmit power |
||||||
|
* - sta_dhcp_lt = DHCP server lease time |
||||||
|
* - sta_ip = station mode static IP |
||||||
|
* - sta_mask = station mode static IP mask (apply only if 'ip' is also sent) |
||||||
|
* - sta_gw = station mode default gateway (apply only if 'ip' is also sent) |
||||||
|
* (can be left out, then 0.0.0.0 is used and outbound connections won't work - |
||||||
|
* but we're normally not making any) |
||||||
|
* - dhcp = enable or disable DHCP on the station interface |
||||||
|
*/ |
||||||
|
httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) |
||||||
|
{ |
||||||
|
int len, len2, len3; |
||||||
|
char buff[50]; |
||||||
|
char buff2[50]; |
||||||
|
char buff3[50]; |
||||||
|
|
||||||
|
// TODO change so that settings are not applied immediately, but persisted first
|
||||||
|
// TODO apply temporary changes like static IP in wifi event CBs
|
||||||
|
|
||||||
|
if (connData->conn == NULL) { |
||||||
|
//Connection aborted. Clean up.
|
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
|
||||||
|
// AP channel (applies in AP-only mode)
|
||||||
|
len = httpdFindArg(connData->getArgs, "ap_ch", buff, sizeof(buff)); |
||||||
|
if (len > 0) { |
||||||
|
info("Setting WiFi channel for AP-only mode to: %s", buff); |
||||||
|
int channel = atoi(buff); |
||||||
|
if (channel > 0 && channel < 15) { |
||||||
|
dbg("Setting channel=%d", channel); |
||||||
|
|
||||||
|
struct softap_config wificfg; |
||||||
|
wifi_softap_get_config(&wificfg); |
||||||
|
wificfg.channel = (uint8) channel; |
||||||
|
wifi_softap_set_config(&wificfg); |
||||||
|
} else { |
||||||
|
warn("Bad channel value %s, allowed 1-14", buff); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// SSID name in AP mode
|
||||||
|
len = httpdFindArg(connData->getArgs, "ap_ssid", buff, sizeof(buff)); |
||||||
|
if (len > 0) { |
||||||
|
int i; |
||||||
|
for (i = 0; i < 32; i++) { |
||||||
|
char c = buff[i]; |
||||||
|
if (c == 0) break; |
||||||
|
if (c < 32 || c >= 127) buff[i] = '_'; |
||||||
|
} |
||||||
|
buff[i] = 0; |
||||||
|
|
||||||
|
info("Setting SSID to %s", buff); |
||||||
|
|
||||||
|
struct softap_config wificfg; |
||||||
|
wifi_softap_get_config(&wificfg); |
||||||
|
sprintf((char *) wificfg.ssid, buff); |
||||||
|
wificfg.ssid_len = strlen((char *) wificfg.ssid); |
||||||
|
wifi_softap_set_config(&wificfg); |
||||||
|
} |
||||||
|
|
||||||
|
// WiFi mode
|
||||||
|
len = httpdFindArg(connData->getArgs, "opmode", buff, sizeof(buff)); |
||||||
|
if (len > 0) { |
||||||
|
dbg("Setting WiFi opmode to: %s", buff); |
||||||
|
int mode = atoi(buff); |
||||||
|
if (mode > NULL_MODE && mode < MAX_MODE) { |
||||||
|
wifi_set_opmode(mode); |
||||||
|
reset_later(200); |
||||||
|
} else { |
||||||
|
warn("Bad opmode value %s", buff); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Hostname in station mode (for DHCP)
|
||||||
|
len = httpdFindArg(connData->getArgs, "hostname", buff, sizeof(buff)); |
||||||
|
if (len > 0) { |
||||||
|
dbg("Setting station sta_hostname to: %s", buff); |
||||||
|
wifi_station_set_hostname(buff); |
||||||
|
// TODO persistency, re-apply on boot
|
||||||
|
} |
||||||
|
|
||||||
|
// Hostname in station mode (for DHCP)
|
||||||
|
len = httpdFindArg(connData->getArgs, "tpw", buff, sizeof(buff)); |
||||||
|
if (len > 0) { |
||||||
|
dbg("Setting AP power to: %s", buff); |
||||||
|
int tpw = atoi(buff); |
||||||
|
// min tpw to avoid user locking themselves out TODO verify
|
||||||
|
if (tpw >= 0 && tpw <= 82) { |
||||||
|
// TODO persistency, re-apply on boot
|
||||||
|
system_phy_set_max_tpw(tpw); |
||||||
|
} else { |
||||||
|
warn("tpw %s out of allowed range 0-82.", buff); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// DHCP server lease time
|
||||||
|
len = httpdFindArg(connData->getArgs, "ap_dhcp_lt", buff, sizeof(buff)); |
||||||
|
if (len > 0) { |
||||||
|
dbg("Setting DHCP lease time to: %s min.", buff); |
||||||
|
int min = atoi(buff); |
||||||
|
if (min >= 1 && min <= 2880) { |
||||||
|
// TODO persistency, re-apply on boot
|
||||||
|
// TODO set only if we're in the right opmode
|
||||||
|
wifi_softap_set_dhcps_lease_time(min); |
||||||
|
} else { |
||||||
|
warn("Lease time %s out of allowed range 1-2880.", buff); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// DHCP enable / disable (disable means static IP is enabled)
|
||||||
|
len = httpdFindArg(connData->getArgs, "sta_dhcp", buff, sizeof(buff)); |
||||||
|
if (len > 0) { |
||||||
|
dbg("DHCP enable = %s", buff); |
||||||
|
int enable = atoi(buff); |
||||||
|
if (enable != 0) { |
||||||
|
wifi_station_dhcpc_stop(); |
||||||
|
} else { |
||||||
|
wifi_station_dhcpc_start(); |
||||||
|
} |
||||||
|
// TODO persistency
|
||||||
|
} |
||||||
|
|
||||||
|
// Static IP
|
||||||
|
len = httpdFindArg(connData->getArgs, "sta_ip", buff, sizeof(buff)); |
||||||
|
len2 = httpdFindArg(connData->getArgs, "sta_mask", buff2, sizeof(buff2)); |
||||||
|
len3 = httpdFindArg(connData->getArgs, "sta_gw", buff3, sizeof(buff3)); |
||||||
|
if (len > 0) { |
||||||
|
// TODO set only if we're in the right opmode
|
||||||
|
// TODO persistency
|
||||||
|
dbg("Setting static IP = %s", buff); |
||||||
|
struct ip_info ipinfo; |
||||||
|
ipinfo.ip.addr = ipaddr_addr(buff); |
||||||
|
ipinfo.netmask.addr = IPADDR_NONE; |
||||||
|
ipinfo.gw.addr = IPADDR_NONE; |
||||||
|
if (len2 > 0) { |
||||||
|
dbg("Netmask = %s", buff2); |
||||||
|
ipinfo.netmask.addr = ipaddr_addr(buff2); |
||||||
|
} |
||||||
|
if (len3 > 0) { |
||||||
|
dbg("Gateway = %s", buff3); |
||||||
|
ipinfo.gw.addr = ipaddr_addr(buff3); |
||||||
|
} |
||||||
|
// TODO ...
|
||||||
|
wifi_station_dhcpc_stop(); |
||||||
|
wifi_set_ip_info(STATION_IF, &ipinfo); |
||||||
|
} |
||||||
|
|
||||||
|
httpdRedirect(connData, "/wifi"); |
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//Template code for the WLAN page.
|
||||||
|
httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) |
||||||
|
{ |
||||||
|
char buff[500]; |
||||||
|
int x; |
||||||
|
int connectStatus; |
||||||
|
static struct station_config stconf; |
||||||
|
static struct softap_config apconf; |
||||||
|
|
||||||
|
if (token == NULL) { |
||||||
|
// We're done
|
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
||||||
|
|
||||||
|
wifi_station_get_config(&stconf); |
||||||
|
wifi_softap_get_config(&apconf); |
||||||
|
|
||||||
|
|
||||||
|
strcpy(buff, "Unknown"); |
||||||
|
if (streq(token, "WiFiMode")) { |
||||||
|
x = wifi_get_opmode(); |
||||||
|
strcpy(buff, opmode2str(x)); |
||||||
|
} |
||||||
|
else if (streq(token, "WiFiModeNum")) { |
||||||
|
x = wifi_get_opmode(); |
||||||
|
sprintf(buff, "%d", x); |
||||||
|
} |
||||||
|
else if (streq(token, "WiFiChannel")) { |
||||||
|
sprintf(buff, "%d", apconf.channel); |
||||||
|
} |
||||||
|
else if (streq(token, "APName")) { |
||||||
|
sprintf(buff, "%s", apconf.ssid); |
||||||
|
} |
||||||
|
else if (streq(token, "StaIP")) { |
||||||
|
x = wifi_get_opmode(); |
||||||
|
connectStatus = wifi_station_get_connect_status(); |
||||||
|
|
||||||
|
if (x == SOFTAP_MODE || connectStatus != STATION_GOT_IP) { |
||||||
|
strcpy(buff, ""); |
||||||
|
} |
||||||
|
else { |
||||||
|
struct ip_info info; |
||||||
|
wifi_get_ip_info(STATION_IF, &info); |
||||||
|
sprintf(buff, IPSTR, GOOD_IP2STR(info.ip.addr)); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (streq(token, "StaSSID")) { |
||||||
|
connectStatus = wifi_station_get_connect_status(); |
||||||
|
x = wifi_get_opmode(); |
||||||
|
if (x == SOFTAP_MODE || connectStatus != STATION_GOT_IP) { |
||||||
|
strcpy(buff, ""); |
||||||
|
} |
||||||
|
else { |
||||||
|
strcpy(buff, (char *) stconf.ssid); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (streq(token, "WiFiPasswd")) { |
||||||
|
strcpy(buff, (char *) stconf.password); |
||||||
|
} |
||||||
|
else if (streq(token, "WiFiapwarn")) { |
||||||
|
// TODO get rid of this
|
||||||
|
x = wifi_get_opmode(); |
||||||
|
if (x == SOFTAP_MODE) { // 2
|
||||||
|
strcpy(buff, "<a href=\"/wifi/setmode?mode=3\">Enable client</a> for scanning."); |
||||||
|
} |
||||||
|
else if (x == STATIONAP_MODE) { // 3
|
||||||
|
strcpy(buff, |
||||||
|
"Switch: <a href=\"/wifi/setmode?mode=1\">Client only</a>, <a href=\"/wifi/setmode?mode=2\">AP only</a>"); |
||||||
|
} |
||||||
|
else { // 1
|
||||||
|
strcpy(buff, |
||||||
|
"Switch: <a href=\"/wifi/setmode?mode=3\">Client+AP</a>, <a href=\"/wifi/setmode?mode=2\">AP only</a>"); |
||||||
|
} |
||||||
|
} |
||||||
|
httpdSend(connData, buff, -1); |
||||||
|
return HTTPD_CGI_DONE; |
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
#ifndef CGIWIFI_H |
||||||
|
#define CGIWIFI_H |
||||||
|
|
||||||
|
#include "httpd.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert IP hex to arguments for printf. |
||||||
|
* Library IP2STR(ip) does not work correctly due to unaligned memory access. |
||||||
|
*/ |
||||||
|
#define GOOD_IP2STR(ip) ((ip)>>0)&0xff, ((ip)>>8)&0xff, ((ip)>>16)&0xff, ((ip)>>24)&0xff |
||||||
|
|
||||||
|
httpd_cgi_state cgiWiFiScan(HttpdConnData *connData); |
||||||
|
httpd_cgi_state cgiWiFiConnect(HttpdConnData *connData); |
||||||
|
httpd_cgi_state cgiWiFiConnStatus(HttpdConnData *connData); |
||||||
|
httpd_cgi_state cgiWiFiSetParams(HttpdConnData *connData); |
||||||
|
httpd_cgi_state tplWlan(HttpdConnData *connData, char *token, void **arg); |
||||||
|
|
||||||
|
// WiFi config options:
|
||||||
|
// - Persistent
|
||||||
|
// - channel
|
||||||
|
// - AP ssid
|
||||||
|
// - opmode
|
||||||
|
// - AP to connect to
|
||||||
|
// - Temporary
|
||||||
|
// - sta_hostname (sta)
|
||||||
|
// - tpw (ap, sta+ap?)
|
||||||
|
// - dhcp_lt (ap, sta+ap)
|
||||||
|
// - static IP
|
||||||
|
// - static mask
|
||||||
|
// - static gw
|
||||||
|
// - dhcp enable or disable
|
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,194 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/07/08.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "wifi_manager.h" |
||||||
|
|
||||||
|
WiFiSettingsBlock wificonf; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore defaults in the WiFi config block. |
||||||
|
* This is to be called if the WiFi config is corrupted on startup, |
||||||
|
* before applying the config. |
||||||
|
*/ |
||||||
|
void wifimgr_restore_defaults(void) |
||||||
|
{ |
||||||
|
u8 mac[6]; |
||||||
|
wifi_get_macaddr(SOFTAP_IF, mac); |
||||||
|
|
||||||
|
wificonf.opmode = STATIONAP_MODE; |
||||||
|
wificonf.tpw = 20; |
||||||
|
wificonf.ap_channel = 1; |
||||||
|
sprintf((char *) wificonf.ap_ssid, "TERM-%02X%02X%02X", mac[3], mac[4], mac[5]); |
||||||
|
wificonf.ap_password[0] = 0; // PSK2 always if password is not null.
|
||||||
|
wificonf.ap_dhcp_lease_time = 120; |
||||||
|
wificonf.ap_hidden = false; |
||||||
|
|
||||||
|
IP4_ADDR(&wificonf.ap_ip.ip, 192, 168, mac[5], 1); |
||||||
|
IP4_ADDR(&wificonf.ap_ip.netmask, 255, 255, 255, 0); |
||||||
|
IP4_ADDR(&wificonf.ap_ip.gw, 192, 168, mac[5], 1); |
||||||
|
|
||||||
|
// --- Client config ---
|
||||||
|
wificonf.sta_ssid[0] = 0; |
||||||
|
wificonf.sta_password[0] = 0; |
||||||
|
//sprintf((char *) wificonf.sta_ssid, "Chlivek");
|
||||||
|
//sprintf((char *) wificonf.sta_password, "prase chrochta");
|
||||||
|
strcpy((char *) wificonf.sta_hostname, (char *) wificonf.ap_ssid); // use the same value for sta_hostname as AP name
|
||||||
|
wificonf.sta_dhcp_enable = true; |
||||||
|
|
||||||
|
IP4_ADDR(&wificonf.sta_ip.ip, 192, 168, 0, (mac[5]==1?2:mac[5]));// avoid being the same as "default gw"
|
||||||
|
IP4_ADDR(&wificonf.sta_ip.netmask, 255, 255, 255, 0); |
||||||
|
IP4_ADDR(&wificonf.sta_ip.gw, 192, 168, 0, 1); |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler |
||||||
|
*/ |
||||||
|
void wifimgr_event_cb(System_Event_t *event) |
||||||
|
{ |
||||||
|
switch (event->event) { |
||||||
|
// case EVENT_STAMODE_CONNECTED:
|
||||||
|
// EVENT_STAMODE_DISCONNECTED,
|
||||||
|
// EVENT_STAMODE_AUTHMODE_CHANGE,
|
||||||
|
// EVENT_STAMODE_GOT_IP,
|
||||||
|
// EVENT_STAMODE_DHCP_TIMEOUT,
|
||||||
|
// EVENT_SOFTAPMODE_STACONNECTED,
|
||||||
|
// EVENT_SOFTAPMODE_STADISCONNECTED,
|
||||||
|
// EVENT_SOFTAPMODE_PROBEREQRECVED,
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void configure_station(void) |
||||||
|
{ |
||||||
|
info("[WiFi] Configuring Station mode..."); |
||||||
|
struct station_config conf; |
||||||
|
strcpy((char *) conf.ssid, (char *) wificonf.sta_ssid); |
||||||
|
strcpy((char *) conf.password, (char *) wificonf.sta_password); |
||||||
|
dbg("[WiFi] Connecting to \"%s\", password \"%s\"", conf.ssid, conf.password); |
||||||
|
conf.bssid_set = 0; |
||||||
|
conf.bssid[0] = 0; |
||||||
|
wifi_station_disconnect(); |
||||||
|
wifi_station_set_config_current(&conf); |
||||||
|
dbg("[WiFi] Hostname = %s", wificonf.sta_hostname); |
||||||
|
wifi_station_set_hostname((char*)wificonf.sta_hostname); |
||||||
|
|
||||||
|
if (wificonf.sta_dhcp_enable) { |
||||||
|
dbg("[WiFi] Starting DHCP..."); |
||||||
|
if (!wifi_station_dhcpc_start()) { |
||||||
|
error("[WiFi] DHCp failed to start!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
info("[WiFi] Setting up static IP..."); |
||||||
|
dbg("[WiFi] Client.ip = "IPSTR, GOOD_IP2STR(wificonf.sta_ip.ip.addr)); |
||||||
|
dbg("[WiFi] Client.mask = "IPSTR, GOOD_IP2STR(wificonf.sta_ip.netmask.addr)); |
||||||
|
dbg("[WiFi] Client.gw = "IPSTR, GOOD_IP2STR(wificonf.sta_ip.gw.addr)); |
||||||
|
|
||||||
|
wifi_station_dhcpc_stop(); |
||||||
|
// Load static IP config
|
||||||
|
if (!wifi_set_ip_info(STATION_IF, &wificonf.sta_ip)) { |
||||||
|
error("[WiFi] Error setting static IP!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
info("[WiFi] Trying to connect to AP..."); |
||||||
|
wifi_station_connect(); |
||||||
|
} |
||||||
|
|
||||||
|
static void configure_ap(void) |
||||||
|
{ |
||||||
|
bool suc; |
||||||
|
|
||||||
|
info("[WiFi] Configuring SoftAP mode..."); |
||||||
|
// AP is enabled
|
||||||
|
struct softap_config conf; |
||||||
|
conf.channel = wificonf.ap_channel; |
||||||
|
strcpy((char *) conf.ssid, (char *) wificonf.ap_ssid); |
||||||
|
strcpy((char *) conf.password, (char *) wificonf.ap_password); |
||||||
|
conf.authmode = (wificonf.ap_password[0] == 0 ? AUTH_OPEN : AUTH_WPA2_PSK); |
||||||
|
conf.ssid_len = strlen((char *) conf.ssid); |
||||||
|
conf.ssid_hidden = wificonf.ap_hidden; |
||||||
|
conf.max_connection = 4; // default 4 (max possible)
|
||||||
|
conf.beacon_interval = 100; // default 100 ms
|
||||||
|
|
||||||
|
// Set config
|
||||||
|
//ETS_UART_INTR_DISABLE();
|
||||||
|
suc = wifi_softap_set_config_current(&conf); |
||||||
|
//ETS_UART_INTR_ENABLE();
|
||||||
|
if (!suc) { |
||||||
|
error("[WiFi] AP config set fail!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// Set IP
|
||||||
|
info("[WiFi] Configuring SoftAP local IP..."); |
||||||
|
dbg("[WiFi] SoftAP.ip = "IPSTR, GOOD_IP2STR(wificonf.ap_ip.ip.addr)); |
||||||
|
dbg("[WiFi] SoftAP.mask = "IPSTR, GOOD_IP2STR(wificonf.ap_ip.netmask.addr)); |
||||||
|
dbg("[WiFi] SoftAP.gw = "IPSTR, GOOD_IP2STR(wificonf.ap_ip.gw.addr)); |
||||||
|
|
||||||
|
wifi_softap_dhcps_stop(); |
||||||
|
|
||||||
|
// Configure DHCP
|
||||||
|
if (!wifi_set_ip_info(SOFTAP_IF, &wificonf.ap_ip)) { |
||||||
|
error("[WiFi] IP set fail!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
info("[WiFi] Configuring SoftAP DHCP server..."); |
||||||
|
struct dhcps_lease dhcp_lease; |
||||||
|
struct ip_addr ip; |
||||||
|
ip.addr = wificonf.ap_ip.ip.addr; |
||||||
|
ip.addr = (ip.addr & 0x00FFFFFFUL) | ((((ip.addr >> 24) & 0xFF) + 99UL) << 24); |
||||||
|
dhcp_lease.start_ip.addr = ip.addr; |
||||||
|
ip.addr = (ip.addr & 0x00FFFFFFUL) | ((((ip.addr >> 24) & 0xFF) + 100UL) << 24); |
||||||
|
dhcp_lease.end_ip.addr = ip.addr; |
||||||
|
|
||||||
|
dbg("[WiFi] DHCP.start = "IPSTR, GOOD_IP2STR(dhcp_lease.start_ip.addr)); |
||||||
|
dbg("[WiFi] DHCP.end = "IPSTR, GOOD_IP2STR(dhcp_lease.end_ip.addr)); |
||||||
|
dbg("[WiFi] DHCP.lease = %d minutes", wificonf.ap_dhcp_lease_time); |
||||||
|
|
||||||
|
if (!wifi_softap_set_dhcps_lease(&dhcp_lease)) { |
||||||
|
error("[WiFi] DHCP address range set fail!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (!wifi_softap_set_dhcps_lease_time(wificonf.ap_dhcp_lease_time)) { |
||||||
|
error("[WiFi] DHCP lease time set fail!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// some weird magic shit about router
|
||||||
|
uint8 mode = 1; |
||||||
|
wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode); |
||||||
|
|
||||||
|
if (!wifi_softap_dhcps_start()) { |
||||||
|
error("[WiFi] Failed to start DHCP server!"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the WiFi event listener, cycle WiFi, apply settings |
||||||
|
*/ |
||||||
|
void wifimgr_apply_settings(void) |
||||||
|
{ |
||||||
|
info("[WiFi] Initializing WiFi manager..."); |
||||||
|
// wifi_set_event_handler_cb(wifimgr_event_cb);
|
||||||
|
|
||||||
|
// Force wifi cycle
|
||||||
|
dbg("[WiFi] WiFi reset to apply new settings"); |
||||||
|
wifi_set_opmode(NULL_MODE); |
||||||
|
wifi_set_opmode(wificonf.opmode); |
||||||
|
|
||||||
|
// Configure the client
|
||||||
|
if (wificonf.opmode == STATIONAP_MODE || wificonf.opmode == STATION_MODE) { |
||||||
|
configure_station(); |
||||||
|
} |
||||||
|
|
||||||
|
// Configure the AP
|
||||||
|
if (wificonf.opmode == STATIONAP_MODE || wificonf.opmode == SOFTAP_MODE) { |
||||||
|
configure_ap(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/07/08.
|
||||||
|
// This module handles all WiFi configuration and is interfaced
|
||||||
|
// by the cgi_wifi functions.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESP_VT100_FIRMWARE_WIFI_MANAGER_H |
||||||
|
#define ESP_VT100_FIRMWARE_WIFI_MANAGER_H |
||||||
|
|
||||||
|
#include <esp8266.h> |
||||||
|
#include "cgi_wifi.h" |
||||||
|
|
||||||
|
/**
|
||||||
|
* A structure holding all configured WiFi parameters |
||||||
|
* and the active state. |
||||||
|
* |
||||||
|
* This block can be used eg. for WiFi config backup. |
||||||
|
*/ |
||||||
|
typedef struct { |
||||||
|
WIFI_MODE opmode : 32; |
||||||
|
u8 sta_hostname[32]; |
||||||
|
u32 tpw; |
||||||
|
|
||||||
|
// --- AP config ---
|
||||||
|
u32 ap_channel; // 32 for alignment, needs 8
|
||||||
|
u8 ap_ssid[32]; |
||||||
|
u8 ap_password[32]; |
||||||
|
u32 ap_hidden; |
||||||
|
u32 ap_dhcp_lease_time; // in minutes
|
||||||
|
|
||||||
|
struct ip_info ap_ip; |
||||||
|
|
||||||
|
// --- Client config ---
|
||||||
|
u8 sta_ssid[32]; |
||||||
|
u8 sta_password[64]; |
||||||
|
u32 sta_dhcp_enable; |
||||||
|
|
||||||
|
struct ip_info sta_ip; |
||||||
|
} WiFiSettingsBlock; |
||||||
|
|
||||||
|
extern WiFiSettingsBlock wificonf; |
||||||
|
|
||||||
|
void wifimgr_restore_defaults(void); |
||||||
|
|
||||||
|
void wifimgr_apply_settings(void); |
||||||
|
|
||||||
|
#endif //ESP_VT100_FIRMWARE_WIFI_MANAGER_H
|
Loading…
Reference in new issue