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.
335 lines
9.7 KiB
335 lines
9.7 KiB
4 months ago
|
// #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;
|
||
|
}
|