/* HTTP Server Example This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "freertos/semphr.h" #include "esp_log.h" #include "esp_err.h" #include "esp_vfs.h" #include "esp_spiffs.h" #include "esp_http_server.h" #include "cJSON.h" #include "driver/twai.h" #include "twai.h" static const char *TAG = "SERVER"; //static SemaphoreHandle_t ctrl_task_sem; extern QueueHandle_t xQueue_twai_tx; #define SCRATCH_BUFSIZE (1024) typedef struct rest_server_context { char base_path[ESP_VFS_PATH_MAX + 1]; // Not used in this project char scratch[SCRATCH_BUFSIZE]; } rest_server_context_t; /* Handler for roor get handler */ static esp_err_t root_get_handler(httpd_req_t *req) { ESP_LOGI(TAG, "root_get_handler req->uri=[%s]", req->uri); /* Send empty chunk to signal HTTP response completion */ httpd_resp_sendstr_chunk(req, NULL); return ESP_OK; } /* Handler for getting system information handler */ // curl 'http://esp32-server.local:8000/api/system/info' | python -m json.tool static esp_err_t system_info_get_handler(httpd_req_t *req) { ESP_LOGI(TAG, "system_info_get_handler req->uri=[%s]", req->uri); httpd_resp_set_type(req, "application/json"); cJSON *root = cJSON_CreateObject(); esp_chip_info_t chip_info; esp_chip_info(&chip_info); cJSON_AddStringToObject(root, "version", IDF_VER); cJSON_AddNumberToObject(root, "cores", chip_info.cores); //const char *sys_info = cJSON_Print(root); char *sys_info = cJSON_Print(root); httpd_resp_sendstr(req, sys_info); // Buffers returned by cJSON_Print must be freed by the caller. // Please use the proper API (cJSON_free) rather than directly calling stdlib free. cJSON_free(sys_info); cJSON_Delete(root); return ESP_OK; } // Create array cJSON *Create_array_of_anything(cJSON **objects,int array_num) { cJSON *prev = 0; cJSON *root; root = cJSON_CreateArray(); for (int i=0;ichild=objects[i]; } else { prev->next=objects[i]; objects[i]->prev=prev; } prev=objects[i]; } return root; } char *JSON_Types(int type) { if (type == cJSON_Invalid) return ("cJSON_Invalid"); if (type == cJSON_False) return ("cJSON_False"); if (type == cJSON_True) return ("cJSON_True"); if (type == cJSON_NULL) return ("cJSON_NULL"); if (type == cJSON_Number) return ("cJSON_Number"); if (type == cJSON_String) return ("cJSON_String"); if (type == cJSON_Array) return ("cJSON_Array"); if (type == cJSON_Object) return ("cJSON_Object"); if (type == cJSON_Raw) return ("cJSON_Raw"); return NULL; } /* Handler for twai send handler */ // curl -X POST -H "Content-Type: application/json" -d '{"canid": 513, "frame": "standard", "data": [11, 12, 13, 14]}' http://esp32-server.local:8000/api/twai/send static esp_err_t twai_send_handler(httpd_req_t *req) { ESP_LOGI(TAG, "twai_send_handler req->uri=[%s]", req->uri); 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'; ESP_LOGI(TAG, "buf=[%s]", buf); bool parse = true; cJSON *root = cJSON_Parse(buf); // Search canid item int32_t canid = 0; cJSON* state = cJSON_GetObjectItem(root, "canid"); if (state) { canid = cJSON_GetObjectItem(root, "canid")->valueint; ESP_LOGI(TAG, "canid=%x", canid); } else { ESP_LOGE(TAG, "canid item not found"); parse = false; } // Search frame item char frameStr[12]; uint16_t frame = 0; state = cJSON_GetObjectItem(root, "frame"); if (state) { strcpy(frameStr, cJSON_GetObjectItem(root,"frame")->valuestring); ESP_LOGI(TAG, "frameStr=[%s]", frameStr); if (strcmp(frameStr, "standard") != 0 && strcmp(frameStr, "extended") != 0 ) { ESP_LOGE(TAG, "frame item not correct"); parse = false; } else { if (strcmp(frameStr, "standard") == 0) frame = STANDARD_FRAME; if (strcmp(frameStr, "extended") == 0) frame = EXTENDED_FRAME; } } else { ESP_LOGE(TAG, "frame item not found"); parse = false; } // Search data item int16_t data_len; char data_value[8]; state = cJSON_GetObjectItem(root, "data"); if (state) { cJSON *data_array = cJSON_GetObjectItem(root,"data"); ESP_LOGI(TAG, "data_array->type=%s", JSON_Types(data_array->type)); if (data_array->type == cJSON_Array) { int data_array_size = cJSON_GetArraySize(data_array); ESP_LOGI(TAG, "data_array_size=%d", data_array_size); bool data_valid = true; data_len = data_array_size; for (int i=0;itype=%s", JSON_Types(array->type)); uint16_t data_int = array->valueint; ESP_LOGI(TAG, "data_int[%d]=%x", i, data_int); if (data_int <= 0xff) { data_value[i] = data_int; } else { ESP_LOGE(TAG, "data too large"); data_valid = false; } } // end for if (data_valid == false) { parse = false; } } else { ESP_LOGE(TAG, "data item not array"); parse = false; } // end if } else { ESP_LOGE(TAG, "data item not found"); parse = false; } cJSON_Delete(root); // JSON parse success. Send twai data. if (parse) { ESP_LOGI(TAG, "twai_send_handler frame=%d canid=%x data_len=%d", frame, canid, data_len); ESP_LOG_BUFFER_HEX(TAG, data_value, data_len); twai_message_t tx_msg; tx_msg.extd = frame; tx_msg.ss = 1; tx_msg.self = 0; tx_msg.dlc_non_comp = 0; tx_msg.identifier = canid; tx_msg.data_length_code = data_len; for (int i=0;i