diff -r eb9dd60aa791 -r 81bf78a7618e thermferm/rdconfig.c --- a/thermferm/rdconfig.c Wed Jun 25 19:42:03 2014 +0200 +++ b/thermferm/rdconfig.c Thu Jun 26 20:00:00 2014 +0200 @@ -73,6 +73,7 @@ void killconfig(void) { w1_therm *tmp1, *old1; + units_list *tmp2; if (Config.name) free(Config.name); @@ -90,6 +91,26 @@ } Config.w1therms = NULL; Config.my_port = 6554; + Config.tempFormat = 'C'; + + for (tmp2 = Config.units; tmp2; tmp2 = tmp2->next) { + if (tmp2->uuid) + free(tmp2->uuid); + if (tmp2->name) + free(tmp2->name); + if (tmp2->air_address) + free(tmp2->air_address); + if (tmp2->beer_address) + free(tmp2->beer_address); + if (tmp2->io1_address) + free(tmp2->io1_address); + if (tmp2->io2_address) + free(tmp2->io2_address); + if (tmp2->profile) + free(tmp2->profile); + free(tmp2); + } + Config.units = NULL; #ifdef HAVE_WIRINGPI_H Config.lcd_cols = 16; @@ -347,7 +368,7 @@ syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", MBSE_SS(tmp3->name))) < 0) { + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", tmp3->name)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } @@ -355,19 +376,19 @@ syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "AIR_ADDRESS", "%s", MBSE_SS(tmp3->air_address))) < 0) { + if (tmp3->air_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "AIR_ADDRESS", "%s", tmp3->air_address)) < 0)) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BEER_ADDRESS", "%s", MBSE_SS(tmp3->beer_address))) < 0) { + if (tmp3->beer_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BEER_ADDRESS", "%s", tmp3->beer_address)) < 0)) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO1_ADDRESS", "%s", MBSE_SS(tmp3->io1_address))) < 0) { + if (tmp3->io1_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO1_ADDRESS", "%s", tmp3->io1_address)) < 0)) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } - if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO2_ADDRESS", "%s", MBSE_SS(tmp3->io2_address))) < 0) { + if (tmp3->io2_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO2_ADDRESS", "%s", tmp3->io2_address)) < 0)) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } @@ -469,11 +490,299 @@ +/* + * Parse one LCD display + */ +#ifdef HAVE_WIRINGPI_H +int parseLCD(xmlDocPtr doc, xmlNodePtr cur) +{ + xmlChar *key; + int ival; + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"COLUMNS"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + Config.lcd_cols = ival; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"ROWS"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + Config.lcd_rows = ival; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"ADDRESS"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%x", &ival) == 1) + Config.lcd_address = ival; + xmlFree(key); + } + cur = cur->next; + } + + return 0; +} + + + +int parseLCDs(xmlDocPtr doc, xmlNodePtr cur) +{ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"LCD"))) { + parseLCD(doc, cur); + } + cur = cur->next; + } + return 0; +} +#endif + + + +int parseW1therm(xmlDocPtr doc, xmlNodePtr cur) +{ + xmlChar *key; + int ival; + w1_therm *w1therm, *tmp; + + w1therm = (w1_therm *)malloc(sizeof(w1_therm)); + w1therm->next = NULL; + w1therm->master = w1therm->name = w1therm->alias = NULL; + w1therm->bus = w1therm->present = w1therm->lastval = w1therm->update = 0; + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"VERSION"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (xmlStrcmp(key, (const xmlChar *)"1")) { + xmlFree(key); + return 1; + } + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"MASTER"))) { + w1therm->master = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"BUS"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + w1therm->bus = ival; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) { + w1therm->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"ALIAS"))) { + w1therm->alias = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + cur = cur->next; + } + + if (Config.w1therms == NULL) { + Config.w1therms = w1therm; + } else { + for (tmp = Config.w1therms; tmp; tmp = tmp->next) { + if (tmp->next == NULL) { + tmp->next = w1therm; + break; + } + } + } + + return 0; +} + + + +int parseW1therms(xmlDocPtr doc, xmlNodePtr cur) +{ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"W1TERM"))) { + parseW1therm(doc, cur); + } + cur = cur->next; + } + return 0; +} + + + +/* + * Parse a fermenter unit + */ +int parseUnit(xmlDocPtr doc, xmlNodePtr cur) +{ + xmlChar *key; + int i, ival; + float val; + units_list *unit, *tmp; + + unit = (units_list *)malloc(sizeof(units_list)); + unit->next = NULL; + unit->uuid = unit->name = unit->air_address = unit->beer_address = unit->io1_address = unit->io2_address = unit->profile = NULL; + unit->volume = 0.0; + unit->heater_available = unit->cooler_available = unit->fan_available = FALSE; + unit->air_temp = unit->beer_temp = unit->beer_set = unit->fridge_set = 20.0; + unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = 0; + unit->temp_set_min = 1.0; + unit->temp_set_max = 30.0; + unit->idle_rangeH = 1.0; + unit->idle_rangeL = -1.0; + unit->prof_started = (time_t)0; + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"VERSION"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (xmlStrcmp(key, (const xmlChar *)"1")) { + xmlFree(key); + return 1; + } + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"UUID"))) { + unit->uuid = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) { + unit->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"VOLUME"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->volume = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"AIR_ADDRESS"))) { + unit->air_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"BEER_ADDRESS"))) { + unit->beer_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"IO1_ADDRESS"))) { + unit->io1_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"IO2_ADDRESS"))) { + unit->io2_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"HEATER"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (! xmlStrcmp(key, (const xmlChar *)"TRUE")) + unit->heater_available = TRUE; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"COOLER"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (! xmlStrcmp(key, (const xmlChar *)"TRUE")) + unit->cooler_available = TRUE; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"FAN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (! xmlStrcmp(key, (const xmlChar *)"TRUE")) + unit->fan_available = TRUE; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"MODE"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + for (i = 0; i < 5; i++) { + if (! xmlStrcmp(key, (const xmlChar *)UNITMODE[i])) { + unit->mode = i; + break; + } + } + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"BEER_SET"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->beer_set = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"FRIDGE_SET"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->fridge_set = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMP_SET_MIN"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->temp_set_min = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMP_SET_MAX"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->temp_set_max = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"IDLE_RANGE_L"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->idle_rangeL = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"IDLE_RANGE_H"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + unit->idle_rangeH = val; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROFILE"))) { + unit->profile = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROF_STARTED"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + unit->prof_started = ival; + xmlFree(key); + } + cur = cur->next; + } + + if (Config.units == NULL) { + Config.units = unit; + } else { + for (tmp = Config.units; tmp; tmp = tmp->next) { + if (tmp->next == NULL) { + tmp->next = unit; + break; + } + } + } + + return 0; +} + + + +int parseFermenters(xmlDocPtr doc, xmlNodePtr cur) +{ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"UNIT"))) { + parseUnit(doc, cur); + } + cur = cur->next; + } + return 0; +} + + + int rdconfig(char *config) { - char buf[256], *p; - FILE *fp; - int i, rc = 0; +// char buf[256], *p; +// FILE *fp; +// int i, rc = 0; + int rc = 0, ival; + xmlDocPtr doc; + xmlNodePtr cur; + xmlChar *key; killconfig(); @@ -489,28 +798,78 @@ } mypath = xstrcat(mypath, (char *)"/mbsepi-apps/"); mypath = xstrcat(mypath, config); - if ((fp = fopen(mypath, "r")) == NULL) { + if ((doc = xmlParseFile(mypath)) == NULL) { + //if ((fp = fopen(mypath, "r")) == NULL) { /* * Not in the users home directory */ free(mypath); mypath = xstrcpy((char *)"/etc/mbsepi-apps/"); mypath = xstrcat(mypath, config); - if ((fp = fopen(mypath, "r")) == NULL) { + if ((doc = xmlParseFile(mypath)) == NULL) { + //if ((fp = fopen(mypath, "r")) == NULL) { /* * Try /usr/local/etc */ free(mypath); mypath = xstrcpy((char *)"/usr/local/etc/mbsepi-apps/"); mypath = xstrcat(mypath, config); - if ((fp = fopen(mypath, "r")) == NULL) { - syslog(LOG_NOTICE, "rdconfig: could find %s", config); + if ((doc = xmlParseFile(mypath)) == NULL) { + //if ((fp = fopen(mypath, "r")) == NULL) { + syslog(LOG_NOTICE, "rdconfig: could not parse %s", config); return 1; } } } syslog(LOG_NOTICE, "rdconfig: using %s", mypath); + if ((cur = xmlDocGetRootElement(doc)) == NULL) { + syslog(LOG_NOTICE, "XML file %s empty.", mypath); + xmlFreeDoc(doc); + return 1; + } + if (xmlStrcmp(cur->name, (const xmlChar*)"THERMFERM")) { + syslog(LOG_NOTICE, "XML file %s is not a valid configuration file.\n", mypath); + xmlFreeDoc(doc); + return 1; + } + + /* + * Parse configuration + */ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + // VERSION LISTEN_PORT TEMPFORMAT LCDS FERMENTERS +// if ((!xmlStrcmp(cur->name, (const xmlChar *)"VERSION"))) { +// recipe->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); +// } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"LISTEN_PORT"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + Config.my_port = ival; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMPFORMAT"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + Config.tempFormat = key[0]; + xmlFree(key); + } +#ifdef HAVE_WIRINGPI_H + if ((!xmlStrcmp(cur->name, (const xmlChar *)"LCDS"))) { + parseLCDs(doc, cur); + } +#endif + if ((!xmlStrcmp(cur->name, (const xmlChar *)"W1TERMS"))) { + parseW1therms(doc, cur); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"FERMENTERS"))) { + parseFermenters(doc, cur); + } + cur = cur->next; + } + xmlFreeDoc(doc); + + /* linecnt = 0; while (fgets(buf, sizeof(buf) -1, fp)) { linecnt++; @@ -552,6 +911,7 @@ } fclose(fp); + */ free(mypath); mypath = NULL;