From 30691e90ce433c2dae325bf72f99ed7466974ffe Mon Sep 17 00:00:00 2001 From: PrincessPi3 Date: Mon, 10 Jun 2024 18:23:54 -0600 Subject: [PATCH] initial fork update --- CMakeLists.txt | 3 +- LICENSE | 2 +- README.md | 32 ++++++++++++ csv/index.html | 79 ++++++++++++++++++++++++++++++ flask/can.py | 2 +- main/Kconfig.projbuild | 12 ++--- main/http_post.c | 2 +- main/http_server.c | 75 +++++++++++++++++++++++----- main/init_malloci.h | 8 +++ main/main.c | 44 +++++++++++++++-- main/twai.c | 64 +++++++++++++++++++----- partitions.csv | 4 +- powershell_helpers/ESPPORT.ps1 | 1 + powershell_helpers/build.ps1 | 3 ++ powershell_helpers/reset_clean.ps1 | 20 ++++++++ sdkconfig.defaults | 33 ++++++++----- sdkconfig.defaults.non-debug | 23 +++++++++ 17 files changed, 354 insertions(+), 53 deletions(-) create mode 100644 csv/index.html create mode 100644 main/init_malloci.h create mode 100644 powershell_helpers/ESPPORT.ps1 create mode 100644 powershell_helpers/build.ps1 create mode 100644 powershell_helpers/reset_clean.ps1 create mode 100644 sdkconfig.defaults.non-debug diff --git a/CMakeLists.txt b/CMakeLists.txt index 114213b..612709f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,7 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(can2http) -# Create a SPIFFS image from the contents of the 'font' directory -# that fits the partition named 'storage'. FLASH_IN_PROJECT indicates that +# Create a SPIFFS image from the contents of the 'csv' FLASH_IN_PROJECT indicates that # the generated image should be flashed when the entire project is flashed to # the target with 'idf.py -p PORT flash spiffs_create_partition_image(storage csv FLASH_IN_PROJECT) diff --git a/LICENSE b/LICENSE index 988896a..3d55d6b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 nopnop2002 +Copyright (c) 2024 PrincessPi3 and nopnop2002 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 09db1d4..30f5914 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,35 @@ +# Sillyfilly-CAN +A fork of [esp-idf-can2http](https://github.com/nopnop2002/esp-idf-can2http) + +A CAN bus tool built for the esp32. It has a builtin web interface and works with nearly any CAN transceiver like the [N65HVD230](https://www.amazon.com/SN65HVD230-CAN-Board-Communication-Development/dp/B00KM6XMXO/) or the [TJA1050](https://www.amazon.com/Comimark-Transceiver-TJA1050-Controller-Schnittstelle/dp/B07W4VZ2F2/) + +## Hardware needed +* esp32(-X) (My favorite esp32)[https://www.amazon.com/Espressif-ESP32-S3-DevKitC-1-N32R8V-Development-Board/dp/B09R4GSDJM] +* CAN transceiver like the [N65HVD230](https://www.amazon.com/SN65HVD230-CAN-Board-Communication-Development/dp/B00KM6XMXO/) or the [TJA1050](https://www.amazon.com/Comimark-Transceiver-TJA1050-Controller-Schnittstelle/dp/B07W4VZ2F2/) +some jumper wires +* Jumper wires + +## Optional +* [ODB2 pigtail](https://www.amazon.com/iKKEGOL-Connector-Diagnostic-Extension-Pigtail/dp/B0828YHWFG/) + +## Installation +1) install [esp-idf](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/index.html#installation) if not installed on your computer already +2) open esp-idf terminal +3) plug in your esp32 to computer via USB cable +4) Run these commands: +``` +git clone https://github.com/PrincessPi3/Sillyfilly-CAN.git +cd Sillyfilly-CAN +idf.py set-target esp32s3 # example idf.py set-target +idf.py menuconfig +``` +5) Under "Sillyfilly-CAN Configuration" set your settings like wifi and CRX and CTX pins. +6) Wire transceiver to the pins: CRX->RX, CTX-TX, GND->GND +7) run this command +```idf.py flash monitor # ctrl+] to exit monitor``` + can be one of 'esp32', 'esp32s2', 'esp32c3', 'esp32s3', 'esp32c2', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5', 'esp32c61' + +# Original README.md # esp-idf-can2http CANbus to http bridge using esp32. It's purpose is to be a bridge between a CAN-Bus and a HTTP-Server. diff --git a/csv/index.html b/csv/index.html new file mode 100644 index 0000000..06686de --- /dev/null +++ b/csv/index.html @@ -0,0 +1,79 @@ +

Sillyfilly CAN Interface

+
+
+ + +
+
+
+ +
+ + +
+
+ + +
+ +

TX

+
none yet
+

RX

+
none yet
+
+ + \ No newline at end of file diff --git a/flask/can.py b/flask/can.py index 2343465..184cbf1 100644 --- a/flask/can.py +++ b/flask/can.py @@ -76,5 +76,5 @@ if __name__ == "__main__": print("lines={}".format(args.lines)) app.config['lines'] = args.lines #app.run() - app.run(host='0.0.0.0', port=args.port, debug=True) + app.run(host='127.0.0.1', port=args.port, debug=True) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 8c8f195..1ceef57 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -1,4 +1,4 @@ -menu "Application Configuration" +menu "Sillyfilly-CAN Configuration" config GPIO_RANGE_MAX int @@ -73,7 +73,7 @@ menu "Application Configuration" config ENABLE_PRINT bool "Output the received CAN FRAME to STDOUT" - default y + default true help Output the received CAN FRAME to STDOUT. @@ -83,13 +83,13 @@ menu "Application Configuration" config ESP_WIFI_SSID string "WiFi SSID" - default "myssid" + default "wifi-name" help SSID (network name) to connect to. config ESP_WIFI_PASSWORD string "WiFi Password" - default "mypassword" + default "wifi-password" help WiFi password (WPA or WPA2) to connect to. @@ -101,7 +101,7 @@ menu "Application Configuration" config MDNS_HOSTNAME string "mDNS Hostname" - default "esp32-server" + default "esp32-can-server" help The mDNS host name used by the ESP32. @@ -138,7 +138,7 @@ menu "Application Configuration" config WEB_SERVER string "HTTP Server IP or mDNS" - default "http-server.local" + default "esp32-can-server" help The host name or IP address of the HTTP server to use. diff --git a/main/http_post.c b/main/http_post.c index cbafebf..f58360e 100644 --- a/main/http_post.c +++ b/main/http_post.c @@ -91,7 +91,7 @@ esp_err_t _http_event_handler(esp_http_client_event_t *evt) ESP_LOGI(TAG, "Last esp error code: 0x%x", err); ESP_LOGI(TAG, "Last mbedtls failure: 0x%x", mbedtls_err); } - break; + break; #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) case HTTP_EVENT_REDIRECT: ESP_LOGD(TAG, "HTTP_EVENT_REDIRECT"); diff --git a/main/http_server.c b/main/http_server.c index 209cdc8..19ea387 100644 --- a/main/http_server.c +++ b/main/http_server.c @@ -8,6 +8,7 @@ */ #include +#include #include #include @@ -23,36 +24,79 @@ #include "esp_chip_info.h" #include "cJSON.h" #include "driver/twai.h" - #include "twai.h" -static const char *TAG = "SERVER"; -//static SemaphoreHandle_t ctrl_task_sem; +#define SCRATCH_BUFSIZE (1024) + +#define TAG "HTTP_SERVER" + +int pointer = 0; +static char *base_path = "/spiffs"; extern QueueHandle_t xQueue_twai_tx; - -#define SCRATCH_BUFSIZE (1024) +extern char* twai_string_buf; +extern int twai_allocation_size; +extern char* file_read_buf; +extern int allocation_size; 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; +esp_err_t readFile(char *ifile) { + int c; + ESP_LOGI(TAG, "File read llocated memory confirmed!: %d bytes", allocation_size); + char *spiffspath = "/spiffs"; + int buflen = strlen(spiffspath)+strlen(ifile)+1; + char buf[buflen]; + snprintf(buf, sizeof(buf), "%s%s", spiffspath, ifile); + ESP_LOGI(TAG, "buflen: %d, spiffspath: %s, ifile: %s, buf: %s, base_path: %s",buflen,spiffspath,ifile,buf,base_path); + FILE* f = fopen(buf, "r"); + ESP_LOGI(TAG, "Begin reading file"); + int i = 0; + while ((c = fgetc(f)) != EOF) { + file_read_buf[i] = c; + i++; + }; + file_read_buf[i] = '\0'; + fclose(f); + ESP_LOGI(TAG, "Read File - Iterations: %d", i); + return ESP_OK; +} /* Handler for roor get handler */ -static esp_err_t root_get_handler(httpd_req_t *req) +esp_err_t root_get_handler(httpd_req_t *req) { ESP_LOGI(TAG, "root_get_handler req->uri=[%s]", req->uri); + readFile("/index.html"); + esp_err_t sendcheck = httpd_resp_send(req, file_read_buf, HTTPD_RESP_USE_STRLEN); + //httpd_resp_sendstr_chunk(req, NULL); - /* Send empty chunk to signal HTTP response completion */ - httpd_resp_sendstr_chunk(req, NULL); - + if(sendcheck == ESP_OK) { + //free(file_read_buf); + memset(twai_string_buf, '\0', allocation_size); + ESP_LOGI(TAG, "malloc freed"); + return ESP_OK; + } else { + return ESP_ERR_HTTPD_RESP_SEND; + } return ESP_OK; } +static esp_err_t twai_read_handler(httpd_req_t *req) +{ + httpd_resp_sendstr(req, twai_string_buf); + // Buffers returned by cJSON_Print must be freed by the caller. + // Please use the proper API (cJSON_free) rather than directly + //twai_string_buf = {0}; + memset(twai_string_buf, '\0', twai_allocation_size); + return ESP_OK; +} + /* Handler for getting system information handler */ -// curl 'http://esp32-server.local:8000/api/system/info' | python -m json.tool +// curl 'http://esp32-can-server: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); @@ -225,7 +269,7 @@ static esp_err_t twai_send_handler(httpd_req_t *req) if (xQueueSend(xQueue_twai_tx, &tx_msg, portMAX_DELAY) != pdPASS) { ESP_LOGE(TAG, "xQueueSend Fail"); } - httpd_resp_sendstr(req, "twai send successfully"); + httpd_resp_sendstr(req, "CAN tx sent successfully"); } else { ESP_LOGE(TAG, "Request parameter not correct"); httpd_resp_sendstr(req, "Request parameter not correct"); @@ -284,6 +328,15 @@ esp_err_t start_server(const char *base_path, int port) }; httpd_register_uri_handler(server, &twai_send_post_uri); + /* URI handler for send twai */ + httpd_uri_t twai_read = { + .uri = "/api/twai/read", + .method = HTTP_GET, + .handler = twai_read_handler, + //.user_ctx = rest_context + }; + httpd_register_uri_handler(server, &twai_read); + return ESP_OK; } diff --git a/main/init_malloci.h b/main/init_malloci.h new file mode 100644 index 0000000..7f517e7 --- /dev/null +++ b/main/init_malloci.h @@ -0,0 +1,8 @@ +#define MAX_FILE_SIZE_KB 10 +#define MAX_TWAI_SIZE_KB 5 +#define MALLOCHI_TAG "INIT_MALLOCHI" + +char* file_read_buf; +char* twai_string_buf; +int allocation_size; +int twai_allocation_size; \ No newline at end of file diff --git a/main/main.c b/main/main.c index be295b7..6a63b02 100644 --- a/main/main.c +++ b/main/main.c @@ -27,9 +27,8 @@ #include "mdns.h" #include "lwip/dns.h" #include "driver/twai.h" // Update from V4.2 - #include "twai.h" - +#include "init_malloci.h" #define TAG "MAIN" static const twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); @@ -70,6 +69,7 @@ static EventGroupHandle_t s_wifi_event_group; #define WIFI_FAIL_BIT BIT1 static int s_retry_num = 0; +static char *base_path = "/spiffs"; QueueHandle_t xQueue_http_client; QueueHandle_t xQueue_twai_tx; @@ -77,6 +77,9 @@ QueueHandle_t xQueue_twai_tx; TOPIC_t *publish; int16_t npublish; +//extern char* twai_string_buf; +//extern esp_err_t init_twai_read_malloc(); + static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { @@ -204,10 +207,9 @@ esp_err_t mountSPIFFS(char * partition_label, char * base_path) { esp_vfs_spiffs_conf_t conf = { .base_path = base_path, .partition_label = partition_label, - .max_files = 5, + .max_files = 4, .format_if_mount_failed = true }; - // Use settings defined above to initialize and mount SPIFFS filesystem. // Note: esp_vfs_spiffs_register is an all-in-one convenience function. esp_err_t ret = esp_vfs_spiffs_register(&conf); @@ -242,6 +244,7 @@ esp_err_t mountSPIFFS(char * partition_label, char * base_path) { return ret; } + esp_err_t build_table(TOPIC_t **topics, char *file, int16_t *ntopic) { ESP_LOGI(TAG, "build_table file=%s", file); @@ -354,6 +357,35 @@ void dump_table(TOPIC_t *topics, int16_t ntopic) } +esp_err_t init_file_malloc() { + allocation_size = (MAX_FILE_SIZE_KB*1024*sizeof(char)); + file_read_buf = (char*)malloc(allocation_size); + + if (file_read_buf == NULL) { + ESP_LOGE(MALLOCHI_TAG, "File read memory not allocated."); + return ESP_FAIL; + } else { + ESP_LOGI(MALLOCHI_TAG, "File read malloc succeeded! %d bytes allocated", allocation_size); + return ESP_OK; + } + + return ESP_OK; +} + +esp_err_t init_twai_read_malloc() { + twai_allocation_size = (sizeof(char)*1024*MAX_TWAI_SIZE_KB); + twai_string_buf = (char*)malloc(twai_allocation_size); + + if (twai_string_buf == NULL) { + ESP_LOGE(MALLOCHI_TAG, "TWAI memory not allocated."); + return ESP_FAIL; + } else { + ESP_LOGI(MALLOCHI_TAG, "TWAI malloc succeeded! %d bytes allocated", twai_allocation_size); + return ESP_OK; + } + return ESP_OK; +} + void http_client_task(void *pvParameters); void http_server_task(void *pvParameters); void twai_task(void *pvParameters); @@ -371,6 +403,8 @@ void app_main() ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); wifi_init_sta(); initialise_mdns(); + init_twai_read_malloc(); + init_file_malloc(); // Install and start TWAI driver ESP_LOGI(TAG, "%s",BITRATE); @@ -385,7 +419,7 @@ void app_main() // Mount SPIFFS char *partition_label = "storage"; - char *base_path = "/spiffs"; + //char *base_path = "/spiffs"; ret = mountSPIFFS(partition_label, base_path); if (ret != ESP_OK) { ESP_LOGE(TAG, "mountSPIFFS fail"); diff --git a/main/twai.c b/main/twai.c index 894ee3b..c71990d 100644 --- a/main/twai.c +++ b/main/twai.c @@ -18,8 +18,9 @@ #include "esp_err.h" #include "esp_log.h" #include "driver/twai.h" // Update from V4.2 - #include "twai.h" +#include "cJSON.h" +//#include "init_malloci.h" static const char *TAG = "TWAI"; @@ -28,6 +29,10 @@ extern QueueHandle_t xQueue_twai_tx; extern TOPIC_t *publish; extern int16_t npublish; +int str_iterator = 0; +extern char* twai_string_buf; + +//extern esp_err_t init_twai_read_malloc(); void dump_table(TOPIC_t *topics, int16_t ntopic); @@ -35,10 +40,14 @@ void twai_task(void *pvParameters) { ESP_LOGI(TAG,"task start"); dump_table(publish, npublish); - twai_message_t rx_msg; twai_message_t tx_msg; FRAME_t frameBuf; + char* ftype; + //char* fdata = (char*)malloc(32*sizeof(char)); + //int iterator = 0; + char flags[4]; + char identifier[4]; while (1) { esp_err_t ret = twai_receive(&rx_msg, pdMS_TO_TICKS(10)); if (ret == ESP_OK) { @@ -51,22 +60,55 @@ void twai_task(void *pvParameters) #if CONFIG_ENABLE_PRINT if (ext == STANDARD_FRAME) { - printf("Standard ID: 0x%03"PRIx32" ", rx_msg.identifier); + printf("Standard ID: 0x%03"PRIx32, rx_msg.identifier); } else { printf("Extended ID: 0x%08"PRIx32, rx_msg.identifier); } printf(" DLC: %d Data: ", rx_msg.data_length_code); - if (rtr == 0) { - for (int i = 0; i < rx_msg.data_length_code; i++) { - printf("0x%02x ", rx_msg.data[i]); - } - } else { - printf("REMOTE REQUEST FRAME"); - - } printf("\n"); #endif +// JSON fun fun fun output for da api + if (ext == STANDARD_FRAME) { + ftype = "STANDARD_FRAME"; + } else { + ftype = "EXTENDED_FRAME"; + } + + cJSON *twai_root = cJSON_CreateObject(); + + int charslen_each = 6; + int data_len_chars = rx_msg.data_length_code*charslen_each; + char tmp_buf[charslen_each+2]; + char fdata[data_len_chars]; + + if (rx_msg.data_length_code != 0) { + for (int i = 0; i < rx_msg.data_length_code; i++) { + snprintf(tmp_buf, charslen_each, "0x%02x ",rx_msg.data[i]); + strcat(fdata, tmp_buf); + } + fdata[strlen(fdata)-1] = '\0'; + cJSON_AddStringToObject(twai_root, "data", fdata); + } + snprintf(flags, sizeof(rx_msg.flags), "0x%"PRIx32, rx_msg.flags); + snprintf(identifier, sizeof(rx_msg.identifier), "0x%"PRIx32, rx_msg.identifier); + + cJSON_AddStringToObject(twai_root, "type", ftype); + cJSON_AddStringToObject(twai_root, "id", identifier); + cJSON_AddStringToObject(twai_root, "flags", flags); + cJSON_AddNumberToObject(twai_root, "ext", ext); + cJSON_AddNumberToObject(twai_root, "rtr", rtr); + cJSON_AddNumberToObject(twai_root, "dlc",rx_msg.data_length_code); + + char *string = cJSON_Print(twai_root); + char br[] = "
\n"; + + strcat(twai_string_buf,string); + strcat(twai_string_buf,br); + + cJSON_free(string); + cJSON_Delete(twai_root); +// end json buffer funssss for(int index=0;index