一、原生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));

};
Ajax部分示例

后端核心代码(以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);
    }
}
app_httpd.cpp
#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'>&ensp;&ensp;&ensp;&ensp;&ensp;&ensp;:</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>
templates/index.html
function send_cmd_submit(self) {
    var data = $('#self_cmd_text').val();
    $.ajax({
        url:"",
        data: {'self_cmd_text':data},
        type:"POST",
    })
}
Ajax部分示例

后端核心代码(以树莓派下的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
z_main.py
# -*- 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请求部分的示例

注意:此处均以Ajax技术下的post请求为例

posted on 2023-05-26 10:23  始终不够啊  阅读(26)  评论(0)    收藏  举报