diff --git a/src/api/config.c b/src/api/config.c index 91eaaec5..e5820566 100644 --- a/src/api/config.c +++ b/src/api/config.c @@ -122,6 +122,8 @@ static cJSON *addJSONvalue(const enum conf_type conf_type, union conf_value *val return cJSON_CreateStringReference(get_listeningMode_str(val->listeningMode)); case CONF_ENUM_WEB_THEME: return cJSON_CreateStringReference(get_web_theme_str(val->web_theme)); + case CONF_ENUM_TEMP_UNIT: + return cJSON_CreateStringReference(get_temp_unit_str(val->temp_unit)); case CONF_STRUCT_IN_ADDR: { char addr4[INET_ADDRSTRLEN] = { 0 }; @@ -366,6 +368,19 @@ static const char *getJSONvalue(struct conf_item *conf_item, cJSON *elem, struct log_debug(DEBUG_CONFIG, "Set %s to %d", conf_item->k, conf_item->v.web_theme); break; } + case CONF_ENUM_TEMP_UNIT: + { + // Check type + if(!cJSON_IsString(elem)) + return "not of type string"; + const int temp_unit = get_temp_unit_val(elem->valuestring); + if(temp_unit == -1) + return "invalid option"; + // Set item + conf_item->v.temp_unit = temp_unit; + log_debug(DEBUG_CONFIG, "Set %s to %d", conf_item->k, conf_item->v.temp_unit); + break; + } case CONF_ENUM_PRIVACY_LEVEL: { // Check type @@ -514,9 +529,9 @@ static int api_config_get(struct ftl_conn *api) // Special case: write-only values if(conf_item->f & FLAG_WRITE_ONLY) - JSON_ADD_ITEM_TO_OBJECT(leaf, "value", val); - else JSON_REF_STR_IN_OBJECT(leaf, "value", ""); + else + JSON_ADD_ITEM_TO_OBJECT(leaf, "value", val); // Add default value cJSON *dval = addJSONvalue(conf_item->t, &conf_item->d); diff --git a/src/api/info.c b/src/api/info.c index 7587db83..fe2ec217 100644 --- a/src/api/info.c +++ b/src/api/info.c @@ -318,14 +318,14 @@ static int read_hwmon_sensors(struct ftl_conn *api, double temp = 1e-3*raw_temp; double max = 1e-3*raw_max; double crit = 1e-3*raw_crit; - if(config.webserver.api.temp.unit.v.s[0] == 'F') + if(config.webserver.api.temp.unit.v.temp_unit == TEMP_UNIT_F) { // Convert °Celsius to °Fahrenheit temp = 1.8*temp + 32; max = 1.8*max + 32; crit = 1.8*crit + 32; } - else if(config.webserver.api.temp.unit.v.s[0] == 'K') + else if(config.webserver.api.temp.unit.v.temp_unit == TEMP_UNIT_K) { // Convert °Celsius to Kelvin temp += 273.15; @@ -657,9 +657,9 @@ int api_info_sensors(struct ftl_conn *api) // Add unit const char *unit = "C"; - if(config.webserver.api.temp.unit.v.s[0] == 'F') + if(config.webserver.api.temp.unit.v.temp_unit == TEMP_UNIT_F) unit = "F"; - else if(config.webserver.api.temp.unit.v.s[0] == 'K') + else if(config.webserver.api.temp.unit.v.temp_unit == TEMP_UNIT_K) unit = "K"; JSON_REF_STR_IN_OBJECT(sensors, "unit", unit); diff --git a/src/config/cli.c b/src/config/cli.c index c8748dbb..d4fa7822 100644 --- a/src/config/cli.c +++ b/src/config/cli.c @@ -272,6 +272,21 @@ static bool readStringValue(struct conf_item *conf_item, const char *value, stru } break; } + case CONF_ENUM_TEMP_UNIT: + { + const int temp_unit = get_temp_unit_val(value); + if(temp_unit != -1) + conf_item->v.temp_unit = temp_unit; + else + { + char *allowed = NULL; + CONFIG_ITEM_ARRAY(conf_item->a, allowed); + log_err("Config setting %s is invalid, allowed options are: %s", conf_item->k, allowed); + free(allowed); + return false; + } + break; + } case CONF_STRUCT_IN_ADDR: { struct in_addr addr4 = { 0 }; diff --git a/src/config/config.c b/src/config/config.c index f649b96a..b0e389b6 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -253,6 +253,7 @@ void duplicate_config(struct config *dst, struct config *src) case CONF_ENUM_PRIVACY_LEVEL: case CONF_ENUM_LISTENING_MODE: case CONF_ENUM_WEB_THEME: + case CONF_ENUM_TEMP_UNIT: case CONF_STRUCT_IN_ADDR: case CONF_STRUCT_IN6_ADDR: case CONF_ALL_DEBUG_BOOL: @@ -288,6 +289,7 @@ bool compare_config_item(const enum conf_type t, const union conf_value *val1, c case CONF_ENUM_PRIVACY_LEVEL: case CONF_ENUM_LISTENING_MODE: case CONF_ENUM_WEB_THEME: + case CONF_ENUM_TEMP_UNIT: case CONF_STRUCT_IN_ADDR: case CONF_STRUCT_IN6_ADDR: case CONF_ALL_DEBUG_BOOL: @@ -343,6 +345,7 @@ void free_config(struct config *conf) case CONF_ENUM_PRIVACY_LEVEL: case CONF_ENUM_LISTENING_MODE: case CONF_ENUM_WEB_THEME: + case CONF_ENUM_TEMP_UNIT: case CONF_STRUCT_IN_ADDR: case CONF_STRUCT_IN6_ADDR: case CONF_ALL_DEBUG_BOOL: @@ -870,7 +873,7 @@ void initConfig(struct config *conf) // sub-struct api conf->webserver.api.localAPIauth.k = "webserver.api.localAPIauth"; - conf->webserver.api.localAPIauth.h = "Does local clients need to authenticate to access the API?"; + conf->webserver.api.localAPIauth.h = "Do local clients need to authenticate to access the API?"; conf->webserver.api.localAPIauth.t = CONF_BOOL; conf->webserver.api.localAPIauth.d.b = true; @@ -930,8 +933,8 @@ void initConfig(struct config *conf) }; CONFIG_ADD_ENUM_OPTIONS(conf->webserver.api.temp.unit.a, temp_unit); } - conf->webserver.api.temp.unit.t = CONF_STRING; - conf->webserver.api.temp.unit.d.s = (char*)"C"; + conf->webserver.api.temp.unit.t = CONF_ENUM_TEMP_UNIT; + conf->webserver.api.temp.unit.d.temp_unit = TEMP_UNIT_C; // struct files @@ -1361,6 +1364,7 @@ const char * __attribute__ ((const)) get_conf_type_str(const enum conf_type type case CONF_ENUM_REFRESH_HOSTNAMES: case CONF_ENUM_LISTENING_MODE: case CONF_ENUM_WEB_THEME: + case CONF_ENUM_TEMP_UNIT: return "enum (string)"; case CONF_STRUCT_IN_ADDR: return "IPv4 address"; diff --git a/src/config/config.h b/src/config/config.h index 1569738b..506640a1 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -48,6 +48,7 @@ union conf_value { enum debug_flag debug_flag; // enum debug_flag value enum listening_mode listeningMode; // enum listening_mode value enum web_theme web_theme; // enum web_theme value + enum temp_unit temp_unit; // enum temp_unit value struct in_addr in_addr; // struct in_addr value struct in6_addr in6_addr; // struct in6_addr value cJSON *json; // cJSON * value @@ -71,6 +72,7 @@ enum conf_type { CONF_ENUM_PRIVACY_LEVEL, CONF_ENUM_LISTENING_MODE, CONF_ENUM_WEB_THEME, + CONF_ENUM_TEMP_UNIT, CONF_STRUCT_IN_ADDR, CONF_STRUCT_IN6_ADDR, CONF_JSON_STRING_ARRAY, diff --git a/src/config/toml_helper.c b/src/config/toml_helper.c index 616b8104..6cd1f6e1 100644 --- a/src/config/toml_helper.c +++ b/src/config/toml_helper.c @@ -335,6 +335,9 @@ void writeTOMLvalue(FILE * fp, const int indent, const enum conf_type t, union c case CONF_ENUM_WEB_THEME: printTOMLstring(fp, get_web_theme_str(v->web_theme), toml); break; + case CONF_ENUM_TEMP_UNIT: + printTOMLstring(fp, get_temp_unit_str(v->temp_unit), toml); + break; case CONF_STRUCT_IN_ADDR: { char addr4[INET_ADDRSTRLEN] = { 0 }; @@ -589,6 +592,22 @@ void readTOMLvalue(struct conf_item *conf_item, const char* key, toml_table_t *t log_debug(DEBUG_CONFIG, "%s DOES NOT EXIST or is not of type string", conf_item->k); break; } + case CONF_ENUM_TEMP_UNIT: + { + const toml_datum_t val = toml_string_in(toml, key); + if(val.ok) + { + const int temp_unit = get_temp_unit_val(val.u.s); + free(val.u.s); + if(temp_unit != -1) + conf_item->v.temp_unit = temp_unit; + else + log_warn("Config setting %s is invalid, allowed options are: %s", conf_item->k, conf_item->h); + } + else + log_debug(DEBUG_CONFIG, "%s DOES NOT EXIST or is not of type string", conf_item->k); + break; + } case CONF_ENUM_PRIVACY_LEVEL: { const toml_datum_t val = toml_int_in(toml, key); diff --git a/src/datastructure.c b/src/datastructure.c index 82043f30..37deb9a6 100644 --- a/src/datastructure.c +++ b/src/datastructure.c @@ -1055,4 +1055,31 @@ int __attribute__ ((pure)) get_web_theme_val(const char *web_theme) // Invalid value return -1; -} \ No newline at end of file +} + +const char * __attribute__ ((const)) get_temp_unit_str(const enum temp_unit temp_unit) +{ + switch(temp_unit) + { + case TEMP_UNIT_C: + return "C"; + case TEMP_UNIT_F: + return "F"; + case TEMP_UNIT_K: + return "K"; + } + return NULL; +} + +int __attribute__ ((pure)) get_temp_unit_val(const char *temp_unit) +{ + if(strcasecmp(temp_unit, "C") == 0) + return TEMP_UNIT_C; + else if(strcasecmp(temp_unit, "F") == 0) + return TEMP_UNIT_F; + else if(strcasecmp(temp_unit, "K") == 0) + return TEMP_UNIT_K; + + // Invalid value + return -1; +} diff --git a/src/datastructure.h b/src/datastructure.h index a071bc71..73bd8d29 100644 --- a/src/datastructure.h +++ b/src/datastructure.h @@ -161,6 +161,8 @@ const char * get_listeningMode_str(const enum listening_mode listeningMode) __at int get_listeningMode_val(const char *listeningMode) __attribute__ ((pure)); const char * __attribute__ ((const)) get_web_theme_str(const enum web_theme web_theme); int __attribute__ ((pure)) get_web_theme_val(const char *web_theme); +const char * __attribute__ ((const)) get_temp_unit_str(const enum temp_unit temp_unit); +int __attribute__ ((pure)) get_temp_unit_val(const char *temp_unit); // Pointer getter functions #define getQuery(queryID, checkMagic) _getQuery(queryID, checkMagic, __LINE__, __FUNCTION__, __FILE__) diff --git a/src/enums.h b/src/enums.h index ff54c1ac..b6f72b7b 100644 --- a/src/enums.h +++ b/src/enums.h @@ -301,4 +301,10 @@ enum web_theme { THEME_LCARS } __attribute__ ((packed)); +enum temp_unit { + TEMP_UNIT_C = 0, + TEMP_UNIT_F, + TEMP_UNIT_K +} __attribute__ ((packed)); + #endif // ENUMS_H diff --git a/src/setupVars.c b/src/setupVars.c index 3381f779..cc16368e 100644 --- a/src/setupVars.c +++ b/src/setupVars.c @@ -193,9 +193,9 @@ static void get_conf_weblayout_from_setupVars(void) static void get_conf_webtheme_from_setupVars(void) { // Try to obtain listening mode - const char *listeningMode = read_setupVarsconf("WEBTHEME"); + const char *webTheme = read_setupVarsconf("WEBTHEME"); - if(listeningMode == NULL) + if(webTheme == NULL) { // Do not change default value, this value is not set in setupVars.conf log_debug(DEBUG_CONFIG, "setupVars.conf:WEBTHEME -> Not set"); @@ -206,7 +206,7 @@ static void get_conf_webtheme_from_setupVars(void) } bool set = false; - int web_theme_enum = get_web_theme_val(listeningMode); + int web_theme_enum = get_web_theme_val(webTheme); if(web_theme_enum != -1) { set = true; @@ -230,6 +230,46 @@ static void get_conf_webtheme_from_setupVars(void) } } +static void get_conf_temp_unit_from_setupVars(void) +{ + // Try to obtain listening mode + const char *temp_unit = read_setupVarsconf("TEMPERATURE_UNIT"); + + if(temp_unit == NULL) + { + // Do not change default value, this value is not set in setupVars.conf + log_debug(DEBUG_CONFIG, "setupVars.conf:TEMPERATURE_UNIT -> Not set"); + + // Free memory, harmless to call if read_setupVarsconf() didn't return a result + clearSetupVarsArray(); + return; + } + + bool set = false; + int temp_unit_enum = get_temp_unit_val(temp_unit); + if(temp_unit_enum != -1) + { + set = true; + config.webserver.api.temp.unit.v.temp_unit = temp_unit_enum; + } + + // Free memory, harmless to call if read_setupVarsconf() didn't return a result + clearSetupVarsArray(); + + if(set) + { + // Parameter present in setupVars.conf + log_debug(DEBUG_CONFIG, "setupVars.conf:TEMPERATURE_UNIT -> Setting %s to %s", + config.webserver.interface.theme.k, + get_temp_unit_str(config.webserver.api.temp.unit.v.temp_unit)); + } + else + { + // Parameter not present in setupVars.conf + log_debug(DEBUG_CONFIG, "setupVars.conf:TEMPERATURE_UNIT -> Not set (found invalid value)"); + } +} + static void get_conf_listeningMode_from_setupVars(void) { // Try to obtain listening mode @@ -287,7 +327,7 @@ void importsetupVarsConf(void) get_conf_temp_limit_from_setupVars(); // Try to obtain password hash from setupVars.conf - get_conf_string_from_setupVars("TEMPERATURE_UNIT", &config.webserver.api.temp.unit); + get_conf_temp_unit_from_setupVars(); // Try to obtain web layout get_conf_weblayout_from_setupVars();