Browse Source

Integrate the new sysvars package, replace using the environment

H. Peter Anvin 1 year ago
parent
commit
e0c50e4aa3

+ 12 - 0
esp32/max80/common.h

@@ -68,6 +68,18 @@ static inline no_return exit_task(void)
     }
 }
 
+/*
+ * Convert a NULL pointer string to ""
+ */
+static inline const char *notempty(const char *str)
+{
+    return str ? str : "";
+}
+static inline char *dupstr(const char *str)
+{
+    return strdup(notempty(str));
+}
+
 /*
  * Reboot system
  */

+ 25 - 172
esp32/max80/config.c

@@ -6,85 +6,8 @@
 
 #define CONFIG_FILE	"/spiffs/config.txt"
 
-struct env_var {
-    const char *var, *val;
-};
-static const struct env_var default_config[] = {
-    {"LANG","sv"},
-    {"TZ", "CET-1CEST,M3.5.0,M10.5.0/3"}, /* Sweden */
-    {"tzname", "Europe/Stockholm"},
-    {"hostname", "max80"},
-    {"mdns.enabled", "1"},
-    {"sntp.enabled", "1"},
-    {"sntp.server","time.max80.abc80.org"},
-    {"abc.hosttype","auto"}
-};
-
 static int save_config(void);
 
-static bool config_changed;
-int setenv_config(const char *name, const char *value)
-{
-    config_changed = true;
-    if (name[0] == '-') {
-	name++;
-	value = NULL;
-    }
-    return setenv_cond(name, value);
-}
-
-int setenv_cond(const char *name, const char *value)
-{
-    const char *pfx;
-    size_t skip;
-
-    if (!strncmp("status.", name, 7)) {
-	pfx = "STATUS";
-	skip = 7;
-    } else {
-	pfx = "CONFIG";
-	skip = 0;
-    }
-    logmsg(pfx, "%s <- %s\n", name+skip, value ? value : "(deleted)");
-
-    if (value)
-      return setenv(name, value, 1);
-    else
-      return unsetenv(name);
-}
-
-static void reset_config(void)
-{
-    while (1) {
-	char **envp;
-
-	for (envp = environ; *envp; envp++) {
-	    if (!strncmp("status.", *envp, 7))
-		continue;
-	    else
-		break;
-	}
-
-	if (!*envp)
-	    break;
-
-	const char *eq = strchr(*envp, '=');
-	if (!eq)
-	    continue;		/* This should never happen... */
-
-	char ename[eq - *envp + 1];
-	memcpy(ename, *envp, eq - *envp);
-	ename[eq - *envp] = '\0';
-
-	setenv_cond(ename, NULL);
-    }
-
-    size_t i;
-    for (i = 0; i < ARRAY_SIZE(default_config); i++)
-	setenv_cond(default_config[i].var, default_config[i].val);
-
-    config_changed = true;
-}
 
 static bool is_end_of_string(int c)
 {
@@ -124,7 +47,10 @@ static int set_config_string(char *str, unsigned int separator)
 	    return -EOVERFLOW;
 
 	q[-1] = '\0';
-	setenv_config(var, p);
+	size_t nvar = sysvar_find(sysvar_ns_config, var);
+	if (nvar) {
+	    setvar_fromstr(nvar, p);
+	}
 
 	p = q;
     } while (c == separator);
@@ -134,12 +60,13 @@ static int set_config_string(char *str, unsigned int separator)
 
 static void finish_config_update(bool save)
 {
-    if (config_changed) {
+    if (sysvar_changed < sysvar_ns[sysvar_ns_status].first) {
 	if (save)
 	    save_config();
-	tzset();
-	config_changed = false;
+
+	/* Can do other things here... */
     }
+    sysvar_changed = sysvar_count;
 }
 
 /*
@@ -197,14 +124,16 @@ exit:
     return err;
 };
 
-int write_env(FILE *f, bool status)
+int write_sysvars(FILE *f, bool status)
 {
-    size_t skip = status ? 7 : 0;
-    for (char **var = environ; *var; var++) {
-	if (!strncmp(*var, "status.", 7) == status) {
-		fputs(*var + skip, f);
-		putc('\n', f);
-	}
+    size_t ns = status ? sysvar_ns_status : sysvar_ns_config;
+    sysvar_ns_t nsi = sysvar_ns[ns];
+
+    for (size_t var = nsi.first; var < nsi.first + nsi.count; var++) {
+	fputs(sysvar_name[var], f);
+	putc('=', f);
+	fputs(notempty(getvar_tostr(var)), f);
+	putc('\n', f);
     }
 
     return ferror(f) ? -1 : 0;
@@ -216,7 +145,7 @@ static int save_config(void)
 
     FILE *f = fopen(CONFIG_FILE, "w");
     if (f) {
-	err = write_env(f, false);
+	err = write_sysvars(f, false);
 	fclose(f);
     }
 
@@ -243,7 +172,7 @@ void init_config(void)
 		   spiffs_conf.base_path, err);
     }
 
-    reset_config();
+    sysvar_reset();
 
     FILE *f = fopen(CONFIG_FILE, "r");
     if (!f)
@@ -254,90 +183,14 @@ void init_config(void)
 	fclose(f);
 }
 
-const char *getenv_def(const char *var, const char *def)
-{
-    const char *val = getenv(var);
-    return val ? val : def;
-}
-
-long getenv_l(const char *var, long def)
-{
-    const char *ep;
-
-    var = getenv(var);
-    if (!var || !*var)
-	return def;
-
-    long val = strtol(var, (char **)&ep, 0);
-    return *ep ? def : val;
-}
-
-void setenv_l(const char *var, long val)
-{
-    char vbuf[2+3*sizeof val];
-    snprintf(vbuf, sizeof vbuf, "%ld", val);
-    setenv_cond(var, vbuf);
-}
-
-unsigned long getenv_ul(const char *var, unsigned long def)
-{
-    const char *ep;
-
-    var = getenv(var);
-    if (!var || !*var)
-	return def;
-
-    unsigned long val = strtol(var, (char **)&ep, 0);
-    return *ep ? def : val;
-}
-
-void setenv_ul(const char *var, unsigned long val)
-{
-    char vbuf[2+3*sizeof val];
-    snprintf(vbuf, sizeof vbuf, "%lu", val);
-    setenv_cond(var, vbuf);
-}
-
-bool getenv_bool(const char *var)
-{
-    var = getenv(var);
-
-    if (!var)
-	return false;
-
-    unsigned char c = *var;
-    unsigned char cl = c | 0x20;
-
-    return !(!c || c == '0' || cl == 'f' || cl == 'n' || cl == 'd' ||
-	     (cl == 'o' && (var[1] | 0x20) == 'f'));
-}
-
-void setenv_bool(const char *var, bool val)
+void log_config_status(void)
 {
-    return setenv_ul(var, val);
-}
+    const sysvar_ns_t *nsi = &sysvar_ns[0];
 
-const char *getenv_notempty(const char *env)
-{
-    const char *str = getenv(env);
-    if (str && !*str)
-	str = NULL;
-    return str;
-}
+    for (size_t var = 1; var < (size_t)sysvar_count; var++) {
+	if (var >= nsi->first + nsi->count)
+	    nsi++;
 
-void log_config_status(void)
-{
-    const char *pfx;
-    size_t skip;
-
-    for (char **var = environ; *var; var++) {
-	if (!strncmp(*var, "status.", 7)) {
-	    pfx = "STATUS";
-	    skip = 7;
-	} else {
-	    pfx = "CONFIG";
-	    skip = 0;
-	}
-	logmsg(pfx, "%s\n", *var+skip);
+	logmsg(nsi->name, "%s\n", notempty(getvar_tostr(var)));
     }
 }

+ 2 - 12
esp32/max80/config.h

@@ -1,25 +1,15 @@
 #pragma once
 
 #include "common.h"
+#include "sysvars.h"
 
 #include <stdio.h>
 
 #define MAX_CONFIG_LINE 256
 
 extern_c int read_config(FILE *, bool save);
-extern_c int write_env(FILE *, bool status);
+extern_c int write_sysvars(FILE *, bool status);
 extern_c void init_config(void);
-
 extern_c int set_config_url_string(const char *str);
 
-extern_c int setenv_cond(const char *var, const char *val);
-extern_c int setenv_config(const char *var, const char *val);
-extern_c const char *getenv_def(const char *var, const char *def);
-extern_c long getenv_l(const char *var, long def);
-extern_c void setenv_l(const char *var, long val);
-extern_c unsigned long getenv_ul(const char *var, unsigned long def);
-extern_c void setenv_ul(const char *var, unsigned long val);
-extern_c bool getenv_bool(const char *var);
-extern_c void setenv_bool(const char *var, bool val);
-extern_c const char *getenv_notempty(const char *var);
 extern_c void log_config_status(void);

+ 3 - 3
esp32/max80/fpgasvc.c

@@ -142,7 +142,7 @@ esp_err_t fpga_service_init(void)
 {
     pinMode(PIN_FPGA_INT, INPUT);
 
-    setenv_bool("status.max80.fpga", false);
+    setvar_bool(status_max80_fpga, false);
 
     fpga_service_evgroup = null_check(xEventGroupCreate());
     spi_mutex = null_check(xSemaphoreCreateRecursiveMutex());
@@ -255,7 +255,7 @@ static bool fpga_online(void)
 	   (int)(sizeof head.signature - 1), head.signature);
     esplink_start(&head);
 
-    setenv_bool("status.max80.fpga", true);
+    setvar_bool(status_max80_fpga, true);
     xSemaphoreGiveRecursive(spi_mutex);
 
     xTimerStart(fpga_timesync_timer, portMAX_DELAY);
@@ -269,7 +269,7 @@ static void fpga_offline(void)
     memset(&head, 0, sizeof head);
     xSemaphoreTakeRecursive(spi_mutex, portMAX_DELAY);
     xTimerStop(fpga_timesync_timer, portMAX_DELAY);
-    setenv_bool("status.max80.fpga", false);
+    setvar_bool(status_max80_fpga, false);
     esplink_start(NULL);	/* Stop esplink */
 }
 

+ 16 - 12
esp32/max80/httpd.c

@@ -444,8 +444,7 @@ static esp_err_t httpd_set_board_rev(httpd_req_t *req)
 		    /* Otherwise input truncated or invalid */
 		    printf("[HTTP] setting board revision: %s\n", rev_str);
 		    if (!board_info_set(rev_str)) {
-			setenv_cond("status.max80.hw.ver",
-				    board_info.version_str);
+			setvar_str(status_max80_hw_ver, board_info.version_str);
 			err = Z_OK;
 		    } else {
 			err = FWUPDATE_ERR_CONFIG_SAVE;
@@ -476,13 +475,12 @@ static esp_err_t httpd_set_board_rev(httpd_req_t *req)
 
 static void httpd_get_status_extra(FILE *f, httpd_req_t *req)
 {
-    static const char refresh_time_config[] = "http.status.refresh";
     char timebuf[64];
     size_t len;
     struct timeval tv;
 
     unsigned long statref;
-    statref = Max(getenv_ul(refresh_time_config, 0), MIN_STATUS_REF);
+    statref = Max(getvar_uint(config_http_status_refresh), MIN_STATUS_REF);
 
     if (httpd_req_get_url_query_str(req, timebuf, sizeof timebuf) == ESP_OK &&
 	*timebuf) {
@@ -490,11 +488,11 @@ static void httpd_get_status_extra(FILE *f, httpd_req_t *req)
 	unsigned long newstatref = strtoul(timebuf, &ep, 10);
 	if (!*ep && newstatref >= MIN_STATUS_REF && newstatref != statref) {
 	    statref = newstatref;
-	    setenv_config(refresh_time_config, timebuf);
+	    setvar_uint(config_http_status_refresh, statref);
 	    read_config(NULL, true); /* Save changed config */
 	}
     }
-    fprintf(f, "%s=%lu\n", refresh_time_config, statref);
+    fprintf(f, "http.status.refresh=%lu\n", statref);
 
     gettimeofday(&tv,NULL);
     const struct tm *tm = localtime(&tv.tv_sec);
@@ -518,7 +516,7 @@ static esp_err_t httpd_get_config_status(httpd_req_t *req, bool status)
     if (status)
 	httpd_get_status_extra(f, req);
 
-    int rv = write_env(f, status);
+    int rv = write_sysvars(f, status);
     fclose(f);
     return rv ? ESP_FAIL : ESP_OK;
 }
@@ -527,7 +525,7 @@ static esp_err_t httpd_set_lang(httpd_req_t *req, const char *query)
 {
     if (query) {
 	int qlen = strlen(query);
-	setenv_config("LANG", qlen && qlen <= MAX_LANG_LEN ? query : NULL);
+	setvar_str(config_LANG, qlen && qlen <= MAX_LANG_LEN ? query : NULL);
 	read_config(NULL, true);	/* Save configuration */
     }
 
@@ -539,18 +537,24 @@ static esp_err_t httpd_set_lang(httpd_req_t *req, const char *query)
     return httpd_send_plain(req, 303, NULL, 0, HSP_REFERER, 0);
 }
 
-static esp_err_t httpd_get_lang(httpd_req_t *req)
+static const char *get_lang(void)
 {
-    const char *lang = getenv_def("LANG", "");
+    const char *lang = getvar_str(config_LANG);
+    if (!lang)
+	lang = fallback_language;
+    return lang;
+}
 
+static esp_err_t httpd_get_lang(httpd_req_t *req)
+{
+    const char *lang = get_lang();
     return httpd_send_plain(req, 200, lang, strlen(lang), HSP_CRLF, 0);
 }
 
 static esp_err_t httpd_lang_redirect(httpd_req_t *req)
 {
     char lang_buf[sizeof req->uri + MAX_LANG_LEN];
-    int len = snprintf(lang_buf, sizeof lang_buf, "/lang/%s%s",
-		       getenv_def("LANG", fallback_language),
+    int len = snprintf(lang_buf, sizeof lang_buf, "/lang/%s%s", get_lang(),
 		       req->uri + (sizeof("/sys/lang")-1));
 
     return httpd_send_plain(req, 302, lang_buf, len, 0, 0);

+ 5 - 5
esp32/max80/max80.ino

@@ -54,9 +54,9 @@ static void heap_info()
 static void dump_config()
 {
     printf("--- Configuration:\n");
-    write_env(stdout, false);
+    write_sysvars(stdout, false);
     printf("--- Status:\n");
-    write_env(stdout, true);
+    write_sysvars(stdout, true);
     printf("--- End configuration and status\n");
 }
 
@@ -104,13 +104,13 @@ void setup() {
 
     printf("[FW]   MAX80 firmware compiled on %s\n", fwdate);
     printf("[PCB]  MAX80 board version: %s\n", board_info.version_str);
-    setenv_cond("status.max80.hw.ver", board_info.version_str);
+    setvar_str(status_max80_hw_ver, board_info.version_str);
     printf("[PCB]  MAX80 serial number: %s\n", serial_number);
-    setenv_cond("status.max80.hw.serial", serial_number);
+    setvar_str(status_max80_hw_serial, serial_number);
     Serial.println("MAX80 start");
 
     init_config();
-    setenv_cond("status.max80.fw.date", fwdate);
+    setvar_str(status_max80_fw_date, fwdate);
     fpga_service_init();
     fpga_service_enable(true);
     SetupWiFi();

+ 47 - 16
esp32/max80/sysvar.c

@@ -60,7 +60,7 @@ const struct sysvar_ops sysvar_bool_ops = {
 
 static const char *sysvar_int_tostr(sysvar_t from, char *buf)
 {
-    snprintf(buf, INT_BUFLEN, "%"PRId32, from.v_int);
+    snprintf(buf, INT_BUFLEN, "%ld", from.v_int);
     return buf;
 }
 
@@ -82,7 +82,7 @@ const struct sysvar_ops sysvar_int_ops = {
 
 static const char *sysvar_uint_tostr(sysvar_t from, char *buf)
 {
-    snprintf(buf, UINT_BUFLEN, "%"PRIu32, from.v_uint);
+    snprintf(buf, UINT_BUFLEN, "%lu", from.v_uint);
     return buf;
 }
 
@@ -102,13 +102,13 @@ const struct sysvar_ops sysvar_uint_ops = {
     .buflen = UINT_BUFLEN
 };
 
-static const char *sysvar_string_tostr(sysvar_t from, char *buf)
+static const char *sysvar_str_tostr(sysvar_t from, char *buf)
 {
     (void)buf;
-    return from.v_string;
+    return from.v_str;
 }
 
-static bool sysvar_string_fromstr(sysvar_t *to, const char *from)
+static bool sysvar_str_fromstr(sysvar_t *to, const char *from)
 {
     char *ns;
 
@@ -119,19 +119,19 @@ static bool sysvar_string_fromstr(sysvar_t *to, const char *from)
 	if (!ns)
 	    return false;
     }
-    to->v_string = ns;
+    to->v_str = ns;
     return true;
 }
 
-static bool sysvar_string_set(sysvar_t *to, sysvar_t from)
+static bool sysvar_str_set(sysvar_t *to, sysvar_t from)
 {
-    return sysvar_string_fromstr(to, from.v_string);
+    return sysvar_str_fromstr(to, from.v_str);
 }
 
-const struct sysvar_ops sysvar_string_ops = {
-    .set = sysvar_string_set,
-    .tostr = sysvar_string_tostr,
-    .fromstr = sysvar_string_fromstr,
+const struct sysvar_ops sysvar_str_ops = {
+    .set = sysvar_str_set,
+    .tostr = sysvar_str_tostr,
+    .fromstr = sysvar_str_fromstr,
     .is_ptr = true
 };
 
@@ -145,9 +145,9 @@ static void sysvar_tz_update(sysvar_t val, bool isset)
 }
 
 const struct sysvar_ops sysvar_tz_ops = {
-    .set = sysvar_string_set,
-    .tostr = sysvar_string_tostr,
-    .fromstr = sysvar_string_fromstr,
+    .set = sysvar_str_set,
+    .tostr = sysvar_str_tostr,
+    .fromstr = sysvar_str_fromstr,
     .update = sysvar_tz_update,
     .is_ptr = true
 };
@@ -160,7 +160,8 @@ static const char *sysvar_ip_tostr(sysvar_t from, char *buf)
     } ip;
 
     ip.l = from.v_ip;
-    snprintf(buf, IP_BUFLEN, "%u.%u.%u.%u", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
+    snprintf(buf, IP_BUFLEN,
+	     "%u.%u.%u.%u", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
     return buf;
 }
 
@@ -252,6 +253,9 @@ const struct sysvar_ops sysvar_mac_ops = {
 
 /* --- Generic getters/setters --- */
 
+/* Contains the lowest numbered sysvar changed; or sysvar_count if nothing */
+enum sysvars_enum sysvar_changed;
+
 sysvar_t getvar(size_t var)
 {
     if (var >= (size_t)sysvar_count)
@@ -279,6 +283,9 @@ static bool do_setvar(size_t var, sysvar_t val, bool is_set)
     if (free_ptr)
 	free(free_ptr);
 
+    if (var < (size_t)sysvar_changed)
+	sysvar_changed = (enum sysvars_enum)var;
+
     sysvar_isset[var] = is_set;
     if (type->update)
 	type->update(*to, is_set);
@@ -340,6 +347,9 @@ bool setvar_fromstr(size_t var, const char *str)
     if (!type->fromstr(to, str))
 	return false;
 
+    if (var < (size_t)sysvar_changed)
+	sysvar_changed = (enum sysvars_enum)var;
+
     if (free_ptr)
 	free(free_ptr);
 
@@ -347,10 +357,31 @@ bool setvar_fromstr(size_t var, const char *str)
     return true;
 }
 
+/* --- Find the index of a specific variable --- */
+
+size_t sysvar_find(size_t ns, const char *name)
+{
+    if (ns >= (size_t)sysvar_nscount)
+	return 0;
+
+    const sysvar_ns_t *nsi = &sysvar_ns[ns];
+    const char * const *varname;
+
+    varname = bsearch(name, sysvar_name + nsi->first,
+		      nsi->count, sizeof(const char *),
+		      (int (*)(const void *, const void *))strcmp);
+    if (!varname)
+	return 0;
+
+    return varname - sysvar_name;
+}
+
 /* --- Initialization/reset to defaults --- */
 
 void sysvar_reset(void)
 {
     for (size_t i = sysvar_null; i < (size_t)sysvar_count; i++)
 	unsetvar(i);
+
+    sysvar_changed = sysvar_null;
 }

+ 32 - 17
esp32/max80/sysvar_common.h

@@ -5,11 +5,24 @@
 #include <stdbool.h>
 #include <inttypes.h>
 
+#ifndef extern_c
+# ifdef __cplusplus
+#  define extern_c extern "C"
+# else
+#  define extern_c extern
+# endif
+#endif
+
+typedef struct sysvar_namespace {
+    const char *name;
+    size_t first, count;
+} sysvar_ns_t;
+
 typedef union sysvar_value {
     bool v_bool;
-    int32_t v_int;
-    uint32_t v_uint;
-    const char *v_string;
+    long int v_int;
+    unsigned long int v_uint;
+    const char *v_str;
     const char *v_tz;		/* Timezone */
     uint32_t v_ip;		/* IPv4 address */
     const uint8_t *v_mac;	/* MAC address */
@@ -32,20 +45,23 @@ typedef const struct sysvar_ops *sysvar_type_t;
 
 /* Buffer size needed to represent some data types */
 #define BOOL_BUFLEN 2
-#define INT_BUFLEN  12		/* 10 digits + sign + null */
+#define INT_BUFLEN  (3*sizeof(unsigned int)+2)
 #define UINT_BUFLEN INT_BUFLEN
 #define IP_BUFLEN   (4*4)
 #define MAC_BUFLEN  (3*6)
 
-#define SYSVAR_BUFLEN	(3*6)	/* Maximum */
+#define SYSVAR_BUFLEN	32	/* Conservative minimum */
+
+extern_c sysvar_t getvar(size_t var);
+extern_c bool setvar(size_t var, sysvar_t val);
+extern_c bool unsetvar(size_t var);
+extern_c const char *getvar_tostr(size_t var);
+extern_c const char *getvar_tostr_r(size_t var, char *buf);
+extern_c bool setvar_fromstr(size_t var, const char *str);
+extern_c void sysvar_reset(void);
+extern_c size_t sysvar_find(size_t ns, const char *name);
 
-sysvar_t getvar(size_t var);
-bool setvar(size_t var, sysvar_t val);
-bool unsetvar(size_t var);
-const char *getvar_tostr(size_t var);
-const char *getvar_tostr_r(size_t var, char *buf);
-bool setvar_fromstr(size_t var, const char *str);
-void sysvar_reset(void);
+extern_c const struct sysvar_ops sysvar_nulltype_ops;
 
 /* Type-specific definitions/getters/setters */
 
@@ -60,13 +76,12 @@ void sysvar_reset(void);
 	vv.v_ ## t = v;						\
 	return setvar(var, vv);					\
     }								\
-    extern const struct sysvar_ops sysvar_ ## t ## _ops
+    extern_c const struct sysvar_ops sysvar_ ## t ## _ops
 
-extern const struct sysvar_ops sysvar_nulltype_ops;
 SYSVAR_MKTYPE(bool, bool);
-SYSVAR_MKTYPE(int, int32_t);
-SYSVAR_MKTYPE(uint, uint32_t);
-SYSVAR_MKTYPE(string, const char *);
+SYSVAR_MKTYPE(int, long int);
+SYSVAR_MKTYPE(uint, unsigned long int);
+SYSVAR_MKTYPE(str, const char *);
 SYSVAR_MKTYPE(tz, const char *);
 SYSVAR_MKTYPE(ip, uint32_t);
 SYSVAR_MKTYPE(mac, const uint8_t *);

+ 1 - 1
esp32/max80/time.c

@@ -20,7 +20,7 @@ void time_net_sync(const struct timeval *tv)
 
     if (synced != time_net_sync_status) {
 	time_net_sync_status = synced;
-	setenv_bool("status.net.sntp.sync", synced);
+	setvar_bool(status_net_sntp_sync, synced);
 	if (!synced) {
 	    printf("[SNTP] Time synchronization lost\n");
 	} else {

+ 64 - 73
esp32/max80/wifi.cpp

@@ -16,7 +16,8 @@
 
 WiFiUDP UDP;
 
-static const char *ssid, *password, *hostname, *dnsserver;
+static const char *ssid, *password, *hostname;
+static IPAddress dnsserver;
 static TimerHandle_t sta_failure_timer;
 
 enum connected {
@@ -27,6 +28,28 @@ enum connected {
 static volatile bool sta_timeout_enabled;
 static volatile unsigned int sta_timeout_count;
 static unsigned int connected;
+static const IPAddress null_ip(0,0,0,0);
+
+static inline bool setvar_ip(enum sysvars_enum var, const esp_ip_addr_t &ip)
+{
+    return setvar_ip(var, ip.u_addr.ip4.addr);
+}
+static inline bool setvar_ip(enum sysvars_enum var, const ip_addr_t &ip)
+{
+    return setvar_ip(var, ip.u_addr.ip4.addr);
+}
+static inline esp_ip_addr_t *ip_toesp(esp_ip_addr_t *eip, IPAddress ip)
+{
+    memset(eip, 0, sizeof *eip);
+    eip->u_addr.ip4.addr = (uint32_t)ip;
+    return eip;
+}
+static inline ip_addr_t *ip_toaddr(ip_addr_t *eip, IPAddress ip)
+{
+    memset(eip, 0, sizeof *eip);
+    eip->u_addr.ip4.addr = (uint32_t)ip;
+    return eip;
+}
 
 static void sta_bounce(void)
 {
@@ -93,13 +116,13 @@ static void sntp_sync_cb(struct timeval *tv)
 
 static void my_sntp_start(void)
 {
-    setenv_bool("status.net.sntp.sync", false);
+    setvar_bool(status_net_sntp_sync, false);
 
-    if (getenv_bool("sntp.enabled")) {
+    if (getvar_bool(config_sntp_enabled)) {
 	sntp_set_time_sync_notification_cb(sntp_sync_cb);
 
 	sntp_setoperatingmode(SNTP_OPMODE_POLL);
-	sntp_servermode_dhcp(!getenv_bool("ip4.dhcp.nosntp"));
+	sntp_servermode_dhcp(!getvar_bool(config_ip4_dhcp_nosntp));
 	sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED); // Until first sync
 	sntp_init();
     } else {
@@ -129,11 +152,10 @@ static void sntp_server_show(void)
     const ip_addr_t *sntp_ip = sntp_getserver(0);
 
     if (!invalid_ip(sntp_ip)) {
-	const char *sntp_server = inet_ntoa(*sntp_ip);
-	printf("[SNTP] Time server: %s\n", sntp_server);
-	setenv_cond("status.net.sntp.server", sntp_server);
+	printf("[SNTP] Time server: %s\n", inet_ntoa(*sntp_ip));
+	setvar_ip(status_net_sntp_server, *sntp_ip);
     } else {
-	setenv_cond("status.net.sntp.server", NULL);
+	setvar_ip(status_net_sntp_server, null_ip);
     }
 }
 
@@ -165,27 +187,17 @@ static void dns_setup(void)
 {
     const ip_addr_t *dns_ip = dns_getserver(0);
 
-    if (invalid_ip(dns_ip) || getenv_bool("ip4.dhcp.nodns")) {
+    if (invalid_ip(dns_ip) || getvar_bool(config_ip4_dhcp_nodns)) {
 	/* Static DNS server configuration */
 	ip_addr_t addr;
-	if (dnsserver && inet_aton(dnsserver, &addr)) {
-	    if (memcmp(dns_ip, &addr, sizeof addr))
-		dns_setserver(0, &addr);
-	}
+	ip_toaddr(&addr, dnsserver);
+	if (memcmp(&addr, dns_ip, sizeof addr))
+	    dns_setserver(0, &addr);
     }
 
     dns_ip = dns_getserver(0);
-    const char *dns_server_str = inet_ntoa(*dns_ip);
-    printf("[DNS]  DNS server: %s\n", dns_server_str);
-    setenv_cond("status.net.dns.server", dns_server_str);
-}
-
-static esp_ip_addr_t ipaddr_toesp(IPAddress ip)
-{
-    esp_ip_addr_t eip;
-    memset(&eip, 0, sizeof eip);
-    eip.u_addr.ip4.addr = (uint32_t)ip;
-    return eip;
+    printf("[DNS]  DNS server: %s\n", inet_ntoa(*dns_ip));
+    setvar_ip(status_net_dns_server, *dns_ip);
 }
 
 static void mdns_setup(void)
@@ -204,7 +216,7 @@ static void mdns_setup(void)
     if (mdns_started)
 	mdns_free();
 
-    if (!getenv_bool("mdns.enabled"))
+    if (!getvar_bool(config_mdns_enabled))
 	return;
 
     mdns_started = mdns_init() == ESP_OK;
@@ -219,7 +231,7 @@ static void mdns_setup(void)
     snprintf(unique_name, sizeof unique_name, "MAX80-%s", serial_number);
     if (connected & CON_STA) {
 	mdns_ip_addr_t iplist;
-	iplist.addr = ipaddr_toesp(WiFi.localIP());
+	ip_toesp(&iplist.addr, WiFi.localIP());
 	iplist.next = NULL;
 	unique_mdns = mdns_delegate_hostname_add(unique_name, &iplist);
 	printf("[MDNS] mDNS unique hostname: %s\n", unique_name);
@@ -242,7 +254,7 @@ static void start_services(void)
 
     // If Arduino supported both of these at the same that would be
     // awesome, but it requires ESP-IDF reconfiguration...
-    if (getenv_bool("sntp.enabled")) {
+    if (getvar_bool(config_sntp_enabled)) {
 	if (!invalid_ip(sntp_getserver(0))) {
 	    sntp_server_show();
 	} else {
@@ -259,18 +271,6 @@ static void start_services(void)
     }
 }
 
-static const char *ip_str(const IPAddress &ip)
-{
-    static char ip_buf[4*4];
-    const IPAddress ip_none(0,0,0,0);
-    return strcpy(ip_buf, ip == ip_none ? "" : ip.toString().c_str());
-}
-
-static void setenv_ip(const char *var, const IPAddress &ip)
-{
-    setenv_config(var, ip_str(ip));
-}
-
 static bool force_conn_update;
 
 static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
@@ -281,7 +281,7 @@ static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
     static int ap_clients;
     int prev_ap_clients = ap_clients;
     IPAddress wifi_local_ip = WiFi.localIP();
-    const char *local_ip = ip_str(wifi_local_ip);
+    const char *local_ip = wifi_local_ip.toString().c_str();
 
     switch (event) {
     case ARDUINO_EVENT_WIFI_READY:
@@ -416,20 +416,20 @@ static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
 	force_conn_update = false;
 
 	if (conn_change & CON_STA) {
-	    setenv_bool("status.net.sta.conn", connected & CON_STA);
-	    setenv_config("status.net.sta.ip4",
-			  connected & CON_STA ? local_ip : "");
-	    setenv_ip("status.net.sta.ip4.mask", WiFi.subnetMask());
-	    setenv_ip("status.net.sta.ip4.gw", WiFi.gatewayIP());
+	    setvar_bool(status_net_sta_conn, connected & CON_STA);
+	    setvar_ip(status_net_sta_ip4,
+		      connected & CON_STA ? wifi_local_ip : null_ip);
+	    setvar_ip(status_net_sta_ip4_mask, WiFi.subnetMask());
+	    setvar_ip(status_net_sta_ip4_gw, WiFi.gatewayIP());
 	}
 	if (conn_change & CON_AP)
-	    setenv_bool("status.net.ap.conn", connected & CON_AP);
+	    setvar_bool(status_net_ap_conn, connected & CON_AP);
 	if (conn_change & CON_ETH) {
-	    setenv_bool("status.net.eth.conn", connected & CON_ETH);
-	    setenv_config("status.net.eth.ip4",
-			  connected & CON_ETH ? local_ip : "");
-	    setenv_ip("status.net.eth.ip4.mask", WiFi.subnetMask());
-	    setenv_ip("status.net.eth.ip4.gw", WiFi.gatewayIP());
+	    setvar_bool(status_net_eth_conn, connected & CON_ETH);
+	    setvar_ip(status_net_eth_ip4,
+		      connected & CON_STA ? wifi_local_ip : null_ip);
+	    setvar_ip(status_net_eth_ip4_mask, WiFi.subnetMask());
+	    setvar_ip(status_net_eth_ip4_gw, WiFi.gatewayIP());
 	}
 
 	if (!ssid) {
@@ -445,7 +445,7 @@ static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
     }
 
     if (ap_clients != prev_ap_clients)
-	setenv_ul("status.net.ap.clients", ap_clients);
+	setvar_uint(status_net_ap_clients, ap_clients);
 
     /*
      * Don't keep retrying if there are AP clients - makes the AP
@@ -456,15 +456,6 @@ static void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
     }
 }
 
-static void setenv_mac(const char *var, const uint8_t mac[6])
-{
-    char mac_str[3*6];
-
-    snprintf(mac_str, sizeof mac_str, "%02x:%02x:%02x:%02x:%02x:%02x",
-	     mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-    setenv_cond(var, mac_str);
-}
-
 static void wifi_config_ap(void)
 {
     /* No network configuration set */
@@ -476,7 +467,7 @@ static void wifi_config_ap(void)
     static char ap_ssid[64];
 
     WiFi.softAPmacAddress(mac);
-    setenv_mac("status.net.ap.mac", mac);
+    setvar_mac(status_net_ap_mac, mac);
 
     /* The last two bytes of the efuse MAC */
     snprintf(ap_ssid, sizeof ap_ssid, "MAX80_%02X%02X",
@@ -485,10 +476,10 @@ static void wifi_config_ap(void)
     printf("[WIFI] AP SSID %s IP %s netmask %s channel %u\n",
 	   ap_ssid, AP_IP.toString().c_str(),
 	   AP_Netmask.toString().c_str(), channel);
-    setenv_cond("status.net.ap.ssid", ap_ssid);
-    setenv_ip("status.net.ap.ip4", AP_IP);
-    setenv_ip("status.net.ap.ip4.mask", AP_Netmask);
-    setenv_ul("status.net.ap.clients", 0);
+    setvar_str(status_net_ap_ssid, ap_ssid);
+    setvar_ip(status_net_ap_ip4, AP_IP);
+    setvar_ip(status_net_ap_ip4_mask, AP_Netmask);
+    setvar_uint(status_net_ap_clients, 0);
 
     printf("WiFi.softAP\n");
     WiFi.softAP(ap_ssid, NULL, channel, 0, 4, true);
@@ -513,10 +504,10 @@ static void wifi_config_sta(void)
     printf("WiFi.macAddress\n");
     WiFi.macAddress(mac);
     printf("setenv_mac\n");
-    setenv_mac("status.net.sta.mac", mac);
+    setvar_mac(status_net_sta_mac, mac);
 
     printf("setenv ssid\n");
-    setenv_cond("status.net.sta.ssid", ssid);
+    setvar_str(status_net_sta_ssid, ssid);
     if (!ssid) {
 	WiFi.enableSTA(false);
 	return;
@@ -539,10 +530,10 @@ static void wifi_config_sta(void)
 
 static void wifi_config(void)
 {
-    ssid         = getenv_notempty("wifi.ssid");
-    password     = getenv_notempty("wifi.psk");
-    hostname     = getenv_def("hostname", "max80");
-    dnsserver    = getenv_notempty("ip4.dns");
+    ssid         = dupstr(getvar_str(config_wifi_ssid));
+    password     = dupstr(getvar_str(config_wifi_psk));
+    hostname     = dupstr(getvar_str(config_hostname));
+    dnsserver    = IPAddress(getvar_ip(config_ip4_dns));
 
     force_conn_update = true;
 
@@ -553,7 +544,7 @@ static void wifi_config(void)
 
     WiFi.setTxPower(WIFI_POWER_19_5dBm);
 
-    setenv_config("status.hostname", hostname);
+    setvar_str(status_hostname, hostname);
     WiFi.hostname(hostname);
 
     printf("wifi_config_ap\n");

BIN
esp32/output/max80.ino.bin


+ 16 - 13
esp32/sysvars.pl

@@ -90,28 +90,25 @@ print $h "#define $htag\n\n";
 
 print $h "#include \"sysvar_common.h\"\n\n";
 
-print $h "enum sysvar_ns {\n";
+print $h "enum sysvar_ns_enum {\n";
 print $h map { "\tsysvar_ns_$_,\n" } @nslist;
 print $h "\tsysvar_nscount\n};\n\n";
 
-print $h "enum sysvars {\n";
+print $h "enum sysvars_enum {\n";
 print $h map { "\t$_,\n" } @varenum;
 print $h "\tsysvar_count\n};\n\n";
 
 push(@varenum, 'sysvar_count');
 
-foreach my $ns (@nslist) {
-    print $h "#define sysvar_ns_${ns}_start ", $varenum[$nsfirst{$ns}], "\n";
-    print $h "#define sysvar_ns_${ns}_end   ", $varenum[$nsfirst{$ns}+$nscount{$ns}], "\n";
-    print $h "#define sysvar_ns_${ns}_count ", $nscount{$ns}, "\n";
-}
-
 print $h "\n";
-print $h "extern const char * const sysvar_name[$cnt];\n";
-print $h "extern const sysvar_type_t sysvar_type[$cnt];\n";
-print $h "extern const sysvar_t sysvar_defval[$cnt];\n";
-print $h "extern sysvar_t sysvar_val[$cnt];\n";
-print $h "extern bool sysvar_isset[$cnt];\n";
+
+printf $h "extern_c const sysvar_ns_t sysvar_ns[%d];\n", scalar(@nslist);
+print $h "extern_c const char * const sysvar_name[$cnt];\n";
+print $h "extern_c const sysvar_type_t sysvar_type[$cnt];\n";
+print $h "extern_c const sysvar_t sysvar_defval[$cnt];\n";
+print $h "extern_c sysvar_t sysvar_val[$cnt];\n";
+print $h "extern_c bool sysvar_isset[$cnt];\n";
+print $h "extern_c enum sysvars_enum sysvar_changed;\n";
 
 print $h "\n#endif /* $htag */\n";
 close($h);
@@ -120,6 +117,12 @@ open(my $c, '>', $cfile) or die "$0:$cfile: $!\n";
 print $c "#include <stddef.h>\n";
 print $c "#include \"", basename($hfile), "\"\n\n";
 
+printf $c "const sysvar_ns_t sysvar_ns[%d] = {\n", scalar(@nslist);
+foreach my $ns (@nslist) {
+    printf $c "\t{ \"%s\", %d, %d },\n", $ns, $nsfirst{$ns}, $nscount{$ns};
+}
+printf $c "};\n";
+
 print $c "const char * const sysvar_name[$cnt] = {\n";
 print $c "\tNULL,\n";
 foreach my $ns (@nslist) {

+ 15 - 14
esp32/sysvars.vars

@@ -1,30 +1,31 @@
 @config
-LANG			string "sv"
+LANG			str "sv"
 TZ			tz "CET-1CEST,M3.5.0,M10.5.0/3"
-abc.hosttype		string "auto"
-hostname		string "max80"
+abc.hosttype		str "auto"
+hostname		str "max80"
+http.status.refresh	uint 10
 ip4.dhcp.nodns		bool
 ip4.dhcp.nosntp		bool
 ip4.dns			ip
 mdns.enabled		bool true
 sntp.enabled		bool true
-sntp.server		string "time.max80.abc80.org"
-tzname			string "Europe/Stockholm"
-wifi.psk		string
-wifi.ssid		string
+sntp.server		str "time.max80.abc80.org"
+tzname			str "Europe/Stockholm"
+wifi.psk		str
+wifi.ssid		str
 
 @status
-hostname		string
+hostname		str
 max80.fpga		bool
-max80.fw.date		string
-max80.hw.serial		string
-max80.hw.ver		string
-net.ap.clients		int
+max80.fw.date		str
+max80.hw.serial		str
+max80.hw.ver		str
+net.ap.clients		uint
 net.ap.conn		bool
 net.ap.ip4		ip
 net.ap.ip4.mask		ip
 net.ap.mac		mac
-net.ap.ssid		string
+net.ap.ssid		str
 net.dns.server		ip
 net.eth.conn		bool
 net.eth.ip4		ip
@@ -37,4 +38,4 @@ net.sta.ip4		ip
 net.sta.ip4.gw		ip
 net.sta.ip4.mask	ip
 net.sta.mac		mac
-net.sta.ssid		string
+net.sta.ssid		str

+ 2 - 2
fpga/max80.qpf

@@ -19,12 +19,12 @@
 #
 # Quartus Prime
 # Version 22.1std.0 Build 915 10/25/2022 SC Lite Edition
-# Date created = 22:54:03  February 09, 2023
+# Date created = 22:49:04  August 30, 2023
 #
 # -------------------------------------------------------------------------- #
 
 QUARTUS_VERSION = "22.1"
-DATE = "22:54:03  February 09, 2023"
+DATE = "22:49:04  August 30, 2023"
 
 # Revisions
 

BIN
fpga/output/bypass.rbf.gz


BIN
fpga/output/bypass.rpd.gz


BIN
fpga/output/bypass.sof


BIN
fpga/output/bypass.svf.gz


BIN
fpga/output/bypass.xsvf.gz


BIN
fpga/output/max80.fw


BIN
fpga/output/v1.fw


BIN
fpga/output/v1.jic


BIN
fpga/output/v1.rbf.gz


BIN
fpga/output/v1.rpd.gz


BIN
fpga/output/v1.sof


BIN
fpga/output/v1.svf.gz


BIN
fpga/output/v1.xsvf.gz


BIN
fpga/output/v2.fw


BIN
fpga/output/v2.jic


BIN
fpga/output/v2.rbf.gz


BIN
fpga/output/v2.rpd.gz


BIN
fpga/output/v2.sof


BIN
fpga/output/v2.svf.gz


BIN
fpga/output/v2.xsvf.gz