基于ESP8266实现串口服务器

描述

1 串口服务器

ESP8266工作在TCP服务器模式时,可以借助IOTGATEWAY很轻松地将传统设备接入物联网,实现多设备实时监控

2 参数配置

串口服务器就像是一个路由器一样,用户可以通过浏览器访问后台来配置模块的相关参数

2.1串口参数

服务器

2.2 WiFi参数

esp8266的wifi可以工作在三种模式下,AP模式、STA模式、AP+STA模式,作为串口服务器时,一般工作在AP+STA模式下

2.2.1 AP模式

在该模式下可以产生一个WIFI,供外部设备连接

服务器

2.2.2 STA模式

在该模式下会连接到路由器的WIFI上,需要填写路由器WIFI的相关信息

服务器

2.3 TCP通信参数

无论是服务器还是客户端,原理都是将串口收到的数据透传输出,将TCP收到的数据通过串口再发送出去

服务器

2.4 固件升级

服务器

3 实现方法

esp8266通过响应来网页端的get、post请求来实现参数的存储,数据的读取,官方有现成的http服务器的例子可以参考一下

3.1 网页端代码

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <link href="favicon.png" rel="shortcut icon">
        <title>
            串口服务器
        title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0">
        <script stype="text/javascript">
        var work_mode_ap_sta = '0';
        var work_mode_sta = '1';
        var mode_current = '0';
        var mode_last = '0';
        var port_remote = '8081';
        var port_tcp = '8080';
        var xmlobj = null;
        var xmlHttp = null;
        function CreateXMLHttpRequest() {
            xmlobj = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHttp")
        }
        function CreateXMLHttpRequest_ap() {
            if (null == xmlHttp) xmlHttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHttp")
        }
        function processRequest() {
            if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                var res = xmlHttp.responseText;
                if (res.length > 0) {
                    document.getElementById("ap_list").options.length = 0;
                    var a_list = new Array();
                    a_list = res.split("^$&");
                    for (i = 0; i < a_list.length; i++) {
                        if (a_list[i].length > 0) {
                            var t = a_list[i];
                            document.getElementById("ap_list").options.add(new Option(t, t))
                        }
                    }
                }
            }
        }
        function doPostResp() {
            if (xmlobj.readyState == 4 && xmlobj.status == 200) {
                var res = xmlobj.responseText;
                if (res.length > 0) {
                    alert(res)
                }
            }
        }
        function submit_post(parm) {
            console.log('submit_post' + parm);
            CreateXMLHttpRequest();
            xmlobj.open("POST", "/setpara", true);
            xmlobj.onreadystatechange = doPostResp;
            xmlobj.send(parm)
        }
        function submit_postDefault(parm) {
            CreateXMLHttpRequest();
            xmlobj.open("POST", "/default", true);
            xmlobj.onreadystatechange = doPostResp;
            xmlobj.send(parm)
        }
        function submit_post_mode(parm) {
            CreateXMLHttpRequest();
            xmlobj.open("POST", "/setmode", true);
            xmlobj.onreadystatechange = doPostResp;
            xmlobj.send(parm)
        }
        function getVByName(name) {
            var tt = document.getElementsByName(name);
            for (var iIndex = 0; iIndex < tt.length; iIndex++) {
                if (tt[iIndex].checked) {
                    return tt[iIndex].value
                }
            }
        }
        function isValidIP(ip) {
            var reg = /^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$/;
            return reg.test(ip)
        }
        function isValidMask(mask) {
            var reg = /^(254|252|248|240|224|192|128|0)\\.0\\.0\\.0|255\\.(254|252|248|240|224|192|128|0)\\.0\\.0|255\\.255\\.(254|252|248|240|224|192|128|0)\\.0|255\\.255\\.255\\.(254|252|248|240|224|192|128|0)$/;
            return reg.test(mask)
        }
        function IsPortValid(str) {
            var RegUrl = new RegExp();
            RegUrl.compile("^[1-9]$|(^[1-9][0-9]$)|(^[1-9][0-9][0-9]$)|(^[1-9][0-9][0-9][0-9]$)|(^[1-6][0-5][0-5][0-3][0-5]$)");
            if (!RegUrl.test(str)) {
                return false
            }
            return true
        }
        function IsTimeoutValid(time_out) {
            if ((time_out < 1) || (time_out > 7200)) {
                return false
            }
            return true
        }
        function submitForm() {
            var work_mode = document.getElementById('work_mode').value;
            var baud = document.getElementById('baud').value;
            var bits = document.getElementById('bits').value;
            var parity = document.getElementById('parity').value;
            var stop = document.getElementById('stop').value;
            var ap_enc_mode = document.getElementById('ap_enc_mode').value;
            var ap_hide = getVByName('ap_hide');
            var ap_name = document.getElementById('ap_name').value;
            var ap_paswd = document.getElementById('ap_paswd').value;
            var ip_ap = document.getElementById('ip_ap').value; 
            var gateway_ap = document.getElementById('gateway_ap').value;
            var sta_name = document.getElementById('sta_name').value;
            var sta_paswd = document.getElementById('sta_paswd').value;
            var sta_dhcp_en = getVByName('sta_dhcp_en');
            var ip_sta = document.getElementById('ip_sta').value; 
            var gateway_sta = document.getElementById('gateway_sta').value;
            var tcp_type = getVByName('tcp_type');
            var ip_tcp = document.getElementById('ip_tcp').value;
            var tcp_port = document.getElementById('tcp_port').value;
            var time_out = document.getElementById('time_out').value;
            if ((IsPortValid(tcp_port) == false) || (80 == tcp_port) || (0 == tcp_port) || (0xFFFF < tcp_port)) {
                alert('port is invalid');
                return
            }
            if (false == isValidIP(ip_tcp)) {
                alert('tcp ip error');
                return
            }
            if (IsTimeoutValid(time_out) == false) {
                alert('time_out is invalid');
                return
            }
            if (false == isValidIP(ip_ap)) {
                alert('sta ip error');
                return
            } 
            if (false == isValidIP(gateway_ap)) {
                alert('gateway error');
                return
            }
            if (0 == sta_dhcp_en) {
                if (false == isValidIP(ip_sta)) {
                    alert('sta ip error');
                    return
                } 
                if (false == isValidIP(gateway_sta)) {
                    alert('gateway error');
                    return
                }
            }
            var post_work_mode = 'work_mode=' + work_mode + '&';
            var uart = 'baud=' + baud + '&bits=' + bits + '&parity=' + parity + '&stop=' + stop + '&';
            var post_ap_wifi = 'ap_enc_mode=' + ap_enc_mode + '&ap_hide=' + ap_hide + '&ap_name=' + encodeURI(ap_name) + '&ap_paswd=' + ap_paswd + '&';
            var post_ap_ip = 'ip_ap=' + ip_ap  + '&gateway_ap=' + gateway_ap + '&';
            var post_sta_wifi = 'sta_name=' + sta_name + "" + '&sta_paswd=' + sta_paswd + '&';
            var post_sta_ip = 'sta_dhcp_en=' + sta_dhcp_en + '&';
            if (0 == sta_dhcp_en) {
                post_sta_ip += 'ip_sta=' + ip_sta  + '&gateway_sta=' + gateway_sta + '&'
            }
            var post_tcp = 'tcp_type=' + tcp_type + '&ip_tcp=' + ip_tcp + '&time_out=' + time_out + '&';
            if (2 == tcp_type) {
                post_tcp = post_tcp + 'remote_port=' + tcp_port + '&'
            } else {
                post_tcp = post_tcp + 'tcp_port=' + tcp_port + '&'
            }
            var obj = document.getElementById('work_mode');
            var mode = obj.value;
            console.log('mode=' + mode);
            if (mode == work_mode_sta) {
                if (sta_name == "" || sta_name == null) {
                    alert('enter ssid');
                    return
                }
                if (sta_paswd == "" || sta_paswd == null) {
                    alert('enter password');
                    return
                }
                if (sta_name.length > 16) {
                    alert('ssid len error');
                    return
                }
                if ((sta_paswd.length > 16) || (sta_paswd.length < 8)) {
                    alert('password len error');
                    return
                }
            } else if (mode == work_mode_ap_sta) {
                if (ap_name == "" || ap_name == null) {
                    alert('enter apssid');
                    return
                }
                if (ap_paswd == "" || ap_paswd == null) {
                    alert('enter appassword');
                    return
                }
                if (sta_name == "" || sta_name == null) {
                    alert('enter stassid');
                    return
                }
                if (sta_paswd == "" || sta_paswd == null) {
                    alert('enter stapassword');
                    return
                }
                if (sta_name.length > 16) {
                    alert('stassid len error');
                    return
                }
                if ((sta_paswd.length > 16) || (sta_paswd.length < 8)) {
                    alert('stapassword len error');
                    return
                }
                if (ap_name.length > 16) {
                    alert('apssid len error');
                    return
                }
                if ((ap_paswd.length > 16) || (ap_paswd.length < 8)) {
                    alert('appassword len error');
                    return
                }
            }
            submit_post(post_work_mode + uart + post_ap_wifi + post_ap_ip + post_sta_wifi + post_sta_ip + post_tcp)
        }
        function change_port() {
            var tcp_type = getVByName('tcp_type');
            var obj = document.getElementById("tcp_port");
            if (2 == tcp_type) {
                port_remote = obj.value;
                console.log("port_remote=" + port_remote)
            } else {
                port_tcp = obj.value;
                console.log("port_tcp=" + port_tcp)
            }
        }
        function sockttypeClicked(_mode) {
            if (_mode == 2) {
                var obj = document.getElementById("label_port");
                obj.innerText = "远程端口:";
                obj = document.getElementById("ip_tcp");
                obj.disabled = false;
                document.getElementById("tcp_port").value = port_remote;
                console.log("(_mode == 2) ");
                console.log("obj.val=" + port_remote)
            } else {
                var obj = document.getElementById("label_port");
                obj.innerText = "本地端口:";
                obj = document.getElementById("ip_tcp");
                obj.disabled = true;
                document.getElementById("tcp_port").value = port_tcp;
                console.log("_mode=" + _mode);
                console.log("obj.val=" + port_tcp)
            }
        }
        function setParaRadioChecked(name, id) {
            var obj = document.getElementsByName(name);
            for (var i = 0; i <= obj.length; i++) {
                if (obj[i].id == id) {
                    obj[i].checked = 1;
                    if (name == "tcp_type") sockttypeClicked(id);
                    break
                }
            }
        }
        function setParaSelectOption(id, value) {
            var obj = document.getElementById(id);
            for (var i = 0; i <= obj.length; i++) {
                if (obj.options[i].value == value) {
                    obj.options[i].selected = true;
                    if (id == 'ap_enc_mode' && value == 0) document.getElementById('ap_paswd').disabled = true;
                    break
                }
            }
        }
        function ap_enc_mode_check() {
            var obj = document.getElementById('ap_enc_mode');
            if (obj.value == 0) document.getElementById('ap_paswd').disabled = true;
            else document.getElementById('ap_paswd').disabled = false
        }
        function work_mode_check() {
            var obj = document.getElementById('work_mode');
            mode_current = obj.value;
            console.log('mode_current=' + mode_current);
            if (mode_current == work_mode_sta) {
                console.log('hide ap show sta');
                var nodes = document.getElementById("ap").getElementsByTagName('*');
                for (var i = 0; i < nodes.length; i++) {
                    nodes[i].disabled = true
                }
            } else if (mode_current == work_mode_ap_sta) {
                console.log('show ap and sta');
                var nodes = document.getElementById("ap").getElementsByTagName('*');
                for (var i = 0; i < nodes.length; i++) {
                    nodes[i].disabled = false
                }
            }
            if (mode_last != mode_current) {
                mode_last = mode_current
            }
        }
        function set_ip_en(mode) {
            console.log("set_ip_en mode=" + mode);
            if (mode == '1') {
                console.log("disable ip info");
                var nodes = document.getElementById("ip_en").getElementsByTagName('*');
                for (var i = 0; i < nodes.length; i++) {
                    nodes[i].disabled = true
                }
            } else {
                console.log("enable ip info");
                var nodes = document.getElementById("ip_en").getElementsByTagName('*');
                for (var i = 0; i < nodes.length; i++) {
                    nodes[i].disabled = false
                }
            }
        }
script>
    <style>
        body {
          background:#e2e2e2;
          max-width: 642px;
          font-family: 'Roboto', sans-serif;
          margin: auto auto;
          box-shadow: 0 0 10px 10px rgba(0,0,0,.5);
          border-radius: 10px; 

      }
      .mytabs {
          display: flex;
          flex-wrap: wrap; 
          margin: 1em auto;
          line-height: 2em;    

      }
      .mytabs input[type="radio"] {
          display: none;
      }
      .mytabs label {
          padding: 25px;
          font-weight: bold;
          border-radius: 10px 10px 0 0 ;
      }

      .mytabs .tab {
          width: 100%; 
          background: white;
          order: 1;
          display: none;
          border-radius: 0 0 10px 10px; 
          min-height:270px;
      } 

      .mytabs input[type='radio']:checked + label + .tab {
          display: block;
      }

      .mytabs input[type="radio"]:checked + label {
          background: white;
      }

      .control_group
      {
        width:100%;   
      }

      .control_group label
      {
          padding:unset;
          font-size: 14px;
          width:40%;
          display:inline-block;
          text-align:right;
          padding-right:5%; 
          background-color:transparent; 
      }
      .control_group .title
      {
        margin-top:5%;
      }  

      .control_group input[type="radio"]{
          display:unset;
      }


      button {
        border:none;
        border-radius:4px;
        line-height:2em;
        color:#fff;
        margin-right:1em
    }


    button.green {
        background:#45c01a
    }


    button.button.blue {
        background:#466
    }
    .gray {
        background:gray
    } 
style>
head>
<body>
    <form name="hotform" id="hotform" action='' method="post">
  <div class="mytabs">
    <input type="radio" id="tab_basic_config" name="mytabs" checked="checked">
    <label for="tab_basic_config">基础参数label>
    <div class="tab">
      <div id='uart'>
        <div class="control_group">
            <label class="title">
                工作模式:
            label>
            <select class="select" id="work_mode" name="mode" onchange="work_mode_check()">
                <option value="0">
                    AP+STA
                option>
                <option value="1">
                    STA
                option>
            select>
            <label>
                波特率:
            label>
            <select id="baud" name="baud">
                <option value="9600">
                    9600
                option>
                <option value="19200">
                    19200
                option>
                <option value="38400">
                    38400
                option>
                <option value="57600">
                    57600
                option>
                <option value="74880">
                    74880
                option>
                <option value="115200">
                    115200
                option>
            select>
        div>
        <div class="control_group">
            <label>
                数据位:
            label>
            <select id="bits" name="bits">
                <option value=2>
                    7
                option>
                <option value=3>
                    8
                option>
            select>
        div>
        <div class="control_group">
            <label>
                奇偶校验:
            label>
            <select id="parity" name="parity">
                <option value=0>
                    NONE
                option>
                <option value=3>
                    ODD
                option>
                <option value=2>
                    EVEN
                option>
            select>
        div>
        <div class="control_group">
            <label>
                停止位:
            label>
            <select id="stop" name="stop">
                <option value=1>
                    1
                option>
                <option value=2>
                    1.5
                option>
                <option value=3>
                    2
                option>
            select>
        div>
    div>
    div>
    <input type="radio" id="tab_ap_config" name="mytabs">
    <label for="tab_ap_config">热点模式label>
    <div class="tab">
        <div id='ap'>
            <div class="control_group">
                <label class="title">
                    热点名:
                label>
                <input name="ap_name" id="ap_name" type="text" maxlength=32>
            div>
            <div class="control_group">
                <label>
                    密码:
                label>
                <input Name="ap_paswd" id="ap_paswd" type="text" minlength=8 maxlength=16>
            div>
            <div class="control_group">
                <label>
                    加密方式:
                label>
                <select id="ap_enc_mode" name="ap_enc_mode" onchange="ap_enc_mode_check()">
                    <option value=0>
                        OPEN
                    option>
                    <option value=2>
                        WPA_PSK
                    option>
                    <option value=3>
                        WPA_PSK2
                    option>
                    <option value=4>
                        WPA_WPA2_PSK
                    option>
                select>
            div>
            <div class="control_group" id='ap_hide'>
                <label>
                    隐藏热点:
                label>
                <input name="ap_hide" id="1" value="1" type="radio"><input name="ap_hide" id="0" value="0" type="radio">div>
            <div>
                <div class="control_group">
                    <label>
                        IP:
                    label>
                    <input name="ip_ap" id="ip_ap" type="text" maxlength=15>
                div>   
                <div class="control_group">
                    <label>
                        网关:
                    label>
                    <input name="gateway_ap" id="gateway_ap" type="text" maxlength=15>
                div>
            div>
        div>
    div>
    <input type="radio" id="tab_sta_config" name="mytabs">
    <label for="tab_sta_config">客户端模式label>
    <div class="tab">
        <div id='station'>
            <div class="control_group">
                <label class="title">
                    WIFI名:
                label>
                <input name="sta_name" id="sta_name" type="text" maxlength=32>
            div>
            <div class="control_group">
                <label>
                    连接状态:
                label>
                <input name="sta_status" id="sta_status" type="text" maxlength=32>
            div>
            <div class="control_group">
                <label>
                    WIFI列表:
                label>
                <select name="ap_list" id="ap_list" maxlength=20 onchange="document.getElementById('sta_name').value=this.value;">
                select>
                <button class="green" style="width: 48px;" onclick="get_ap_list();return false;">
                    刷新
                button>
            div>
            <div class="control_group">
                <label>
                    WIFI密码:
                label>
                <input name="sta_paswd" id="sta_paswd" type="text" maxlength=16>
            div>
            <div class="control_group">
                <label>
                    动态获取IP:
                label>
                <input name="sta_dhcp_en" id="1" value="1" type="radio" onclick="set_ip_en('1')"><input name="sta_dhcp_en" id="0" value="0" type="radio" onclick="set_ip_en('0')">div>
            <div id='ip_en'>
                <div class="control_group">
                    <label>
                        IP:
                    label>
                    <input name="ip_sta" id="ip_sta" type="text" maxlength=15>
                div> 
                <div class="control_group">
                    <label>
                        网关:
                    label>
                    <input name="gateway_sta" id="gateway_sta" type="text" maxlength=15>
                div>
            div>
        div>
    div>
    <input type="radio" id="tab_net_config" name="mytabs">
    <label for="tab_net_config">TCP通信label>
    <div class="tab">
        <div id='network'> 
            <div class="control_group">
                <label class="title">
                    Socket类型:
                label>
                <input name="tcp_type" id="1" value="1" checked="checked" type="radio"
                onclick="sockttypeClicked(1)">
                服务器
                <input name="tcp_type" id="2" value="2" type="radio" onclick="sockttypeClicked(2)">
                客户端
            div>
            <div class="control_group">
                <label>
                    远端IP:
                label>
                <input name="ip_tcp" id="ip_tcp" type="text" maxlength=64>
            div>
            <div class="control_group">
                <label id="label_port">
                    本地端口:
                label>
                <input name="tcp_port" id="tcp_port" type="text" maxlength=5 onchange="change_port()"
                onKeyUp="value=value.replace(/\\D/g,'')" onafterpaste="value=value.replace(/\\D/g,'')">
            div>
            <div class="control_group">
                <label>
                    超时时间(s):
                label>
                <input name="time_out" id="time_out" type="text" maxlength=4>
            div>
        div>
    div>
    <input type="radio" id="tab_ota" name="mytabs">
    <label for="tab_ota">固件升级label>
    <div class="tab">
        <div class='ota'> 
            <label class="title">

            label>
            <div class="control_group">         
                <input id="file-name" readonly type="text" style="width: 80px; margin-left: 200px; "/>
                <input type="file" onchange="fileChange(this)" id="file-info" name="file">
                <button class="green" style="margin-left: -85px; " onclick="postOta();return false;">updatebutton>
            div>
            <div class="control_group">
                <label style="margin:0 0;">
                    version:
                label>
                <input id="ver" readonly type="text" />
            div>
        div>
    div>
  div>
  <div style="width:100%; text-align: center; line-height: 2em;">
    <div class="button_group">
        <button class="green" style="width: 120px; margin-bottom: 10px;" onclick="submitForm();return false;">
            保存参数
        button>
    div>
    <div class="button_group">
        <button class="green" style="width: 120px; margin-bottom: 10px;" onclick="set_confirm();return false;">
            恢复默认参数
        button>
    div>
    <img src="logo.png">img>
  div>
    form>
    <script stype="text/javascript">    
        var timeoutNum = 0;
        var Ajax = {
            get: function(e, d) {
                var f;
                if (window.XMLHttpRequest) {
                    f = new XMLHttpRequest()
                } else {
                    if (window.ActiveObject) {
                        f = new ActiveXobject("Microsoft.XMLHTTP")
                    }
                }
                f.open("GET", e, true);
                f.onreadystatechange = function() {
                    if (f.readyState == 4) {
                        console.log(f.status);
                        if (f.status == 200 || f.status == 304) {
                            d.call(this, f.responseText)
                        } else {}
                    }
                };
                f.send()
            },
            post: function(e, g, h) {
                showLoading();
                var f;
                if (window.XMLHttpRequest) {
                    f = new XMLHttpRequest()
                } else {
                    if (window.ActiveObject) {
                        f = new ActiveXobject("Microsoft.XMLHTTP")
                    }
                }
                f.open("POST", e, true);
                f.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
                f.onreadystatechange = function() {
                    if (f.readyState == 4) {
                        if (f.status == 200 || f.status == 304) {
                            h.call(this, f.responseText)
                        } else {}
                    }
                };
                f.send(g)
            },
            postFile: function(e, g, h) {
                var f;
                if (window.XMLHttpRequest) {
                    f = new XMLHttpRequest()
                } else {
                    if (window.ActiveObject) {
                        f = new ActiveXobject("Microsoft.XMLHTTP")
                    }
                }
                f.open("POST", e, true);
                f.setRequestHeader("Content-Type", "application/octet-stream;charset=UTF-8");
                f.onreadystatechange = function() {
                    if (f.readyState == 4) {
                        if (f.status == 200 || f.status == 304) {
                            h.call(this, f.responseText)
                        } else {}
                    }
                };
                f.send(g)
            }
        };
        function postOta() {
            timeoutNum = 0;
            var b = document.getElementById("file-info").files;
            if (b && b.length > 0) {
                b = b[0];
                Ajax.postFile("/setotadata", b,
                function(a) {
                    a = JSON.parse(a);
                    console.log(a);
                    if (a.state == 0) {
                        console.log("otaSuc")
                    } else {
                        console.log("otaFailed")
                    }
                })
            } else {}
        }
        function fileChange(e) {
            var c = e.files;
            if (c && c.length > 0) {
                c = c[0];
                var d = c.name.toLowerCase();
                if (d.indexOf(".bin") != (d.length - 4)) {
                    document.getElementById("file-info").value = "";
                    return
                }
                if (c.size >= 2097152) {
                    document.getElementById("file-info").value = "";
                    return
                }
                document.getElementById("file-name").value = d;
                console.log(document.getElementById("file-info").files)
            }
        }
        function check_valid_bits(val) {
            if (!/^([01])$/.test(val)) {
                alert("手机号码有误,请重填");
                return false
            }
            return true
        }
        function init_parameters() {
            Ajax.get("/getpara",
            function(c) {
                c = JSON.parse(c);
                try {
                    console.log('workmode=' + c.work_mode);
                    console.log('ap_enc_mode=' + c.ap_enc_mode);
                    console.log('ap_hide=' + c.ap_hide);
                    console.log('sta_dhcp_en=' + c.sta_dhcp_en);
                    c.work_mode = c.work_mode + '';
                    c.ap_enc_mode = c.ap_enc_mode + '';
                    c.ap_hide = c.ap_hide + '';
                    c.sta_dhcp_en = c.sta_dhcp_en + '';
                    console.log('after');
                    console.log('workmode=' + c.work_mode);
                    console.log('ap_enc_mode=' + c.ap_enc_mode);
                    console.log('ap_hide=' + c.ap_hide);
                    console.log('sta_dhcp_en=' + c.sta_dhcp_en);
                    console.log("res=" + check_valid_bits(c.work_mode));
                    if ((c.work_mode != work_mode_ap_sta) && (c.work_mode != work_mode_sta)) {
                        c.work_mode = work_mode_ap_sta
                    }
                    document.getElementById("work_mode").value = c.work_mode;
                    setParaRadioChecked('ap_hide', c.ap_hide);
                    setParaSelectOption('ap_enc_mode', c.ap_enc_mode);
                    document.getElementById("ap_name").value = c.ap_name;
                    document.getElementById("ap_paswd").value = c.ap_paswd;
                    document.getElementById("sta_name").value = c.sta_name;
                    document.getElementById("sta_paswd").value = c.sta_paswd;
                    setParaRadioChecked('sta_dhcp_en', c.sta_dhcp_en);
                    set_ip_en(c.sta_dhcp_en);
                    if (0 == c.sta_dhcp_en) {
                        document.getElementById("ip_sta").value = c.ip_sta;
                        document.getElementById("gateway_sta").value = c.gateway_sta;
                    } else {
                        get_sta_ip_info();
                    }
                    get_sta_status();
                    document.getElementById("sta_status").disabled = true;
                    var obj = document.getElementById('work_mode');
                    var mode = obj.value;
                    console.log('mode=' + mode);
                    work_mode_check();
                    get_ap_list();
                    document.getElementById("ip_ap").value = c.ip_ap; 
                    document.getElementById("gateway_ap").value = c.gateway_ap;
                    setParaSelectOption('baud', c.baud);
                    setParaSelectOption('bits', c.bits);
                    setParaSelectOption('parity', c.parity);
                    setParaSelectOption('stop', c.stop);
                    setParaRadioChecked('tcp_type', c.tcp_type);
                    document.getElementById('ip_tcp').value = c.ip_tcp;
                    document.getElementById('tcp_port').value = c.tcp_port;
                    port_remote = c.remote_port;
                    port_tcp = c.tcp_port;
                    console.log("c.tcp_type=" + c.tcp_type);
                    if (2 == c.tcp_type) {
                        document.getElementById('tcp_port').value = c.remote_port
                    }
                    document.getElementById('time_out').value = c.time_out
                } catch(d) {}
            })
        }
        function get_ap_list() {
            Ajax.get("/getaplist",
            function(c) {
                if (!isEmpty(c)) {
                    console.log(c);
                    var res = c;
                    if (res.length > 0) {
                        document.getElementById("ap_list").options.length = 0;
                        var a_list = new Array();
                        a_list = res.split("^$&");
                        for (i = 0; i < a_list.length; i++) {
                            if (a_list[i].length > 0) {
                                var t = a_list[i];
                                document.getElementById("ap_list").options.add(new Option(t, t))
                            }
                        }
                    }
                }
            })
        }
        function isEmpty(str) {
            if (typeof str == null || str == "" || str == "undefined") {
                return true
            } else {
                return false
            }
        }
        function get_sta_ip_info() {
            Ajax.get("/getip",
            function(c) {
                if (!isEmpty(c)) {
                    c = JSON.parse(c);
                    console.log(c);
                    try {
                        if (c.ip_sta) {
                            document.getElementById("ip_sta").value = c.ip_sta;
                        }
                        if (c.gateway_sta) {
                            document.getElementById("gateway_sta").value = c.gateway_sta;
                        }
                    } catch(d) {}
                }
            })
        }
        function get_sta_status() {
            Ajax.get("/getstatus",
            function(c) {
                if (!isEmpty(c)) {
                    c = JSON.parse(c);
                    console.log(c);
                    try {
                        if (c.status) {
                            document.getElementById("sta_status").value = c.status
                        }
                    } catch(d) {}
                }
            })
        }
        function get_ver() {
                Ajax.get("/getotainfo",
                function(c) {
                    if (!isEmpty(c)) 
          {
                        console.log(c);
                        var res = JSON.parse(c); 
                        try {
                            if (res.fw_version) {
                                document.getElementById("ver").value = res.fw_version
                            }
                        } catch(d) {}
                    }
                })
            }
        function set_confirm() {
            var se = confirm("restore the module?");
            if (se == true) {
                submit_postDefault();
            }
        }
        init_parameters();
        get_ver();
script>
body>
html>

3.2 http服务器端
3.2.1 基本请求
工作在AP模式下,在浏览器打开192.168.4.1后,相当于发起了一个HTTP GET请求,路径是/,那么服务器端会发送一个html的网页内容到浏览器上,图片也可以通过这种方式发出去

httpd_uri_t basic_handlers[] = 
{
    {"/", HTTP_GET, hello_get_handler,NULL},
    {"/logo.png", HTTP_GET, logo_png_get_handler,NULL},
    {"/favicon.png", HTTP_GET, favicon_png_get_handler,NULL},
    {"/getpara", HTTP_GET, config_wifi_get_handler, NULL},
    {"/getaplist", HTTP_GET, ap_record_get_handler, NULL},
    {"/setpara", HTTP_POST, config_wifi_post_handler, NULL},
    {"/default", HTTP_POST, config_wifi_default_handler, NULL},
    {"/getip", HTTP_GET, config_ip_get_handler, NULL},
    {"/getstatus", HTTP_GET, sta_get_status, NULL},
};

3.2.2 固件升级
esp8266已经有封装好的api,可以很简单的实现OTA功能,只需要简单的配置一下就好了。
-选择分区表为Factory app,two OTA definitions

服务器

  • 对应的地址分布
    0x11000+F0000刚好是2M

服务器

-请求响应
主要是获取当前版本号,发送APP文件

httpd_uri_t basic_handlers[] = 
{
   {"/getotainfo", HTTP_GET, ota_info_get_handler, NULL},
 {"/setotadata", HTTP_POST, ota_data_post_handler, NULL}, 
};

处理客户端获取版本信息

static esp_err_t ota_info_get_handler(httpd_req_t *req)
{
    int32_t json_len = 0;
    char *temp_json_str = ((web_server_context_t*) (req->user_ctx))->scratch;

    memset(temp_json_str, '\\0', ESP_AT_WEB_SCRATCH_BUFSIZE * sizeof(char));


    httpd_resp_set_type(req, "application/json");
    json_len += sprintf(temp_json_str + json_len, "{\\"fw_version\\":\\"%s\\"}", CONFIG_VERSION_AT); // it means http context OK


    ESP_LOGD(TAG, "now ota get json str is %s\\n", temp_json_str);
    httpd_resp_send(req, temp_json_str, strlen(temp_json_str));


    return ESP_OK;
}

接收OTA文件

static esp_err_t ota_data_post_handler(httpd_req_t *req)
{
    char *buf = ((web_server_context_t*) (req->user_ctx))->scratch;
    int total_len = req->content_len;
    int remaining_len = req->content_len;
    int received_len = 0;
    esp_err_t err = ESP_FAIL;
    esp_ota_handle_t update_handle = 0;
    const esp_partition_t *update_partition = at_web_get_ota_update_partition();
    // check post data size
    if (update_partition->size < total_len) {
        ESP_LOGE(TAG, "ota data too long, partition size is %u, bin size is %d", update_partition->size, total_len);
        goto err_handler;
    }
    ESP_LOGI(TAG, "bin size is %d", total_len);
    memset(buf, 0x0, ESP_AT_WEB_SCRATCH_BUFSIZE * sizeof(char));

    // Send a message to MCU.


    ESP_LOGI(TAG, "%s", s_ota_start_response);

    // start ota
    err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "ota begin failed (%s)", esp_err_to_name(err));
        goto err_handler;
    }

    // receive ota data
    while (remaining_len > 0) {
        received_len = httpd_req_recv(req, buf, MIN(remaining_len, ESP_AT_WEB_SCRATCH_BUFSIZE)); // Receive the file part by part into a buffer
        if (received_len <= 0) { // received error
            if (received_len == HTTPD_SOCK_ERR_TIMEOUT) {
                /* Retry if timeout occurred */
                continue;
            }
            ESP_LOGE(TAG, "Failed to receive post ota data, err = %d", received_len);
            esp_ota_end(update_handle);
            goto err_handler;
        }else { // received successfully
            err = esp_ota_write(update_handle, buf, received_len);
            if (err != ESP_OK) {
                ESP_LOGE(TAG, "ota write failed (%s)", esp_err_to_name(err));
                esp_ota_end(update_handle);
                goto err_handler;
            }
            remaining_len -= received_len;
        }
    }
    err = at_web_ota_end(update_handle, update_partition);
    if (err != ESP_OK) {
        goto err_handler;
    }
    at_web_response_ok(req);
    //esp_at_port_write_data((uint8_t*)s_ota_receive_success_response, strlen(s_ota_receive_success_response));

    ESP_LOGI(TAG, "%s", s_ota_receive_success_response);

    ESP_LOGI(TAG, "ota end successfully, please restart");

    const char *temp_str = CONFIG_MSG_REMIND;
    httpd_resp_set_type(req, HTTPD_TYPE_TEXT);
    httpd_resp_set_status(req, HTTPD_200);
    httpd_resp_send(req, temp_str, strlen(temp_str));


    sleep(2);


    esp_restart();


    return ESP_OK;


err_handler:
    at_web_response_error(req, HTTPD_500);
    //esp_at_port_write_data((uint8_t*)s_ota_receive_fail_response, strlen(s_ota_receive_fail_response));
    ESP_LOGI(TAG, "%s", s_ota_receive_fail_response);

    return ESP_FAIL;
}

4 TCP通信

#define CONFIG_S_TIMEOUT_CLIENT         1
#define BACKLOG                         5


extern EventGroupHandle_t wifi_event_group_check;


static const char *TAG="APP_TCP";


static void client_remove_all(tcp_multiclient_t *p_clients);
static void client_remove(tcp_multiclient_t *p_clients,int8_t idx);


#define TCP_RX_BUF_SIZE 2048
char tcp_rx_buffer[TCP_RX_BUF_SIZE];


rt_slist_t tcp_clients_list;


tcp_multiclient_t s_clients[BACKLOG]; 


volatile int socket_tcp_client = 0;
int8_t online_client = 0;
static fd_set fdsr_tcp;


static void client_remove(tcp_multiclient_t *p_clients,int8_t idx)
{
    if ((p_clients) && (idx >= 0))
    {
        ESP_LOGE(TAG,"client[%d] close fd[%d]", idx ,p_clients[idx].fd);

        close(p_clients[idx].fd);
        FD_CLR(p_clients[idx].fd, &fdsr_tcp);
        p_clients[idx].fd = -1;

        if (online_client > 0)
        {
            online_client--;
        }

        ESP_LOGE(TAG,"online_client[%d]", online_client);
    }
}


static void client_remove_all(tcp_multiclient_t *p_clients)
{
    uint8_t idx = 0;

    if (p_clients)
    {
        ESP_LOGE(TAG, "remove all client");

        for (idx = 0; idx < BACKLOG; idx++) 
        {
            if (p_clients[idx].fd != -1) 
            {
                shutdown(p_clients[idx].fd, 0);
                close(p_clients[idx].fd);
                p_clients[idx].fd = -1;
                s_clients[idx].idx = -1;
                p_clients[idx].timeout_tick = 0;
            }
        }
    }

    online_client = 0;
}


uint32_t xTaskGetTickCount_new(void)
{
    struct timeval tv;
    struct timezone tz;

    if (gettimeofday(&tv, &tz) == 0) 
    {
        return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
    }

    return 0;
}


void showclient(void)
{
    int i;

    ESP_LOGI(TAG,"client amount: %d", online_client);

    for (i = 0; i < BACKLOG; i++) 
    {
        ESP_LOGI(TAG,"[%d]:%d  ", i, s_clients[i].fd);
    }

    ESP_LOGI(TAG,"\\r\\n");
}


void tcp_server_task(void *pvParameters)
{
    char addr_str[128];
    int addr_family;
    int ip_protocol;
    struct timeval tv;
    int i;
    int yes = 1;
    int listen_sock = -1;


    tcp_server_parameter_t get_config = {CONFIG_PORT_TCP_SERVER,CONFIG_S_TIMEOUT_TCP_SERVER};


    struct sockaddr_in client_addr;

    int maxsockfd;

    if (pvParameters)
    {
        memcpy(&get_config,pvParameters,sizeof(tcp_server_parameter_t));
    }


    ESP_LOGI(TAG, "server port[%d] timeout[%d]",get_config.port,get_config.timeout);


    ESP_LOGI(TAG, "tcp_server_task waiting for ip...");

    xEventGroupWaitBits(wifi_event_group_check, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY);


    while (1) 
    {
        struct sockaddr_in destAddr;
        destAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        destAddr.sin_family = AF_INET;
        destAddr.sin_port = htons(get_config.port);
        addr_family = AF_INET;
        ip_protocol = IPPROTO_IP;
        inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);


        listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);

        if (listen_sock < 0) 
        {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);

            break;
        }

        ESP_LOGI(TAG, "Socket created");


        //allow  socket address reuse
        if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) 
        {
            perror("setsockopt");
            //exit(1);
        }

        ESP_LOGI(TAG, "address reuse ok");


        int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
        if (err != 0) 
        {
            ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
            break;
        }

        ESP_LOGI(TAG, "Socket binded");


        err = listen(listen_sock, BACKLOG);
        if (err != 0) 
        {
            ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
            break;
        }

        ESP_LOGI(TAG, "Socket listening");


#ifdef CONFIG_EXAMPLE_IPV6
        struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
#else
        struct sockaddr_in sourceAddr;
#endif


        uint addrLen = sizeof(sourceAddr);


        maxsockfd = listen_sock;//use for select() to check the readable fd


        ESP_LOGI(TAG, "maxsockfd [%d]",maxsockfd);

        for (i = 0; i < BACKLOG; i++) 
        {
           s_clients[i].fd = -1;
           s_clients[i].idx = -1;
           s_clients[i].timeout_tick = xTaskGetTickCount_new();//tick_count
        }

        online_client = 0;

        rt_slist_init(&tcp_clients_list);


        memset(tcp_rx_buffer,0,TCP_RX_BUF_SIZE);


        for (;;)
        {
            uint32_t get_val = 0;

            if( pdTRUE == xTaskNotifyWait( 0,//在函数开始出将消息对应的位清零
                                           0,//在函数退出时将消息对应的位清零,只有在接收到通知才有效
                                           &get_val,//接收到的消息值
                                           0 ))      //阻塞的时间
            {
                ESP_LOGI(TAG, "server recv notify get_val:%d",get_val);


                goto free_task;
            }

            // initialize file descriptor set
            FD_ZERO(&fdsr_tcp);
            FD_SET(listen_sock, &fdsr_tcp);


            // timeout setting


            // add active connection to fd set
            tcp_multiclient_t* p_client_cur = NULL;
            tcp_multiclient_t* p_client_check = NULL;
            rt_list_t* node_check;

            rt_slist_for_each(node_check, &tcp_clients_list)
            {
                p_client_check = rt_slist_entry(node_check,  tcp_multiclient_t, list);

                if (p_client_check)
                {
                    FD_CLR(p_client_check->fd, &fdsr_tcp);
                    FD_SET(p_client_check->fd, &fdsr_tcp);
                    p_client_cur = p_client_check;
                }
            }

            tv.tv_sec = 1;
            tv.tv_usec = 0;


            //block here until listen_sock can read
            int ret = select(maxsockfd+1, &fdsr_tcp, NULL, NULL, &tv);


            if (ret < 0) 
            {
                perror("select");
                break;
            } 
            else if (ret == 0) 
            {                
                //ESP_LOGI(TAG, "timeout_s[%d]",CONFIG_S_TIMEOUT_CLIENT*get_config.timeout);

                if (p_client_cur)
                {
                    int check_tick = (xTaskGetTickCount_new() - p_client_cur->timeout_tick);

                    //ESP_LOGI(TAG, "check_tick[%d]",check_tick);

                    if (check_tick  >= ((CONFIG_S_TIMEOUT_CLIENT*get_config.timeout)*1000))
                    {
                        ESP_LOGI(TAG, "timeout with idx[%d] fd[%d]",p_client_cur->fd,p_client_cur->idx);
                        p_client_cur->timeout_tick = xTaskGetTickCount_new();
                        rt_slist_remove(&tcp_clients_list, &(p_client_cur->list));
                        client_remove(s_clients,p_client_cur->idx);
                    }
                }

                continue;
            }

            // check whether a new connection comes and handler the new connection
            if (FD_ISSET(listen_sock, &fdsr_tcp)) 
            {
                int new_connect = accept(listen_sock, (struct sockaddr *)&client_addr, &addrLen);
                if (new_connect <= 0) 
                {
                    perror("accept");
                    continue;
                }
                ESP_LOGI(TAG, "Socket accepted");


                // add to fd queue
                if (online_client < BACKLOG) 
                {
                    if (s_clients[online_client].fd != -1)
                    {
                        ESP_LOGI(TAG,"replace fd[%d]",s_clients[online_client].fd);
                        close(s_clients[online_client].fd);
                        FD_CLR(s_clients[online_client].fd, &fdsr_tcp);
                        s_clients[online_client].fd = -1;


                        if (online_client> 0)
                        {
                            online_client--;
                            ESP_LOGI(TAG,"reset online_client[%d]",online_client);
                        }
                    }

                    s_clients[online_client].timeout_tick = xTaskGetTickCount_new();
                    s_clients[online_client].fd = new_connect;
                    s_clients[online_client].idx = online_client;

                    ESP_LOGI(TAG,"new client timeout_tick=%d",s_clients[online_client].timeout_tick);
                    ESP_LOGI(TAG,"new connection client[%d] %s:%d", online_client,
                    inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));


                    rt_slist_append(&tcp_clients_list, &(s_clients[online_client].list));

                    if (new_connect > maxsockfd)
                    maxsockfd = new_connect;

                    online_client++;


                    ESP_LOGI(TAG,"online_client=[%d]",online_client);


                    uint32_t get_len = rt_slist_len(&tcp_clients_list);

                    ESP_LOGI(TAG,"list len=[%d]",get_len);


                    if (get_len > 1)
                    {
                        tcp_multiclient_t *check_client=NULL;
                        tcp_multiclient_t *new_client = rt_slist_tail_entry(&tcp_clients_list,tcp_multiclient_t,list);

                        rt_list_t* node;

                        ESP_LOGI(TAG,"new_client id[%d],fd[%d]",new_client->idx,new_client->fd);

                        rt_slist_for_each(node, &tcp_clients_list)
                        {
                            check_client = rt_slist_entry(node,  tcp_multiclient_t, list);
                            ESP_LOGI(TAG,"check_client id[%d],fd[%d]",check_client->idx,check_client->fd);

                            if (check_client->fd == -1)
                            {
                                ESP_LOGI(TAG,"remove id[%d],fd[%d]",check_client->idx,check_client->fd);
                                rt_slist_remove(&tcp_clients_list, &(check_client->list));
                                client_remove(s_clients,check_client->idx);
                            }
                            else if (check_client->fd != new_client->fd)
                            {
                                ESP_LOGI(TAG,"remove id[%d],fd[%d]",check_client->idx,check_client->fd);
                                rt_slist_remove(&tcp_clients_list, &(check_client->list));
                                client_remove(s_clients,check_client->idx);
                            }
                        }
                    }
                }
                else 
                {
                    ESP_LOGI(TAG,"max connections arrive, exit");
                    send(new_connect, "bye", 4, 0);
                    close(new_connect);
                    continue;
                }
            }


            if (p_client_cur)
            {
                int get_fd = -1;

                if( lock_tcp() == pdTRUE )
                {
                    get_fd = p_client_cur->fd;

                    unlock_tcp();
                }
                else
                {
                    ESP_LOGI(TAG, "take uart mux error");
                }

                uint32_t get_tick = p_client_cur->timeout_tick;
                int8_t idx_client = p_client_cur->idx;

                if (FD_ISSET(get_fd, &fdsr_tcp)) 
                {
                    p_client_cur->timeout_tick = xTaskGetTickCount_new(); 

                    //ESP_LOGI(TAG,"s_clients[%d],idx=[%d]", get_fd, idx_client);

                    int ret = recv(get_fd, tcp_rx_buffer, TCP_RX_BUF_SIZE - 1, 0);

                    if (ret < 0) 
                    {
                        ESP_LOGE(TAG, "recv failed : errno %d,ret=%d,s_clients.fd=%d", errno,ret,get_fd);
                        break;
                    }
                    else if (0 == ret) 
                    {
                        ESP_LOGE(TAG,"close fd[%d] idx[%d]" ,get_fd, idx_client);

                        client_remove(s_clients,idx_client);

                        rt_slist_remove(&tcp_clients_list, &(p_client_cur->list));

                        continue;
                    } 
                    else 
                    {
                        #if 0
                        if (ret < TCP_RX_BUF_SIZE)
                        {
                            memset(&tcp_rx_buffer[ret],0, 1);
                        }
                        #endif

                        if( lock_uart() == pdTRUE )
                        {
                            uart_write_bytes(EX_UART_NUM, (const char *) tcp_rx_buffer, ret);

                            unlock_uart();
                        }
                        else
                        {
                            ESP_LOGI(TAG, "take uart mux error");
                        }
                        #if 0    
                        uint8_t idx = 0;
                        ESP_LOGI(TAG,"uwrite");

                        for (idx=0; idxESP_LOGE(TAG,"%02x " ,tcp_rx_buffer[idx]);
                        }

                        ESP_LOGI(TAG,"\\n");
                        #endif
                    }
                }
            }

            //showclient();
        }

        //  when select() return error, close other connections

        ESP_LOGE(TAG, "Shutting down socket and restarting...");

        client_remove_all(s_clients);


        shutdown(listen_sock,0);
        close(listen_sock);

        usleep(5000);
    }


    free_task:

    client_remove_all(s_clients);
    rt_slist_init(&tcp_clients_list);

    shutdown(listen_sock,0);
    close(listen_sock);
    xEventGroupSetBits(wifi_event_group_check,TCP_TASK_FREE_BIT);

    vTaskDelete(NULL);
}


void tcp_client_task(void *pvParameters)
{
    char addr_str[128];
    int addr_family;
    int ip_protocol;
    int get_fd = -1;

    tcp_client_parameter_t get_config = {CONFIG_IP_TCP_SERVER,CONFIG_PORT_REMOTE};

    if (pvParameters)
    {
        memcpy(&get_config,pvParameters,sizeof(tcp_client_parameter_t));
    }


    ESP_LOGI(TAG, "tcp_client_task waiting for ip...");


    ESP_LOGI(TAG, "client port[%d] host[%s]",get_config.port_remote,get_config.ip_remote);


    xEventGroupWaitBits(wifi_event_group_check, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY);


    while (1) 
    {
        struct sockaddr_in destAddr;
        destAddr.sin_addr.s_addr = inet_addr(get_config.ip_remote);
        destAddr.sin_family = AF_INET;
        destAddr.sin_port = htons(get_config.port_remote);
        addr_family = AF_INET;
        ip_protocol = IPPROTO_IP;
        inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);

        if( lock_tcp() == pdTRUE )
        {
            socket_tcp_client =  socket(addr_family, SOCK_STREAM, ip_protocol);

            if (socket_tcp_client < 0) 
            {
                ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
                break;
            }

            get_fd = socket_tcp_client;

            unlock_tcp();
        }
        else
        {
            ESP_LOGI(TAG, "take uart mux error");
        }

        ESP_LOGI(TAG, "Socket created");


        int err = connect(get_fd, (struct sockaddr *)&destAddr, sizeof(destAddr));

        if (err != 0) 
        {
            ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
        }

        ESP_LOGI(TAG, "Successfully connected");


        while (1) 
        {
            uint32_t get_val = 0;

            if( pdTRUE == xTaskNotifyWait( 0,//在函数开始出将消息对应的位清零
                                           0,//在函数退出时将消息对应的位清零,只有在接收到通知才有效
                                           &get_val,//接收到的消息值
                                           0 ))      //阻塞的时间
            {
                ESP_LOGI(TAG, "client recv notify get_val:%d",get_val);


                goto free_task;
            }


            ESP_LOGI(TAG, "recv");

            int len = recv(get_fd, tcp_rx_buffer, sizeof(tcp_rx_buffer) - 1, 0);

            // Error occured during receiving
            if (len <= 0) 
            {
                ESP_LOGE(TAG, "recv failed: errno %d", errno);
                break;
            }
            // Data received
            else //if (len > 0) 
            {
                if( lock_uart() == pdTRUE )
                {
                    uart_write_bytes(EX_UART_NUM, (const char *) tcp_rx_buffer, len);

                    unlock_uart();
                }
                else
                {
                    ESP_LOGI(TAG, "take uart mux error");
                }


                //tcp_rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
                ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
                //ESP_LOGI(TAG, "%s", tcp_rx_buffer);
            }

            //ESP_LOGI(TAG, "vTaskDelay");

            //vTaskDelay(100 / portTICK_PERIOD_MS);//200/10=20
        }


        if (get_fd != -1) 
        {
            ESP_LOGE(TAG, "Shutting down socket and restarting...");
            shutdown(get_fd, 0);
            close(get_fd);
        }
    }


    free_task:

    if (get_fd != -1)
    {
        shutdown(get_fd, 0);
        close(get_fd);
        get_fd = -1;
    }

    xEventGroupSetBits(wifi_event_group_check,TCP_TASK_FREE_BIT);

    vTaskDelete(NULL);
}

5 演示效果
6 总结

我们可以自己实现一套固件升级的协议,也可用通用的文件传输协议(例如ymodem),通过串口把固件分包再转发给其他MCU,实现具体产品的固件升级,通过无线来升级固件是非常方便的,可以节省拆卸外壳的时间,减少维护成本

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分