You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
334 lines
9.7 KiB
334 lines
9.7 KiB
// #include "storage.h" |
|
#include "esp_log.h" |
|
#include "esp_vfs.h" |
|
#include "esp_vfs_fat.h" |
|
#include "jsmn.h" |
|
#include "esp_lan.h" |
|
|
|
static const char *TAG = "storage"; |
|
const char *base_path = "/storage"; |
|
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE; |
|
|
|
typedef struct |
|
{ |
|
char *client_config; |
|
char *controller_config; |
|
} load_config; |
|
|
|
typedef struct |
|
{ |
|
bool debug; |
|
uint16_t log_level; |
|
struct network_config *network; |
|
} main_config; |
|
|
|
// allocates memory! free space after use! |
|
static char *read_file(char *host_filename) |
|
{ |
|
ESP_LOGI(TAG, "Reading file"); |
|
FILE *f; |
|
char *fileContent; |
|
f = fopen(host_filename, "rb"); |
|
if (f == NULL) |
|
{ |
|
ESP_LOGE(TAG, "Failed to open file for reading"); |
|
return NULL; |
|
} |
|
size_t result; |
|
fseek(f, 0, SEEK_END); |
|
int fileSize = ftell(f); |
|
rewind(f); |
|
ESP_LOGI(TAG, "fileSize: %i\n", fileSize); |
|
fileContent = (char *)malloc(sizeof(char) * fileSize + 1); |
|
if (fileContent == NULL) |
|
{ |
|
ESP_LOGE(TAG, "Memory error"); |
|
return NULL; |
|
} |
|
result = fread(fileContent, 1, fileSize, f); |
|
if (result != fileSize) |
|
{ |
|
ESP_LOGE(TAG, "Reading error"); |
|
free(fileContent); |
|
return NULL; |
|
} |
|
fileContent[fileSize] = '\0'; |
|
fclose(f); |
|
return fileContent; |
|
}; |
|
|
|
static int jsoneq(const char *json, jsmntok_t *tok, const char *s) |
|
{ |
|
if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && |
|
strncmp(json + tok->start, s, tok->end - tok->start) == 0) |
|
{ |
|
return 0; |
|
} |
|
return -1; |
|
} |
|
|
|
void parse_trst_config(main_config *cfg, char *fileContent) |
|
{ |
|
int i; |
|
int r; |
|
jsmn_parser p; |
|
jsmntok_t t[256]; /* We expect no more than 128 tokens */ |
|
|
|
jsmn_init(&p); |
|
// should be end at \0 so set max file size to not having to count |
|
r = jsmn_parse(&p, fileContent, 8192, t, |
|
sizeof(t) / sizeof(t[0])); |
|
if (r < 0) |
|
{ |
|
printf("Failed to parse JSON: %d\n", r); |
|
return; |
|
} |
|
|
|
/* Assume the top-level element is an object */ |
|
if (r < 1 || t[0].type != JSMN_OBJECT) |
|
{ |
|
printf("Object expected\n"); |
|
return; |
|
} |
|
|
|
/* Loop over all keys of the root object */ |
|
for (i = 1; i < r; i++) |
|
{ |
|
if (jsoneq(fileContent, &t[i], "user") == 0) |
|
{ |
|
/* We may use strndup() to fetch string value */ |
|
printf("- User: %.*s\n", t[i + 1].end - t[i + 1].start, |
|
fileContent + t[i + 1].start); |
|
i++; |
|
} |
|
else if (jsoneq(fileContent, &t[i], "admin") == 0) |
|
{ |
|
/* We may additionally check if the value is either "true" or "false" */ |
|
printf("- Admin: %.*s\n", t[i + 1].end - t[i + 1].start, |
|
fileContent + t[i + 1].start); |
|
i++; |
|
} |
|
else if (jsoneq(fileContent, &t[i], "debug") == 0) |
|
{ |
|
|
|
/* We may additionally check if the value is either "true" or "false" */ |
|
printf("-debug: %.*s\n", t[i + 1].end - t[i + 1].start, |
|
fileContent + t[i + 1].start); |
|
i++; |
|
} |
|
else if (jsoneq(fileContent, &t[i], "uid") == 0) |
|
{ |
|
/* We may want to do strtol() here to get numeric value */ |
|
printf("- UID: %.*s\n", t[i + 1].end - t[i + 1].start, |
|
fileContent + t[i + 1].start); |
|
i++; |
|
} |
|
else if (jsoneq(fileContent, &t[i], "groups") == 0) |
|
{ |
|
int j; |
|
printf("- Groups:\n"); |
|
if (t[i + 1].type != JSMN_ARRAY) |
|
{ |
|
continue; /* We expect groups to be an array of strings */ |
|
} |
|
for (j = 0; j < t[i + 1].size; j++) |
|
{ |
|
jsmntok_t *g = &t[i + j + 2]; |
|
printf(" * %.*s\n", g->end - g->start, fileContent + g->start); |
|
} |
|
i += t[i + 1].size + 1; |
|
} |
|
else |
|
{ |
|
printf("Unexpected key%i: %.*s\n", i, t[i].end - t[i].start, |
|
fileContent + t[i].start); |
|
} |
|
} |
|
} |
|
|
|
char* parse_string(jsmntok_t *token,char* fileContent){ |
|
uint16_t size = (token->end - token->start); |
|
char* value = malloc(size+1); |
|
strncpy(value, fileContent + token->start, size); |
|
value[size] = '\0'; |
|
return value; |
|
} |
|
|
|
bool parse_bool(jsmntok_t *token,char* fileContent){ |
|
if(fileContent[token->start] == 't'){ |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
uint16_t parse_int(jsmntok_t *token,char* fileContent){ |
|
// uint16_t size = (token.end - token.start); |
|
return atoi(fileContent + token->start); |
|
} |
|
|
|
int parse_eth_config(lan_eth_config *cfg,jsmntok_t *token, char *fileContent){ |
|
ESP_LOGI(TAG, "t->start:(%d),t->end:(%d),t->size:(%d)", token->start, token->end, token->size); |
|
return NULL; |
|
} |
|
|
|
int parse_network_config(network_config *cfg,jsmntok_t *token, char *fileContent){// add pos? |
|
ESP_LOGI(TAG, "t->start:(%d),t->end:(%d),t->size:(%d)", token->start, token->end, token->size); |
|
int stringPos = token->start; |
|
int tokenPos = 1; |
|
while(stringPos < token->end){ |
|
ESP_LOGI(TAG, "stringPos:(%d),tokenPos:(%d)", stringPos, tokenPos); |
|
if (jsoneq(fileContent, &token[tokenPos], "debug") == 0){ |
|
|
|
stringPos = token[tokenPos].end; |
|
tokenPos++; |
|
} else |
|
{ |
|
stringPos = token[tokenPos].end; |
|
printf("Unexpected nc key%i: %.*s\n", tokenPos, token[tokenPos].end - token[tokenPos].start, |
|
fileContent + token[tokenPos].start); |
|
tokenPos++; |
|
} |
|
ESP_LOGI(TAG, "stringPos(%d)",stringPos); |
|
}; |
|
return tokenPos+1; |
|
} |
|
|
|
void parse_main_config(main_config *cfg, char *fileContent) |
|
{ |
|
int i; |
|
int r; |
|
jsmn_parser p; |
|
jsmntok_t t[256]; /* We expect no more than 256 tokens */ |
|
|
|
jsmn_init(&p); |
|
// should be end at \0 so set max file size to not having to count |
|
r = jsmn_parse(&p, fileContent, 8192, t, |
|
sizeof(t) / sizeof(t[0])); |
|
if (r < 0) |
|
{ |
|
printf("Failed to parse JSON: %d\n", r); |
|
return; |
|
} |
|
|
|
/* Assume the top-level element is an object */ |
|
if (r < 1 || t[0].type != JSMN_OBJECT) |
|
{ |
|
printf("Object expected\n"); |
|
return; |
|
} |
|
|
|
/* Loop over all keys of the root object */ |
|
for (i = 1; i < r; i++) |
|
{ |
|
if (jsoneq(fileContent, &t[i], "debug") == 0) |
|
{ |
|
cfg->debug = parse_bool(&t[i + 1],fileContent); |
|
i++; |
|
} |
|
else if (jsoneq(fileContent, &t[i], "log_level") == 0) |
|
{ |
|
cfg->log_level = parse_int(&t[i + 1],fileContent); |
|
i++; |
|
} |
|
else if (jsoneq(fileContent, &t[i], "network") == 0) |
|
{ |
|
if(t[i+1].type == JSMN_OBJECT){ |
|
cfg->network = malloc(sizeof(network_config)); |
|
int size = parse_network_config(cfg->network, &t[i+1],fileContent); |
|
i = i+size; |
|
} else { |
|
// error |
|
} |
|
} |
|
else |
|
{ |
|
printf("Unexpected key%i: %.*s\n", i, t[i].end - t[i].start, |
|
fileContent + t[i].start); |
|
} |
|
} |
|
} |
|
|
|
void parse_load_config(load_config *cfg, char *fileContent) |
|
{ |
|
int i; |
|
int r; |
|
jsmn_parser p; |
|
jsmntok_t t[32]; /* We expect no more than 128 tokens */ |
|
|
|
jsmn_init(&p); |
|
// should be end at \0 so set max file size to not having to count |
|
r = jsmn_parse(&p, fileContent, 8192, t, |
|
sizeof(t) / sizeof(t[0])); |
|
if (r < 0) |
|
{ |
|
printf("Failed to parse JSON: %d\n", r); |
|
return; |
|
} |
|
|
|
/* Assume the top-level element is an object */ |
|
if (r < 1 || t[0].type != JSMN_OBJECT) |
|
{ |
|
printf("Object expected\n"); |
|
return; |
|
} |
|
|
|
/* Loop over all keys of the root object */ |
|
for (i = 1; i < r; i++) |
|
{ |
|
if (jsoneq(fileContent, &t[i], "client_config") == 0) |
|
{ |
|
printf("parse_string client_config\n"); |
|
cfg->client_config = parse_string(&t[i+1],fileContent); |
|
i++; |
|
} |
|
else if (jsoneq(fileContent, &t[i], "controller_config") == 0) |
|
{ |
|
cfg->controller_config = parse_string(&t[i+1],fileContent); |
|
i++; |
|
} |
|
else |
|
{ |
|
printf("Unexpected key%i: %.*s\n", i, t[i].end - t[i].start, |
|
fileContent + t[i].start); |
|
} |
|
} |
|
} |
|
|
|
main_config *init_config() |
|
{ |
|
ESP_LOGI(TAG, "init_config:"); |
|
// main_config *l_cfg = load_load_config("/storage/load.cfg.json"); |
|
ESP_LOGI(TAG, "Mounting FAT filesystem"); |
|
// To mount device we need name of device partition, define base_path |
|
// and allow format partition in case if it is new one and was not formatted before |
|
const esp_vfs_fat_mount_config_t mount_config = { |
|
.format_if_mount_failed = false, |
|
.max_files = 4, |
|
.allocation_unit_size = 512, |
|
.disk_status_check_enable = false}; |
|
esp_err_t err; |
|
|
|
err = esp_vfs_fat_spiflash_mount_rw_wl(base_path, "storage", &mount_config, &s_wl_handle); |
|
|
|
if (err != ESP_OK) |
|
{ |
|
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err)); |
|
return NULL; |
|
} |
|
char *fileContent = read_file("/storage/load.cfg.json"); |
|
load_config *load_cfg = malloc(sizeof(load_config)); |
|
parse_load_config(load_cfg, fileContent); |
|
free(fileContent); |
|
|
|
ESP_LOGI(TAG, "controller_config:(%s),client_config:(%s)", load_cfg->controller_config, load_cfg->client_config); |
|
|
|
fileContent = read_file(load_cfg->controller_config); |
|
main_config *main_cfg = malloc(sizeof(main_config)); |
|
parse_main_config(main_cfg, fileContent); |
|
free(fileContent); |
|
ESP_LOGI(TAG, "main_cfg->debug:(%d)", main_cfg->debug); |
|
|
|
ESP_ERROR_CHECK(esp_vfs_fat_spiflash_unmount_rw_wl(base_path, s_wl_handle)); |
|
return main_cfg; |
|
}
|
|
|