上一篇我已经简单的实现了数据上传云平台,这一篇我们简单把ESP8266配置成web服务器,用手机(或电脑)的浏览器来访问8266上的服务器,8266将模拟的温度数据发送给浏览器。
WEB实验简介:
今天我们使用HTTP协议中的GET方法来获取8266的温度数据。首先我们把8266配置成web server,然后通过浏览器输入8266的IP地址来访问,8266服务器每隔2秒更新一次温度数据(温度数据每访问一次自动加1)。
程序流程如下图所示:
一个简单的HTML网页
那要访问web服务器了,是不是我们也要制作一个网站让浏览器访问呢?
是的,简单弄了一个HTML网页,并使用Javascript脚本语言实现了服务器每隔2秒更新一下温度数据。
HTML网页的程序我们就不讲了,我把它贴到下面,大家复制下就可以了,到时候下载到8266就可以访问,程序如下:
<!DOCTYPE html PUBLIC "-//xsc//DTD XHTML 1.0 Transitional//EN" "https://mp.weixin.qq.com/s/9l5G5uIFHQzYhEnqQy5DtA">
<html xmlns="https://mp.weixin.qq.com/s/9l5G5uIFHQzYhEnqQy5DtA">
<head>
<style type="text/css">
INPUT {font-size:30px};
TEXTAREA{font-size:30px};
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>*嵌入式小书虫</title>
</head>
<body>
<divid="嵌入式小书虫">温度为:0℃</div>
<script type="text/javascript">
var syp_http_request;
var Myhost=window.location.host;
var URL="http://" Myhost "/xiaoshuchong.php";
var myid;
if(window.XMLHttpRequest)
{
syp_http_request=new XMLHttpRequest;
if(syp_http_request.overrideMimeType)
{
syp_http_request.overrideMimeType("text/xml");
}
}else if(window.ActiveXObject)
{
try{
syp_http_request=new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){}
}
if(!syp_http_request)
{
window.alert("不能创建 嵌入式小书虫XMLHTTPRequest对象!");
}
myid=window.setInterval(mytip,2000);
my_send_request("GET",URL "&random=" Math.random(),"","TEXT",syp_processTextResponse);
function mytip()
{
my_send_request("GET",URL "&random=" Math.random(),"","TEXT",syp_processTextResponse);
}
function my_send_request(method,url,content,responseType,callback){
if(responseType.toLowerCase()=="text"){
syp_http_request.onreadystatechange=callback;
}else if(responseType.toLowerCase()=="xml"){
syp_http_request.onreadystatechange=callback;
window.alert("响应参数错误");
return false;
}
if(method.toLowerCase()=="get"){
syp_http_request.open(method,url,true);
}else if(method.toLowerCase()=="post"){
syp_http_request.open(method,url,true);
syp_http_request.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
syp_http_request.setRequestHeader("Accept-Language","Zh-cn");
}else{
alert("HTTP请求错误");
return false;
}
syp_http_request.send(content);
}
function syp_processTextResponse(){
if(syp_http_request.readyState==4 && syp_http_request.status==200){
var b=syp_http_request.responseText;
var myobject=eval('(' b ')');
document.getElementById("嵌入式小书虫").innerHTML="温度为:" (myobject.success.value)/10 "℃" ;
}
}
</script>
</body>
</html>
- 把这个文件复制到XXXXX.html文件中,复制完成后用浏览器就可以打开, 查看是否复制正确,正确会出现一个网页。
8266web程序设计
把8266配置成AP(路由)模式 |
开启HTTP web服务 |
侦听 TCP 连接 |
有client客户端连接,发送温度数据 |
温度数据加1 |
浏览器中查看温度数据 |
8266web程序实现
首先我们把8266配置成AP(路由)模式,程序如下:
void ICACHE_FLASH_ATTR syp_userAP_init(void) {
structip_infoinfo;
||设置成AP模式
wifi_set_opmode(STATIONAP_MODE); //Set softAP station mode
||停止dhcp服务
wifi_softap_dhcps_stop();
||设置8266服务器IP
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);
dhcps_lease_test();
||启动dhcp服务
wifi_softap_dhcps_start();
||开启web服务
start_web_server();
}
开启web服务的程序如下:
voidICACHE_FLASH_ATTRstart_web_server(void){
struct ip_info info;
||获取服务器IP
wifi_get_ip_info(SOFTAP_IF, &info);
||初始化web server
syp_web_server_init(&info.ip,80);
}
void ICACHE_FLASH_ATTR syp_web_server_init(struct ip_addr *local_ip,int port){
LOCAL struct espconn esp_conn_syp;
||初始化espconn参数
esp_conn_syp.type=ESPCONN_TCP;
esp_conn_syp.state=ESPCONN_NONE;
esp_conn_syp.proto.tcp=(esp_tcp *)os_malloc(sizeof(esp_tcp));
os_memcpy(esp_conn_syp.proto.tcp->local_ip,local_ip,4);
esp_conn_syp.proto.tcp->local_port=port;
||注册连接成功回调函数和重新连接回调函数
espconn_regist_connectcb(&esp_conn_syp,web_server_listen_syp);
espconn_regist_reconcb(&esp_conn_syp,web_server_recon_syp);
||侦听 TCP 连接
espconn_accept(&esp_conn_syp);
}
回调函数如下:
void ICACHE_FLASH_ATTR web_server_listen_syp(void *arg) {
struct espconn *pespconn = arg;
||注册接收回调函数
espconn_regist_recvcb(pespconn, web_server_recv_syp);
||注册发送回调函数
espconn_regist_sentcb(pespconn, web_server_sent_syp);
|| 断开连接回调函数
espconn_regist_disconcb(pespconn, web_server_discon_syp);
}
void ICACHE_FLASH_ATTR web_server_recon_syp(void *arg,sint8 err){
os_printf("连接错误,错误代码为:%d\r\n",err);
}
void ICACHE_FLASH_ATTR web_server_sent_syp(void *arg){
os_printf("发送成功\r\n");
}
void ICACHE_FLASH_ATTR web_server_discon_syp(void *arg){
os_printf("连接已经断开!");
}
web 服务器接收回调函数程序如下:
#define tempjson "{\"success\": {\"key\": \"temp\",\"value\": \"%d\",\"value2\": \"20\"}}"
||解析URL
bool ICACHE_FLASH_ATTR parse_url_syp(char *precv_data,URLFrame *pURL_frame){
char *pbuffer_date=NULL;
char *str=NULL;
int length=0;
||数据为空,返回false
if(precv_data==NULL || pURL_frame==NULL){
os_printf("%s","Wrong");
return false;
}
||查找host
pbuffer_date=(char*)os_strstr(precv_data,"Host:");
if(pbuffer_date!=NULL){
os_memset(pURL_frame->pFilename,0,URLSize);
if(os_strncmp(precv_data,"GET",4)==0){
||查找GET
pURL_frame->Type = GET;
pbuffer_date = precv_data 4;
}else if(os_strncmp(precv_data,"POST ",5)==0){
||查找POST
pURL_frame->Type=POST;
pbuffer_date=precv_data 5;
}else{
return false;
}
pbuffer_date ;
||查找HTTP
str=(char *)os_strstr(pbuffer_date," HTTP");
if(str !=NULL){
length=str-pbuffer_date;
os_memcpy(pURL_frame->pFilename,pbuffer_date,length);
}else{
os_printf("%s","Can not find HTTP");
}
}else{
os_printf("%s","Can not find Host");
return false;
}
return true;
}
voidICACHE_FLASH_ATTRweb_server_recv_syp(void*arg,char*pdata,unsignedshortlen){
char index2[4096];
URLFrame *pURLFrame=NULL;
char *pParseBuffer=NULL;
char *precvdata = NULL;
static int Temp = 0;
pURLFrame=(URLFrame *)os_zalloc(sizeof(URLFrame));
precvdata=(char *)os_zalloc(len 1);
os_memcpy(precvdata,pdata,len);
||解析URL
parse_url_syp(precvdata,pURLFrame);
switch(pURLFrame->Type)
{
case GET:
if(strncmp(pURLFrame->pFilename,"xiaoshuchong.php",16)==0)
{
os_printf("收到浏览器发来的数据xiaoshuchong.php:%s", pdata);
os_sprintf(index2,tempjson,Temp);
||温度数据每次加1
Temp ;
||发送温度数据
data_send_syp(arg,true,index2);
}else{
os_printf("收到浏览器发来的数据:%s", pdata);
err = spi_flash_read(0x10 * 4096, (uint32 *) index2, 4096);
index2[INDEX_SIZE]=0;
||发送网页
data_send_syp(arg, true, index2);
}
break;
casePOST:
break;
}
os_free(pURLFrame);
pURLFrame=NULL;
os_free(precvdata);
precvdata=NULL;
}
- 如果收到GET请求包的文件名是xiaoshuchong.php则发送温度数据
- 否则发送flash中保存的网页数据。
HTTP web服务器发送温度数据函数如下
voidICACHE_FLASH_ATTRdata_send_syp(void*arg,boolresponseis_OK,char*psenddata){
char httphead[256];
char *sypbuf_datas=NULL;
uint16 date_length;
struct espconn *syp_espconn=arg;
if(responseis_OK){
||HTTP请求正确,回复200
os_sprintf(httphead,"HTTP/1.1 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n",psenddata ? os_strlen(psenddata) : 0);
if(psenddata){
||准备HTTP数据头
os_sprintf(httphead strlen(httphead),"Content-Type: text/html; charset=utf-8\r\nPragma: no-cache\r\n\r\n");
date_length=os_strlen(httphead) os_strlen(psenddata);
sypbuf_datas=(char *)os_zalloc(date_length 1);
os_memcpy(sypbuf_datas,httphead,os_strlen(httphead));
os_memcpy(sypbuf_datas os_strlen(httphead),psenddata,os_strlen(psenddata));
}else{
os_sprintf(httphead os_strlen(httphead),"\r\n");
date_length=os_strlen(httphead);
}
}else{
||HTTP请求错误,回复400
os_sprintf(httphead,"HTTP/1.1 400 BadRequest\r\nContent-Length: 0\r\nServer: lwIP/1.4.0\r\n");
date_length=os_strlen(httphead);
}
||发送数据
if(psenddata){
espconn_sent(syp_espconn,sypbuf_datas,date_length);
}else{
espconn_sent(syp_espconn,httphead,date_length);
}
||释放内存
if(sypbuf_datas){
os_free(sypbuf_datas);
sypbuf_datas=NULL;
}
}
程序编写完成,编译下载,电脑连接8266的热点,打开浏览器,输入8266服务器IP,就会出现温度数据,如下图:
同样的操作,在手机端也连接8266的热点并打开浏览器查看,如下图:
看到了吧,我们的温度是变化的。
我们在看下串口助手打印的数据,如下图:
好了,今天web服务器应用就讲完了,接下来我们会讲一下arm公司开源的arm-2D,据说是专门为小资源单片机设计的,连接如下:
为什么说Arm-2D是小资源单片机的GUI人权卡
补充:
今天的网页文件XXXX.html要烧写到FLASH的0x10000这个地址,如下图: