1. 程式人生 > >Esp8266 進階之路32【高階篇】當esp8266遇到 Html,該怎麼內建網頁控制裝置,理清內建網頁的實現過程,實現無需路由器手機也可以控制esp8266。(附帶韌體)

Esp8266 進階之路32【高階篇】當esp8266遇到 Html,該怎麼內建網頁控制裝置,理清內建網頁的實現過程,實現無需路由器手機也可以控制esp8266。(附帶韌體)

一、前言;

  • 這個月也快結束了,時間真快,我伺服器知識自學依然在路途中,這幾天聽到熱點網頁配置esp8266連線路由器,那麼我想這個不是很複雜,不過需要一些通訊協議的基礎,以及對esp8266SDK開發的熟悉,這幾天擼了幾下也就輕鬆弄出來了!不過我今天給大家帶來的是實現的原理,我是用作於gpio口控制,也就是一盞燈的點亮點滅!當然了,你可以沿著我思路去做網頁內建配網哦!

二、整體思路;

Created with Raphaël 2.2.0確定好要展示的前端介面(越簡潔越好)編寫:寫一個Html介面,並根據html的表單提交內容編寫業務程式!燒錄:html檔案燒錄到指定程式程式碼外的位置。
執行:上單後,讀取指定位置燒錄的 html 程式碼,之後裝置發出熱點,手機連線此熱點,訪問固定ip地址,彈出html介面; 回撥:根據html介面請求的是 post 提交,對 gpio 腳做出對應的處理,並且原路返回客戶端;結束
  • 必須要知道的知識:
  • ①:以手機瀏覽器為例,其訪問指定的ip地址,過程是怎麼樣的?

     我們都在用手機瀏覽器,很少知道他是怎麼實現訪問互動資料的。這裡我們把esp8266作為伺服器端,手機瀏覽器作為客戶端,一般地,都是get請求,除非指定post提交,而請求的資料格式,大家可以去百度下http協議的資料格式,這裡不再累贅!而請求之後,esp8266

那肯定是要以http協議資料來回復內容的,這內容也就包含了gpio的管腳狀態!從而實現了資料互動!

  • ②:編寫好的html對應燒錄的地址,應該怎麼注意什麼?

      這裡我就不再多說html的檔案怎麼編寫,這需要一定的前端知識。對應的燒錄地址必須在程式碼塊外的地址燒錄,大家不懂哪些是程式碼塊外的地址,可以去看看我上個月寫的25q16儲存晶片的分佈,點我檢視!,之後我們需要在程式碼中讀取這個網頁,之後傳送給客戶端就可以了!

三、編寫一個簡單的Html檔案;

  • 非常簡單,我這裡直接上程式碼:
    • 用的是post提交,不是get請求!
    • 當點選開燈,傳送powerOn=1,點選關燈傳送powerOn=0
    • 注意編碼是utf-8!
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8"></meta><title>esp8266內建網頁單開關燈</title></head>
	<body>
		<h2 align="center">esp8266熱點內建網頁單開關燈By半顆心臟</h2>
		<h3 align="center">%s</h3>
		<form method="post"action="setLight">
			<table align="center"><tr><td>開燈:</td><td>
				<button name="powerOn"type="submit"value="1">點我開燈</button>
			</td></tr><tr><td>關燈:</td><td>
				<button name="powerOff"type="submit"value="0">點我關燈</button>
			</td></tr>
		   </table>
	</form>
</body>
</html>

用電腦瀏覽器開啟預覽如下:

在這裡插入圖片描述

四、esp8266程式設計;

看標題大家都知道,這個裝置esp8266是作為一個熱點讓客戶端去主動連線,那麼esp8266必須要開啟熱點模式,我這裡讓它固定一個ip地址192.168.5.1,當然了,你也可以不設定固定地址,因為預設就是192.168.4.1!開啟熱點之後,等待客戶端連線,如果客戶端有成功連線後,開啟tcp伺服器(其實就是web伺服器第一步),這時候就是一直處於和客戶端連線互動資料的狀態了!

4.1 配置熱點模式,開啟軟路由!

下面程式碼中的webEsp8266是裝置發出的熱點名字,xh12345678是密碼,192, 168, 5, 1是固定自定義的ip地址,允許最大四個的客戶端連線,而且分配的ip是從192, 168, 5, 100192, 168, 5, 105;


	wifi_set_opmode(SOFTAP_MODE);
	struct softap_config *config = (struct softap_config *) zalloc(
			sizeof(struct softap_config)); // 初始化

	wifi_softap_get_config(config);
	sprintf(config->ssid, "webEsp8266");
	sprintf(config->password, "xh12345678");
	config->authmode = AUTH_WPA_WPA2_PSK;
	config->ssid_len = 0;
	config->max_connection = 4;
	wifi_softap_set_config(config); // Set ESP8266 soft-AP config
	free(config);

	struct station_info * station = wifi_softap_get_station_info();
	while (station) {
		printf("bssid : MACSTR, ip : IPSTR/n", MAC2STR(station->bssid),
				IP2STR(&station->ip));
		station = STAILQ_NEXT(station, next);
	}
	wifi_softap_free_station_info(); // Free it by calling functionss
	wifi_softap_dhcps_stop(); // disable soft-AP DHCP server

	//配置dhcp,固定esp8266的ip為 192, 168, 5, 1
	struct ip_info info;
	IP4_ADDR(&info.ip, 192, 168, 5, 1);
	IP4_ADDR(&info.gw, 192, 168, 5, 1);
	IP4_ADDR(&info.netmask, 255, 255, 255, 0);
	wifi_set_ip_info(SOFTAP_IF, &info);
	struct dhcps_lease dhcp_lease;
	IP4_ADDR(&dhcp_lease.start_ip, 192, 168, 5, 100); //分配的網段ip開始
	IP4_ADDR(&dhcp_lease.end_ip, 192, 168, 5, 105); //分配的網段ip結束
	wifi_softap_set_dhcps_lease(&dhcp_lease);
	wifi_softap_dhcps_start(); // 使能 soft-AP DHCP 服務

4.2 建立tcp伺服器!

程式碼比較複雜,總的來說,先初始化socket,之後bind繫結埠號,大家都知道瀏覽器的預設訪問的埠是80,那麼這裡也肯定是80,然後監聽這個埠,阻塞等待訊息!

	int32 listenfd;
	int32 ret = 0;
	char input[1024] = { 0 };
	char output[1024] = { 0 };
	struct sockaddr_in server_addr, remote_addr;
	int stack_counter = 0;
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = INADDR_ANY;
	server_addr.sin_len = sizeof(server_addr);
	server_addr.sin_port = htons(80);

	printf("[XHLogUtils] Task_local_server init succeed!!! \n");

	/* Create socket for incoming connections */
	do {
		listenfd = socket(AF_INET, SOCK_STREAM, 0);
		printf("[XHLogUtils] Create socket for incoming connections !!! \n");
		if (listenfd == -1) {
			printf(
					"[XHLogUtils] Create socket for incoming connections -1 !!! \n");
			vTaskDelay(1000 / portTICK_RATE_MS);
		}
	} while (listenfd == -1);

	/* Bind to the local port */
	do {
		ret = bind(listenfd, (struct sockaddr * )&server_addr,
				sizeof(server_addr));
		printf("[XHLogUtils] Create socket binding !!! \n");
		if (ret != 0) {
			printf("Create socket binding = -1 \n");
			vTaskDelay(1000 / portTICK_RATE_MS);
		}
	} while (ret != 0);

	do {
		// Listen to the local connection
		ret = listen(listenfd, 4);
		printf("[XHLogUtils] Create socket listening !!! \n");
		if (ret != 0) {
			printf(
					"[XHLogUtils] Create socket listening = -1 will close!!! \n");
			vTaskDelay(1000 / portTICK_RATE_MS);
		}
	} while (ret != 0);

	int32 client_sock;
	int32 len = sizeof(struct sockaddr_in);

	for (;;) {

		printf(
				"[XHLogUtils] Task_local_server block here waiting remote connect request !!! \n");

		/*block here waiting remote connect request*/
		if ((client_sock = accept(listenfd, (struct sockaddr * )&remote_addr,
				(socklen_t * )&len)) < 0) {
			printf("[XHLogUtils] acceptting < 0...\n");
			continue;
		} else {
			printf("[XHLogUtils] acceptting > 0...\n");
		}
	}