/********************************************************************************* * Copyright: (C) 2019 LingYun IoT System Studio * All rights reserved. * * Filename: conf.c * Description: This file is iotd configure file parser function * * Version: 1.0.0(2019年06月25日) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "2019年06月25日 22时23分55秒" * ********************************************************************************/ #include "conf.h" #include "logger.h" #include "iniparser.h" enum { _TYPE_INPUT, _TYPE_OUTPUT, }; /* conf format: "{light_indoor:6:0},{light_livroomL:13:0},{light_livroomR:19:0},{light_hallway:26:0}" */ int parser_gpio_info(int type, gpio_t *gpio, char *conf) { char *ptr; char *pstart; char *pend; char buf[64]; int cnt = 0; int rv = 0; if( !gpio || !conf || strlen(conf)<3 ) { log_error("Invalid input arguments.\n"); return -1; } pstart = strchr(conf, '{'); if( !pstart ) return 0; pend = strchr(pstart, '}'); while( pstart && pend ) { memset(buf, 0, sizeof(buf)); strncpy(buf, pstart+1, pend-pstart-1); /* parser and get the GPIO name, BCM pin number, active power level */ { /* check GPIO configure name too long or not */ ptr = strchr(buf, ':'); if( !ptr ) { log_error("Found invalid GPIO configure: %s\n", buf); goto NEXT_LOOP; } if( ptr-buf > sizeof(gpio->input[cnt].name) ) { log_error("Found GPIO name too long\n", buf); goto NEXT_LOOP; } /* use sscanf() to parser GPIO configured values */ if(_TYPE_INPUT == type ) { rv = sscanf(buf, "%[^:]:%d:%d", gpio->input[cnt].name, &gpio->input[cnt].pin, &gpio->input[cnt].active_level); if( 3 == rv) { log_info("parser GPIO input[%s] BCM[%d] active[%d]\n", gpio->input[cnt].name, gpio->input[cnt].pin, gpio->input[cnt].active_level); if( strstr(gpio->input[cnt].name, "infrared") ) { log_info("parser GPIO enable infrared detect\n"); gpio->infrared_enable = 1; } cnt++; gpio->incnt = cnt; } else { log_error("Found invalid GPIO configure: %s\n", buf); } } else { rv = sscanf(buf, "%[^:]:%d:%d", gpio->output[cnt].name, &gpio->output[cnt].pin, &gpio->output[cnt].active_level); if( 3 == rv) { log_info("parser GPIO output[%s] BCM[%d] active[%d]\n", gpio->output[cnt].name, gpio->output[cnt].pin, gpio->output[cnt].active_level); cnt++; gpio->outcnt = cnt; } else { log_error("Found invalid GPIO configure: %s\n", buf); } } } NEXT_LOOP: pstart = strchr(pend, '{'); if( pstart ) pend = strchr(pstart, '}'); } return gpio->outcnt; } int parser_conf(const char *conf_file, iotd_ctx_t *ctx, int debug) { dictionary *ini; const char *str; int val; log_ctx_t *log_ctx; hal_ctx_t *hal_ctx; mqtt_ctx_t *mqtt_ctx; gpio_t *gpio; if( !conf_file || !ctx ) { fprintf(stderr, "ERROR: parser configure file or ctx is NULL\n"); return 0; } memset(ctx, 0, sizeof(*ctx)); log_ctx = &ctx->log_ctx; hal_ctx = &ctx->hal_ctx; mqtt_ctx = &ctx->mqtt_ctx; ini = iniparser_load(conf_file); if( !ini ) { fprintf(stderr, "ERROR: cannot parse file: '%s'\n", conf_file); return -1; } /*+------------------------------------------------------+ *| parser logger settings and start logger system | *+------------------------------------------------------+*/ if( !debug ) { str = iniparser_getstring(ini, "logger:file", "/tmp/iotd.log"); strncpy(log_ctx->logfile, str, sizeof(log_ctx->logfile)); log_ctx->logsize = iniparser_getint(ini, "logger:size", 1024); log_ctx->loglevel = iniparser_getint(ini, "logger:level", LOG_LEVEL_DEBUG); } else { strncpy(log_ctx->logfile, "console", sizeof(log_ctx->logfile)); log_ctx->loglevel = LOG_LEVEL_DEBUG; } if( log_open(log_ctx->logfile, log_ctx->loglevel, log_ctx->logsize, LOG_LOCK_DISABLE) < 0 ) { fprintf(stderr, "Logger system initialise failure\n"); return -2; } log_info("Logger system initialise ok\n"); /*+------------------------------------------------------+ *| parser production ID | *+------------------------------------------------------+*/ if( !(str=iniparser_getstring(ini, "common:id", NULL)) ) { log_error("ERROR: parser production ID failure\n"); return -2; } /* cJSON parser ID will get "" */ snprintf(mqtt_ctx->id, sizeof(mqtt_ctx->id), "\"%s\"", str); log_info("parser production ID [%s]\n", mqtt_ctx->id); /*+------------------------------------------------------+ *| parser hardware module configuration ID | *+------------------------------------------------------+*/ gpio = &hal_ctx->gpio; /* parser GPIO output pins */ if( !(str=iniparser_getstring(ini, "hardware:gpio_outpin", NULL)) ) { log_warn("parser no GPIO output pins\n"); } else { parser_gpio_info(_TYPE_OUTPUT, gpio, (char *)str); log_info("parser [%d] GPIO output pins configured\n", gpio->outcnt); } gpio->light_intval = iniparser_getint(ini, "hardware:light_intval", 20); log_info("parser relay controled light interval time [%d]\n", gpio->light_intval); /* parser GPIO input pins */ if( !(str=iniparser_getstring(ini, "hardware:gpio_inpin", NULL)) ) { log_warn("parser no GPIO input pins\n"); } else { parser_gpio_info(_TYPE_INPUT, gpio, (char *)str); log_info("parser [%d] GPIO input pins\n", gpio->incnt); } hal_ctx->lux_enable = iniparser_getint(ini, "hardware:lux", 0); if( hal_ctx->lux_enable ) { hal_ctx->lux_threshold = iniparser_getdouble(ini, "hardware:lux_threshold", 0.1); log_info("parser LUX enable and threshold value set be [%.03f]\n", hal_ctx->lux_threshold); } hal_ctx->sht2x_enable = iniparser_getint(ini, "hardware:sht2x", 0); if( hal_ctx->sht2x_enable ) { log_info("parser SHT2x sensor enabled\n"); } hal_ctx->ds18b20_enable = iniparser_getint(ini, "hardware:ds18b20", 0); if( hal_ctx->ds18b20_enable ) { log_info("parser DS18B20 sensor enabled\n"); } /*+------------------------------------------------------+ *| parser broker settings | *+------------------------------------------------------+*/ if( !(str=iniparser_getstring(ini, "broker:hostname", NULL)) ) { log_error("ERROR: Parser broker server hostname failure\n"); return -2; } strncpy(mqtt_ctx->host, str, sizeof(mqtt_ctx->host) ); if( (val=iniparser_getint(ini, "broker:port", -1)) < 0 ) { log_error("ERROR: Parser broker server port failure\n"); return -2; } mqtt_ctx->port = val; log_info("Parser broker server [%s:%d]\n", mqtt_ctx->host, mqtt_ctx->port); str=iniparser_getstring(ini, "broker:username", NULL); strncpy(mqtt_ctx->uid, str, sizeof(mqtt_ctx->uid) ); str=iniparser_getstring(ini, "broker:password", NULL); strncpy(mqtt_ctx->pwd, str, sizeof(mqtt_ctx->pwd) ); log_info("Parser broker author by [%s:%s]\n", mqtt_ctx->uid, mqtt_ctx->pwd); mqtt_ctx->keepalive = iniparser_getint(ini, "broker:keepalive", 30); log_info("Parser broker keepalive timeout [%d] seconds\n", mqtt_ctx->keepalive); /*+------------------------------------------------------+ *| parser subscriber settings | *+------------------------------------------------------+*/ if( !(str=iniparser_getstring(ini, "subsciber:subTopic", NULL)) ) { log_warn("WARNNING: Parser MQTT subscribe topic failure\n"); } else { strncpy(mqtt_ctx->subTopic, str, sizeof(mqtt_ctx->subTopic) ); mqtt_ctx->subQos = iniparser_getint(ini, "subsciber:subQos", 0); mqtt_ctx->sub_enable = 1; log_info("Parser subscriber topic \"%s\" with Qos[%d]\n", mqtt_ctx->subTopic, mqtt_ctx->subQos); } /*+------------------------------------------------------+ *| parser publisher settings | *+------------------------------------------------------+*/ if( !(str=iniparser_getstring(ini, "publisher:pubTopic", NULL)) ) { log_warn("WARNNING: Parser MQTT publisher topic failure\n"); } else { strncpy(mqtt_ctx->pubTopic, str, sizeof(mqtt_ctx->pubTopic) ); mqtt_ctx->pubQos = iniparser_getint(ini, "publisher:pubQos", 0); mqtt_ctx->interval = iniparser_getint(ini, "publisher:interval", 60); mqtt_ctx->pub_enable = 1; log_info("Parser publisher topic \"%s\" with Qos[%d]\n", mqtt_ctx->pubTopic, mqtt_ctx->pubQos); } return 0; }