基于ESP32 IDF的WebServer实现以及OTA固件升级实现记录(二)

iot-lorawan 2024-07-18 10:33:02 阅读 74

        续上文大体描述了官网webserver demo的运行步骤运行效果以及部分配置需要注意的外开始继续大体讲解下官网webserver的代码实现,方便接下来可以基于官方demo代码进行改造成自己的webserver。

        官方的demo如下

           整体还是比较简洁,一个main用来挂载分区,启动httpserver,即作为webserver用,代码的主要内容基本不用改可以直接用。另一个rest_server.c就是主要的restful api的各接口的业务代码实现。

<code>esp_err_t start_rest_server(const char *base_path)

{

REST_CHECK(base_path, "wrong base path", err);

rest_server_context_t *rest_context = calloc(1, sizeof(rest_server_context_t));

REST_CHECK(rest_context, "No memory for rest context", err);

strlcpy(rest_context->base_path, base_path, sizeof(rest_context->base_path));

httpd_handle_t server = NULL;

httpd_config_t config = HTTPD_DEFAULT_CONFIG();

config.uri_match_fn = httpd_uri_match_wildcard;

ESP_LOGI(REST_TAG, "Starting HTTP Server");

REST_CHECK(httpd_start(&server, &config) == ESP_OK, "Start server failed", err_start);

/* URI handler for fetching system info */

httpd_uri_t system_info_get_uri = {

.uri = "/api/v1/system/info",

.method = HTTP_GET,

.handler = system_info_get_handler,

.user_ctx = rest_context

};

httpd_register_uri_handler(server, &system_info_get_uri);

/* URI handler for fetching temperature data */

httpd_uri_t temperature_data_get_uri = {

.uri = "/api/v1/temp/raw",

.method = HTTP_GET,

.handler = temperature_data_get_handler,

.user_ctx = rest_context

};

httpd_register_uri_handler(server, &temperature_data_get_uri);

/* URI handler for light brightness control */

httpd_uri_t light_brightness_post_uri = {

.uri = "/api/v1/light/brightness",

.method = HTTP_POST,

.handler = light_brightness_post_handler,

.user_ctx = rest_context

};

httpd_register_uri_handler(server, &light_brightness_post_uri);

/* URI handler for getting web server files */

httpd_uri_t common_get_uri = {

.uri = "/*",

.method = HTTP_GET,

.handler = rest_common_get_handler,

.user_ctx = rest_context

};

httpd_register_uri_handler(server, &common_get_uri);

return ESP_OK;

err_start:

free(rest_context);

err:

return ESP_FAIL;

}

如上每个restful api都需要注册一个,api的http method按约定的接口进行,如get或者post

 /* URI handler for getting web server files */

    httpd_uri_t common_get_uri = {

        .uri = "/*",

        .method = HTTP_GET,

        .handler = rest_common_get_handler,

        .user_ctx = rest_context

    };

    httpd_register_uri_handler(server, &common_get_uri);

以调节rgb颜色的进行说明如下,亮度调节用post方法

    /* URI handler for light brightness control */

    httpd_uri_t light_brightness_post_uri = {

        .uri = "/api/v1/light/brightness",

        .method = HTTP_POST,

        .handler = light_brightness_post_handler,

        .user_ctx = rest_context

    };

    httpd_register_uri_handler(server, &light_brightness_post_uri);

对应的回调以及接受的json数据解析在回调里进行实现light_brightness_post_handler,

/* Simple handler for light brightness control */

static esp_err_t light_brightness_post_handler(httpd_req_t *req)

{

int total_len = req->content_len;

int cur_len = 0;

char *buf = ((rest_server_context_t *)(req->user_ctx))->scratch;

int received = 0;

if (total_len >= SCRATCH_BUFSIZE) {

/* Respond with 500 Internal Server Error */

httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "content too long");

return ESP_FAIL;

}

while (cur_len < total_len) {

received = httpd_req_recv(req, buf + cur_len, total_len);

if (received <= 0) {

/* Respond with 500 Internal Server Error */

httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to post control value");

return ESP_FAIL;

}

cur_len += received;

}

buf[total_len] = '\0';

cJSON *root = cJSON_Parse(buf);

int red = cJSON_GetObjectItem(root, "red")->valueint;

int green = cJSON_GetObjectItem(root, "green")->valueint;

int blue = cJSON_GetObjectItem(root, "blue")->valueint;

ESP_LOGI(REST_TAG, "Light control: red = %d, green = %d, blue = %d", red, green, blue);

cJSON_Delete(root);

httpd_resp_sendstr(req, "Post control value successfully");

return ESP_OK;

}

该代码提供了json数据的解析参考,同时参考代码里也有提供了json数据构造返回的参考。

实际基于官方sample来改造成适配自己使用的resetful接口的话基本就是修改如上的回调以及注册的restful api相关方法路径即可。

        官方demo大体代码了解后即可开始准备进行改造为自己的webserver,首先如果不用官方web前端demo页面的话可以自行替换为自己构建的web后台ui,web后台直接参考网上开源的,这里以vue前端为例,找到开源想用的web后台参考后基本就是npm install, npm run dev查看页面效果,npm run build打包dist。

本机运行web效果大体没问题后就可以直接构建dist部署文件,构建后把dist文件下的所有文件复制到restful_server\front\web-demo\dist目录下,idf build后烧录到esp32后确认可以访问并且效果和pc段的模拟效果一样。

        web前端效果没问题后前端路由的rest接口按自己约定的统一和esp32底层实现的restful接口一致,同时修改分区文件新增ota分区,用于让esp32支持ota升级功能。修改后支持ota升级以及支持web部署文件的分区表如下,

        在进行实际的web ota升级代码改造前先举例下要自行修改一个restful api接口的话需要如何修改,

        1、web端的restful api接口实现

                前端有比较好用的开源http库,这里以axios为例,如下为向url  /api/v1/staus请求数据,请求的数据拿到后web前端可以按实际数据进行页面渲染

<code> axios

.get('/api/v1/status')

.then(response => (this.data = response.data))

.catch(function (error) {

console.log(error);

});

        2、esp32嵌入式端的api接口实现

        注册restful api的底层交互实现,处理http get请求并按json格式返回

static esp_err_t system_info_get_handler(httpd_req_t *req)

{

httpd_resp_set_type(req, "application/json");

cJSON *root = cJSON_CreateObject();

cJSON *apObject = NULL;

cJSON *staObject = NULL;

apObject = cJSON_CreateObject();

if (apObject == NULL)

{

}

cJSON_AddItemToObject(root, "ap", apObject);

cJSON_AddStringToObject(apObject, "ssid", "11111");

cJSON_AddNumberToObject(apObject, "num", 1);

staObject = cJSON_CreateObject();

if (staObject == NULL)

{

}

cJSON_AddItemToObject(root, "sta", staObject);

cJSON_AddStringToObject(staObject, "ssid", "111111");

cJSON_AddStringToObject(staObject, "status", "connected");

const char *sys_info = cJSON_Print(root);

httpd_resp_sendstr(req, sys_info);

free((void *)sys_info);

cJSON_Delete(root);

return ESP_OK;

}

httpd_uri_t system_info_get_uri = {

.uri = "/api/v1/status",///api/v1/system/info",

.method = HTTP_GET,

.handler = system_info_get_handler,

.user_ctx = rest_context

};

httpd_register_uri_handler(server, &system_info_get_uri);

          大体了解前端web和esp32嵌入式后台的实际代码交互后下篇将描述最终的ota实现代码以及细节。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。