ESP8266 系統與 WiFi 資訊
蒐集列出基本的系統資訊的取得處理,及 WiFi 的。而本文分成幾個區段,但使用上是合併起來的。
因為使用 ESP8266,WiFi 的使用便不可少,能獲取的資訊也不少,所以也會附上創建 AP/STA 模式,及創建 HTTP Server/Client。
系統與 WiFi 的常數
const char * const RST_REASONS[] =
{
"REASON_DEFAULT_RST",
"REASON_WDT_RST",
"REASON_EXCEPTION_RST",
"REASON_SOFT_WDT_RST",
"REASON_SOFT_RESTART",
"REASON_DEEP_SLEEP_AWAKE",
"REASON_EXT_SYS_RST"
};
const char * const FLASH_SIZE_MAP_NAMES[] =
{
"FLASH_SIZE_4M_MAP_256_256",
"FLASH_SIZE_2M",
"FLASH_SIZE_8M_MAP_512_512",
"FLASH_SIZE_16M_MAP_512_512",
"FLASH_SIZE_32M_MAP_512_512",
"FLASH_SIZE_16M_MAP_1024_1024",
"FLASH_SIZE_32M_MAP_1024_1024"
};
const char * const OP_MODE_NAMES[]
{
"NULL_MODE",
"STATION_MODE",
"SOFTAP_MODE",
"STATIONAP_MODE"
};
const char * const AUTH_MODE_NAMES[]
{
"AUTH_OPEN",
"AUTH_WEP",
"AUTH_WPA_PSK",
"AUTH_WPA2_PSK",
"AUTH_WPA_WPA2_PSK",
"AUTH_MAX"
};
const char * const PHY_MODE_NAMES[]
{
"",
"PHY_MODE_11B",
"PHY_MODE_11G",
"PHY_MODE_11N"
};
const char * const EVENT_NAMES[]
{
"EVENT_STAMODE_CONNECTED",
"EVENT_STAMODE_DISCONNECTED",
"EVENT_STAMODE_AUTHMODE_CHANGE",
"EVENT_STAMODE_GOT_IP",
"EVENT_SOFTAPMODE_STACONNECTED",
"EVENT_SOFTAPMODE_STADISCONNECTED",
"EVENT_MAX"
};
const char * const EVENT_REASONS[]
{
"",
"REASON_UNSPECIFIED",
"REASON_AUTH_EXPIRE",
"REASON_AUTH_LEAVE",
"REASON_ASSOC_EXPIRE",
"REASON_ASSOC_TOOMANY",
"REASON_NOT_AUTHED",
"REASON_NOT_ASSOCED",
"REASON_ASSOC_LEAVE",
"REASON_ASSOC_NOT_AUTHED",
"REASON_DISASSOC_PWRCAP_BAD",
"REASON_DISASSOC_SUPCHAN_BAD",
"REASON_IE_INVALID",
"REASON_MIC_FAILURE",
"REASON_4WAY_HANDSHAKE_TIMEOUT",
"REASON_GROUP_KEY_UPDATE_TIMEOUT",
"REASON_IE_IN_4WAY_DIFFERS",
"REASON_GROUP_CIPHER_INVALID",
"REASON_PAIRWISE_CIPHER_INVALID",
"REASON_AKMP_INVALID",
"REASON_UNSUPP_RSN_IE_VERSION",
"REASON_INVALID_RSN_IE_CAP",
"REASON_802_1X_AUTH_FAILED",
"REASON_CIPHER_SUITE_REJECTED",
};
取得基本系統資訊
void print_system_info(Stream & consolePort)
{
const rst_info * resetInfo = system_get_rst_info();
consolePort.print(F("system_get_rst_info() reset reason: "));
consolePort.println(RST_REASONS[resetInfo->reason]);
consolePort.print(F("system_get_free_heap_size(): "));
consolePort.println(system_get_free_heap_size());
consolePort.print(F("system_get_os_print(): "));
consolePort.println(system_get_os_print());
system_set_os_print(1);
consolePort.print(F("system_get_os_print(): "));
consolePort.println(system_get_os_print());
consolePort.print(F("system_print_meminfo(): "));
consolePort.println(system_get_os_print());
system_print_meminfo();
consolePort.print(F("system_get_chip_id(): 0x"));
consolePort.println(system_get_chip_id(), HEX);
consolePort.print(F("system_get_sdk_version(): "));
consolePort.println(system_get_sdk_version());
consolePort.print(F("system_get_boot_version(): "));
consolePort.println(system_get_boot_version());
consolePort.print(F("system_get_userbin_addr(): 0x"));
consolePort.println(system_get_userbin_addr(), HEX);
consolePort.print(F("system_get_boot_mode(): "));
consolePort.println(system_get_boot_mode() == 0 ? F("SYS_BOOT_ENHANCE_MODE") : F("SYS_BOOT_NORMAL_MODE"));
consolePort.print(F("system_get_cpu_freq(): "));
consolePort.println(system_get_cpu_freq());
consolePort.print(F("spi_flash_get_id(): 0x"));
consolePort.println(spi_flash_get_id(), HEX);
consolePort.print(F("system_get_flash_size_map(): "));
consolePort.println(FLASH_SIZE_MAP_NAMES[system_get_flash_size_map()]);
}
- 其中傳入的參數是 UART stream object,但也可以是其他的 stream object。
- UART 的就作如此創建:
- Stream &ehConsolePort(Serial);
- 也就是建立一個名為 ehConsolePort 的 stream 物件,但注意,它是個別名物件,因我們的 UART 只有一個,其來源便是 Serial,其在系統預設下既已被創建此物件了。
- 得到的結果例如下:
10:09:53.952 -> system_get_rst_info() reset reason: REASON_EXT_SYS_RST
10:09:53.985 -> system_get_free_heap_size(): 50344
10:09:53.985 -> system_get_os_print(): 0
10:09:53.985 -> system_get_os_print(): 1
10:09:53.985 -> system_print_meminfo(): 1
10:09:53.985 -> system_get_chip_id(): 0xBA03ED
10:09:53.985 -> system_get_sdk_version(): 2.2.2-dev(38a443e)
10:09:53.985 -> system_get_boot_version(): 31
10:09:53.985 -> system_get_userbin_addr(): 0x0
10:09:53.985 -> system_get_boot_mode(): SYS_BOOT_NORMAL_MODE
10:09:53.985 -> system_get_cpu_freq(): 160
10:09:54.018 -> spi_flash_get_id(): 0x164020
10:09:54.018 -> system_get_flash_size_map(): FLASH_SIZE_32M_MAP_512_512
超頻至 160MHz,及獲取系統啟動後歴時(us)
// Try pushing frequency to 160MHz.
system_update_cpu_freq(SYS_CPU_160MHZ);
// System usually boots up in about 200ms.
Serial.print(F("system_get_time(): "));
Serial.println(system_get_time());
Serial.print(F("system_get_cpu_freq(): "));
Serial.println(system_get_cpu_freq());
獲取 WiFi 預設資訊(通常於設置 WiFi 之前)
Serial.print(F("wifi_get_opmode(): "));
Serial.print(wifi_get_opmode());
Serial.print(F(" - "));
Serial.println(OP_MODE_NAMES[wifi_get_opmode()]);
Serial.print(F("wifi_get_opmode_default(): "));
Serial.print(wifi_get_opmode_default());
Serial.print(F(" - "));
Serial.println(OP_MODE_NAMES[wifi_get_opmode_default()]);
Serial.print(F("wifi_get_broadcast_if(): "));
Serial.println(wifi_get_broadcast_if());
通常我們可以在 setup() 最後再從內建物件 ESP 獲取系統資訊
void post_setup(){
Serial.printf("getResetReason: %s\r\n", ESP.getResetReason().c_str());
Serial.printf("getFreeHeap: %d\r\n", ESP.getFreeHeap());
Serial.printf("getChipId: %d\r\n", ESP.getChipId());
Serial.printf("getCoreVersion: %s\r\n", ESP.getCoreVersion().c_str());
Serial.printf("getSdkVersion: %s\r\n", ESP.getSdkVersion());
Serial.printf("getCpuFreqMHz: %u\r\n", ESP.getCpuFreqMHz());
Serial.printf("getSketchSize: %u\r\n", ESP.getSketchSize());
Serial.printf("getFreeSketchSpace: %u\r\n", ESP.getFreeSketchSpace());
Serial.printf("getSketchMD5: %s\r\n", ESP.getSketchMD5().c_str());
Serial.printf("getFlashChipId: %d\r\n", ESP.getFlashChipId());
Serial.printf("getFlashChipSize: %u\r\n", ESP.getFlashChipSize());
Serial.printf("getFlashChipRealSize: %u\r\n", ESP.getFlashChipRealSize());
Serial.printf("getFlashChipSpeed: %u\r\n", ESP.getFlashChipSpeed());
Serial.printf("getCycleCount: %u\r\n", ESP.getCycleCount());
Serial.printf("getVcc: %d\r\n", ESP.getVcc());
}
輸出結果例如下:
10:30:52.144 -> getResetReason: External System
10:30:52.144 -> getFreeHeap: 50712
10:30:52.144 -> getChipId: 12190701
10:30:52.144 -> getCoreVersion: 2_7_4
10:30:52.144 -> getSdkVersion: 2.2.2-dev(38a443e)
10:30:52.144 -> getCpuFreqMHz: 80
10:30:52.177 -> getSketchSize: 288976
10:30:52.177 -> getFreeSketchSpace: 1806336
10:30:52.210 -> getSketchMD5: 00195e1c0c179b10c1b9eb5f752e353b
10:30:52.243 -> getFlashChipId: 1458208
10:30:52.243 -> getFlashChipSize: 4194304
10:30:52.243 -> getFlashChipRealSize: 4194304
10:30:52.243 -> getFlashChipSpeed: 40000000
10:30:52.243 -> getCycleCount: 901964769
10:30:52.243 -> getVcc: 65535
設置 WiFi 的自動訊息/通常用於 AP
// callback function
void wifi_event_handler_cb(System_Event_t * event)
{
if (int(event->event)==7) return;
if (event->event<sizeof(EVENT_NAMES)/sizeof(EVENT_NAMES[0]))
ehConsolePort.print(EVENT_NAMES[event->event]);
ehConsolePort.print(" [wifi_auto_info] (");
switch (event->event)
{
case EVENT_STAMODE_CONNECTED:
break;
case EVENT_STAMODE_DISCONNECTED:
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
break;
case EVENT_STAMODE_GOT_IP:
break;
case EVENT_SOFTAPMODE_STACONNECTED:
case EVENT_SOFTAPMODE_STADISCONNECTED:
{
char mac[32] = {0};
snprintf(mac, 32, MACSTR ", aid: %d" , MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid);
ehConsolePort.print(mac);
}
break;
default:
ehConsolePort.print(int(event->event));
}
ehConsolePort.println(")");
}
// 用於裝定 callback function
wifi_set_event_handler_cb(wifi_event_handler_cb);
// 其中,callback function 內需有 stream object 用以導出訊息
進入 AP 模式
void print_softap_config(Stream &consolePort, softap_config const &config)
{
consolePort.println();
consolePort.println(F("SoftAP Configuration"));
consolePort.println(F("--------------------"));
consolePort.print(F("ssid: "));
consolePort.println((char *) config.ssid);
consolePort.print(F("password: "));
consolePort.println((char *) config.password);
consolePort.print(F("ssid_len: "));
consolePort.println(config.ssid_len);
consolePort.print(F("channel: "));
consolePort.println(config.channel);
consolePort.print(F("authmode: "));
consolePort.println(AUTH_MODE_NAMES[config.authmode]);
consolePort.print(F("ssid_hidden: "));
consolePort.println(config.ssid_hidden);
consolePort.print(F("max_connection: "));
consolePort.println(config.max_connection);
consolePort.print(F("beacon_interval: "));
consolePort.print(config.beacon_interval);
consolePort.println("ms");
consolePort.println(F("--------------------"));
consolePort.println();
}
void print_wifi_general(Stream &consolePort)
{
consolePort.print(F("wifi_get_channel(): "));
consolePort.println(wifi_get_channel());
consolePort.print(F("wifi_get_phy_mode(): "));
consolePort.println(PHY_MODE_NAMES[wifi_get_phy_mode()]);
}
void secure_softap_config(softap_config *config, const char *ssid, const char *password)
{
// it tests if new data size over the storage and truncates.
size_t ssidLen = strlen(ssid) < sizeof(config->ssid) ? strlen(ssid) : sizeof(config->ssid);
size_t passwordLen = strlen(password) < sizeof(config->password) ? strlen(password) : sizeof(config->password);
memset(config->ssid, 0, sizeof(config->ssid));
memcpy(config->ssid, ssid, ssidLen);
memset(config->password, 0, sizeof(config->password));
memcpy(config->password, password, passwordLen);
config->ssid_len = ssidLen;
config->channel = 1;
config->authmode = AUTH_WPA2_PSK;
config->ssid_hidden = 1;
config->max_connection = 4;
config->beacon_interval = 1000;
}
//#define AP_MODE_MYSSID "ESP_TESTAP"
//#define AP_MODE_MYPW "87654321"
void enter_ap_mode(){
WiFi.softAP(AP_MODE_MYSSID, AP_MODE_MYPW);
IPAddress myIP = WiFi.softAPIP();
Serial.println("");
Serial.println("[-= Enter AP Mode =-]");
Serial.print("AP IP ADDR: ");
Serial.println(myIP);
// get the default config and print it.
softap_config config;
wifi_softap_get_config(&config);
/// if want to be more secure(hidden), modify the configurations.
/// secure_softap_config(&config, AP_MODE_MYSSID, AP_MODE_MYPW);
/// after config is arranged, set it in.
/// wifi_softap_set_config(&config);
print_softap_config(Serial, config);
print_wifi_general(Serial);
// start dhcps
wifi_softap_dhcps_start();
if (wifi_softap_dhcps_status()==DHCP_STARTED) Serial.println(F("DHCP started"));
else Serial.println(F("DHCP stopped"));
// get the AP basic info and print it.
ip_info info;
wifi_get_ip_info(SOFTAP_IF, &info);
/// method 1
/// Serial.printf("AP IP ADDR: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.ip), ip4_addr2(&info.ip), ip4_addr3(&info.ip), ip4_addr4(&info.ip));
/// Serial.printf("AP GATEWAY: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.gw), ip4_addr2(&info.gw), ip4_addr3(&info.gw), ip4_addr4(&info.gw));
/// Serial.printf("AP NETMASK: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.netmask), ip4_addr2(&info.netmask), ip4_addr3(&info.netmask), ip4_addr4(&info.netmask));
// method2
Serial.printf("AP IP ADDR: " IPSTR "\r\n", IP2STR(&info.ip));
Serial.printf("AP GATEWAY: " IPSTR "\r\n", IP2STR(&info.gw));
Serial.printf("AP NETMASK: " IPSTR "\r\n", IP2STR(&info.netmask));
// This doesn't work on an ESP-01.
// wifi_set_sleep_type(LIGHT_SLEEP_T);
// Try this dirty little thing.
// Doesn't work because ESP-01 module doesn't link XPD_DCDC -> RST.
// ESP.deepSleep(15000);
}
輸出結果例如下:
12:31:10.755 -> [-= Enter AP Mode =-]
12:31:10.755 -> AP IP ADDR: 192.168.4.1
12:31:10.755 ->
12:31:10.755 -> SoftAP Configuration
12:31:10.755 -> --------------------
12:31:10.755 -> ssid: ESP_TESTAP
12:31:10.755 -> password: 87654321
12:31:10.755 -> ssid_len: 10
12:31:10.755 -> channel: 6
12:31:10.755 -> authmode: AUTH_WPA2_PSK
12:31:10.788 -> ssid_hidden: 0
12:31:10.788 -> max_connection: 4
12:31:10.788 -> beacon_interval: 100ms
12:31:10.788 -> --------------------
12:31:10.788 ->
12:31:10.788 -> wifi_get_channel(): 6
12:31:10.788 -> wifi_get_phy_mode(): PHY_MODE_11N
12:31:10.788 -> DHCP started
12:31:10.788 -> AP IP ADDR: 192.168.4.1
12:31:10.788 -> AP GATEWAY: 192.168.4.1
12:31:10.788 -> AP NETMASK: 255.255.255.0
AP 模式下的 clients 資訊,並回傳有幾個 clients 連線
extern char remote_ip[16]; // to store the ip of each time of retrieved client info
int connected_station_status(){
///// this function for count couldn't sync the number of stat_infos retrieved at realtime.
unsigned char number_client=wifi_softap_get_station_num(); // Count of stations
struct station_info *stat_info;
IPAddress address;
int i;
Serial.print("Total connected clients: ");
Serial.println(number_client);
for (i=0, stat_info=wifi_softap_get_station_info(); stat_info!=NULL && i<number_client; i++){
address=(stat_info->ip).addr;
snprintf(remote_ip, 16, "" IPSTR, IP2STR(&(stat_info->ip)));
Serial.printf("Station %d. ", i+1);
Serial.print("IP= ");
Serial.print(address);
Serial.print(" with MAC= ");
Serial.print(stat_info->bssid[0],HEX);
Serial.print(stat_info->bssid[1],HEX);
Serial.print(stat_info->bssid[2],HEX);
Serial.print(stat_info->bssid[3],HEX);
Serial.print(stat_info->bssid[4],HEX);
Serial.print(stat_info->bssid[5],HEX);
Serial.println();
stat_info = STAILQ_NEXT(stat_info, next);
}
wifi_softap_free_station_info();
delay(100);
return i; // not the number_client
}
進入 STAtion 模式
// 4 seconds waiting
//#define STA_MODE_SSID AP_MODE_MYSSID
//#define STA_MODE_PW AP_MODE_MYPW
extern char remote_ip[16]; // to store the ip
bool enter_station_mode(){
unsigned char u=0;
// Connect to WiFi network
Serial.println("");
Serial.println("[-= Enter Station Mode =-]");
Serial.print("Connecting to ");
Serial.print(STA_MODE_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(STA_MODE_SSID, STA_MODE_PW);
while (WiFi.status() != WL_CONNECTED) {
delay(200);
Serial.print(".");
if (u++>20) break; // 4 seconds
}
Serial.println("");
if (WiFi.status() != WL_CONNECTED){
Serial.println(" WiFi connection failed...");
return false;
}
Serial.println("WiFi connected");
// Print the remote MAC address
uint8_t macAddr[6];
WiFi.macAddress(macAddr);
Serial.printf("Remote MAC adr: %02X:%02X:%02X:%02X:%02X:%02X\r\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
ip_info info;
wifi_get_ip_info(STATION_IF, &info);
Serial.printf("IP ADDR: " IPSTR "\r\n", IP2STR(&info.ip));
Serial.printf("GATEWAY: " IPSTR "\r\n", IP2STR(&info.gw));
Serial.printf("NETMASK: " IPSTR "\r\n", IP2STR(&info.netmask));
// resolve the remote ip
uint32 x=*(uint32*)(&info.ip)&*(uint32*)(&info.netmask);
ip_addr y=*(ip_addr*)(&x);
snprintf(remote_ip, 16, "%d.%d.%d.%d",\
ip4_addr1(&y)? ip4_addr1(&y): 1,\
ip4_addr2(&y)? ip4_addr2(&y): 1,\
ip4_addr3(&y)? ip4_addr3(&y): 1,\
ip4_addr4(&y)? ip4_addr4(&y): 1
);
Serial.print(F("Remote AP IP: "));
Serial.println(remote_ip);
Serial.printf("Default local hostname: %s\r\n", WiFi.hostname().c_str());
Serial.print("DNS #1, #2 IP: ");
WiFi.dnsIP().printTo(Serial);
Serial.print(", ");
WiFi.dnsIP(1).printTo(Serial);
Serial.println();
Serial.printf("RSSI: %d dBm\r\n", WiFi.RSSI());
WiFi.printDiag(Serial);
// Print the local IP address
Serial.println("");
Serial.print("IP is assigned: ");
Serial.println(WiFi.localIP());
return true;
}
創建 HTTP/HTTPS WebServer
// The certificate is stored in PMEM
static const uint8_t x509[] PROGMEM = {
0x30, 0x82, 0x01, 0x3d, 0x30, 0x81, 0xe8, 0x02, 0x09, 0x00, 0xfe, 0x56,
0x46, 0xf2, 0x78, 0xc6, 0x51, 0x17, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x26, 0x31,
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x38, 0x31,
0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x31,
0x32, 0x35, 0x31, 0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x30, 0x26, 0x31,
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
0x31, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02,
0x41, 0x00, 0xc6, 0x72, 0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7,
0x3a, 0x2a, 0x5a, 0x49, 0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6,
0xbb, 0xa3, 0xd6, 0x6f, 0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33,
0x50, 0x80, 0xec, 0x49, 0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d,
0x81, 0x85, 0x23, 0x24, 0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3,
0x3c, 0x10, 0x40, 0x05, 0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
0x05, 0x00, 0x03, 0x41, 0x00, 0x69, 0xdc, 0x6c, 0x9b, 0xa7, 0x62, 0x57,
0x7e, 0x03, 0x01, 0x45, 0xad, 0x9a, 0x83, 0x90, 0x3a, 0xe7, 0xdf, 0xe8,
0x8f, 0x46, 0x00, 0xd3, 0x5f, 0x2b, 0x0a, 0xde, 0x92, 0x1b, 0xc5, 0x04,
0xc5, 0xc0, 0x76, 0xf4, 0xf6, 0x08, 0x36, 0x97, 0x27, 0x82, 0xf1, 0x60,
0x76, 0xc2, 0xcd, 0x67, 0x6c, 0x4b, 0x6c, 0xca, 0xfd, 0x97, 0xfd, 0x33,
0x9e, 0x12, 0x67, 0x6b, 0x98, 0x7e, 0xd5, 0x80, 0x8f
};
// And so is the key. These could also be in DRAM
static const uint8_t rsakey[] PROGMEM = {
0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xc6, 0x72,
0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7, 0x3a, 0x2a, 0x5a, 0x49,
0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6, 0xbb, 0xa3, 0xd6, 0x6f,
0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33, 0x50, 0x80, 0xec, 0x49,
0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d, 0x81, 0x85, 0x23, 0x24,
0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3, 0x3c, 0x10, 0x40, 0x05,
0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x35, 0x0b, 0x74,
0xd3, 0xff, 0x15, 0x51, 0x44, 0x0f, 0x13, 0x2e, 0x9b, 0x0f, 0x93, 0x5c,
0x3f, 0xfc, 0xf1, 0x17, 0xf9, 0x72, 0x94, 0x5e, 0xa7, 0xc6, 0xb3, 0xf0,
0xfe, 0xc9, 0x6c, 0xb1, 0x1e, 0x83, 0xb3, 0xc6, 0x45, 0x3a, 0x25, 0x60,
0x7c, 0x3d, 0x92, 0x7d, 0x53, 0xec, 0x49, 0x8d, 0xb5, 0x45, 0x10, 0x99,
0x9b, 0xc6, 0x22, 0x3a, 0x68, 0xc7, 0x13, 0x4e, 0xb6, 0x04, 0x61, 0x21,
0x01, 0x02, 0x21, 0x00, 0xea, 0x8c, 0x21, 0xd4, 0x7f, 0x3f, 0xb6, 0x91,
0xfa, 0xf8, 0xb9, 0x2d, 0xcb, 0x36, 0x36, 0x02, 0x5f, 0xf0, 0x0c, 0x6e,
0x87, 0xaa, 0x5c, 0x14, 0xf6, 0x56, 0x8e, 0x12, 0x92, 0x25, 0xde, 0xb3,
0x02, 0x21, 0x00, 0xd8, 0x99, 0x01, 0xf1, 0x04, 0x0b, 0x98, 0xa3, 0x71,
0x56, 0x1d, 0xea, 0x6f, 0x45, 0xd1, 0x36, 0x70, 0x76, 0x8b, 0xab, 0x69,
0x30, 0x58, 0x9c, 0xe0, 0x45, 0x97, 0xe7, 0xb6, 0xb5, 0xef, 0xc1, 0x02,
0x21, 0x00, 0xa2, 0x01, 0x06, 0xc0, 0xf2, 0xdf, 0xbc, 0x28, 0x1a, 0xb4,
0xbf, 0x9b, 0x5c, 0xd8, 0x65, 0xf7, 0xbf, 0xf2, 0x5b, 0x73, 0xe0, 0xeb,
0x0f, 0xcd, 0x3e, 0xd5, 0x4c, 0x2e, 0x91, 0x99, 0xec, 0xb7, 0x02, 0x20,
0x4b, 0x9d, 0x46, 0xd7, 0x3c, 0x01, 0x4c, 0x5d, 0x2a, 0xb0, 0xd4, 0xaa,
0xc6, 0x03, 0xca, 0xa0, 0xc5, 0xac, 0x2c, 0xe0, 0x3f, 0x4d, 0x98, 0x71,
0xd3, 0xbd, 0x97, 0xe5, 0x55, 0x9c, 0xb8, 0x41, 0x02, 0x20, 0x02, 0x42,
0x9f, 0xd1, 0x06, 0x35, 0x3b, 0x42, 0xf5, 0x64, 0xaf, 0x6d, 0xbf, 0xcd,
0x2c, 0x3a, 0xcd, 0x0a, 0x9a, 0x4d, 0x7c, 0xad, 0x29, 0xd6, 0x36, 0x57,
0xd5, 0xdf, 0x34, 0xeb, 0x26, 0x03
};
WiFiServer* create_http_server(){
// Create an instance of the server
// specify the 80 port to listen on as an argument
WiFiServer *a=new WiFiServer(80);
/// WiFiServerSecure *a=new WiFiServerSecure(443);
/// a->setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
/// a->begin();
// Start the server
a->begin();
Serial.println("HTTP Server started");
return a;
}
WebServer 的運作範例
// example to GPIO2 high if request is "/gpio/1", low if "/gpio/0".
// using polling, so it needs to improvement
/// server_p=create_http_server();
WiFiServer &http_server=*server_p;
// Check if a client has connected
WiFiClient client = http_server.available();
if (!client) return;
// Wait until the client sends some data
Serial.println("");
Serial.println("[New client arrived]");
// polling and has to have timeout treatment
for (int x=0; !client.available(); x++){
if (x>10){
Serial.println("[Client missing]");
client.flush();
client.stop();
return;
}
delay(10);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
Serial.printf("[Request: [%s]]\r\n", req.c_str());
// Matching the request
int val;
if (req.indexOf("/gpio/0") != -1){
val = 0;
}
else if (req.indexOf("/gpio/1") != -1){
val = 1;
}
else {
Serial.println("[Invalid request]");
client.print("HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html><body>Not found</body></html>");
client.flush();
client.stop();
return;
}
// Set GPIO2 according to the request
digitalWrite(2, val);
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nLED is now ";
s += (val)? "OFF": "ON";
s += "</html>\r\n";
// Send the response to the client
client.print(s);
delay(1);
Serial.println("[Client disonnected]");
client.flush();
client.stop();
// The client will actually be disconnected when the function returns and 'client' object is detroyed
創建 HTTP/HTTPS Client
extern char remote_ip[16];
void http_client_connect(const char *url){
#if 0 // faster but always got nothing
/// #include <ESP8266HTTPClient.h>
HTTPClient http;
Serial.print("\r\n[HTTP begin...]\r\n");
// configure traged server and url
/// http.begin("https://192.168.1.12/test.html", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); // HTTPS
http.begin(url); // HTTP
Serial.print("[HTTP GET...]\r\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0){
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP GET... code: %d]\r\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK){ // the connection may be broken and stuck here
Serial.println(" -= data =- ---------");
Serial.println(http.getString()); // usually has no data return, so failed.
Serial.println(" ===================");
}
else Serial.printf("[HTTP GET... failed, error: %s]\r\n", http.errorToString(httpCode).c_str());
}
else Serial.printf("[HTTP Protocol failed, error: %s]\r\n", http.errorToString(httpCode).c_str());
http.end();
delay(150);
#else // slower but usually failed connection
// Use WiFiClient class to create TCP connections
WiFiClient client;
int httpPort = 80;
if (!client.connect(remote_ip, httpPort)) {
Serial.println("");
Serial.println("[HTTP Protocol failed, error: 0]");
Serial.println("");
return;
}
Serial.print("[Requesting URL: [");
Serial.print(url);
Serial.println("]");
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +\
"Host: " + remote_ip + "\r\n" +\
"Connection: close\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 4000) {
Serial.println("[Client Timeout !]");
client.stop();
return;
}
delay(50);
}
// Read all the lines of the reply from server and print them to Serial
Serial.println(" -= data =- ---------");
while(client.available()){
String line = client.readStringUntil('\r');
Serial.println(line);
}
Serial.println(" ===================");
delay(50);
#endif
}
HTTP/HTTPS Client 的使用範例
extern String web_link;
extern char remote_ip[16];
void loop() {
static int x=0;
web_link="http://";
web_link+=remote_ip;
web_link+="/gpio/";
http_client_connect((web_link+(x^=1)).c_str());
delay(300);
}
以上打成懶人包,含 AP/STA,HTTP Server/Client
/*
* This sketch demonstrates how to set up a simple HTTP-like server.
* The server will set a GPIO pin depending on the request
* http://server_ip/gpio/0 will set the GPIO2 low,
* http://server_ip/gpio/1 will set the GPIO2 high
* server_ip is the IP address of the ESP8266 module, will be
* printed to Serial when the module is connected.
*/
#include <ESP8266WiFi.h>
#ifdef ESP8266
extern "C" {
#include "user_interface.h"
}
#endif
#include <ESP8266HTTPClient.h>
// Set up output serial port (could be a SoftwareSerial
// if really wanted).
// Wired to the blue LED on an ESP-01 board, active LOW.
//
// Cannot be used simultaneously with Serial.print/println()
// calls, as TX is wired to the same pin.
//
// UNLESS: You swap the TX pin using the alternate pinout.
#define AP_MODE_MYSSID "ESP_TESTAP"
#define AP_MODE_MYPW "87654321"
#if 0
#define STA_MODE_SSID "--------"
#define STA_MODE_PW "--------"
#else
#define STA_MODE_SSID AP_MODE_MYSSID
#define STA_MODE_PW AP_MODE_MYPW
#endif
#define HTTP_SERVER 0
#define HTTP_CLIENT (!HTTP_SERVER)
#define AP_MODE 1
#define STA_MODE (!AP_MODE)
Stream &ehConsolePort(Serial);
// for http server
WiFiServer *server_p;
// for remote ip
char remote_ip[16] = {0};
// for url
String web_link;
// for station mode is entered
bool is_station_entered=false;
const char * const RST_REASONS[] =
{
"REASON_DEFAULT_RST",
"REASON_WDT_RST",
"REASON_EXCEPTION_RST",
"REASON_SOFT_WDT_RST",
"REASON_SOFT_RESTART",
"REASON_DEEP_SLEEP_AWAKE",
"REASON_EXT_SYS_RST"
};
const char * const FLASH_SIZE_MAP_NAMES[] =
{
"FLASH_SIZE_4M_MAP_256_256",
"FLASH_SIZE_2M",
"FLASH_SIZE_8M_MAP_512_512",
"FLASH_SIZE_16M_MAP_512_512",
"FLASH_SIZE_32M_MAP_512_512",
"FLASH_SIZE_16M_MAP_1024_1024",
"FLASH_SIZE_32M_MAP_1024_1024"
};
const char * const OP_MODE_NAMES[]
{
"NULL_MODE",
"STATION_MODE",
"SOFTAP_MODE",
"STATIONAP_MODE"
};
const char * const AUTH_MODE_NAMES[]
{
"AUTH_OPEN",
"AUTH_WEP",
"AUTH_WPA_PSK",
"AUTH_WPA2_PSK",
"AUTH_WPA_WPA2_PSK",
"AUTH_MAX"
};
const char * const PHY_MODE_NAMES[]
{
"",
"PHY_MODE_11B",
"PHY_MODE_11G",
"PHY_MODE_11N"
};
const char * const EVENT_NAMES[]
{
"EVENT_STAMODE_CONNECTED",
"EVENT_STAMODE_DISCONNECTED",
"EVENT_STAMODE_AUTHMODE_CHANGE",
"EVENT_STAMODE_GOT_IP",
"EVENT_SOFTAPMODE_STACONNECTED",
"EVENT_SOFTAPMODE_STADISCONNECTED",
"EVENT_MAX"
};
const char * const EVENT_REASONS[]
{
"",
"REASON_UNSPECIFIED",
"REASON_AUTH_EXPIRE",
"REASON_AUTH_LEAVE",
"REASON_ASSOC_EXPIRE",
"REASON_ASSOC_TOOMANY",
"REASON_NOT_AUTHED",
"REASON_NOT_ASSOCED",
"REASON_ASSOC_LEAVE",
"REASON_ASSOC_NOT_AUTHED",
"REASON_DISASSOC_PWRCAP_BAD",
"REASON_DISASSOC_SUPCHAN_BAD",
"REASON_IE_INVALID",
"REASON_MIC_FAILURE",
"REASON_4WAY_HANDSHAKE_TIMEOUT",
"REASON_GROUP_KEY_UPDATE_TIMEOUT",
"REASON_IE_IN_4WAY_DIFFERS",
"REASON_GROUP_CIPHER_INVALID",
"REASON_PAIRWISE_CIPHER_INVALID",
"REASON_AKMP_INVALID",
"REASON_UNSUPP_RSN_IE_VERSION",
"REASON_INVALID_RSN_IE_CAP",
"REASON_802_1X_AUTH_FAILED",
"REASON_CIPHER_SUITE_REJECTED",
};
void print_system_info(Stream & consolePort)
{
const rst_info * resetInfo = system_get_rst_info();
consolePort.print(F("system_get_rst_info() reset reason: "));
consolePort.println(RST_REASONS[resetInfo->reason]);
consolePort.print(F("system_get_free_heap_size(): "));
consolePort.println(system_get_free_heap_size());
consolePort.print(F("system_get_os_print(): "));
consolePort.println(system_get_os_print());
system_set_os_print(1);
consolePort.print(F("system_get_os_print(): "));
consolePort.println(system_get_os_print());
consolePort.print(F("system_print_meminfo(): "));
consolePort.println(system_get_os_print());
system_print_meminfo();
consolePort.print(F("system_get_chip_id(): 0x"));
consolePort.println(system_get_chip_id(), HEX);
consolePort.print(F("system_get_sdk_version(): "));
consolePort.println(system_get_sdk_version());
consolePort.print(F("system_get_boot_version(): "));
consolePort.println(system_get_boot_version());
consolePort.print(F("system_get_userbin_addr(): 0x"));
consolePort.println(system_get_userbin_addr(), HEX);
consolePort.print(F("system_get_boot_mode(): "));
consolePort.println(system_get_boot_mode() == 0 ? F("SYS_BOOT_ENHANCE_MODE") : F("SYS_BOOT_NORMAL_MODE"));
consolePort.print(F("system_get_cpu_freq(): "));
consolePort.println(system_get_cpu_freq());
consolePort.print(F("spi_flash_get_id(): 0x"));
consolePort.println(spi_flash_get_id(), HEX);
consolePort.print(F("system_get_flash_size_map(): "));
consolePort.println(FLASH_SIZE_MAP_NAMES[system_get_flash_size_map()]);
}
void post_setup(){
Serial.printf("getResetReason: %s\r\n", ESP.getResetReason().c_str());
Serial.printf("getFreeHeap: %d\r\n", ESP.getFreeHeap());
Serial.printf("getChipId: %d\r\n", ESP.getChipId());
Serial.printf("getCoreVersion: %s\r\n", ESP.getCoreVersion().c_str());
Serial.printf("getSdkVersion: %s\r\n", ESP.getSdkVersion());
Serial.printf("getCpuFreqMHz: %u\r\n", ESP.getCpuFreqMHz());
Serial.printf("getSketchSize: %u\r\n", ESP.getSketchSize());
Serial.printf("getFreeSketchSpace: %u\r\n", ESP.getFreeSketchSpace());
Serial.printf("getSketchMD5: %s\r\n", ESP.getSketchMD5().c_str());
Serial.printf("getFlashChipId: %d\r\n", ESP.getFlashChipId());
Serial.printf("getFlashChipSize: %u\r\n", ESP.getFlashChipSize());
Serial.printf("getFlashChipRealSize: %u\r\n", ESP.getFlashChipRealSize());
Serial.printf("getFlashChipSpeed: %u\r\n", ESP.getFlashChipSpeed());
Serial.printf("getCycleCount: %u\r\n", ESP.getCycleCount());
Serial.printf("getVcc: %d\r\n", ESP.getVcc());
}
// callback function
void wifi_event_handler_cb(System_Event_t * event)
{
if (int(event->event)>=7) return;
if (event->event<sizeof(EVENT_NAMES)/sizeof(EVENT_NAMES[0]))
ehConsolePort.print(EVENT_NAMES[event->event]);
ehConsolePort.print(" [wifi_auto_info] (");
switch (event->event)
{
case EVENT_STAMODE_CONNECTED:
break;
case EVENT_STAMODE_DISCONNECTED:
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
break;
case EVENT_STAMODE_GOT_IP:
break;
case EVENT_SOFTAPMODE_STACONNECTED:
case EVENT_SOFTAPMODE_STADISCONNECTED:
{
char mac[32] = {0};
snprintf(mac, 32, MACSTR ", aid: %d" , MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid);
ehConsolePort.print(mac);
}
break;
default:
ehConsolePort.print(int(event->event));
}
ehConsolePort.println(")");
}
void print_softap_config(Stream &consolePort, softap_config const &config)
{
consolePort.println();
consolePort.println(F("SoftAP Configuration"));
consolePort.println(F("--------------------"));
consolePort.print(F("ssid: "));
consolePort.println((char *) config.ssid);
consolePort.print(F("password: "));
consolePort.println((char *) config.password);
consolePort.print(F("ssid_len: "));
consolePort.println(config.ssid_len);
consolePort.print(F("channel: "));
consolePort.println(config.channel);
consolePort.print(F("authmode: "));
consolePort.println(AUTH_MODE_NAMES[config.authmode]);
consolePort.print(F("ssid_hidden: "));
consolePort.println(config.ssid_hidden);
consolePort.print(F("max_connection: "));
consolePort.println(config.max_connection);
consolePort.print(F("beacon_interval: "));
consolePort.print(config.beacon_interval);
consolePort.println("ms");
consolePort.println(F("--------------------"));
consolePort.println();
}
void print_wifi_general(Stream &consolePort)
{
consolePort.print(F("wifi_get_channel(): "));
consolePort.println(wifi_get_channel());
consolePort.print(F("wifi_get_phy_mode(): "));
consolePort.println(PHY_MODE_NAMES[wifi_get_phy_mode()]);
}
void secure_softap_config(softap_config *config, const char *ssid, const char *password)
{
// it tests if new data size over the storage and truncates.
size_t ssidLen = strlen(ssid) < sizeof(config->ssid) ? strlen(ssid) : sizeof(config->ssid);
size_t passwordLen = strlen(password) < sizeof(config->password) ? strlen(password) : sizeof(config->password);
memset(config->ssid, 0, sizeof(config->ssid));
memcpy(config->ssid, ssid, ssidLen);
memset(config->password, 0, sizeof(config->password));
memcpy(config->password, password, passwordLen);
config->ssid_len = ssidLen;
config->channel = 1;
config->authmode = AUTH_WPA2_PSK;
config->ssid_hidden = 1;
config->max_connection = 4;
config->beacon_interval = 1000;
}
void enter_ap_mode(){
WiFi.softAP(AP_MODE_MYSSID, AP_MODE_MYPW);
IPAddress myIP = WiFi.softAPIP();
Serial.println("");
Serial.println("[-= Enter AP Mode =-]");
Serial.print("AP IP ADDR: ");
Serial.println(myIP);
// get the default config and print it.
softap_config config;
wifi_softap_get_config(&config);
/// if want to be more secure(hidden), modify the configurations.
/// secure_softap_config(&config, AP_MODE_MYSSID, AP_MODE_MYPW);
/// after config is arranged, set it in.
/// wifi_softap_set_config(&config);
print_softap_config(Serial, config);
print_wifi_general(Serial);
// start dhcps
wifi_softap_dhcps_start();
if (wifi_softap_dhcps_status()==DHCP_STARTED) Serial.println(F("DHCP started"));
else Serial.println(F("DHCP stopped"));
// get the AP basic info and print it.
ip_info info;
wifi_get_ip_info(SOFTAP_IF, &info);
/// method 1
/// Serial.printf("AP IP ADDR: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.ip), ip4_addr2(&info.ip), ip4_addr3(&info.ip), ip4_addr4(&info.ip));
/// Serial.printf("AP GATEWAY: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.gw), ip4_addr2(&info.gw), ip4_addr3(&info.gw), ip4_addr4(&info.gw));
/// Serial.printf("AP NETMASK: %3d.%3d.%3d.%3d\r\n", ip4_addr1(&info.netmask), ip4_addr2(&info.netmask), ip4_addr3(&info.netmask), ip4_addr4(&info.netmask));
// method2
Serial.printf("AP IP ADDR: " IPSTR "\r\n", IP2STR(&info.ip));
Serial.printf("AP GATEWAY: " IPSTR "\r\n", IP2STR(&info.gw));
Serial.printf("AP NETMASK: " IPSTR "\r\n", IP2STR(&info.netmask));
// This doesn't work on an ESP-01.
// wifi_set_sleep_type(LIGHT_SLEEP_T);
// Try this dirty little thing.
// Doesn't work because ESP-01 module doesn't link XPD_DCDC -> RST.
// ESP.deepSleep(15000);
}
int connected_station_status(){
///// this function for count couldn't sync the number of stat_infos retrieved at realtime.
unsigned char number_client=wifi_softap_get_station_num(); // Count of stations
struct station_info *stat_info;
IPAddress address;
int i;
Serial.print("Total connected clients: ");
Serial.println(number_client);
for (i=0, stat_info=wifi_softap_get_station_info(); stat_info!=NULL && i<number_client; i++){
address=(stat_info->ip).addr;
snprintf(remote_ip, 16, "" IPSTR, IP2STR(&(stat_info->ip)));
Serial.printf("Station %d. ", i+1);
Serial.print("IP= ");
Serial.print(address);
Serial.print(" with MAC= ");
Serial.print(stat_info->bssid[0],HEX);
Serial.print(stat_info->bssid[1],HEX);
Serial.print(stat_info->bssid[2],HEX);
Serial.print(stat_info->bssid[3],HEX);
Serial.print(stat_info->bssid[4],HEX);
Serial.print(stat_info->bssid[5],HEX);
Serial.println();
stat_info = STAILQ_NEXT(stat_info, next);
}
wifi_softap_free_station_info();
delay(100);
return i; // not the number_client
}
// 12 seconds waiting
bool enter_station_mode(){
unsigned char u=0;
// Connect to WiFi network
Serial.println("");
Serial.println("[-= Enter Station Mode =-]");
Serial.print("Connecting to ");
Serial.print(STA_MODE_SSID);
WiFi.mode(WIFI_STA);
WiFi.begin(STA_MODE_SSID, STA_MODE_PW);
while (WiFi.status() != WL_CONNECTED) {
delay(200);
Serial.print(".");
if (u++>60) break; // 12 seconds, might not enough
}
Serial.println("");
if (WiFi.status() != WL_CONNECTED){
Serial.println(" WiFi connection failed...");
return false;
}
Serial.println("WiFi connected");
// Print the remote MAC address
uint8_t macAddr[6];
WiFi.macAddress(macAddr);
Serial.printf("Remote MAC adr: %02X:%02X:%02X:%02X:%02X:%02X\r\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
ip_info info;
wifi_get_ip_info(STATION_IF, &info);
Serial.printf("IP ADDR: " IPSTR "\r\n", IP2STR(&info.ip));
Serial.printf("GATEWAY: " IPSTR "\r\n", IP2STR(&info.gw));
Serial.printf("NETMASK: " IPSTR "\r\n", IP2STR(&info.netmask));
// resolve the remote ip
uint32 x=*(uint32*)(&info.ip)&*(uint32*)(&info.netmask);
ip_addr y=*(ip_addr*)(&x);
snprintf(remote_ip, 16, "%d.%d.%d.%d",\
ip4_addr1(&y)? ip4_addr1(&y): 1,\
ip4_addr2(&y)? ip4_addr2(&y): 1,\
ip4_addr3(&y)? ip4_addr3(&y): 1,\
ip4_addr4(&y)? ip4_addr4(&y): 1
);
Serial.print(F("Remote AP IP: "));
Serial.println(remote_ip);
Serial.printf("Default local hostname: %s\r\n", WiFi.hostname().c_str());
Serial.print("DNS #1, #2 IP: ");
WiFi.dnsIP().printTo(Serial);
Serial.print(", ");
WiFi.dnsIP(1).printTo(Serial);
Serial.println();
Serial.printf("RSSI: %d dBm\r\n", WiFi.RSSI());
WiFi.printDiag(Serial);
// Print the local IP address
Serial.println("");
Serial.print("IP is assigned: ");
Serial.println(WiFi.localIP());
return true;
}
// The certificate is stored in PMEM
static const uint8_t x509[] PROGMEM = {
0x30, 0x82, 0x01, 0x3d, 0x30, 0x81, 0xe8, 0x02, 0x09, 0x00, 0xfe, 0x56,
0x46, 0xf2, 0x78, 0xc6, 0x51, 0x17, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x26, 0x31,
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x38, 0x31,
0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x31,
0x32, 0x35, 0x31, 0x34, 0x34, 0x39, 0x31, 0x38, 0x5a, 0x30, 0x26, 0x31,
0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x45, 0x53,
0x50, 0x38, 0x32, 0x36, 0x36, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0c, 0x09, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
0x31, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02,
0x41, 0x00, 0xc6, 0x72, 0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7,
0x3a, 0x2a, 0x5a, 0x49, 0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6,
0xbb, 0xa3, 0xd6, 0x6f, 0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33,
0x50, 0x80, 0xec, 0x49, 0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d,
0x81, 0x85, 0x23, 0x24, 0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3,
0x3c, 0x10, 0x40, 0x05, 0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
0x05, 0x00, 0x03, 0x41, 0x00, 0x69, 0xdc, 0x6c, 0x9b, 0xa7, 0x62, 0x57,
0x7e, 0x03, 0x01, 0x45, 0xad, 0x9a, 0x83, 0x90, 0x3a, 0xe7, 0xdf, 0xe8,
0x8f, 0x46, 0x00, 0xd3, 0x5f, 0x2b, 0x0a, 0xde, 0x92, 0x1b, 0xc5, 0x04,
0xc5, 0xc0, 0x76, 0xf4, 0xf6, 0x08, 0x36, 0x97, 0x27, 0x82, 0xf1, 0x60,
0x76, 0xc2, 0xcd, 0x67, 0x6c, 0x4b, 0x6c, 0xca, 0xfd, 0x97, 0xfd, 0x33,
0x9e, 0x12, 0x67, 0x6b, 0x98, 0x7e, 0xd5, 0x80, 0x8f
};
// And so is the key. These could also be in DRAM
static const uint8_t rsakey[] PROGMEM = {
0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xc6, 0x72,
0x6c, 0x12, 0xe1, 0x20, 0x4d, 0x10, 0x0c, 0xf7, 0x3a, 0x2a, 0x5a, 0x49,
0xe2, 0x2d, 0xc9, 0x7a, 0x63, 0x1d, 0xef, 0xc6, 0xbb, 0xa3, 0xd6, 0x6f,
0x59, 0xcb, 0xd5, 0xf6, 0xbe, 0x34, 0x83, 0x33, 0x50, 0x80, 0xec, 0x49,
0x63, 0xbf, 0xee, 0x59, 0x94, 0x67, 0x8b, 0x8d, 0x81, 0x85, 0x23, 0x24,
0x06, 0x52, 0x76, 0x55, 0x9d, 0x18, 0x09, 0xb3, 0x3c, 0x10, 0x40, 0x05,
0x01, 0xf3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x35, 0x0b, 0x74,
0xd3, 0xff, 0x15, 0x51, 0x44, 0x0f, 0x13, 0x2e, 0x9b, 0x0f, 0x93, 0x5c,
0x3f, 0xfc, 0xf1, 0x17, 0xf9, 0x72, 0x94, 0x5e, 0xa7, 0xc6, 0xb3, 0xf0,
0xfe, 0xc9, 0x6c, 0xb1, 0x1e, 0x83, 0xb3, 0xc6, 0x45, 0x3a, 0x25, 0x60,
0x7c, 0x3d, 0x92, 0x7d, 0x53, 0xec, 0x49, 0x8d, 0xb5, 0x45, 0x10, 0x99,
0x9b, 0xc6, 0x22, 0x3a, 0x68, 0xc7, 0x13, 0x4e, 0xb6, 0x04, 0x61, 0x21,
0x01, 0x02, 0x21, 0x00, 0xea, 0x8c, 0x21, 0xd4, 0x7f, 0x3f, 0xb6, 0x91,
0xfa, 0xf8, 0xb9, 0x2d, 0xcb, 0x36, 0x36, 0x02, 0x5f, 0xf0, 0x0c, 0x6e,
0x87, 0xaa, 0x5c, 0x14, 0xf6, 0x56, 0x8e, 0x12, 0x92, 0x25, 0xde, 0xb3,
0x02, 0x21, 0x00, 0xd8, 0x99, 0x01, 0xf1, 0x04, 0x0b, 0x98, 0xa3, 0x71,
0x56, 0x1d, 0xea, 0x6f, 0x45, 0xd1, 0x36, 0x70, 0x76, 0x8b, 0xab, 0x69,
0x30, 0x58, 0x9c, 0xe0, 0x45, 0x97, 0xe7, 0xb6, 0xb5, 0xef, 0xc1, 0x02,
0x21, 0x00, 0xa2, 0x01, 0x06, 0xc0, 0xf2, 0xdf, 0xbc, 0x28, 0x1a, 0xb4,
0xbf, 0x9b, 0x5c, 0xd8, 0x65, 0xf7, 0xbf, 0xf2, 0x5b, 0x73, 0xe0, 0xeb,
0x0f, 0xcd, 0x3e, 0xd5, 0x4c, 0x2e, 0x91, 0x99, 0xec, 0xb7, 0x02, 0x20,
0x4b, 0x9d, 0x46, 0xd7, 0x3c, 0x01, 0x4c, 0x5d, 0x2a, 0xb0, 0xd4, 0xaa,
0xc6, 0x03, 0xca, 0xa0, 0xc5, 0xac, 0x2c, 0xe0, 0x3f, 0x4d, 0x98, 0x71,
0xd3, 0xbd, 0x97, 0xe5, 0x55, 0x9c, 0xb8, 0x41, 0x02, 0x20, 0x02, 0x42,
0x9f, 0xd1, 0x06, 0x35, 0x3b, 0x42, 0xf5, 0x64, 0xaf, 0x6d, 0xbf, 0xcd,
0x2c, 0x3a, 0xcd, 0x0a, 0x9a, 0x4d, 0x7c, 0xad, 0x29, 0xd6, 0x36, 0x57,
0xd5, 0xdf, 0x34, 0xeb, 0x26, 0x03
};
WiFiServer* create_http_server(){
// Create an instance of the server
// specify the 80 port to listen on as an argument
WiFiServer *a=new WiFiServer(80);
/// WiFiServerSecure *a=new WiFiServerSecure(443);
/// a->setServerKeyAndCert_P(rsakey, sizeof(rsakey), x509, sizeof(x509));
/// a->begin();
// Start the server
a->begin();
Serial.println("HTTP Server started");
return a;
}
void http_client_connect(const char *url){
#if 0 // faster but always got nothing
/// #include <ESP8266HTTPClient.h>
HTTPClient http;
Serial.print("\r\n[HTTP begin...]\r\n");
// configure traged server and url
/// http.begin("https://192.168.1.12/test.html", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); // HTTPS
http.begin(url); // HTTP
Serial.print("[HTTP GET...]\r\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0){
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP GET... code: %d]\r\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK){ // the connection may be broken and stuck here
Serial.println(" -= data =- ---------");
Serial.println(http.getString()); // usually has no data return, so failed.
Serial.println(" ===================");
}
else Serial.printf("[HTTP GET... failed, error: %s]\r\n", http.errorToString(httpCode).c_str());
}
else Serial.printf("[HTTP Protocol failed, error: %s]\r\n", http.errorToString(httpCode).c_str());
http.end();
delay(150);
#else // slower but usually failed connection
// Use WiFiClient class to create TCP connections
WiFiClient client;
int httpPort = 80;
if (!client.connect(remote_ip, httpPort)) {
Serial.println("");
Serial.println("[HTTP Protocol failed, error: 0]");
Serial.println("");
return;
}
Serial.print("[Requesting URL: [");
Serial.print(url);
Serial.println("]");
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +\
"Host: " + remote_ip + "\r\n" +\
"Connection: close\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 4000) {
Serial.println("[Client Timeout !]");
client.stop();
return;
}
delay(50);
}
// Read all the lines of the reply from server and print them to Serial
Serial.println(" -= data =- ---------");
while(client.available()){
String line = client.readStringUntil('\r');
Serial.println(line);
}
Serial.println(" ===================");
delay(50);
#endif
}
bool Timeout_10s(){
static int current_time = millis();
int new_time = millis();
if (new_time < (current_time + 10000)) return false;
current_time = new_time;
return true;
}
bool Timeout_4s(){
static int current_time = millis();
int new_time = millis();
if (new_time < (current_time + 4000)) return false;
current_time = new_time;
return true;
}
void setup(){
Serial.begin(115200);
delay(5000);
print_system_info(Serial);
// Try pushing frequency to 160MHz.
system_update_cpu_freq(SYS_CPU_160MHZ);
// System usually boots up in about 200ms.
Serial.print(F("system_get_time(): "));
Serial.println(system_get_time());
Serial.print(F("system_get_cpu_freq(): "));
Serial.println(system_get_cpu_freq());
Serial.print(F("wifi_get_opmode(): "));
Serial.print(wifi_get_opmode());
Serial.print(F(" - "));
Serial.println(OP_MODE_NAMES[wifi_get_opmode()]);
Serial.print(F("wifi_get_opmode_default(): "));
Serial.print(wifi_get_opmode_default());
Serial.print(F(" - "));
Serial.println(OP_MODE_NAMES[wifi_get_opmode_default()]);
Serial.print(F("wifi_get_broadcast_if(): "));
Serial.println(wifi_get_broadcast_if());
post_setup();
#if AP_MODE
enter_ap_mode();
wifi_set_event_handler_cb(wifi_event_handler_cb);
#elif STA_MODE
is_station_entered=enter_station_mode();
#endif
#if HTTP_SERVER
pinMode(2, OUTPUT);
server_p=create_http_server();
#elif HTTP_CLIENT
web_link="http://";
web_link+=remote_ip;
web_link+="/gpio/";
#endif
}
void loop() {
#if AP_MODE
static int has_conns=0;
if (Timeout_10s())
Serial.printf("Current STA connections: %d\r\n", (has_conns=connected_station_status()));
if (has_conns<=0) return;
#elif STA_MODE
if (!is_station_entered){
if (Timeout_4s()){
is_station_entered=enter_station_mode();
}
return;
}
#endif
#if HTTP_SERVER
// example to GPIO2 high if request is "/gpio/1", low if "/gpio/0".
// using polling, so it needs to improvement
/// server_p=create_http_server();
WiFiServer &http_server=*server_p;
// Check if a client has connected
WiFiClient client = http_server.available();
if (!client) return;
// Wait until the client sends some data
Serial.println("");
Serial.println("[New client arrived]");
// polling and has to have timeout treatment
for (int x=0; !client.available(); x++){
if (x>10){
Serial.println("[Client missing]");
client.flush();
client.stop();
return;
}
delay(10);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
Serial.printf("[Request: [%s]]\r\n", req.c_str());
// Matching the request
int val;
if (req.indexOf("/gpio/0") != -1){
val = 0;
}
else if (req.indexOf("/gpio/1") != -1){
val = 1;
}
else {
Serial.println("[Invalid request]");
client.print("HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html><body>Not found</body></html>");
client.flush();
client.stop();
return;
}
// Set GPIO2 according to the request
digitalWrite(2, val);
// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nLED is now ";
s += (val)? "OFF": "ON";
s += "</html>\r\n";
// Send the response to the client
client.print(s);
delay(1);
Serial.println("[Client disonnected]");
client.flush();
client.stop();
// The client will actually be disconnected when the function returns and 'client' object is detroyed
#elif HTTP_CLIENT
static int x=0;
http_client_connect((web_link+(x^=1)).c_str());
delay(300);
#endif
}