Thu, 26 Jun 2014 20:00:00 +0200
Switched to xml configuration
/***************************************************************************** * Copyright (C) 2014 * * Michiel Broek <mbroek at mbse dot eu> * * This file is part of the mbsePi-apps * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * mbsePi-apps is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with EC-65K; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ #include "thermferm.h" int debug = FALSE; static char *mypath; static char *k, *v; static int linecnt = 0; sys_config Config; /* System configuration */ #define MY_ENCODING "utf-8" const char UNITMODE[5][8] = { "OFF", "NONE", "FRIDGE", "BEER", "PROFILE" }; //static int getstr(char **); static int getw1(char **); #ifdef HAVE_WIRINGPI_H static int getint(char **); #endif static int getuch(char **); static int getfloat(char **); //static int getbyt(char **); //static int gethex(char **); #define XSTR(x) #x #define STR(x) XSTR(x) /* * System configuration table */ key_list keytab[] = { {(char *)"w1therm", getw1, (char **)&Config.w1therms}, #ifdef HAVE_WIRINGPI_H {(char *)"lcd_cols", getint, (char **)&Config.lcd_cols}, {(char *)"lcd_rows", getint, (char **)&Config.lcd_rows}, #endif {(char *)"cs_mode", getuch, (char **)&Config.cs_mode}, {(char *)"cs_beerSet", getfloat, (char **)&Config.cs_beerSet}, {(char *)"cs_fridgeSet", getfloat, (char **)&Config.cs_fridgeSet}, {(char *)"cs_heatEstimator", getfloat, (char **)&Config.cs_heatEstimator}, {(char *)"cs_coolEstimator", getfloat, (char **)&Config.cs_coolEstimator}, {(char *)"cc_tempFormat", getuch, (char **)&Config.tempFormat}, {(char *)"cc_tempSetMin", getfloat, (char **)&Config.cc_tempSetMin}, {(char *)"cc_tempSetMax", getfloat, (char **)&Config.cc_tempSetMax}, {(char *)"cc_idleRangeH", getfloat, (char **)&Config.cc_idleRangeH}, {(char *)"cc_idleRangeL", getfloat, (char **)&Config.cc_idleRangeL}, {NULL, NULL, NULL} }; void killconfig(void) { w1_therm *tmp1, *old1; units_list *tmp2; if (Config.name) free(Config.name); Config.name = NULL; for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) { old1 = tmp1->next; if (tmp1->master) free(tmp1->master); if (tmp1->name) free(tmp1->name); if (tmp1->alias) free(tmp1->alias); free(tmp1); } 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; Config.lcd_rows = 2; #endif defaultControlSettings(); defaultControlConstants(); } int wrconfig(char *config, char *confxml) { int rc = 0; FILE *fp; xmlTextWriterPtr writer; xmlBufferPtr buf; w1_therm *tmp1; units_list *tmp3; if (getenv((char *)"USER") == NULL) { mypath = xstrcpy((char *)"/root"); } else { mypath = xstrcpy(getenv((char *)"HOME")); } mypath = xstrcat(mypath, (char *)"/mbsepi-apps/"); mypath = xstrcat(mypath, config); if (debug) fprintf(stdout, "Writing %s\n", mypath); if ((fp = fopen(mypath, "w")) == NULL) { syslog(LOG_NOTICE, "could not rewrite %s", mypath); return 1; } fprintf(fp, "# Configuration file for thermferm %s\n", VERSION); fprintf(fp, "\n"); #ifdef HAVE_WIRINGPI_H fprintf(fp, "# LCD display\n"); fprintf(fp, "#\n"); fprintf(fp, "lcd_cols %d\n", Config.lcd_cols); fprintf(fp, "lcd_rows %d\n", Config.lcd_rows); fprintf(fp, "\n"); #endif fprintf(fp, "# DS18B20 temperature sensors on the 1-wire bus.\n"); fprintf(fp, "#\n"); fprintf(fp, "# kwd master bus name alias\n"); for (tmp1 = Config.w1therms; tmp1; tmp1 = tmp1->next) { fprintf(fp, "w1therm %s %d %s %s\n", tmp1->master, tmp1->bus, tmp1->name, tmp1->alias); } fprintf(fp, "\n"); fprintf(fp, "# Control Settings.\n"); fprintf(fp, "#\n"); fprintf(fp, "cs_mode %c\n", Config.cs_mode); fprintf(fp, "cs_beerSet %.1f\n", Config.cs_beerSet); fprintf(fp, "cs_fridgeSet %.1f\n", Config.cs_fridgeSet); fprintf(fp, "cs_heatEstimator %.1f\n", Config.cs_heatEstimator); fprintf(fp, "cs_coolEstimator %.1f\n", Config.cs_coolEstimator); fprintf(fp, "\n"); fprintf(fp, "# Control Constants.\n"); fprintf(fp, "#\n"); fprintf(fp, "cc_tempFormat %c\n", Config.tempFormat); fprintf(fp, "cc_tempSetMin %.1f\n", Config.cc_tempSetMin); fprintf(fp, "cc_tempSetMax %.1f\n", Config.cc_tempSetMax); fprintf(fp, "cc_idleRangeH %.1f\n", Config.cc_idleRangeH); fprintf(fp, "cc_idleRangeL %.1f\n", Config.cc_idleRangeL); fprintf(fp, "\n"); fprintf(fp, "# End of generated configuration\n"); fclose(fp); syslog(LOG_NOTICE, "Written %s rc=%d", mypath, rc); free(mypath); mypath = NULL; /* * Create a new XML buffer, to which the XML document will be written */ if ((buf = xmlBufferCreate()) == NULL) { syslog(LOG_NOTICE, "wrconfig: error creating the xml buffer"); return 1; } /* * Create a new XmlWriter for memory, with no compression. */ if ((writer = xmlNewTextWriterMemory(buf, 0)) == NULL) { syslog(LOG_NOTICE, "wrconfig: error creating the xml writer"); return 1; } /* * Use indentation instead of one long line */ if ((rc = xmlTextWriterSetIndent(writer, 2)) < 0) { syslog(LOG_NOTICE, "wrconfig: error setting Indent"); return 1; } /* * Start the document with the xml default for the version, * encoding ISO 8859-1 and the default for the standalone * declaration. */ if ((rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartDocument"); return 1; } /* * Start an element named "THERMFERM". Since thist is the first * element, this will be the root element of the document. */ if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "THERMFERM")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); return 1; } /* * Add an attribute with name "VERSION" and value "1" to THERMFERM. */ if ((rc = xmlTextWriterWriteElement(writer, BAD_CAST "VERSION", BAD_CAST "1")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "LISTEN_PORT", "%d", Config.my_port)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "TEMPFORMAT", "%c", Config.tempFormat)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } #ifdef HAVE_WIRINGPI_H /* * Start an element named "LCDS" as child of THERMFERM. */ if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "LCDS")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); return 1; } /* * Start one LCD. It is possible to connect 7 LCD displays on the i2c bus. * However this program doesn't use more then one yet. */ if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "LCD")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); return 1; } if ((rc = xmlTextWriterWriteElement(writer, BAD_CAST "VERSION", BAD_CAST "1")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ADDRESS", "0x%x", Config.lcd_address)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "COLUMNS", "%d", Config.lcd_cols)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ROWS", "%d", Config.lcd_rows)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } /* * Close the element named LCD. */ if ((rc = xmlTextWriterEndElement(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement"); return 1; } /* * Close the element LCDS. */ if ((rc = xmlTextWriterEndElement(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement"); return 1; } #endif /* * For backwards compatibility, the old setup */ if (Config.w1therms) { if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "W1THERMS")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); return 1; } for (tmp1 = Config.w1therms; tmp1; tmp1 = tmp1->next) { if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "W1THERM")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); return 1; } if ((rc = xmlTextWriterWriteElement(writer, BAD_CAST "VERSION", BAD_CAST "1")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MASTER", "%s", tmp1->master)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BUS", "%d", tmp1->bus)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", tmp1->name)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ALIAS", "%s", tmp1->alias)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterEndElement(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement"); return 1; } } if ((rc = xmlTextWriterEndElement(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement"); return 1; } } /* * Fermenter units */ if (Config.units) { if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "FERMENTERS")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); return 1; } for (tmp3 = Config.units; tmp3; tmp3 = tmp3->next) { /* * Only configuration items are written, measured values and states * are written to a state file. */ if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "UNIT")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); return 1; } if ((rc = xmlTextWriterWriteElement(writer, BAD_CAST "VERSION", BAD_CAST "1")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "UUID", "%s", tmp3->uuid)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", tmp3->name)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "VOLUME", "%.1f", tmp3->volume)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } 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 (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 (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 (tmp3->io2_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO2_ADDRESS", "%s", tmp3->io2_address)) < 0)) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HEATER", "%s", tmp3->heater_available ? "YES":"NO")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "COOLER", "%s", tmp3->cooler_available? "YES":"NO")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "FAN", "%s", tmp3->fan_available ? "YES":"NO")) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MODE", "%s", UNITMODE[tmp3->mode] )) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BEER_SET", "%.1f", tmp3->beer_set)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "FRIDGE_SET", "%.1f", tmp3->fridge_set)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "TEMP_SET_MIN", "%.1f", tmp3->temp_set_min)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "TEMP_SET_MAX", "%.1f", tmp3->temp_set_max)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IDLE_RANGE_L", "%.1f", tmp3->idle_rangeL)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IDLE_RANGE_H", "%.1f", tmp3->idle_rangeH)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if (tmp3->profile) { if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PROFILE", "%s", tmp3->profile)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "UUID", "%d", (unsigned int)tmp3->prof_started)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); return 1; } } if ((rc = xmlTextWriterEndElement(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement"); return 1; } } if ((rc = xmlTextWriterEndElement(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndElement"); return 1; } } /* * All done, close any open elements */ if ((rc = xmlTextWriterEndDocument(writer)) < 0) { syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterEndDocument"); return 1; } xmlFreeTextWriter(writer); /* * Now write the XML configuration */ if (getenv((char *)"USER") == NULL) { mypath = xstrcpy((char *)"/root"); } else { mypath = xstrcpy(getenv((char *)"HOME")); } mypath = xstrcat(mypath, (char *)"/mbsepi-apps/"); mypath = xstrcat(mypath, confxml); if (debug) fprintf(stdout, "Writing %s\n", mypath); if ((fp = fopen(mypath, "w")) == NULL) { syslog(LOG_NOTICE, "could not rewrite %s", mypath); return 1; } fprintf(fp, "%s", (const char *) buf->content); fclose(fp); xmlBufferFree(buf); return rc; } /* * 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; int rc = 0, ival; xmlDocPtr doc; xmlNodePtr cur; xmlChar *key; killconfig(); syslog(LOG_NOTICE, "HOME='%s' USER='%s' LOGNAME='%s'", MBSE_SS(getenv((char *)"HOME")), MBSE_SS(getenv((char *)"USER")), MBSE_SS(getenv((char *)"LOGNAME"))); /* * Search config file */ if (getenv((char *)"USER") == NULL) { mypath = xstrcpy((char *)"/root"); } else { mypath = xstrcpy(getenv((char *)"HOME")); } mypath = xstrcat(mypath, (char *)"/mbsepi-apps/"); mypath = xstrcat(mypath, config); 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 ((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 ((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++; if (*(p = buf + strlen(buf) -1) != '\n') { syslog(LOG_NOTICE, "rdconfig: %s(%d): \"%s\" - line too long", mypath, linecnt, buf); rc = 1; break; } *p-- = '\0'; while ((p >= buf) && isspace(*p)) *p-- = '\0'; k = buf; while (*k && isspace(*k)) k++; p = k; while (*p && !isspace(*p)) p++; *p++='\0'; v = p; while (*v && isspace(*v)) v++; if ((*k == '\0') || (*k == '#')) { continue; } for (i = 0; keytab[i].key; i++) if (strcasecmp(k,keytab[i].key) == 0) break; if (keytab[i].key == NULL) { syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - unknown keyword", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); rc = 1; break; } else if ((keytab[i].prc(keytab[i].dest))) { rc = 1; break; } } fclose(fp); */ free(mypath); mypath = NULL; return rc; } /* static int getstr(char **dest) { if (debug) syslog(LOG_NOTICE, "rdconfig: getstr: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); *dest = xstrcpy(v); return 0; } */ #ifdef HAVE_WIRINGPI_H static int getint(char **dest) { if (debug) syslog(LOG_NOTICE, "rdconfig: getint: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); if (strspn(v,"0123456789") != strlen(v)) syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - bad numeric", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); else *((int*)dest)=atoi(v); return 0; } #endif static int getw1(char **dest) { char *p, *q = NULL, *r = NULL; w1_therm **tmpm; int rc = 0, tmpp; for (p = v; *p && !isspace(*p); p++); if (*p) *p++ = '\0'; while (*p && isspace(*p)) p++; if (*p == '\0') { syslog(LOG_NOTICE, "rdconfig: %s(%d): less then two tokens", mypath, linecnt); return 1; } for (q = p; *q && !isspace(*q); q++); if (*q && isspace(*q)) { if (*q) *q++ = '\0'; while (*q && isspace(*q)) q++; for (r = q; *r && !isspace(*r); r++); if (*r) *r++ = '\0'; rc = sscanf(p, "%d", &tmpp); if (rc != 1) { syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s is not a integer value", mypath, linecnt, p); return 1; } if (debug) syslog(LOG_NOTICE, "rdconfig: getw1: %s(%d): %s %d %s %s", mypath, linecnt, v, tmpp, q, r); } for (tmpm = (w1_therm**)dest; *tmpm; tmpm=&((*tmpm)->next)); (*tmpm) = (w1_therm *) xmalloc(sizeof(w1_therm)); (*tmpm)->next = NULL; (*tmpm)->master = xstrcpy(v); (*tmpm)->bus = tmpp; (*tmpm)->name = xstrcpy(q); (*tmpm)->alias = xstrcpy(r); (*tmpm)->present = 0; (*tmpm)->lastval = 0; (*tmpm)->update = 0; return 0; } static int getuch(char **dest) { if (debug) syslog(LOG_NOTICE, "rdconfig: getuch: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); if (isalnum(v[0])) { *((unsigned char*)dest) = v[0]; } else { syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - bad character", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); } return 0; } static int getfloat(char **dest) { float val = 0.0; int rc; if (debug) syslog(LOG_NOTICE, "rdconfig: getfloat: %s(%d): %s %s", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); rc = sscanf(v, "%f", &val); if (rc != 1) { syslog(LOG_NOTICE, "rdconfig: %s(%d): %s %s - bad float value", mypath, linecnt, MBSE_SS(k), MBSE_SS(v)); return 1; } *((float*)dest) = val; return 0; } /* static int getbyt(char **dest) { Log_Msg("[rdconfig] getbyt: %s(%d): %s %s", mypath, linecnt, k, v); if (strspn(v,"0123456789") != strlen(v)) Log_Msg("[rdconfig] %s(%d): %s %s - bad numeric", mypath, linecnt, S(k), S(v)); else *((Uint8*)dest)=atoi(v); return 0; } */ /* static int gethex(char **dest) { unsigned int val = 0; int rc; Log_Msg("[rdconfig] gethex: %s(%d): %s %s", mypath, linecnt, k, v); rc = sscanf(v, "%08x", &val); if (rc != 1) { Log_Msg("[rdconfig] %s(%d): %s %s - bad hex value", mypath, linecnt, S(k), S(v)); return 1; } *((int*)dest) = val; return 0; } */