一、原生Ajax技术
网页核心代码:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>ZLTech</title> <style type="text/css" media="screen"> * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; margin-top: 0.2%; margin-bottom:1%; background-color: white; } #out { width: 100%; height: 100%; text-align: center; } #left { display: inline-block; float: left; width: 15%; height: 100%; } #middle { display: inline-block; width: 68%; height: 100%; margin-bottom:2%; } #right { display: inline-block; float: right; width: 15%; height: 100%; } #left_0,#left_1,#left_2,#left_3,#left_4,#left_5,#left_6,#left_7 { margin: 2%; height: 11.5%; } #left_0_form,#left_1_form,#left_2_form,#left_3_form,#left_4_form,#left_5_form,#left_6_form,#left_7_form { display: block; width: 100%; height: 100%; } #left_0_input,#left_1_input,#left_2_input,#left_3_input,#left_4_input,#left_5_input,#left_6_input,#left_7_input { display: block; width: 100%; height: 100%; outline: none; cursor: pointer; text-align:center; font:20px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: .5em; -moz-border-radius: .5em; border-radius: .5em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #d9eef7; border: solid 1px #0076a3; background: #0095cd; background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5)); background: -moz-linear-gradient(top, #00adee, #0078a5); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5'); } #right_0,#right_1,#right_2,#right_3,#right_4,#right_5,#right_6,#right_7 { margin: 2%; height: 11.5%; } #right_0_form,#right_1_form,#right_2_form,#right_3_form,#right_4_form,#right_5_form,#right_6_form,#right_7_form { display: block; width: 100%; height: 100%; } #right_0_input,#right_1_input,#right_2_input,#right_3_input,#right_4_input,#right_5_input,#right_6_input,#right_7_input { display: block; width: 100%; height: 100%; outline: none; cursor: pointer; text-align:center; font:20px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: .5em; -moz-border-radius: .5em; border-radius: .5em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: white; border: solid 1px #0076a3; background: #0095cd; background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5)); background: -moz-linear-gradient(top, #00adee, #0078a5); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5'); } #middle_top { height: 98%; width: 100%; margin-top: 0.4%; margin-bottom: 2%; } img { display: block; height: 100%; width: 100%; -webkit-user-select: none; margin: auto; background-color:hsl(0,0%,25%); } #middle_down { position: absolute; left: 17%; bottom: 1%; height: 37%; width: 66%; } #middle_down_left { display: inline-block; float: left; width: 30%; height: 100%; } #middle_down_right { display: inline-block; float: right; width: 30%; height: 100%; } #lu,#ld,#ru,#rd { margin:0 auto; width: 25%; height: 30%; } #ll_lst_lr,#rl_rst_rr { margin:0 auto; width: 80%; height: 30%; margin-top: 2%; margin-bottom: 2%; } #ll,#rl { display: inline-block; width: 29%; height: 100%; margin-left: 1%; margin-right: 2%; } #lst,#rst { display: inline-block; width: 29%; height: 100%; } #lr,#rr { display: inline-block; width: 29%; height: 100%; margin-left: 2%; } #lu_form,#ld_form,#ll_form,#lr_form,#lst_form { display: block; width: 100%; height: 100%; } #ru_form,#rd_form,#rl_form,#rr_form,#rst_form { display: block; width: 100%; height: 100%; } #lu_input,#ld_input,#ll_input,#lr_input,#lst_input { display: inline-block; width: 100%; height: 100%; outline: none; cursor: pointer; text-align:center; font:15px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: .5em; -moz-border-radius: .5em; border-radius: .5em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #fef4e9; border: solid 1px #da7c0c; background: #f78d1d; background: -webkit-gradient(linear, left top, left bottom, from(#faa5ea), to(#f47a20)); background: -moz-linear-gradient(top, #faa5ea, #f47a20); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#faa5ea', endColorstr='#f47a20'); } #ru_input,#rd_input,#rl_input,#rr_input,#rst_input { display: block; width: 100%; height: 100%; outline: none; cursor: pointer; text-align:center; font:15px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: .5em; -moz-border-radius: .5em; border-radius: .5em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #d9eef7; border: solid 1px #0076a3; background: #0095cd; background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5)); background: -moz-linear-gradient(top, #00adee, #0078a5); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5'); } </style> <script> // Ajax请求的网址,也就是默认网址 192.168.4.1 var request_url = 'http://192.168.4.1/post'; // 按钮对应的文本 var request_text_dict = { 'left_0_input': '0号正', 'left_1_input': '1号正', 'left_2_input': '2号正', 'left_3_input': '3号正', 'left_4_input': '4号正', 'left_5_input': '5号正', 'left_6_input': '6号正', 'left_7_input': '7号正', 'lu_input': '左上', 'ld_input': '左下', 'll_input': '左左', 'lr_input': '左右', 'lst_input': '左中', 'ru_input': '右上', 'rd_input': '右下', 'rl_input': '右左', 'rr_input': '右右', 'rst_input': '右中', 'right_0_input': '0号反', 'right_1_input': '1号反', 'right_2_input': '2号反', 'right_3_input': '3号反', 'right_4_input': '4号反', 'right_5_input': '5号反', 'right_6_input': '6号反', 'right_7_input': '7号反', }; // 按钮对应的指令 var request_cmd_dict = { 'left_0_input_press_cmd': '#000P1000T2000!', 'left_0_input_release_cmd': '#255PDST!', 'left_1_input_press_cmd': '#001P1000T2000!', 'left_1_input_release_cmd': '#255PDST!', 'left_2_input_press_cmd': '#002P1000T2000!', 'left_2_input_release_cmd': '#255PDST!', 'left_3_input_press_cmd': '#003P1000T2000!', 'left_3_input_release_cmd': '#255PDST!', 'left_4_input_press_cmd': '#004P1000T2000!', 'left_4_input_release_cmd': '#255PDST!', 'left_5_input_press_cmd': '#005P1000T2000!', 'left_5_input_release_cmd': '#255PDST!', 'left_6_input_press_cmd': '#006P1000T2000!', 'left_6_input_release_cmd': '#255PDST!', 'left_7_input_press_cmd': '#007P1000T2000!', 'left_7_input_release_cmd': '#255PDST!', 'lu_input_press_cmd': '$DCR:600,600!', 'lu_input_release_cmd': '$DCR:0,0!', 'ld_input_press_cmd': '$DCR:-600,-600!', 'ld_input_release_cmd': '$DCR:0,0!', 'll_input_press_cmd': '$DCR:-600,600!', 'll_input_release_cmd': '$DCR:0,0!', 'lr_input_press_cmd': '$DCR:600,-600!', 'lr_input_release_cmd': '$DCR:0,0!', 'lst_input_press_cmd': '$DCR:0,0!', 'lst_input_release_cmd': '$DCR:0,0!', 'ru_input_press_cmd': '$DCR:900,900!', 'ru_input_release_cmd': '$DCR:0,0!', 'rd_input_press_cmd': '$DCR:-900,-900!', 'rd_input_release_cmd': '$DCR:0,0!', 'rl_input_press_cmd': '$DCR:-900,900!', 'rl_input_release_cmd': '$DCR:0,0!', 'rr_input_press_cmd': '$DCR:900,-900!', 'rr_input_release_cmd': '$DCR:0,0!', 'rst_input_press_cmd': '$DCR:0,0!', 'rst_input_release_cmd': '$DCR:0,0!', 'right_0_input_press_cmd': '#000P2000T2000!', 'right_0_input_release_cmd': '#255PDST!', 'right_1_input_press_cmd': '#001P2000T2000!', 'right_1_input_release_cmd': '#255PDST!', 'right_2_input_press_cmd': '#002P2000T2000!', 'right_2_input_release_cmd': '#255PDST!', 'right_3_input_press_cmd': '#003P2000T2000!', 'right_3_input_release_cmd': '#255PDST!', 'right_4_input_press_cmd': '#004P2000T2000!', 'right_4_input_release_cmd': '#255PDST!', 'right_5_input_press_cmd': '#005P2000T2000!', 'right_5_input_release_cmd': '#255PDST!', 'right_6_input_press_cmd': '#006P2000T2000!', 'right_6_input_release_cmd': '#255PDST!', 'right_7_input_press_cmd': '#007P2000T2000!', 'right_7_input_release_cmd': '#255PDST!', }; // 打开网页后自动将按钮文本填写到对应按钮上 window.onload = function () { var left_0_input = document.getElementById('left_0_input'); var left_1_input = document.getElementById('left_1_input'); var left_2_input = document.getElementById('left_2_input'); var left_3_input = document.getElementById('left_3_input'); var left_4_input = document.getElementById('left_4_input'); var left_5_input = document.getElementById('left_5_input'); var left_6_input = document.getElementById('left_6_input'); var left_7_input = document.getElementById('left_7_input'); var lu_input = document.getElementById('lu_input'); var ld_input = document.getElementById('ld_input'); var ll_input = document.getElementById('ll_input'); var lr_input = document.getElementById('lr_input'); var lst_input = document.getElementById('lst_input'); var ru_input = document.getElementById('ru_input'); var rd_input = document.getElementById('rd_input'); var rl_input = document.getElementById('rl_input'); var rr_input = document.getElementById('rr_input'); var rst_input = document.getElementById('rst_input'); var right_0_input = document.getElementById('right_0_input'); var right_1_input = document.getElementById('right_1_input'); var right_2_input = document.getElementById('right_2_input'); var right_3_input = document.getElementById('right_3_input'); var right_4_input = document.getElementById('right_4_input'); var right_5_input = document.getElementById('right_5_input'); var right_6_input = document.getElementById('right_6_input'); var right_7_input = document.getElementById('right_7_input'); left_0_input.value = request_text_dict.left_0_input; left_1_input.value = request_text_dict.left_1_input; left_2_input.value = request_text_dict.left_2_input; left_3_input.value = request_text_dict.left_3_input; left_4_input.value = request_text_dict.left_4_input; left_5_input.value = request_text_dict.left_5_input; left_6_input.value = request_text_dict.left_6_input; left_7_input.value = request_text_dict.left_7_input; lu_input.value = request_text_dict.lu_input; ld_input.value = request_text_dict.ld_input; ll_input.value = request_text_dict.ll_input; lr_input.value = request_text_dict.lr_input; lst_input.value = request_text_dict.lst_input; ru_input.value = request_text_dict.ru_input; rd_input.value = request_text_dict.rd_input; rl_input.value = request_text_dict.rl_input; rr_input.value = request_text_dict.rr_input; rst_input.value = request_text_dict.rst_input; right_0_input.value = request_text_dict.right_0_input; right_1_input.value = request_text_dict.right_1_input; right_2_input.value = request_text_dict.right_2_input; right_3_input.value = request_text_dict.right_3_input; right_4_input.value = request_text_dict.right_4_input; right_5_input.value = request_text_dict.right_5_input; right_6_input.value = request_text_dict.right_6_input; right_7_input.value = request_text_dict.right_7_input; }; function l0_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l0_press_data = request_cmd_dict.left_0_input_press_cmd; var data = {"self_cmd_text":l0_press_data}; //alert(data.self_cmd_text); xhr.send(JSON.stringify(data)); }; function l0_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l0_release_data = request_cmd_dict.left_0_input_release_cmd; var data = {"self_cmd_text":l0_release_data}; //alert(data.self_cmd_text); xhr.send(JSON.stringify(data)); }; function l1_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l1_press_data = request_cmd_dict.left_1_input_press_cmd; var data = {"self_cmd_text":l1_press_data}; xhr.send(JSON.stringify(data)); }; function l1_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l1_release_data = request_cmd_dict.left_1_input_release_cmd; var data = {"self_cmd_text":l1_release_data}; xhr.send(JSON.stringify(data)); }; function l2_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l2_press_data = request_cmd_dict.left_2_input_press_cmd; var data = {"self_cmd_text":l2_press_data}; xhr.send(JSON.stringify(data)); }; function l2_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l2_release_data = request_cmd_dict.left_2_input_release_cmd; var data = {"self_cmd_text":l2_release_data}; xhr.send(JSON.stringify(data)); }; function l3_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l3_press_data = request_cmd_dict.left_3_input_press_cmd; var data = {"self_cmd_text":l3_press_data}; xhr.send(JSON.stringify(data)); }; function l3_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l3_release_data = request_cmd_dict.left_3_input_release_cmd; var data = {"self_cmd_text":l3_release_data}; xhr.send(JSON.stringify(data)); }; function l4_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l4_press_data = request_cmd_dict.left_4_input_press_cmd; var data = {"self_cmd_text":l4_press_data}; xhr.send(JSON.stringify(data)); }; function l4_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l4_release_data = request_cmd_dict.left_4_input_release_cmd; var data = {"self_cmd_text":l4_release_data}; xhr.send(JSON.stringify(data)); }; function l5_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l5_press_data = request_cmd_dict.left_5_input_press_cmd; var data = {"self_cmd_text":l5_press_data}; xhr.send(JSON.stringify(data)); }; function l5_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l5_release_data = request_cmd_dict.left_5_input_release_cmd; var data = {"self_cmd_text":l5_release_data}; xhr.send(JSON.stringify(data)); }; function l6_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l6_press_data = request_cmd_dict.left_6_input_press_cmd; var data = {"self_cmd_text":l6_press_data}; xhr.send(JSON.stringify(data)); }; function l6_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l6_release_data = request_cmd_dict.left_6_input_release_cmd; var data = {"self_cmd_text":l6_release_data}; xhr.send(JSON.stringify(data)); }; function l7_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l7_press_data = request_cmd_dict.left_7_input_press_cmd; var data = {"self_cmd_text":l7_press_data}; xhr.send(JSON.stringify(data)); }; function l7_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var l7_release_data = request_cmd_dict.left_7_input_release_cmd; var data = {"self_cmd_text":l7_release_data}; xhr.send(JSON.stringify(data)); }; function r0_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r0_press_data = request_cmd_dict.right_0_input_press_cmd; var data = {"self_cmd_text":r0_press_data}; xhr.send(JSON.stringify(data)); } function r0_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r0_release_data = request_cmd_dict.right_0_input_release_cmd; var data = {"self_cmd_text":r0_release_data}; xhr.send(JSON.stringify(data)); } function r1_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r1_press_data = request_cmd_dict.right_1_input_press_cmd; var data = {"self_cmd_text":r1_press_data}; xhr.send(JSON.stringify(data)); } function r1_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r1_release_data = request_cmd_dict.right_1_input_release_cmd; var data = {"self_cmd_text":r1_release_data}; xhr.send(JSON.stringify(data)); } function r2_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r2_press_data = request_cmd_dict.right_2_input_press_cmd; var data = {"self_cmd_text":r2_press_data}; xhr.send(JSON.stringify(data)); } function r2_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r2_release_data = request_cmd_dict.right_2_input_release_cmd; var data = {"self_cmd_text":r2_release_data}; xhr.send(JSON.stringify(data)); } function r3_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r3_press_data = request_cmd_dict.right_3_input_press_cmd; var data = {"self_cmd_text":r3_press_data}; xhr.send(JSON.stringify(data)); } function r3_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r3_release_data = request_cmd_dict.right_3_input_release_cmd; var data = {"self_cmd_text":r3_release_data}; xhr.send(JSON.stringify(data)); } function r4_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r4_press_data = request_cmd_dict.right_4_input_press_cmd; var data = {"self_cmd_text":r4_press_data}; xhr.send(JSON.stringify(data)); } function r4_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r4_release_data = request_cmd_dict.right_4_input_release_cmd; var data = {"self_cmd_text":r4_release_data}; xhr.send(JSON.stringify(data)); } function r5_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r5_press_data = request_cmd_dict.right_5_input_press_cmd; var data = {"self_cmd_text":r5_press_data}; xhr.send(JSON.stringify(data)); } function r5_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r5_release_data = request_cmd_dict.right_5_input_release_cmd; var data = {"self_cmd_text":r5_release_data}; xhr.send(JSON.stringify(data)); } function r6_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r6_press_data = request_cmd_dict.right_6_input_press_cmd; var data = {"self_cmd_text":r6_press_data}; xhr.send(JSON.stringify(data)); } function r6_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r6_release_data = request_cmd_dict.right_6_input_release_cmd; var data = {"self_cmd_text":r6_release_data}; xhr.send(JSON.stringify(data)); } function r7_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r7_press_data = request_cmd_dict.right_7_input_press_cmd; var data = {"self_cmd_text":r7_press_data}; xhr.send(JSON.stringify(data)); } function r7_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var r7_release_data = request_cmd_dict.right_7_input_release_cmd; var data = {"self_cmd_text":r7_release_data}; xhr.send(JSON.stringify(data)); } function lu_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var lu_press_data = request_cmd_dict.lu_input_press_cmd; var data = {"self_cmd_text":lu_press_data}; xhr.send(JSON.stringify(data)); } function lu_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var lu_release_data = request_cmd_dict.lu_input_release_cmd; var data = {"self_cmd_text":lu_release_data}; xhr.send(JSON.stringify(data)); } function ld_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var ld_press_data = request_cmd_dict.ld_input_press_cmd; var data = {"self_cmd_text":ld_press_data}; xhr.send(JSON.stringify(data)); } function ld_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var ld_release_data = request_cmd_dict.ld_input_release_cmd; var data = {"self_cmd_text":ld_release_data}; xhr.send(JSON.stringify(data)); } function ll_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var ll_press_data = request_cmd_dict.ll_input_press_cmd; var data = {"self_cmd_text":ll_press_data}; xhr.send(JSON.stringify(data)); } function ll_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var ll_release_data = request_cmd_dict.ll_input_release_cmd; var data = {"self_cmd_text":ll_release_data}; xhr.send(JSON.stringify(data)); } function lr_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var lr_press_data = request_cmd_dict.lr_input_press_cmd; var data = {"self_cmd_text":lr_press_data}; xhr.send(JSON.stringify(data)); } function lr_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var lr_release_data = request_cmd_dict.lr_input_release_cmd; var data = {"self_cmd_text":lr_release_data}; xhr.send(JSON.stringify(data)); } function lst_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var lst_press_data = request_cmd_dict.lst_input_press_cmd; var data = {"self_cmd_text":lst_press_data}; xhr.send(JSON.stringify(data)); } function ru_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var ru_press_data = request_cmd_dict.ru_input_press_cmd; var data = {"self_cmd_text":ru_press_data}; xhr.send(JSON.stringify(data)); } function ru_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var ru_release_data = request_cmd_dict.ru_input_release_cmd; var data = {"self_cmd_text":ru_release_data}; xhr.send(JSON.stringify(data)); } function rd_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var rd_press_data = request_cmd_dict.rd_input_press_cmd; var data = {"self_cmd_text":rd_press_data}; xhr.send(JSON.stringify(data)); } function rd_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var rd_release_data = request_cmd_dict.rd_input_release_cmd; var data = {"self_cmd_text":rd_release_data}; xhr.send(JSON.stringify(data)); } function rl_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var rl_press_data = request_cmd_dict.rl_input_press_cmd; var data = {"self_cmd_text":rl_press_data}; xhr.send(JSON.stringify(data)); } function rl_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var rl_release_data = request_cmd_dict.rl_input_release_cmd; var data = {"self_cmd_text":rl_release_data}; xhr.send(JSON.stringify(data)); } function rr_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var rr_press_data = request_cmd_dict.rr_input_press_cmd; var data = {"self_cmd_text":rr_press_data}; xhr.send(JSON.stringify(data)); } function rr_release_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var rr_release_data = request_cmd_dict.rr_input_release_cmd; var data = {"self_cmd_text":rr_release_data}; xhr.send(JSON.stringify(data)); } function rst_press_submit(self) { var xhr = new XMLHttpRequest(); xhr.open('post',request_url,true); // 设置请求头 xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 要发送的数据 var rst_press_data = request_cmd_dict.rst_input_press_cmd; var data = {"self_cmd_text":rst_press_data}; xhr.send(JSON.stringify(data)); } </script> </head> <body> <div id='out'> <div id='left'> <div id='left_0'> <form action="" method="post" id='left_0_form'> <input id='left_0_input' type="button" name='left_0_input' value="0号正" onmousedown='l0_press_submit(this)' onmouseup='l0_release_submit(this)' ontouchstart='l0_press_submit(this)' ontouchend='l0_release_submit(this)'> </form> </div> <div id='left_1'> <form action="" method="post" id='left_1_form'> <input id='left_1_input' type="button" name='left_1_input' value="1号正" onmousedown='l1_press_submit(this)' onmouseup='l1_release_submit(this)' ontouchstart='l1_press_submit(this)' ontouchend='l1_release_submit(this)'> </form> </div> <div id='left_2'> <form action="" method="post" id='left_2_form'> <input id='left_2_input' type="button" name='left_2_input' value="2号正" onmousedown='l2_press_submit(this)' onmouseup='l2_release_submit(this)' ontouchstart='l2_press_submit(this)' ontouchend='l2_release_submit(this)'> </form> </div> <div id='left_3'> <form action="" method="post" id='left_3_form'> <input id='left_3_input' type="button" name='left_3_input' value="3号正" onmousedown='l3_press_submit(this)' onmouseup='l3_release_submit(this)' ontouchstart='l3_press_submit(this)' ontouchend='l3_release_submit(this)'> </form> </div> <div id='left_4'> <form action="" method="post" id='left_4_form'> <input id='left_4_input' type="button" name='left_4_input' value="4号正" onmousedown='l4_press_submit(this)' onmouseup='l4_release_submit(this)' ontouchstart='l4_press_submit(this)' ontouchend='l4_release_submit(this)'> </form> </div> <div id='left_5'> <form action="" method="post" id='left_5_form'> <input id='left_5_input' type="button" name='left_5_input' value="5号正" onmousedown='l5_press_submit(this)' onmouseup='l5_release_submit(this)' ontouchstart='l5_press_submit(this)' ontouchend='l5_release_submit(this)'> </form> </div> <div id='left_6'> <form action="" method="post" id='left_1_form'> <input id='left_6_input' type="button" name='left_6_input' value="6号正" onmousedown='l6_press_submit(this)' onmouseup='l6_release_submit(this)' ontouchstart='l6_press_submit(this)' ontouchend='l6_release_submit(this)'> </form> </div> <div id='left_7'> <form action="" method="post" id='left_7_form'> <input id='left_7_input' type="button" name='left_7_input' value="7号正" onmousedown='l7_press_submit(this)' onmouseup='l7_release_submit(this)' ontouchstart='l7_press_submit(this)' ontouchend='l7_release_submit(this)'> </form> </div> </div> <div id='middle'> <div id='middle_top'> <img src='http://192.168.4.1:81/stream'> </div> </div> <div id='right'> <div id='right_0'> <form action="" method="post" id='right_0_form'> <input id='right_0_input' type="button" name='right_0_input' value="0号反" onmousedown='r0_press_submit(this)' onmouseup='r0_release_submit(this)' ontouchstart='r0_press_submit(this)' ontouchend='r0_release_submit(this)'> </form> </div> <div id='right_1'> <form action="" method="post" id='right_1_form'> <input id='right_1_input' type="button" name='right_1_input' value="1号反" onmousedown='r1_press_submit(this)' onmouseup='r1_release_submit(this)' ontouchstart='r1_press_submit(this)' ontouchend='r1_release_submit(this)'> </form> </div> <div id='right_2'> <form action="" method="post" id='right_2_form'> <input id='right_2_input' type="button" name='right_2_input' value="2号反" onmousedown='r2_press_submit(this)' onmouseup='r2_release_submit(this)' ontouchstart='r2_press_submit(this)' ontouchend='r2_release_submit(this)'> </form> </div> <div id='right_3'> <form action="" method="post" id='right_3_form'> <input id='right_3_input' type="button" name='right_3_input' value="3号反" onmousedown='r3_press_submit(this)' onmouseup='r3_release_submit(this)' ontouchstart='r3_press_submit(this)' ontouchend='r3_release_submit(this)'> </form> </div> <div id='right_4'> <form action="" method="post" id='right_4_form'> <input id='right_4_input' type="button" name='right_4_input' value="4号反" onmousedown='r4_press_submit(this)' onmouseup='r4_release_submit(this)' ontouchstart='r4_press_submit(this)' ontouchend='r4_release_submit(this)'> </form> </div> <div id='right_5'> <form action="" method="post" id='right_5_form'> <input id='right_5_input' type="button" name='right_5_input' value="5号反" onmousedown='r5_press_submit(this)' onmouseup='r5_release_submit(this)' ontouchstart='r5_press_submit(this)' ontouchend='r5_release_submit(this)'> </form> </div> <div id='right_6'> <form action="" method="post" id='right_1_form'> <input id='right_6_input' type="button" name='right_6_input' value="6号反" onmousedown='r6_press_submit(this)' onmouseup='r6_release_submit(this)' ontouchstart='r6_press_submit(this)' ontouchend='r6_release_submit(this)'> </form> </div> <div id='right_7'> <form action="" method="post" id='right_7_form'> <input id='right_7_input' type="button" name='right_7_input' value="7号反" onmousedown='r7_press_submit(this)' onmouseup='r7_release_submit(this)' ontouchstart='r7_press_submit(this)' ontouchend='r7_release_submit(this)'> </form> </div> </div> </div> <div id='middle_down'> <div id='middle_down_left'> <div id='lu'> <form action="" method="post" id='lu_form'> <input id='lu_input' name='lu_input' value="lu" type="button" onmousedown='lu_press_submit(this)' onmouseup='lu_release_submit(this)' ontouchstart='lu_press_submit(this)' ontouchend='lu_release_submit(this)'> </form> </div> <div id='ll_lst_lr'> <div id='ll'> <form action="" method="post" id='ll_form'> <input id='ll_input' name='ll_input' value="ll" type="button" onmousedown='ll_press_submit(this)' onmouseup='ll_release_submit(this)' ontouchstart='ll_press_submit(this)' ontouchend='ll_release_submit(this)'> </form> </div> <div id='lst'> <form action="" method="post" id='lst_form'> <input id='lst_input' name='lst_input' value="lst" type="button" onclick='lst_press_submit(this)'> </form> </div> <div id='lr'> <form action="" method="post" id='lr_form'> <input id='lr_input' name='lr_input' value="lr" type="button" onmousedown='lr_press_submit(this)' onmouseup='lr_release_submit(this)' ontouchstart='lr_press_submit(this)' ontouchend='lr_release_submit(this)'> </form> </div> </div> <div id='ld'> <form action="" method="post" id='ld_form'> <input id='ld_input' name='ld_input' value="ld" type="button" onmousedown='ld_press_submit(this)' onmouseup='ld_release_submit(this)' ontouchstart='ld_press_submit(this)' ontouchend='ld_release_submit(this)'> </form> </div> </div> <div id='middle_down_right'> <div id='ru'> <form action="" method="post" id='ru_form'> <input id='ru_input' name='ru_input' value="ru" type="button" onmousedown='ru_press_submit(this)' onmouseup='ru_release_submit(this)' ontouchstart='ru_press_submit(this)' ontouchend='ru_release_submit(this)'> </form> </div> <div id='rl_rst_rr'> <div id='rl'> <form action="" method="post" id='rl_form'> <input id='rl_input' name='rl_input' value="rl" type="button" onmousedown='rl_press_submit(this)' onmouseup='rl_release_submit(this)' ontouchstart='rl_press_submit(this)' ontouchend='rl_release_submit(this)'> </form> </div> <div id='rst'> <form action="" method="post" id='rst_form'> <input id='rst_input' name='rst_input' value="rst" type="button" onclick='rst_press_submit(this)'> </form> </div> <div id='rr'> <form action="" method="post" id='rr_form'> <input id='rr_input' name='rr_input' value="rr" type="button" onmousedown='rr_press_submit(this)' onmouseup='rr_release_submit(this)' ontouchstart='rr_press_submit(this)' ontouchend='rr_release_submit(this)'> </form> </div> </div> <div id='rd'> <form action="" method="post" id='rd_form'> <input id='rd_input' name='rd_input' value="rd" type="button" onmousedown='rd_press_submit(this)' onmouseup='rd_release_submit(this)' ontouchstart='rd_press_submit(this)' ontouchend='rd_release_submit(this)'> </form> </div> </div> </div> </body> </html>
function l0_press_submit(self) {
var xhr = new XMLHttpRequest();
xhr.open('post',request_url,true);
// 设置请求头
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
// 要发送的数据
var l0_press_data = request_cmd_dict.left_0_input_press_cmd;
var data = {"self_cmd_text":l0_press_data};
//alert(data.self_cmd_text);
xhr.send(JSON.stringify(data));
};
后端核心代码(以esp32cam中的c为例):
#include "esp_http_server.h" #include "esp_timer.h" #include "esp_camera.h" #include "img_converters.h" #include "camera_index.h" #include "Arduino.h" #include "fb_gfx.h" #include "fd_forward.h" #include "fr_forward.h" #define ENROLL_CONFIRM_TIMES 5 #define FACE_ID_SAVE_NUMBER 7 #define FACE_COLOR_WHITE 0x00FFFFFF #define FACE_COLOR_BLACK 0x00000000 #define FACE_COLOR_RED 0x000000FF #define FACE_COLOR_GREEN 0x0000FF00 #define FACE_COLOR_BLUE 0x00FF0000 #define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN) #define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN) #define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED) typedef struct { size_t size; //number of values used for filtering size_t index; //current value index size_t count; //value count int sum; int * values; //array to be filled with values } ra_filter_t; typedef struct { httpd_req_t *req; size_t len; } jpg_chunking_t; #define PART_BOUNDARY "123456789000000000000987654321" static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; static ra_filter_t ra_filter; httpd_handle_t stream_httpd = NULL; httpd_handle_t camera_httpd = NULL; static mtmn_config_t mtmn_config = {0}; static int8_t detection_enabled = 0; static int8_t recognition_enabled = 0; static int8_t is_enrolling = 0; static face_id_list id_list = {0}; static ra_filter_t * ra_filter_init(ra_filter_t * filter, size_t sample_size){ memset(filter, 0, sizeof(ra_filter_t)); filter->values = (int *)malloc(sample_size * sizeof(int)); if(!filter->values){ return NULL; } memset(filter->values, 0, sample_size * sizeof(int)); filter->size = sample_size; return filter; } static int ra_filter_run(ra_filter_t * filter, int value){ if(!filter->values){ return value; } filter->sum -= filter->values[filter->index]; filter->values[filter->index] = value; filter->sum += filter->values[filter->index]; filter->index++; filter->index = filter->index % filter->size; if (filter->count < filter->size) { filter->count++; } return filter->sum / filter->count; } static void rgb_print(dl_matrix3du_t *image_matrix, uint32_t color, const char * str){ fb_data_t fb; fb.width = image_matrix->w; fb.height = image_matrix->h; fb.data = image_matrix->item; fb.bytes_per_pixel = 3; fb.format = FB_BGR888; fb_gfx_print(&fb, (fb.width - (strlen(str) * 14)) / 2, 10, color, str); } static int rgb_printf(dl_matrix3du_t *image_matrix, uint32_t color, const char *format, ...){ char loc_buf[64]; char * temp = loc_buf; int len; va_list arg; va_list copy; va_start(arg, format); va_copy(copy, arg); len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg); va_end(copy); if(len >= sizeof(loc_buf)){ temp = (char*)malloc(len+1); if(temp == NULL) { return 0; } } vsnprintf(temp, len+1, format, arg); va_end(arg); rgb_print(image_matrix, color, temp); if(len > 64){ free(temp); } return len; } static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id){ int x, y, w, h, i; uint32_t color = FACE_COLOR_YELLOW; if(face_id < 0){ color = FACE_COLOR_RED; } else if(face_id > 0){ color = FACE_COLOR_GREEN; } fb_data_t fb; fb.width = image_matrix->w; fb.height = image_matrix->h; fb.data = image_matrix->item; fb.bytes_per_pixel = 3; fb.format = FB_BGR888; for (i = 0; i < boxes->len; i++){ // rectangle box x = (int)boxes->box[i].box_p[0]; y = (int)boxes->box[i].box_p[1]; w = (int)boxes->box[i].box_p[2] - x + 1; h = (int)boxes->box[i].box_p[3] - y + 1; fb_gfx_drawFastHLine(&fb, x, y, w, color); fb_gfx_drawFastHLine(&fb, x, y+h-1, w, color); fb_gfx_drawFastVLine(&fb, x, y, h, color); fb_gfx_drawFastVLine(&fb, x+w-1, y, h, color); #if 0 // landmark int x0, y0, j; for (j = 0; j < 10; j+=2) { x0 = (int)boxes->landmark[i].landmark_p[j]; y0 = (int)boxes->landmark[i].landmark_p[j+1]; fb_gfx_fillRect(&fb, x0, y0, 3, 3, color); } #endif } } static int run_face_recognition(dl_matrix3du_t *image_matrix, box_array_t *net_boxes){ dl_matrix3du_t *aligned_face = NULL; int matched_id = 0; aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3); if(!aligned_face){ Serial.println("Could not allocate face recognition buffer"); return matched_id; } if (align_face(net_boxes, image_matrix, aligned_face) == ESP_OK){ if (is_enrolling == 1){ int8_t left_sample_face = enroll_face(&id_list, aligned_face); if(left_sample_face == (ENROLL_CONFIRM_TIMES - 1)){ Serial.printf("Enrolling Face ID: %d\n", id_list.tail); } Serial.printf("Enrolling Face ID: %d sample %d\n", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face); rgb_printf(image_matrix, FACE_COLOR_CYAN, "ID[%u] Sample[%u]", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face); if (left_sample_face == 0){ is_enrolling = 0; Serial.printf("Enrolled Face ID: %d\n", id_list.tail); } } else { matched_id = recognize_face(&id_list, aligned_face); if (matched_id >= 0) { Serial.printf("Match Face ID: %u\n", matched_id); rgb_printf(image_matrix, FACE_COLOR_GREEN, "Hello Subject %u", matched_id); } else { Serial.println("No Match Found"); rgb_print(image_matrix, FACE_COLOR_RED, "Intruder Alert!"); matched_id = -1; } } } else { Serial.println("Face Not Aligned"); //rgb_print(image_matrix, FACE_COLOR_YELLOW, "Human Detected"); } dl_matrix3du_free(aligned_face); return matched_id; } static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){ jpg_chunking_t *j = (jpg_chunking_t *)arg; if(!index){ j->len = 0; } if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){ return 0; } j->len += len; return len; } static esp_err_t capture_handler(httpd_req_t *req){ camera_fb_t * fb = NULL; esp_err_t res = ESP_OK; int64_t fr_start = esp_timer_get_time(); fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); httpd_resp_send_500(req); return ESP_FAIL; } httpd_resp_set_type(req, "image/jpeg"); httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); size_t out_len, out_width, out_height; uint8_t * out_buf; bool s; bool detected = false; int face_id = 0; if(!detection_enabled || fb->width > 400){ size_t fb_len = 0; if(fb->format == PIXFORMAT_JPEG){ fb_len = fb->len; res = httpd_resp_send(req, (const char *)fb->buf, fb->len); } else { jpg_chunking_t jchunk = {req, 0}; res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL; httpd_resp_send_chunk(req, NULL, 0); fb_len = jchunk.len; } esp_camera_fb_return(fb); int64_t fr_end = esp_timer_get_time(); Serial.printf("JPG: %uB %ums\n", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start)/1000)); return res; } dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3); if (!image_matrix) { esp_camera_fb_return(fb); Serial.println("dl_matrix3du_alloc failed"); httpd_resp_send_500(req); return ESP_FAIL; } out_buf = image_matrix->item; out_len = fb->width * fb->height * 3; out_width = fb->width; out_height = fb->height; s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf); esp_camera_fb_return(fb); if(!s){ dl_matrix3du_free(image_matrix); Serial.println("to rgb888 failed"); httpd_resp_send_500(req); return ESP_FAIL; } box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config); if (net_boxes){ detected = true; if(recognition_enabled){ face_id = run_face_recognition(image_matrix, net_boxes); } draw_face_boxes(image_matrix, net_boxes, face_id); free(net_boxes->score); free(net_boxes->box); free(net_boxes->landmark); free(net_boxes); } jpg_chunking_t jchunk = {req, 0}; s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk); dl_matrix3du_free(image_matrix); if(!s){ Serial.println("JPEG compression failed"); return ESP_FAIL; } int64_t fr_end = esp_timer_get_time(); Serial.printf("FACE: %uB %ums %s%d\n", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start)/1000), detected?"DETECTED ":"", face_id); return res; } static esp_err_t stream_handler(httpd_req_t *req){ camera_fb_t * fb = NULL; esp_err_t res = ESP_OK; size_t _jpg_buf_len = 0; uint8_t * _jpg_buf = NULL; char * part_buf[64]; dl_matrix3du_t *image_matrix = NULL; bool detected = false; int face_id = 0; int64_t fr_start = 0; int64_t fr_ready = 0; int64_t fr_face = 0; int64_t fr_recognize = 0; int64_t fr_encode = 0; static int64_t last_frame = 0; if(!last_frame) { last_frame = esp_timer_get_time(); } res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE); if(res != ESP_OK){ return res; } httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); while(true){ detected = false; face_id = 0; fb = esp_camera_fb_get(); if (!fb) { Serial.println("Camera capture failed"); res = ESP_FAIL; } else { fr_start = esp_timer_get_time(); fr_ready = fr_start; fr_face = fr_start; fr_encode = fr_start; fr_recognize = fr_start; if(!detection_enabled || fb->width > 400){ if(fb->format != PIXFORMAT_JPEG){ bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len); esp_camera_fb_return(fb); fb = NULL; if(!jpeg_converted){ Serial.println("JPEG compression failed"); res = ESP_FAIL; } } else { _jpg_buf_len = fb->len; _jpg_buf = fb->buf; } } else { image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3); if (!image_matrix) { Serial.println("dl_matrix3du_alloc failed"); res = ESP_FAIL; } else { if(!fmt2rgb888(fb->buf, fb->len, fb->format, image_matrix->item)){ Serial.println("fmt2rgb888 failed"); res = ESP_FAIL; } else { fr_ready = esp_timer_get_time(); box_array_t *net_boxes = NULL; if(detection_enabled){ net_boxes = face_detect(image_matrix, &mtmn_config); } fr_face = esp_timer_get_time(); fr_recognize = fr_face; if (net_boxes || fb->format != PIXFORMAT_JPEG){ if(net_boxes){ detected = true; if(recognition_enabled){ face_id = run_face_recognition(image_matrix, net_boxes); } fr_recognize = esp_timer_get_time(); draw_face_boxes(image_matrix, net_boxes, face_id); free(net_boxes->score); free(net_boxes->box); free(net_boxes->landmark); free(net_boxes); } if(!fmt2jpg(image_matrix->item, fb->width*fb->height*3, fb->width, fb->height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len)){ Serial.println("fmt2jpg failed"); res = ESP_FAIL; } esp_camera_fb_return(fb); fb = NULL; } else { _jpg_buf = fb->buf; _jpg_buf_len = fb->len; } fr_encode = esp_timer_get_time(); } dl_matrix3du_free(image_matrix); } } } if(res == ESP_OK){ res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); } if(res == ESP_OK){ size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len); res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen); } if(res == ESP_OK){ res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len); } if(fb){ esp_camera_fb_return(fb); fb = NULL; _jpg_buf = NULL; } else if(_jpg_buf){ free(_jpg_buf); _jpg_buf = NULL; } if(res != ESP_OK){ break; } int64_t fr_end = esp_timer_get_time(); int64_t ready_time = (fr_ready - fr_start)/1000; int64_t face_time = (fr_face - fr_ready)/1000; int64_t recognize_time = (fr_recognize - fr_face)/1000; int64_t encode_time = (fr_encode - fr_recognize)/1000; int64_t process_time = (fr_encode - fr_start)/1000; int64_t frame_time = fr_end - last_frame; last_frame = fr_end; frame_time /= 1000; uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time); /* Serial.printf("MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps), %u+%u+%u+%u=%u %s%d\n", (uint32_t)(_jpg_buf_len), (uint32_t)frame_time, 1000.0 / (uint32_t)frame_time, avg_frame_time, 1000.0 / avg_frame_time, (uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time, (detected)?"DETECTED ":"", face_id ); */ } last_frame = 0; return res; } static esp_err_t cmd_handler(httpd_req_t *req){ char* buf; size_t buf_len; char variable[32] = {0,}; char value[32] = {0,}; buf_len = httpd_req_get_url_query_len(req) + 1; if (buf_len > 1) { buf = (char*)malloc(buf_len); if(!buf){ httpd_resp_send_500(req); return ESP_FAIL; } if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) { if (httpd_query_key_value(buf, "con", variable, sizeof(variable)) == ESP_OK && httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) { } else { free(buf); httpd_resp_send_404(req); return ESP_FAIL; } } else { free(buf); httpd_resp_send_404(req); return ESP_FAIL; } free(buf); } else { httpd_resp_send_404(req); return ESP_FAIL; } Serial.printf("con = %s\r\n",variable); Serial.printf("val = %s\r\n",value); int val = atoi(value); sensor_t * s = esp_camera_sensor_get(); int res = 0; if(!strcmp(variable, "framesize")) { if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val); } else if(!strcmp(variable, "quality")) res = s->set_quality(s, val); else if(!strcmp(variable, "contrast")) res = s->set_contrast(s, val); else if(!strcmp(variable, "brightness")) res = s->set_brightness(s, val); else if(!strcmp(variable, "saturation")) res = s->set_saturation(s, val); else if(!strcmp(variable, "gainceiling")) res = s->set_gainceiling(s, (gainceiling_t)val); else if(!strcmp(variable, "colorbar")) res = s->set_colorbar(s, val); else if(!strcmp(variable, "awb")) res = s->set_whitebal(s, val); else if(!strcmp(variable, "agc")) res = s->set_gain_ctrl(s, val); else if(!strcmp(variable, "aec")) res = s->set_exposure_ctrl(s, val); else if(!strcmp(variable, "hmirror")) res = s->set_hmirror(s, val); else if(!strcmp(variable, "vflip")) res = s->set_vflip(s, val); else if(!strcmp(variable, "awb_gain")) res = s->set_awb_gain(s, val); else if(!strcmp(variable, "agc_gain")) res = s->set_agc_gain(s, val); else if(!strcmp(variable, "aec_value")) res = s->set_aec_value(s, val); else if(!strcmp(variable, "aec2")) res = s->set_aec2(s, val); else if(!strcmp(variable, "dcw")) res = s->set_dcw(s, val); else if(!strcmp(variable, "bpc")) res = s->set_bpc(s, val); else if(!strcmp(variable, "wpc")) res = s->set_wpc(s, val); else if(!strcmp(variable, "raw_gma")) res = s->set_raw_gma(s, val); else if(!strcmp(variable, "lenc")) res = s->set_lenc(s, val); else if(!strcmp(variable, "special_effect")) res = s->set_special_effect(s, val); else if(!strcmp(variable, "wb_mode")) res = s->set_wb_mode(s, val); else if(!strcmp(variable, "ae_level")) res = s->set_ae_level(s, val); else if(!strcmp(variable, "face_detect")) { detection_enabled = val; if(!detection_enabled) { recognition_enabled = 0; } } else if(!strcmp(variable, "face_enroll")) is_enrolling = val; else if(!strcmp(variable, "face_recognize")) { recognition_enabled = val; if(recognition_enabled){ detection_enabled = val; } } else { res = -1; } if(res){ return httpd_resp_send_500(req); } httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); return httpd_resp_send(req, NULL, 0); } static esp_err_t status_handler(httpd_req_t *req){ static char json_response[1024]; sensor_t * s = esp_camera_sensor_get(); char * p = json_response; *p++ = '{'; p+=sprintf(p, "\"framesize\":%u,", s->status.framesize); p+=sprintf(p, "\"quality\":%u,", s->status.quality); p+=sprintf(p, "\"brightness\":%d,", s->status.brightness); p+=sprintf(p, "\"contrast\":%d,", s->status.contrast); p+=sprintf(p, "\"saturation\":%d,", s->status.saturation); p+=sprintf(p, "\"sharpness\":%d,", s->status.sharpness); p+=sprintf(p, "\"special_effect\":%u,", s->status.special_effect); p+=sprintf(p, "\"wb_mode\":%u,", s->status.wb_mode); p+=sprintf(p, "\"awb\":%u,", s->status.awb); p+=sprintf(p, "\"awb_gain\":%u,", s->status.awb_gain); p+=sprintf(p, "\"aec\":%u,", s->status.aec); p+=sprintf(p, "\"aec2\":%u,", s->status.aec2); p+=sprintf(p, "\"ae_level\":%d,", s->status.ae_level); p+=sprintf(p, "\"aec_value\":%u,", s->status.aec_value); p+=sprintf(p, "\"agc\":%u,", s->status.agc); p+=sprintf(p, "\"agc_gain\":%u,", s->status.agc_gain); p+=sprintf(p, "\"gainceiling\":%u,", s->status.gainceiling); p+=sprintf(p, "\"bpc\":%u,", s->status.bpc); p+=sprintf(p, "\"wpc\":%u,", s->status.wpc); p+=sprintf(p, "\"raw_gma\":%u,", s->status.raw_gma); p+=sprintf(p, "\"lenc\":%u,", s->status.lenc); p+=sprintf(p, "\"vflip\":%u,", s->status.vflip); p+=sprintf(p, "\"hmirror\":%u,", s->status.hmirror); p+=sprintf(p, "\"dcw\":%u,", s->status.dcw); p+=sprintf(p, "\"colorbar\":%u,", s->status.colorbar); p+=sprintf(p, "\"face_detect\":%u,", detection_enabled); p+=sprintf(p, "\"face_enroll\":%u,", is_enrolling); p+=sprintf(p, "\"face_recognize\":%u", recognition_enabled); *p++ = '}'; *p++ = 0; httpd_resp_set_type(req, "application/json"); httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); return httpd_resp_send(req, json_response, strlen(json_response)); } static esp_err_t index_handler(httpd_req_t *req){ httpd_resp_set_type(req, "text/html"); httpd_resp_set_hdr(req, "Content-Encoding", "gzip"); sensor_t * s = esp_camera_sensor_get(); if (s->id.PID == OV3660_PID) { return httpd_resp_send(req, (const char *)index_ov3660_html_gz, index_ov3660_html_gz_len); } return httpd_resp_send(req, (const char *)index_ov2640_html_gz, index_ov2640_html_gz_len); } static esp_err_t index_post_handler(httpd_req_t *req) { char buf[100]; char cmd_text[20] = {0,}; //char cmd_text[20]; int ret,remaining = req->content_len; // 从HTTP请求中接收数据 while (remaining > 0) { //ret = httpd_req_recv(req, buf, MIN(remaining, sizeof(buf))); if (remaining <= sizeof(buf)) { ret = httpd_req_recv(req, buf, sizeof(buf)); } else if (remaining > sizeof(buf)) { ret = httpd_req_recv(req, buf, remaining); } remaining -= ret; } int i,j,k; int start_index,end_index; for(i=0;i<=100;i++){ if(buf[i]=='#' || buf[i]=='$'){ start_index = i; break; } } for(j=0;j<=100;j++){ if(buf[j]=='!'){ end_index = j; break; } } for(k=start_index;k<=end_index;k++){ cmd_text[k-start_index] = buf[k]; } Serial.println(cmd_text); } void startCameraServer(){ httpd_config_t config = HTTPD_DEFAULT_CONFIG(); httpd_uri_t index_uri = { .uri = "/", .method = HTTP_GET, .handler = index_handler, .user_ctx = NULL }; httpd_uri_t index_post_uri = { .uri = "/post", .method = HTTP_POST, .handler = index_post_handler, .user_ctx = NULL }; httpd_uri_t status_uri = { .uri = "/status", .method = HTTP_GET, .handler = status_handler, .user_ctx = NULL }; httpd_uri_t cmd_uri = { .uri = "/control", .method = HTTP_GET, .handler = cmd_handler, .user_ctx = NULL }; httpd_uri_t capture_uri = { .uri = "/capture", .method = HTTP_GET, .handler = capture_handler, .user_ctx = NULL }; httpd_uri_t stream_uri = { .uri = "/stream", .method = HTTP_GET, .handler = stream_handler, .user_ctx = NULL }; ra_filter_init(&ra_filter, 20); mtmn_config.type = FAST; mtmn_config.min_face = 80; mtmn_config.pyramid = 0.707; mtmn_config.pyramid_times = 4; mtmn_config.p_threshold.score = 0.6; mtmn_config.p_threshold.nms = 0.7; mtmn_config.p_threshold.candidate_number = 20; mtmn_config.r_threshold.score = 0.7; mtmn_config.r_threshold.nms = 0.7; mtmn_config.r_threshold.candidate_number = 10; mtmn_config.o_threshold.score = 0.7; mtmn_config.o_threshold.nms = 0.7; mtmn_config.o_threshold.candidate_number = 1; face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES); Serial.printf("Starting web server on port: '%d'\n", config.server_port); if (httpd_start(&camera_httpd, &config) == ESP_OK) { httpd_register_uri_handler(camera_httpd, &index_uri); httpd_register_uri_handler(camera_httpd, &index_post_uri); httpd_register_uri_handler(camera_httpd, &cmd_uri); httpd_register_uri_handler(camera_httpd, &status_uri); httpd_register_uri_handler(camera_httpd, &capture_uri); } config.server_port += 1; config.ctrl_port += 1; Serial.printf("Starting stream server on port: '%d'\n", config.server_port); if (httpd_start(&stream_httpd, &config) == ESP_OK) { httpd_register_uri_handler(stream_httpd, &stream_uri); } }
#include "esp_http_server.h" #include "esp_timer.h" #include "esp_camera.h" #include "img_converters.h" #include "camera_index.h" #include "Arduino.h" // 处理Ajax请求的函数 static esp_err_t index_post_handler(httpd_req_t *req) { char buf[100]; char cmd_text[20] = {0,}; int ret,remaining = req->content_len; // 从HTTP请求中接收数据 while (remaining > 0) { if (remaining <= sizeof(buf)) { ret = httpd_req_recv(req, buf, sizeof(buf)); } else if (remaining > sizeof(buf)) { ret = httpd_req_recv(req, buf, remaining); } remaining -= ret; } int i,j,k; int start_index,end_index; for(i=0;i<=100;i++){ if(buf[i]=='#' || buf[i]=='$'){ start_index = i; break; } } for(j=0;j<=100;j++){ if(buf[j]=='!'){ end_index = j; break; } } for(k=start_index;k<=end_index;k++){ cmd_text[k-start_index] = buf[k]; } Serial.println(cmd_text); } void startCameraServer(){ httpd_config_t config = HTTPD_DEFAULT_CONFIG(); httpd_uri_t index_uri = { .uri = "/", .method = HTTP_GET, .handler = index_handler, .user_ctx = NULL }; httpd_uri_t index_post_uri = { .uri = "/post", .method = HTTP_POST, .handler = index_post_handler, .user_ctx = NULL }; // 处理Ajax请求的url及函数 httpd_uri_t stream_uri = { .uri = "/stream", .method = HTTP_GET, .handler = stream_handler, .user_ctx = NULL }; ra_filter_init(&ra_filter, 20); mtmn_config.type = FAST; mtmn_config.min_face = 80; mtmn_config.pyramid = 0.707; mtmn_config.pyramid_times = 4; mtmn_config.p_threshold.score = 0.6; mtmn_config.p_threshold.nms = 0.7; mtmn_config.p_threshold.candidate_number = 20; mtmn_config.r_threshold.score = 0.7; mtmn_config.r_threshold.nms = 0.7; mtmn_config.r_threshold.candidate_number = 10; mtmn_config.o_threshold.score = 0.7; mtmn_config.o_threshold.nms = 0.7; mtmn_config.o_threshold.candidate_number = 1; face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES); Serial.printf("Starting web server on port: '%d'\n", config.server_port); if (httpd_start(&camera_httpd, &config) == ESP_OK) { httpd_register_uri_handler(camera_httpd, &index_uri); httpd_register_uri_handler(camera_httpd, &index_post_uri); httpd_register_uri_handler(camera_httpd, &capture_uri); } config.server_port += 1; config.ctrl_port += 1; Serial.printf("Starting stream server on port: '%d'\n", config.server_port); if (httpd_start(&stream_httpd, &config) == ESP_OK) { httpd_register_uri_handler(stream_httpd, &stream_uri); } }
二、jQuery下的Ajax技术
网页核心代码:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>ZLTech</title> <script src="static/jQuery-3.6.1.js"></script> <style type="text/css" media="screen"> * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; margin-top: 1%; margin-bottom:1%; background-color: white; } #out { width: 100%; height: 100%; text-align: center; } #top { display: inline-block; height: 10%; width: 100%; margin-bottom: 1%; } #middle { display: inline-block; height: 60%; width: 100%; } #bottom { display: inline-block; height: 8%; width: 100%; margin-top: 1%; } #top_left { display: inline-block; float: left; width: 20%; height: 100%; } #top_middle { display: inline-block; width: 58%; height: 100%; } #top_right { display: inline-block; float: right; width: 20%; height: 100%; } #setting_form, #mode_change_form { display: block; width: 100%; height: 100%; } #setting { display: inline-block; width: 80%; height: 70%; margin-top: 6%; outline: none; cursor: pointer; text-align:center; font:16px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; padding: .5em 2em .55em; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: 2em; -moz-border-radius: 2em; border-radius: 2em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #e8f0de; border: solid 1px #538312; background: #64991e; background: -webkit-gradient(linear, left top, left bottom, from(#7db72f), to(#4e7d0e)); background: -moz-linear-gradient(top, #7db72f, #4e7d0e); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#7db72f', endColorstr='#4e7d0e'); } #title { display: inline-block; width: 100%; height: 70%; } #webpage_func_mode { display: inline-block; width: 80%; height: 70%; margin-top: 6%; cursor: pointer; text-align:center; font-size: larger; } #middle_left { display: inline-block; float:left; width: 20%; height: 100%; } #middle_middle { display: inline-block; width: 58%; height: 100%; } #middle_right { display: inline-block; width: 20%; height: 100%; float:right; } #middle_left_row_1,#middle_right_row_1 { width: 100%; height: 50%; } #middle_left_row_2,#middle_right_row_2 { width: 100%; height: 50%; } #middle_left_row_1_row_1,#middle_left_row_1_row_2,#middle_left_row_1_row_3 { margin:0 auto; width: 80%; height: 25%; margin-top: 5%; } #middle_right_row_1_row_1,#middle_right_row_1_row_2,#middle_right_row_1_row_3 { margin:0 auto; width: 80%; height: 25%; margin-top: 5%; } #l1_form,#l2_form,#l3_form,#r1_form,#r2_form,#r3_form { display: block; width: 100%; height: 100%; } #l1,#l2,#l3,#r1,#r2,#r3 { display: block; width: 100%; height: 100%; outline: none; cursor: pointer; text-align:center; font:16px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: 2em; -moz-border-radius: 2em; border-radius: 2em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #d9eef7; border: solid 1px #0076a3; background: #0095cd; background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5)); background: -moz-linear-gradient(top, #00adee, #0078a5); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5'); } #lu,#ld,#ru,#rd { margin:0 auto; width: 26%; height: 30%; } #ll_lr,#rl_rr { margin:0 auto; width: 80%; height: 30%; margin-top: 2%; margin-bottom: 2%; } #ll,#rl { display: inline-block; width: 30%; height: 100%; margin-left: 1%; } #lst,#rst { display: inline-block; width: 30%; height: 100%; } #lr,#rr { display: inline-block; width: 30%; height: 100%; margin-left: 1%; } #lu_form,#ld_form,#ll_form,#lr_form,#lst_form { display: block; width: 100%; height: 100%; } #ru_form,#rd_form,#rl_form,#rr_form,#rst_form { display: block; width: 100%; height: 100%; } #lu_input,#ld_input,#ll_input,#lr_input,#lst_input { display: inline-block; width: 100%; height: 100%; outline: none; cursor: pointer; text-align:center; font:16px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: .5em; -moz-border-radius: .5em; border-radius: .5em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #fef4e9; border: solid 1px #da7c0c; background: #f78d1d; background: -webkit-gradient(linear, left top, left bottom, from(#faa5ea), to(#f47a20)); background: -moz-linear-gradient(top, #faa5ea, #f47a20); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#faa5ea', endColorstr='#f47a20'); } #ru_input,#rd_input,#rl_input,#rr_input,#rst_input { display: block; width: 100%; height: 100%; outline: none; cursor: pointer; text-align:center; font:11px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: .5em; -moz-border-radius: .5em; border-radius: .5em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #d9eef7; border: solid 1px #0076a3; background: #0095cd; background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5)); background: -moz-linear-gradient(top, #00adee, #0078a5); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5'); } #bottom_left { display: inline-block; font-size: larger; width: 20%; height: 100%; padding-top: 1%; } #send_cmd_form { display: inline-block; width: 79%; height: 100%; } #bottom_middle { display: inline-block; float: left; width: 73%; height: 100%; margin-left: 2px; } #bottom_right { display: inline-block; width: 20%; height: 100%; margin-left: 3%; } #self_cmd_text { display: inline-block; width: 100%; height: 75%; font-size: larger; } #send_cmd { display: inline-block; width: 100%; height: 80%; outline: none; cursor: pointer; text-align:center; font:16px/100% 'Microsoft yahei',Arial,Helvetica,sans-serif; text-shadow: 0 1px 1px rgba(0,0,0,.3); -webkit-border-shadow: .5em; -moz-border-radius: .5em; border-radius: .5em; -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2); -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2); box-shadow: 0 1px 2px rgba(0,0,0,.2); color: #d9eef7; border: solid 1px #0076a3; background: #0000FF; background: -webkit-gradient(linear, left top, left bottom, from(#3300FF), to(#6600FF)); background: -moz-linear-gradient(top, #3300FF, #6600FF); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#3300FF', endColorstr='#6600FF'); } img { display: block; height: 100%; width: 100%; -webkit-user-select: none; margin: auto; background-color:hsl(0,0%,25%); } </style> <script> window.onload = function () { //标志位,用于按键按下时只让它执行一次触发事件:当标志位为1时,按键按下时执行一次触发事件,按键松开时,再将标志位赋值为0 var key_do_once_flag = 1; //键盘按键对应的keyCode var key_code_dict = { 'UP': 38, 'DOWN': 40, 'LEFT': 37, 'RIGHT': 39, 'W': 87, 'S': 83, 'A': 65, 'D': 68, }; //按键按下及松开时对应要发送的指令 var key_cmd_dict = { 'UP_DOWN':'$QJ!', // 上键 按下时 前进 'UP_UP':'$FW!', // 上键 松开时 停止 'DOWN_DOWN': '$HT!', // 下键 按下时 后退 'DOWN_UP': '$FW!', // 下键 松开时 停止 'LEFT_DOWN': '$ZZ!', // 左键 按下时 左转 'LEFT_UP': '$FW!', // 左键 松开时 停止 'RIGHT_DOWN': '$YZ!', // 右键 按下时 右转 'RIGHT_UP': '$FW!', // 右键 松开时 停止 'W_DOWN': '#001P0600T3000!', // W键 按下时 机械臂上的1号舵机向前 'W_UP': '$DST!', // W键 松开时 机械臂上的1号舵机停止 'S_DOWN': '#001P2400T3000!', // S键 按下时 机械臂上的1号舵机向后 'S_UP': '$DST!', // S键 松开时 机械臂上的1号舵机停止 'A_DOWN': '#000P2400T3000!', // A键 按下时 机械臂上的0号舵机左转 'A_UP': '$DST!', // A键 松开时 机械臂上的0号舵机停止 'D_DOWN': '#000P0600T3000!', // D键 按下时 机械臂上的0号舵机右转 'D_UP': '$DST!', // D键 松开时 机械臂上的0号舵机停止 }; //键盘按键按下事件 window.onkeydown = function (event) { event = event || window.event; if (event.keyCode === key_code_dict.UP && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.UP_DOWN}, type:"POST", }); key_do_once_flag = 0; } else if (event.keyCode === key_code_dict.DOWN && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.DOWN_DOWN}, type:"POST", }); key_do_once_flag = 0; } else if (event.keyCode === key_code_dict.LEFT && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.LEFT_DOWN}, type:"POST", }); key_do_once_flag = 0; } else if (event.keyCode === key_code_dict.RIGHT && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.RIGHT_DOWN}, type:"POST", }); key_do_once_flag = 0; } else if (event.keyCode === key_code_dict.W && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.W_DOWN}, type:"POST", }); key_do_once_flag = 0; } else if (event.keyCode === key_code_dict.S && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.S_DOWN}, type:"POST", }); key_do_once_flag = 0; } else if (event.keyCode === key_code_dict.A && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.A_DOWN}, type:"POST", }); key_do_once_flag = 0; } else if (event.keyCode === key_code_dict.D && key_do_once_flag === 1) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.D_DOWN}, type:"POST", }); key_do_once_flag = 0; } }; //键盘按键松开事件 window.onkeyup = function (event) { event = event || window.event; if (event.keyCode === key_code_dict.UP) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.UP_UP}, type:"POST", }); key_do_once_flag = 1; } else if (event.keyCode === key_code_dict.DOWN) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.DOWN_UP}, type:"POST", }); key_do_once_flag = 1; } else if (event.keyCode === key_code_dict.LEFT) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.LEFT_UP}, type:"POST", }); key_do_once_flag = 1; } else if (event.keyCode === key_code_dict.RIGHT) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.RIGHT_UP}, type:"POST", }); key_do_once_flag = 1; } else if (event.keyCode === key_code_dict.W) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.W_UP}, type:"POST", }); key_do_once_flag = 1; } else if (event.keyCode === key_code_dict.S) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.S_UP}, type:"POST", }); key_do_once_flag = 1; } else if (event.keyCode === key_code_dict.A) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.A_UP}, type:"POST", }); key_do_once_flag = 1; } else if (event.keyCode === key_code_dict.D) { $.ajax({ url:"", data: {'self_cmd_text':key_cmd_dict.D_UP}, type:"POST", }); key_do_once_flag = 1; } }; } // 遥控模式下:网页按扭对应功能 var webpage_button_remote_dict = { 'title': '树莓派六足机器人', 'setting': '复位', 'mode1': '遥控模式', 'mode2': '智能模式', 'self_cmd_text': '自定义指令', 'l1': '攻击', 'l2': '蜷缩', 'l3': '扭动', 'r1': '防御', 'r2': '趴下', 'r3': '得瑟', 'lu': '前进', 'ld': '后退', 'll': '左转', 'lr': '右转', 'lst': '停止', 'ru': '中姿前进', 'rd': '中姿后退', 'rl': '中姿左转', 'rr': '中姿右转', 'rst': '中姿停止', } // 智能模式下:网页按扭对应功能 var webpage_button_ai_dict = { 'title': '树莓派六足机器人', 'setting': '停止', 'mode1': '智能模式', 'mode2': '遥控模式', 'self_cmd_text': '自定义指令', 'l1': '颜色识别', 'l2': '颜色跟随', 'l3': '形状识别', 'r1': '视觉巡迹', 'r2': '自由避障', 'r3': '智能跟随', 'lu': '前进', 'ld': '后退', 'll': '左转', 'lr': '右转', 'lst': '停止', 'ru': '头部抬起', 'rd': '头部低下', 'rl': '头部左转', 'rr': '头部右转', 'rst': '停止', } // 遥控模式下:网页按扭按下及松开时要发送的对应指令 var webpage_button_remote_cmd_dict = { 'setting_cmd': '$FW!', 'l1_down_cmd': '$GJ!', 'l2_down_cmd': '$QS!', 'l3_down_cmd': '$ND!', 'r1_down_cmd': '$FY!', 'r2_down_cmd': '$PX!', 'r3_down_cmd': '$DS!', 'lu_down_cmd': '$QJ!', 'lu_up_cmd': '$FW!', 'ld_down_cmd': '$HT!', 'ld_up_cmd': '$FW!', 'll_down_cmd': '$ZZ!', 'll_up_cmd': '$FW!', 'lr_down_cmd': '$YZ!', 'lr_up_cmd': '$FW!', 'lst_down_cmd': '$FW!', 'ru_down_cmd': '$ZKSQJ!', 'ru_up_cmd': '$ZZFW!', 'rd_down_cmd': '$ZKSHT!', 'rd_up_cmd': '$ZZFW!', 'rl_down_cmd': '$ZKSZZ!', 'rl_up_cmd': '$ZZFW!', 'rr_down_cmd': '$ZKSYZ!', 'rr_up_cmd': '$ZZFW!', 'rst_down_cmd': '$ZZFW!', } // 智能模式下:网页按扭要发送的对应指令(注意有些和遥控模式下是一样的功能) var webpage_button_ai_cmd_dict = { 'setting_cmd': '$FW!', 'l1_down_cmd': '$YSSB!', 'l2_down_cmd': '$YSGS!', 'l3_down_cmd': '$XZSB!', 'r1_down_cmd': '$ZNXJ!', 'r2_down_cmd': '$ZYBZ!', 'r3_down_cmd': '$ZNGS!', 'lu_down_cmd': '$QJ!', 'lu_up_cmd': '$FW!', 'ld_down_cmd': '$HT!', 'ld_up_cmd': '$FW!', 'll_down_cmd': '$ZZ!', 'll_up_cmd': '$FW!', 'lr_down_cmd': '$YZ!', 'lr_up_cmd': '$FW!', 'lst_down_cmd': '$FW!', 'ru_down_cmd': '#001P1900T3000!', 'ru_up_cmd': '$TZ!', 'rd_down_cmd': '#001P1100T3000!', 'rd_up_cmd': '$TZ!', 'rl_down_cmd': '#000P1900T3000!', 'rl_up_cmd': '$TZ!', 'rr_down_cmd': '#000P1100T3000!', 'rr_up_cmd': '$TZ!', 'rst_down_cmd': '$TZ!', } function form_submit() { var mode_form = document.getElementById("mode_change_form"); mode_form.submit(); } function setting_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var setting_data = webpage_button_ai_cmd_dict.setting_cmd; } else { var setting_data = webpage_button_remote_cmd_dict.setting_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':setting_data}, type:"POST", }) } function l1_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var l1_down_data = webpage_button_ai_cmd_dict.l1_down_cmd; } else { var l1_down_data = webpage_button_remote_cmd_dict.l1_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':l1_down_data}, type:"POST", }) } function l2_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var l2_down_data = webpage_button_ai_cmd_dict.l2_down_cmd; } else { var l2_down_data = webpage_button_remote_cmd_dict.l2_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':l2_down_data}, type:"POST", }) } function l3_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var l3_down_data = webpage_button_ai_cmd_dict.l3_down_cmd; } else { var l3_down_data = webpage_button_remote_cmd_dict.l3_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':l3_down_data}, type:"POST", }) } function r1_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var r1_down_data = webpage_button_ai_cmd_dict.r1_down_cmd; } else { var r1_down_data = webpage_button_remote_cmd_dict.r1_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':r1_down_data}, type:"POST", }) } function r2_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var r2_down_data = webpage_button_ai_cmd_dict.r2_down_cmd; } else { var r2_down_data = webpage_button_remote_cmd_dict.r2_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':r2_down_data}, type:"POST", }) } function r3_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var r3_down_data = webpage_button_ai_cmd_dict.r3_down_cmd; } else { var r3_down_data = webpage_button_remote_cmd_dict.r3_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':r3_down_data}, type:"POST", }) } function lu_down_submit(self) { var data = webpage_button_remote_cmd_dict.lu_down_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function lu_up_submit(self) { var data = webpage_button_remote_cmd_dict.lu_up_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function ld_down_submit(self) { var data = webpage_button_remote_cmd_dict.ld_down_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function ld_up_submit(self) { var data = webpage_button_remote_cmd_dict.ld_up_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function ll_down_submit(self) { var data = webpage_button_remote_cmd_dict.ll_down_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function ll_up_submit(self) { var data = webpage_button_remote_cmd_dict.ll_up_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function lr_down_submit(self) { var data = webpage_button_remote_cmd_dict.lr_down_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function lr_up_submit(self) { var data = webpage_button_remote_cmd_dict.lr_up_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function lst_submit(self) { var data = webpage_button_remote_cmd_dict.lst_down_cmd; $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } function ru_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var ru_down_data = webpage_button_ai_cmd_dict.ru_down_cmd; } else { var ru_down_data = webpage_button_remote_cmd_dict.ru_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':ru_down_data}, type:"POST", }) } function ru_up_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var ru_up_data = webpage_button_ai_cmd_dict.ru_up_cmd; } else { var ru_up_data = webpage_button_remote_cmd_dict.ru_up_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':ru_up_data}, type:"POST", }) } function rd_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var rd_down_data = webpage_button_ai_cmd_dict.rd_down_cmd; } else { var rd_down_data = webpage_button_remote_cmd_dict.rd_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':rd_down_data}, type:"POST", }) } function rd_up_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var rd_up_data = webpage_button_ai_cmd_dict.rd_up_cmd; } else { var rd_up_data = webpage_button_remote_cmd_dict.rd_up_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':rd_up_data}, type:"POST", }) } function rl_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var rl_down_data = webpage_button_ai_cmd_dict.rl_down_cmd; } else { var rl_down_data = webpage_button_remote_cmd_dict.rl_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':rl_down_data}, type:"POST", }) } function rl_up_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var rl_up_data = webpage_button_ai_cmd_dict.rl_up_cmd; } else { var rl_up_data = webpage_button_remote_cmd_dict.rl_up_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':rl_up_data}, type:"POST", }) } function rr_down_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var rr_down_data = webpage_button_ai_cmd_dict.rr_down_cmd; } else { var rr_down_data = webpage_button_remote_cmd_dict.rr_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':rr_down_data}, type:"POST", }) } function rr_up_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var rr_up_data = webpage_button_ai_cmd_dict.rr_up_cmd; } else { var rr_up_data = webpage_button_remote_cmd_dict.rr_up_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':rr_up_data}, type:"POST", }) } function rst_submit(self) { var mode_current = $('#select_mode1').val(); if (mode_current === webpage_button_ai_dict.mode1) { var rst_down_data = webpage_button_ai_cmd_dict.rst_down_cmd; } else { var rst_down_data = webpage_button_remote_cmd_dict.rst_down_cmd; }; $.ajax({ url:"", data: {'self_cmd_text':rst_down_data}, type:"POST", }) } function send_cmd_submit(self) { var data = $('#self_cmd_text').val(); $.ajax({ url:"", data: {'self_cmd_text':data}, type:"POST", }) } </script> </head> <body> <div id='out'> <div id='top'> <div id='top_left'> <form action="" method="post" id='setting_form'> <input id='setting' type="button" onclick='setting_submit(this)' name='setting' value="{{ response_dict.setting }}"> </form> </div> <div id='top_middle'> <h1 id='title' name='title'>{{ response_dict.title }}</h1> </div> <div id='top_right'> <form action="" method="post" id='mode_change_form'> <select name="webpage_func_mode" id="webpage_func_mode" onchange="form_submit();"> <option id='select_mode1' value="{{ response_dict.mode1 }}">{{ response_dict.mode1 }}</option> <option id='select_mode2' value="{{ response_dict.mode2 }}">{{ response_dict.mode2 }}</option> </select> </form> </div> </div> <div id='middle'> <div id='middle_left'> <div id='middle_left_row_1'> <div id='middle_left_row_1_row_1'> <form action="" method="post" id='l1_form'> <input id='l1' type="button" name='l1' value="{{ response_dict.l1 }}" onclick='l1_down_submit(this)'> </form> </div> <div id='middle_left_row_1_row_2'> <form action="" method="post" id='l2_form'> <input id='l2' type="button" name='l2' value="{{ response_dict.l2 }}" onclick='l2_down_submit(this)'> </form> </div> <div id='middle_left_row_1_row_3'> <form action="" method="post" id='l3_form'> <input id='l3' type="button" name='l3' value="{{ response_dict.l3 }}" onclick='l3_down_submit(this)'> </form> </div> </div> <div id='middle_left_row_2'> <div id='lu'> <form action="" method="post" id='lu_form'> <input id='lu_input' name='lu' value="{{ response_dict.lu }}" type="button" onmousedown='lu_down_submit(this)' onmouseup='lu_up_submit(this)' ontouchstart='lu_down_submit(this)' ontouchend='lu_up_submit(this)'> </form> </div> <div id='ll_lr'> <div id='ll'> <form action="" method="post" id='ll_form'> <input id='ll_input' name='ll' value="{{ response_dict.ll }}" type="button" onmousedown='ll_down_submit(this)' onmouseup='ll_up_submit(this)' ontouchstart='ll_down_submit(this)' ontouchend='ll_up_submit(this)'> </form> </div> <div id='lst'> <form action="" method="post" id='lst_form'> <input id='lst_input' name='lst' value="{{ response_dict.lst }}" type="button" onclick='lst_submit(this)'> </form> </div> <div id='lr'> <form action="" method="post" id='lr_form'> <input id='lr_input' name='lr' value="{{ response_dict.lr }}" type="button" onmousedown='lr_down_submit(this)' onmouseup='lr_up_submit(this)' ontouchstart='lr_down_submit(this)' ontouchend='lr_up_submit(this)'> </form> </div> </div> <div id='ld'> <form action="" method="post" id='ld_form'> <input id='ld_input' name='ld' value="{{ response_dict.ld }}" type="button" onmousedown='ld_down_submit(this)' onmouseup='ld_up_submit(this)' ontouchstart='ld_down_submit(this)' ontouchend='ld_up_submit(this)'> </form> </div> </div> </div> <div id='middle_middle'> <img src='http://192.168.12.1:8080/?action=stream'> </div> <div id='middle_right'> <div id='middle_right_row_1'> <div id='middle_right_row_1_row_1'> <form action="" method="post" id='r1_form'> <input id='r1' type="button" name='r1' value="{{ response_dict.r1 }}" onclick='r1_down_submit(this)'> </form> </div> <div id='middle_right_row_1_row_2'> <form action="" method="post" id='r2_form'> <input id='r2' type="button" name='r2' value="{{ response_dict.r2 }}" onclick='r2_down_submit(this)'> </form> </div> <div id='middle_right_row_1_row_3'> <form action="" method="post" id='r3_form'> <input id='r3' type="button" name='r3' value="{{ response_dict.r3 }}" onclick='r3_down_submit(this)'> </form> </div> </div> <div id='middle_right_row_2'> <div id='ru'> <form action="" method="post" id='ru_form'> <input id='ru_input' name='ru' value="{{ response_dict.ru }}" type="button" onmousedown='ru_down_submit(this)' onmouseup='ru_up_submit(this)' ontouchstart='ru_down_submit(this)' ontouchend='ru_up_submit(this)'> </form> </div> <div id='rl_rr'> <div id='rl'> <form action="" method="post" id='rl_form'> <input id='rl_input' name='rl' value="{{ response_dict.rl }}" type="button" onmousedown='rl_down_submit(this)' onmouseup='rl_up_submit(this)' ontouchstart='rl_down_submit(this)' ontouchend='rl_up_submit(this)'> </form> </div> <div id='rst'> <form action="" method="post" id='rst_form'> <input id='rst_input' name='rst' value="{{ response_dict.rst }}" type="button" onclick='rst_submit(this)'> </form> </div> <div id='rr'> <form action="" method="post" id='rr_form'> <input id='rr_input' name='rr' value="{{ response_dict.rr }}" type="button" onmousedown='rr_down_submit(this)' onmouseup='rr_up_submit(this)' ontouchstart='rr_down_submit(this)' ontouchend='rr_up_submit(this)'> </form> </div> </div> <div id='rd'> <form action="" method="post" id='rd_form'> <input id='rd_input' name='rd' value="{{ response_dict.rd }}" type="button" onmousedown='rd_down_submit(this)' onmouseup='rd_up_submit(this)' ontouchstart='rd_down_submit(this)' ontouchend='rd_up_submit(this)'> </form> </div> </div> </div> </div> <div id='bottom'> <div id='bottom_left'>自 定 义 指 令  :</div> <form action="" method="post" id='send_cmd_form'> <div id='bottom_middle'> <input id='self_cmd_text' type="text" name='self_cmd_text' placeholder="请输入要发送的指令"> </div> <div id='bottom_right'> <input id='send_cmd' type="button" onclick='send_cmd_submit(this)' value="发送"> </div> </form> </div> </div> </body> </html>
function send_cmd_submit(self) {
var data = $('#self_cmd_text').val();
$.ajax({
url:"",
data: {'self_cmd_text':data},
type:"POST",
})
}
后端核心代码(以树莓派下的python为例):
''' z_main是开机程序,即树梅派开机后会自动运行此程序,正常开机后不能直接运行,先关闭程序(运行killmain.sh脚本) 在打开程序,修改socket端口,将1314修改为其他值。 在终端输入 sudo gedit /etc/init.d/init-app 指令设置开机自启脚本 ''' # -*- coding:utf-8 -*- #导入模块 import os import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #'/home/pi/Desktop/ZL-PI/factory_code/' import threading import cv2 import numpy as np # 导入flask框架所需要的包,模块 from flask import Flask, request, render_template, Response import time # 固定写法 app = Flask(__name__) import ZL_SDK.z_led as myLed # 导入控制led灯的模块 import ZL_SDK.z_beep as myBeep # 导入控制有源蜂鸣器的模块 import ZL_SDK.Z_UartServer as myUart # 导入串口收发数据的模块 import ZL_SDK.ActionGroupControl as AGC # 导入解析和执行动作组的模块 import ZL_SDK.Z_SocketServer as mySocket # 导入socket收发数据的模块 import Camera # 导入摄像头模块 import AI_Functions.Color_detect as Colord # 导入颜色识别模块 import AI_Functions.Color_Follow as CFollow # 导入颜色跟随模块 import AI_Functions.Face_detect as Faced # 导入人脸识别模块 import AI_Functions.Face_Follow as FFollow # 导入人脸跟随模块 import AI_Functions.Shape_detect as Shape # 导入形状识别模块 import AI_Functions.QRD_run as QRDrun # 导入二维码标签交互模块 import AI_Functions.Robot_tracking as Robott # 导入视觉寻迹模块 import AI_Functions.ziyoubizhang as ZYBZ # 导入自由避障模块 import AI_Functions.zhinenggensui as ZNGS # 导入智能跟随模块 # 全局变量定义 systick_ms_led = 0 # 记录系统运行时间,用于让led灯每隔0.5妙闪烁一次 AI_MODE = 0 # 通过赋值不同的值,可以用于开启不同的AI功能,默认开启二维码标签交互功能 webpage_get_ok = 0 # 用于判断网页发送过来的数据格式 webpage_receive_buf = '' # 用于接收保存网页发送过来的数据 response_mode_flag = 0 # 渲染网页时要用到的机器人模式:0是遥控模式,1是智能模式 # MP3播报指令 voice_dict = { '$TZ!':'#030P1540T1000!', '$FW!':'#030P1541T1000!','$ZZFW!':'#030P1542T1000!','$GZFW!':'#030P1543T1000!','$YTFW!':'#030P1544T1000!', '$QJ!':'#030P1545T1000!','$HT!':'#030P1546T1000!', '$ZZ!':'#030P1547T1000!','$YZ!':'#030P1548T1000!', '$DMSQJ!':'#030P1549T1000!','$DMSHT!':'#030P1550T1000!','$DMSZZ!':'#030P1551T1000!','$DMSYZ!':'#030P1552T1000!', '$ZKSQJ!':'#030P1553T1000!','$ZKSHT!':'#030P1554T1000!','$ZKSZZ!':'#030P1555T1000!','$ZKSYZ!':'#030P1556T1000!', '$ZMSQJ!':'#030P1557T1000!','$ZMSHT!':'#030P1558T1000!','$ZMSZZ!':'#030P1559T1000!','$ZMSYZ!':'#030P1560T1000!', '$GKSQJ!':'#030P1561T1000!','$GKSHT!':'#030P1562T1000!','$GKSZZ!':'#030P1563T1000!','$GKSYZ!':'#030P1564T1000!', '$GMSQJ!':'#030P1565T1000!','$GMSHT!':'#030P1566T1000!','$GMSZZ!':'#030P1567T1000!','$GMSYZ!':'#030P1568T1000!', '$YDZT!':'#030P1569T1000!', '$KSZY!':'#030P1570T1000!','$KSYY!':'#030P1571T1000!','$MSZY!':'#030P1572T1000!','$MSYY!':'#030P1573T1000!', '$HNBS!':'#030P1574T1000!','$FY!':'#030P1575T1000!','$PX!':'#030P1576T1000!','$QS!':'#030P1577T1000!', '$DT!':'#030P1578T1000!','$GJ!':'#030P1579T1000!','$ND!':'#030P1580T1000!','$DS!':'#030P1581T1000!', '$YSSB!':'#030P1502T1000!','$YSGS!':'#030P1503T1000!','$RLSB!':'#030P1504T1000!','$RLGS!':'#030P1505T1000!', '$XZSB!':'#030P1506T1000!','$ZNXJ!':'#030P1507T1000!','$ZYBZ!':'#030P1508T1000!','$ZNGS!':'#030P1509T1000!', '$RED!':'#030P1516T1000!','$GREEN!':'#030P1517T1000!','$BLUE!':'#030P1518T1000!','$YELLOW!':'#030P1519T1000!', '$WAKE!':'#030P1590T1000!','$WHO!':'#030P1591T1000!','$WHERE!':'#030P1592T1000!','$WHATDO!':'#030P1593T1000!', } # 动作组指令 group_dict = { '$TZ!':'$DST!', '$FW!':'$DGT:1-1,1!','$ZZFW!':'$DGT:2-2,1!','$GZFW!':'$DGT:3-3,1!', '$YTFW!':'#000P1500T1000!#001P1500T1000!', '$QJ!':'$DGT:5-8,0!','$HT!':'$DGT:9-12,0!','$ZZ!':'$DGT:13-16,0!','$YZ!':'$DGT:17-20,0!', '$DMSQJ!':'$DGT:21-24,0!','$DMSHT!':'$DGT:25-28,0!','$DMSZZ!':'$DGT:29-32,0!','$DMSYZ!':'$DGT:33-36,0!', '$ZKSQJ!':'$DGT:37-40,0!','$ZKSHT!':'$DGT:41-44,0!','$ZKSZZ!':'$DGT:45-48,0!','$ZKSYZ!':'$DGT:49-52,0!', '$ZMSQJ!':'$DGT:53-56,0!','$ZMSHT!':'$DGT:57-60,0!','$ZMSZZ!':'$DGT:61-64,0!','$ZMSYZ!':'$DGT:65-68,0!', '$GKSQJ!':'$DGT:69-72,0!','$GKSHT!':'$DGT:73-76,0!','$GKSZZ!':'$DGT:77-80,0!','$GKSYZ!':'$DGT:81-84,0!', '$GMSQJ!':'$DGT:85-88,0!','$GMSHT!':'$DGT:89-92,0!','$GMSZZ!':'$DGT:93-96,0!','$GMSYZ!':'$DGT:97-100,0!', '$YDZT!':'$DGT:133-133,1!', '$KSZY!':'$DGT:117-120,0!','$KSYY!':'$DGT:121-124,0!','$MSZY!':'$DGT:125-128,0!','$MSYY!':'$DGT:129-132,0!', '$HNBS!':'$DGT:146-160,1!','$FY!':'$DGT:323-323,1!','$PX!':'$DGT:324-324,1!','$QS!':'$DGT:325-325,1!', '$DT!':'$DGT:326-339,1!','$GJ!':'$DGT:340-356,1!','$ND!':'$DGT:357-358,5!', '$DS!':'$DGT:359-379,1!', '$FDLHT!':'$DGT:134-137,0!','$FDLZZ!':'$DGT:138-141,0!','$FDLYZ!':'$DGT:142-145,0!', } # AI功能所对应的序号,后面通过给AI_MODE赋值(AI功能所对应的序号)来执行不同的AI功能 ai_dict = {'$FW!':0, # 复位,复位状态下默认开启二维码标签交互功能 '$YSSB!':1, # 颜色识别功能 '$YSGS!':2, # 颜色跟随功能 '$RLSB!':3, # 人脸识别功能 '$RLGS!':4, # 人脸跟随功能 '$XZSB!':5, # 形状识别功能 '$ZNXJ!':6, # 视觉寻迹功能 '$ZYBZ!':7, # 自由避障功能 '$ZNGS!':8, # 智能跟随功能 } # 颜色列表 color_list = ['RED', 'GREEN', 'BLUE', 'YELLOW'] # 和颜色有关的功能都默认识别绿色,在使用手机app控制时可更改要识别的颜色 color_str = color_list[1] webpage_func_mode_dict = { 'webpage_mode':{ 'remote_mode': '遥控模式', 'ai_mode': '智能模式' }, 'webpage_remote_button_dict':{ 'title': '树莓派六足机器人', 'setting': '复位', 'mode1': '遥控模式', 'mode2': '智能模式', 'self_cmd_text': '自定义指令', 'l1': '攻击', 'l2': '蜷缩', 'l3': '扭动', 'r1': '防御', 'r2': '趴下', 'r3': '得瑟', 'lu': '前进', 'ld': '后退', 'll': '左转', 'lr': '右转', 'lst': '停止', 'ru': '中姿前进', 'rd': '中姿后退', 'rl': '中姿左转', 'rr': '中姿右转', 'rst': '中姿停止', }, 'webpage_ai_button_dict': { 'title': '树莓派六足机器人', 'setting': '停止', 'mode1': '智能模式', 'mode2': '遥控模式', 'self_cmd_text': '自定义指令', 'l1': '颜色识别', 'l2': '颜色跟随', 'l3': '形状识别', 'r1': '视觉巡迹', 'r2': '自由避障', 'r3': '智能跟随', 'lu': '前进', 'ld': '后退', 'll': '左转', 'lr': '右转', 'lst': '停止', 'ru': '头部抬起', 'rd': '头部低下', 'rl': '头部左转', 'rr': '头部右转', 'rst': '停止', } } # 用于接收网页按钮和键盘按键发来的数据 self_cmd_text = None # 进入的首个网页 @app.route('/', methods=['GET','POST']) def webpage_main(): global webpage_get_ok, webpage_receive_buf, response_mode_flag, self_cmd_text webpage_mode = 0 if request.form.get('self_cmd_text'): self_cmd_text = request.form.get('self_cmd_text') if webpage_get_ok == 0: webpage_receive_buf = self_cmd_text uart_get_ok = 0 if webpage_mode == 0: if webpage_receive_buf.find('{') >= 0: webpage_mode = 1 elif webpage_receive_buf.find('$') >= 0: webpage_mode = 2 elif webpage_receive_buf.find('#') >= 0: webpage_mode = 3 if webpage_mode == 1: if webpage_receive_buf.find('}') >= 0: uart_get_ok = 1 webpage_mode = 0 elif webpage_mode == 2: if webpage_receive_buf.find('!') >= 0: uart_get_ok = 2 webpage_mode = 0 elif webpage_mode == 3: if webpage_receive_buf.find('!') >= 0: uart_get_ok = 3 webpage_mode = 0 webpage_get_ok = uart_get_ok return 'ok' if request.form.get('webpage_func_mode') == webpage_func_mode_dict['webpage_mode']['remote_mode']: response_mode_flag = 0 elif request.form.get('webpage_func_mode') == webpage_func_mode_dict['webpage_mode']['ai_mode']: response_mode_flag = 1 if response_mode_flag: response_dict = webpage_func_mode_dict['webpage_ai_button_dict'] else: response_dict = webpage_func_mode_dict['webpage_remote_button_dict'] return render_template("index.html",response_dict=response_dict) # 返回网页 # 要执行的flask线程函数 def flask_thread(): app.run(host='192.168.12.1', port=8090) # 该地址为树莓派的IP地址,端口任意设(也可以用本机的IP地址:127.0.0.2,port:8081) # 对网页发过来的数据进行处理 def loop_webpage(): global webpage_get_ok, webpage_receive_buf # 如果网页发送过来了数据 if webpage_get_ok: myUart.uart_get_ok = webpage_get_ok # 将网页数据赋值给串口数据处进行处理 myUart.uart_receive_buf = webpage_receive_buf # 然后将网页接收数据赋值为空 webpage_receive_buf = '' webpage_get_ok = 0 # 串口指令解析,智能转功能 def parse_cmd(myStr): global color_str try: # 串口接收数据异常时进行处理 if myStr[-1] == '!' and myStr[-2] == '!': myStr = myStr[:-1] # 云台复位 if myStr == '$YTFW!' or myStr == '$YTFW!ST!': myStr = '$YTFW!' # 语音播报 if myStr in voice_dict: mp3_play(myStr) time.sleep(0.5) # 解析动作组 if myStr in group_dict: action_parse(myStr) # 判断是否要执行相应的AI功能 if myStr in ai_dict: fun_mode(myStr) Str = myStr[1:-1] # 此处接收手机app传来的数据,更改要识别的目标颜色 if Str in color_list: color_str = Str # 颜色识别相关的参数都重置 Colord.reset() # 人脸识别的参数重置 Faced.face_step = 0 except Exception as e: print(e) # MP3播报 def mp3_play(myStr): mpStr = voice_dict[myStr] myUart.uart_send_str(mpStr) # 解析动作组控制指令 def action_parse(myStr): groupStr = group_dict[myStr] if myStr == '$YTFW!': myUart.uart_send_str(group_dict[myStr]) # 摄像头复位 else: AGC.groups_parse_cmd(groupStr) # 动作组解析 # 智能模式解析,姿态切换,即摄像头角度调整 def fun_mode(myStr): global AI_MODE AI_MODE = ai_dict[myStr] if AI_MODE == 0 or AI_MODE == 1 or AI_MODE == 2 or AI_MODE == 3 or AI_MODE == 4 or AI_MODE == 5: myUart.uart_send_str(AGC.myList[1]) # 机体呈中姿状态 time.sleep(1) myUart.uart_send_str('#000P1500T1000!#001P1500T1000!') # 云台复位 time.sleep(1) elif AI_MODE == 6: # 智能寻迹时摄像头要向前下方倾斜一些 myUart.uart_send_str(AGC.myList[1]) # 机体呈低姿状态 time.sleep(1) myUart.uart_send_str('#000P1500T1000!#001P1100T1000!') # 摄像头向前下方倾斜 time.sleep(1) # ai模式 def loop_ai_run(): global frame, AI_MODE, color_str if AI_MODE == 0: # AI_MODE等于0时,执行二维码标签交互功能,默认开机之后开启的就是此功能 QRDrun.frame = frame QRDrun.qrd_detect() elif AI_MODE == 1: # AI_MODE等于1时,执行颜色识别功能 Colord.frame = frame Colord.color_detect(color_str) elif AI_MODE == 2: # AI_MODE等于2时,执行颜色跟随功能 CFollow.frame = frame CFollow.color_follow(color_str) elif AI_MODE == 3: # AI_MODE等于3时,执行人脸识别功能 Faced.frame = frame Faced.face_detect() elif AI_MODE == 4: # AI_MODE等于4时,执行人脸跟随功能 FFollow.frame = frame FFollow.face_follow() elif AI_MODE == 5: # AI_MODE等于5时,执行形状识别功能 Shape.frame = frame Shape.shape_detect(color_str) elif AI_MODE == 6: # AI_MODE等于6时,执行视觉寻迹功能 Robott.frame = frame Robott.robot_xunji() elif AI_MODE == 7: # AI_MODE等于7时,执行自由避障功能 ZYBZ.zybz() elif AI_MODE == 8: # AI_MODE等于8时,执行智能跟随功能 ZNGS.zngs() # LED灯循坏闪烁 def loop_led(): global systick_ms_led if int((time.time() * 1000)) - systick_ms_led > 500: systick_ms_led = int((time.time() * 1000)) myLed.flip() # 串口检测,串口接收数据之后进行的处理 def loop_uart(): if myUart.uart_get_ok == 2: myBeep.beep(1, 0.1) parse_cmd(myUart.uart_receive_buf) AGC.groups_parse_cmd(myUart.uart_receive_buf) myUart.uart_receive_buf = '' myUart.uart_get_ok = 0 elif myUart.uart_get_ok == 1 or myUart.uart_get_ok == 3: myUart.uart_send_str(myUart.uart_receive_buf) myUart.uart_receive_buf = '' myUart.uart_get_ok = 0 # 网络连接服务,对socket接收到的数据进行处理 def loop_socket(): if mySocket.socket_get_ok: myUart.uart_get_ok = mySocket.socket_get_ok myUart.uart_receive_buf = mySocket.socket_receive_buf mySocket.socket_receive_buf = '' mySocket.socket_get_ok = 0 # 开机动作组,直接通过串口发送指令执行动作 def start_show(): myUart.uart_send_str('#030P1501T0000!') time.sleep(0.1) myUart.uart_send_str(AGC.myList[1]) time.sleep(1) myUart.uart_send_str(AGC.myList[2]) time.sleep(1) myUart.uart_send_str(AGC.myList[3]) time.sleep(1) myUart.uart_send_str(AGC.myList[2]) time.sleep(1) myUart.uart_send_str(AGC.myList[1]) time.sleep(1) myUart.uart_send_str('#000P1500T1000!#001P1500T1000!') time.sleep(1) myUart.uart_receive_buf = '' # 创建flask线程 flask_task = threading.Thread(target=flask_thread, args=()) # 程序入口 if __name__ == '__main__': # 开启flask线程 flask_task.start() # 延时5秒 time.sleep(5) # 读取动作组文件。输入参数:动作组文件位置 AGC.Group_read('/home/pi/Desktop/ZL-PI/factory_code/Libot_groups/Libot_groups_pi.ini') myLed.setup_led() # led初始化 myBeep.setup_beep() # 蜂鸣器初始化 myUart.setup_uart(115200) # 设置串口 mySocket.setup_socket(1314) # socket初始化 ZYBZ.setup_sr_csb() # 超声波初始化 frame = None cam = Camera.Camera() # 摄像头库实例化 cam.camera_open() # 打开摄像头 myBeep.beep(3, 0.1) # 发出哔哔哔作为开机声音 start_show() # 执行开机动作 # 异常处理 try: # 无限循环 while 1: loop_led() # LED灯循坏闪烁 loop_uart() # 串口检测,串口接收数据之后进行的处理 loop_socket() # 网络连接服务,对socket接收到的数据进行处理,此处是对手机app发送过来的数据进行处理 loop_webpage() # 对网页发送过来的数据进行处理 AGC.loop_group() # 执行动作组 if cam.frame is not None: if 0 <= AI_MODE <= 6: frame = cam.frame.copy() loop_ai_run() # 执行AI功能 except KeyboardInterrupt: pass
# -*- coding:utf-8 -*- #导入模块 import os import sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #'/home/pi/Desktop/ZL-PI/factory_code/' import threading import cv2 import numpy as np # 导入flask框架所需要的包,模块 from flask import Flask, request, render_template, Response import time # 固定写法 app = Flask(__name__) import Camera # 导入摄像头模块 # 全局变量定义 systick_ms_led = 0 # 记录系统运行时间,用于让led灯每隔0.5妙闪烁一次 webpage_get_ok = 0 # 用于判断网页发送过来的数据格式 webpage_receive_buf = '' # 用于接收保存网页发送过来的数据 response_mode_flag = 0 # 渲染网页时要用到的机器人模式:0是遥控模式,1是智能模式 webpage_func_mode_dict = { 'webpage_mode':{ 'remote_mode': '遥控模式', 'ai_mode': '智能模式' }, 'webpage_remote_button_dict':{ 'title': '树莓派六足机器人', 'setting': '复位', 'mode1': '遥控模式', 'mode2': '智能模式', 'self_cmd_text': '自定义指令', 'l1': '攻击', 'l2': '蜷缩', 'l3': '扭动', 'r1': '防御', 'r2': '趴下', 'r3': '得瑟', 'lu': '前进', 'ld': '后退', 'll': '左转', 'lr': '右转', 'lst': '停止', 'ru': '中姿前进', 'rd': '中姿后退', 'rl': '中姿左转', 'rr': '中姿右转', 'rst': '中姿停止', }, 'webpage_ai_button_dict': { 'title': '树莓派六足机器人', 'setting': '停止', 'mode1': '智能模式', 'mode2': '遥控模式', 'self_cmd_text': '自定义指令', 'l1': '颜色识别', 'l2': '颜色跟随', 'l3': '形状识别', 'r1': '视觉巡迹', 'r2': '自由避障', 'r3': '智能跟随', 'lu': '前进', 'ld': '后退', 'll': '左转', 'lr': '右转', 'lst': '停止', 'ru': '头部抬起', 'rd': '头部低下', 'rl': '头部左转', 'rr': '头部右转', 'rst': '停止', } } # 用于接收网页按钮和键盘按键发来的数据 self_cmd_text = None # 进入的首个网页 @app.route('/', methods=['GET','POST']) def webpage_main(): global webpage_get_ok, webpage_receive_buf, response_mode_flag, self_cmd_text webpage_mode = 0 if request.form.get('self_cmd_text'): self_cmd_text = request.form.get('self_cmd_text') if webpage_get_ok == 0: webpage_receive_buf = self_cmd_text uart_get_ok = 0 if webpage_mode == 0: if webpage_receive_buf.find('{') >= 0: webpage_mode = 1 elif webpage_receive_buf.find('$') >= 0: webpage_mode = 2 elif webpage_receive_buf.find('#') >= 0: webpage_mode = 3 if webpage_mode == 1: if webpage_receive_buf.find('}') >= 0: uart_get_ok = 1 webpage_mode = 0 elif webpage_mode == 2: if webpage_receive_buf.find('!') >= 0: uart_get_ok = 2 webpage_mode = 0 elif webpage_mode == 3: if webpage_receive_buf.find('!') >= 0: uart_get_ok = 3 webpage_mode = 0 webpage_get_ok = uart_get_ok return 'ok' if request.form.get('webpage_func_mode') == webpage_func_mode_dict['webpage_mode']['remote_mode']: response_mode_flag = 0 elif request.form.get('webpage_func_mode') == webpage_func_mode_dict['webpage_mode']['ai_mode']: response_mode_flag = 1 if response_mode_flag: response_dict = webpage_func_mode_dict['webpage_ai_button_dict'] else: response_dict = webpage_func_mode_dict['webpage_remote_button_dict'] return render_template("index.html",response_dict=response_dict) # 返回网页 # 要执行的flask线程函数 def flask_thread(): app.run(host='192.168.12.1', port=8090) # 该地址为树莓派的IP地址,端口任意设(也可以用本机的IP地址:127.0.0.2,port:8081) # 对网页发过来的数据进行处理 def loop_webpage(): global webpage_get_ok, webpage_receive_buf # 如果网页发送过来了数据 if webpage_get_ok: myUart.uart_get_ok = webpage_get_ok # 将网页数据赋值给串口数据处进行处理 myUart.uart_receive_buf = webpage_receive_buf # 然后将网页接收数据赋值为空 webpage_receive_buf = '' webpage_get_ok = 0 # 创建flask线程 flask_task = threading.Thread(target=flask_thread, args=()) # 程序入口 if __name__ == '__main__': # 开启flask线程 flask_task.start() # 延时5秒 time.sleep(5) # 异常处理 try: # 无限循环 while 1: loop_webpage() # 对网页发送过来的数据进行处理 except KeyboardInterrupt: pass
注意:此处均以Ajax技术下的post请求为例
浙公网安备 33010602011771号