ESP8266的网页web交互界面
- arduino的菜单库
- https://github.com/neu-rah/ArduinoMenu
- 自带生成html界面
- https://github.com/Hieromon/PageBuilder
- star很多的esp固件
- https://github.com/arendst/Tasmota
- ESP UI
- https://github.com/s00500/ESPUI
- 方法:
- 通过html上的JavaScript脚本向服务器put或pose实现交互
ESP8266做web服务器
https://swf.com.tw/?p=905
按照图中的结构将网页文件放在data文件夹中,然后在arduino中上传到spiffs
void rootRouter() {
File file = SPIFFS.open("/index.htm", "r");//fs以data作为根目录,里面的index.htm的地址就是/index.htm,如果由文件夹image,里面的图片地址就是/image/xxx.png
server.streamFile(file, "text/html");
file.close();
}
void setup()
{
......//连接wifi
server.on("/index.htm", rootRouter);//如果访问的网址是http://192.168.124.8/index.htm时,url是/index.htm,给回调函数rootRouter处理
}
但是这样有个弊端,就是每个url都需要写一个回调函数,比如html里面还有调用了图片,浏览器就会向esp8266更具url请求这个图片,但是esp8266没有写这个图片的url处理函数,所以就会显示不出来
改进方法
String getContentType(String filename){
//通过url的结尾包含哪些字符,判断是什么格式
if(server.hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
else if(filename.endsWith(".css")) return "text/css";
else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".png")) return "image/png";
else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
else if(filename.endsWith(".xml")) return "text/xml";
else if(filename.endsWith(".pdf")) return "application/x-pdf";
else if(filename.endsWith(".zip")) return "application/x-zip";
else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
bool handleFileRead(String path){
Serial.println("handleFileRead: " + path); // 在序列埠显示路径
//在url为根目录的情况下,默认返回/index.htm这个文件
if (path.endsWith("/")) {
path += "index.htm";
}
String contentType = getContentType(path);//获取文件格式,给server.streamFile函数使用
//调用SPIFFS.exists()判断这个url是否在文件系统中存在
if (SPIFFS.exists(path)){
//打开这个文件
File file = SPIFFS.open(path, "r");
//发送这个文件
server.streamFile(file, contentType);
file.close();
return true;
}
//否则就返回没有,404
return false;
}
void setup()
{
//只写一个回调处理函数,只有在没有找到对应文件的情况下,才返回notfound
server.onNotFound([](){
if (!handleFileRead(server.uri())) {
server.send(404, "text/plain", "FileNotFound");
}
});
}
使用Html与arduino交互
用form表单,使用iframe可以达到内部网页,实现不跳转新网页
<form action="" method="post" target="nm_iframe">
<input type="text" id="id_input_text" name="nm_input_text" />
<input type="submit" id="id_submit" name="nm_submit" value="提交" />
</form>
<iframe id="id_iframe" name="nm_iframe" style="display:none;"></iframe>
将结果跳转到新网页上显示
acction表示要请求的url地址,method指示是get还是post,taget指示是新开网页还是当前网页
<form action="toggle" method="get" target="_blank">
<input type="submit" value="开关LED">
</form>
更好的方式是用javascript,使用jQuery库进行开发
https://10.1pxeye.com/http-get-request-in-javascript/
JavaScript 是 HTML5 以及所有现代浏览器中的默认脚本语言
jQuery库
例子html
<!doctype html>
<html>
<head>
<script src="js/jquery.js"> </script>//官网上下载的库
<script src="js/javascript.js"></script>//自己的js脚本
<meta charset="utf-8">
<title>ESP8266</title>
</head>
<body>
<h2>This is a heading</h2>
<p>This is a paragraph.</p>
<p>This is another paragraph.</p>
<button type="button">Click me</button>//type是button的一个属性
</body>
</html>
例子js
$(document).ready(function(){//文档就绪函数
$("button").click(function(){
$("p").hide();
});
});
$(this).hide() - 隐藏当前元素
$(“p”).hide() - 隐藏所有段落
$(".test").hide() - 隐藏所有 class=“test” 的所有元素
$("#test").hide() - 隐藏所有 id=“test” 的元素
button的type属性,
值 | 描述 |
submit | 该按钮是提交按钮(除了 Internet Explorer,该值是其他浏览器的默认值)。 |
button | 该按钮是可点击的按钮(Internet Explorer 的默认值)。 |
reset | 该按钮是重置按钮(清除表单数据)。 |
jQuery 元素选择器
jQuery 使用 CSS 选择器来选取 HTML 元素。
$(“p”) 选取
元素。
$(“p.intro”) 选取所有 class=“intro” 的
元素。
$(“p#demo”) 选取所有 id=“demo” 的
元素。
jQuery 属性选择器
jQuery 使用 XPath 表达式来选择带有给定属性的元素。
$("[href]") 选取所有带有 href 属性的元素。
$("[href=’#’]") 选取所有带有 href 值等于 “#” 的元素。
$("[href!=’#’]") 选取所有带有 href 值不等于 “#” 的元素。
=’.jpg’]") 选取所有 href 值以 “.jpg” 结尾的元素。
button的name就需要用属性选择器
还可以用id的方式
<script type="text/javascript">
$(document).ready(function(){
$("#hide").click(function(){
$("p").hide();
});
$("#show").click(function(){
$("p").show();
});
});
</script>
<button id="hide" type="button">隐藏</button>
<button id="show" type="button">显示</button>
事件
Event 函数 | 绑定函数至 |
$(document).ready(function) | 将函数绑定到文档的就绪事件(当文档完成加载时) |
$(selector).click(function) | 触发或将函数绑定到被选元素的点击事件 |
$(selector).dblclick(function) | 触发或将函数绑定到被选元素的双击事件 |
$(selector).focus(function) | 触发或将函数绑定到被选元素的获得焦点事件 |
$(selector).mouseover(function) | 触发或将函数绑定到被选元素的鼠标悬停事件 |
隐藏显示
jQuery hide() 和 show(),jQuery toggle()
AJAX
https://www.w3school.com.cn/jquery/jquery_ajax_get_post.asp
arduino的webserver库教程
在不重载全部网页的情况下,和服务器做数据交换
能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON
- jQuery load() 方法
jQuery load() 方法是简单但强大的 AJAX 方法。
load() 方法从服务器加载数据,并把返回的数据放入被选元素中。 - jQuery - AJAX get() 和 post() 方法
$("button").click(function(){
$.get("demo_test.asp",function(data,status){
alert("Data: " + data + "\nStatus: " + status);
});
});
HTML语法
- HTML 段落是通过
标签进行定义的。 - HTML 链接是通过 标签进行定义的。
- HTML 标题(Heading)是通过
-
等标签进行定义的。
- HTML 图像是通过 标签进行定义的。
<img src="w3school.jpg" width="104" height="142" />
- <br就是没有关闭标签的空元素
HTML属性
class | classname | 规定元素的类名(classname) |
id | id | 规定元素的唯一 id |
style | style_definition | 规定元素的行内样式(inline style) |
title | text | 规定元素的额外信息(可在工具提示中显示) |
网页模板
https://aspx.sc.chinaz.com/query.aspx?keyword=%E5%90%8E%E5%8F%B0&classID=12
搜索后台,就可以
还可以搜响应菜单
或者搜索Admin Template
有纯html5的,也有用CSS3,也有用Jquery的
定时器
使用js的定时器
教程在菜鸟JS 浏览器BOM
https://www.runoob.com/js/js-timing.html
var int=self.setInterval("clock()",1000);
function clock()
{
var d=new Date();
var t=d.toLocaleTimeString();
$("#time").text(t);
}
//要和jquery分开写
//或者这样写成匿名函数
self.setInterval(function(){
var d=new Date();
var t=d.toLocaleTimeString();
$("#time").text(t);
},1000);
使用jquery的定时器好像不行
居中
<style>
body{text-align:center}
</style>
实例
https://www.runoob.com/js/js-examples.html
表格
<table border="2" cellpadding="10" align=center>
<tr>
<td>
<b>控制中心
</td>
<td>
<p>
切换板载LED灯: <button id="toggle" type="button">Toggle</button>
</p>
</td>
</tr>
<tr>
<td>
<b>数据中心
</td>
<td>
<p id="time">运行时间</p>
</td>
</tr>
</table>
获取单选框的值
所以选择器参考https://www.w3school.com.cn/jquery/jquery_ref_selectors.asp
:冒号是取type是xxx的所有元素
:checked | $(":checked") | 所有被选中的 input 元素 |
:radio | $(":radio") | 所有 type=“radio” 的 元素 |
<input type="radio" id="led" name="led" value="on">开
<input type="radio" id="led" name="led" value="off">关
<button id="setLed" type="button">设置LED</button>
radio单选框,在name相同的时候,才只能选一个
$("#setLed").click(function(){
//使用post发送数据
$.post("setLed",
{
value:$("#led:checked").val()//使用id确定单选框,checked确定勾选的,然后取他的value属性
},
function(data,status){
if(data=="true")
{
alert("切换成功");
}
else
{
alert("切换失败");
}
});
});
arduino使用arg来获取post的数据
void setLedCallback() {
if(server.arg("value") == "on")
digitalWrite(LED_BUILTIN, LOW);
else
digitalWrite(LED_BUILTIN, HIGH);
server.send(200, "text/plain", "true");
}
arduino使用**server.args()**获取一共有多少各参数
使用**server.argName(0)**获取第几个参数的键名
POST数组
在js中是可以post数组的,但是只能以键值对发送
{
value:$("input:radio[name=led]:checked").val(),
list:[1,2,3]
},
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JwmI5ysQ-1648294918509)(C:\Users\87698\AppData\Roaming\Typora\typora-user-images\image-20220109212613173.png)]
这个%5B和%5D其实就是[]
arg[1]=list[]1
接收到的ascii码的键名是list[],值为1
arduino不能直接处理这个格式,需要其他类型转换