• [技术干货] ESP32系列四:搭建http的webserver的服务器-转载
    最近在使用ESP32搭建web服务器测试,发现esp32搭建这类开发环境还是比较方便的。具体的http协议这里就不再赘述,我们主要说一下如何使用ESP32提供的API来搭建我们的http web。  一、web服务器搭建过程  1、配置web服务器  在ESP-IDF中,Web服务器使用httpd组件实现。我们需要先创建httpd_config_t结构体,指定服务器的端口、最大并发连接数、URI匹配处理器等选项。然后,我们通过调用httpd_start函数来启动Web服务器。(使用默认的配置就可以,包括端口号都已经默认配置好了)  httpd_config_t config = HTTPD_DEFAULT_CONFIG(); httpd_handle_t server = NULL;   // 设置服务器端口为80 config.server_port = 80;   // 创建HTTP服务器句柄 if (httpd_start(&server, &config) != ESP_OK) {     printf("Error starting server!\n");     return; }   2、 注册 URI处理器 在Web服务器启动后,我们需要为不同的URI注册处理器函数。当Web服务器接收到请求时,会根据请求的URI选择相应的处理器函数进行处理。在ESP-IDF中,我们可以使用httpd_register_uri_handler函数注册URI处理器。该函数的原型如下  esp_err_t httpd_register_uri_handler(httpd_handle_t hd, const httpd_uri_t *uri) 其中,hd参数为HTTP服务器句柄;uri参数为包含URI路径、HTTP方法、处理函数等信息的结构体指针。例如:  static const httpd_uri_t echo = {     .uri       = "/",     .method    = HTTP_POST,     .handler   = echo_post_handler,     .user_ctx  = NULL }; static esp_err_t echo_post_handler(httpd_req_t *req) {     char buf[100];     // char ssid[10];     // char pswd[10];     int ret, remaining = req->content_len;       while (remaining > 0) {         /* Read the data for the request */         if ((ret = httpd_req_recv(req, buf,                         MIN(remaining, sizeof(buf)))) <= 0) {             if (ret == HTTPD_SOCK_ERR_TIMEOUT) {                 /* Retry receiving if timeout occurred */                 continue;             }             return ESP_FAIL;         }           /* Send back the same data */         httpd_resp_send_chunk(req, buf, ret);         remaining -= ret;           esp_err_t e = httpd_query_key_value(buf,"ssid",wifi_name,sizeof(wifi_name));         if(e == ESP_OK) {             printf("ssid = %s\r\n",wifi_name);         }         else {             printf("error = %d\r\n",e);         }           e = httpd_query_key_value(buf,"password",wifi_password,sizeof(wifi_password));         if(e == ESP_OK) {             printf("pswd = %s\r\n",wifi_password);         }         else {             printf("error = %d\r\n",e);         }         /* Log data received */         ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");         ESP_LOGI(TAG, "%.*s", ret, buf);         ESP_LOGI(TAG, "====================================");     }       // End response     httpd_resp_send_chunk(req, NULL, 0);     if(strcmp(wifi_name ,"\0")!=0 && strcmp(wifi_password,"\0")!=0)     {         xSemaphoreGive(ap_sem);         ESP_LOGI(TAG, "set wifi name and password successfully! goto station mode");     }     return ESP_OK; } html的网页如下:这个网页包含了按钮的定义,以及发送json格式的数据。  最后送json数据的时候,要用JSON.stringify方法格式化data,否则esp32解析json会报错,此处一定要注意!!! 整体html界面非常简单,没有基础的也很容易读懂,里面写了一个js函数,该函数是在点击按钮的时候触发,功能主要是读取文本框输入的数据,将数据封装为json格式,然后post发送数据,xhttp.open(“POST”, “/wifi_data”, true);中的url “/wifi_data”和esp32服务端中的定义要一致,否则是无法成功的。  <!DOCTYPE html> <head>     <meta charset="utf-8">     <title>Web server system</title> </head> <table class="fixed" border="5">     <col width="1000px" /><col width="500px" />     <tr><td>         <h2 style=" text-align:center;"> **** Web Server ***</h2>             <h3>wifi 密码配置</h3>     <div>         <label for="name">wifi名称</label>         <input type="text" id="wifi" name="car_name" placeholder="ssid">         <br>         <label for="type">密码</label>         <input type="text" id="code" name="car_type" placeholder="password">         <br>         <button id ="send_WIFI" type="button" onclick="send_wifi()">提交</button>     </div>     </td><td>         <table border="10">             <tr>                 <td>                     <label for="newfile">Upload a file</label>                 </td>                 <td colspan="2">                     <input id="newfile" type="file" onchange="setpath()" style="width:100%;">                 </td>             </tr>             <tr>                 <td>                     <label for="filepath">Set path on server</label>                 </td>                 <td>                     <input id="filepath" type="text" style="width:100%;">                 </td>                 <td>                     <button id="upload" type="button" onclick="upload()">Upload</button>                 </td>             </tr>         </table>     </td></tr> </table> <script> function setpath() {     var default_path = document.getElementById("newfile").files[0].name;     document.getElementById("filepath").value = default_path; } function upload() {     var filePath = document.getElementById("filepath").value;     var upload_path = "/upload/" + filePath;     var fileInput = document.getElementById("newfile").files;       /* Max size of an individual file. Make sure this      * value is same as that set in file_server.c */     var MAX_FILE_SIZE = 200*1024;     var MAX_FILE_SIZE_STR = "200KB";       if (fileInput.length == 0) {         alert("No file selected!");     } else if (filePath.length == 0) {         alert("File path on server is not set!");     } else if (filePath.indexOf(' ') >= 0) {         alert("File path on server cannot have spaces!");     } else if (filePath[filePath.length-1] == '/') {         alert("File name not specified after path!");     } else if (fileInput[0].size > 200*1024) {         alert("File size must be less than 200KB!");     } else {         document.getElementById("newfile").disabled = true;         document.getElementById("filepath").disabled = true;         document.getElementById("upload").disabled = true;           var file = fileInput[0];         var xhttp = new XMLHttpRequest();         xhttp.onreadystatechange = function() {             if (xhttp.readyState == 4) {                 if (xhttp.status == 200) {                     document.open();                     document.write(xhttp.responseText);                     document.close();                 } else if (xhttp.status == 0) {                     alert("Server closed the connection abruptly!");                     location.reload()                 } else {                     alert(xhttp.status + " Error!\n" + xhttp.responseText);                     location.reload()                 }             }         };         xhttp.open("POST", upload_path, true);         xhttp.send(file);     } }   function send_wifi() {     var input_ssid = document.getElementById("wifi").value;     var input_code = document.getElementById("code").value;     var xhttp = new XMLHttpRequest();         xhttp.open("POST", "/wifi_data", true);         xhttp.onreadystatechange = function() {             if (xhttp.readyState == 4) {                 if (xhttp.status == 200) {                     console.log(xhttp.responseText);                 } else if (xhttp.status == 0) {                     alert("Server closed the connection abruptly!");                     location.reload()                 } else {                     alert(xhttp.status + " Error!\n" + xhttp.responseText);                     location.reload()                 }             }         };     var data = {         "wifi_name":input_ssid,         "wifi_code":input_code     }         xhttp.send(JSON.stringify(data)); }   </script> static esp_err_t html_default_get_handler(httpd_req_t *req) {     // /* Send HTML file header */     // httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");       /* Get handle to embedded file upload script */     extern const unsigned char upload_script_start[] asm("_binary_upload_script_html_start");     extern const unsigned char upload_script_end[] asm("_binary_upload_script_html_end");     const size_t upload_script_size = (upload_script_end - upload_script_start);       /* Add file upload form and script which on execution sends a POST request to /upload */     httpd_resp_send_chunk(req, (const char *)upload_script_start, upload_script_size);       /* Send remaining chunk of HTML file to complete it */     httpd_resp_sendstr_chunk(req, "</body></html> 
  • [问题求助] Cannot find module &apos;fgs-express&apos;
    FunctionGraph集成express,找不到fgs-express模块,看文档说是内置的模块
  • [技术干货] 华为云数据仓库服务-Express加速查询功能于2019年7月22日00:00(北京时间)转商通知
    尊敬的华为云客户::华为云计划于2019/7/22 00:00(北京时间)将数据仓库服务-Express加速查询功能转商。正式商用后,Express加速查询功能将于2019/07/22 00:00(北京时间)开始收费。数据仓库服务-Express价格30元/TB,按需计费,根据Express实际扫描的字节数收费所有DWS集群默认使用该功能,为了保障您的权益,在此建议您在服务正式商用后(2019/07/22 00:00),如果您需要继续Express查询加速功能,请前往服务产品页了解具体计费说明;如果您不再需要使用,请停止进行OBS外表查询,并与我们联系帮助您屏蔽Express功能,避免产生不必要的费用。更多关于数据仓库服务-Express的产品介绍,请您点击了解。如您有任何问题,可随时通过工单或者服务热线(950808)与我们联系。感谢您对华为云的支持!