brewco/rdconfig.c

Sat, 07 Nov 2015 22:04:17 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 07 Nov 2015 22:04:17 +0100
changeset 409
cdf68044adaf
child 434
eb724767860d
permissions
-rw-r--r--

Added a new brewpanel program that runs on an SDL/X screen. It will be an emulator for the hardware panels. Development version 0.5.0

/*****************************************************************************
 * Copyright (C) 2015
 *   
 * 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 ThermFerm; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *****************************************************************************/

#include "rdconfig.h"
#include "brewco.h"
#include "futil.h"
#include "xutil.h"

int		debug = FALSE;
sys_config	Config;			/* System configuration		*/

#define MY_ENCODING "utf-8"

const char	TEMPSTATE[3][8] = { "OK", "MISSING", "ERROR" };
//const char	DEVTYPE[8][6] = { "NA", "W1", "GPIO", "RC433", "DHT", "I2C", "SPI", "SIM" };
//const char	DEVPRESENT[4][6] = { "UNDEF", "NO", "YES", "ERROR" };
//const char	DEVDIR[7][11] = { "UNDEF", "IN_BIN", "OUT_BIN", "IN_ANALOG", "OUT_ANALOG", "OUT_PWM", "INTERN" };
//const char	PIDMODE[3][5] = { "NONE", "AUTO", "BOO" };


void killconfig(void)
{

    if (Config.name)
	free(Config.name);
    Config.name = NULL;

    Config.tempFormat = 'C';
    if (Config.hlt_sensor_address)
	free(Config.hlt_sensor_address);
    if (Config.mlt_sensor_address)
	free(Config.mlt_sensor_address);
    Config.hlt_sensor_address = Config.mlt_sensor_address = NULL;
    Config.hlt_sensor_value = Config.mlt_sensor_value = 20000;
    Config.hlt_sensor_state = Config.mlt_sensor_state = 1;	// missing

#ifdef HAVE_WIRINGPI_H
    Config.lcd_cols = 16;
    Config.lcd_rows = 2;
#endif
}



int do_wrconfig(void);
int do_wrconfig(void)
{
    int			rc = 0;
    FILE		*fp;
    char		*mypath = NULL;
    xmlTextWriterPtr	writer;
    xmlBufferPtr	buf;

    /* 
     * 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 "BREWCO". Since thist is the first
     * element, this will be the root element of the document.
     */
    if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "BREWCO")) < 0) {
	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement");
	return 1;
    }

    /* 
     * Add an attribute with name "VERSION" and value "1" to BRWCO.
     */
    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 "NAME", "%s", Config.name)) < 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;
    }
    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_ADDRESS", "%s", Config.hlt_sensor_address)) < 0) {
	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
	return 1;
    }
    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_STATE", "%d", Config.hlt_sensor_state)) < 0) {
	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
	return 1;                           
    }
    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_VALUE", "%d", Config.hlt_sensor_value)) < 0) {
	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
	return 1;
    }
    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_ADDRESS", "%s", Config.mlt_sensor_address)) < 0) {
	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
	return 1;
    }   
    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_STATE", "%d", Config.mlt_sensor_state)) < 0) {
	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
	return 1;    
    }   
    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_VALUE", "%d", Config.mlt_sensor_value)) < 0) {
	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
	return 1;
    }

#ifdef HAVE_WIRINGPI_H
    /* 
     * Start an element named "LCDS" as child of BREWCO.
     */
    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

    /*
     * 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 *)"/.brewco/etc/");
    mkdirs(mypath, 0755);
    mypath = xstrcat(mypath, (char *)"brewco.xml");

    if (debug)
	fprintf(stdout, "Writing %s\n", mypath);

    if ((fp = fopen(mypath, "w")) == NULL) {
	syslog(LOG_NOTICE, "could not rewrite %s", mypath);
	free(mypath);
	return 1;
    }
    free(mypath);

    fprintf(fp, "%s", (const char *) buf->content);
    fclose(fp);
    xmlBufferFree(buf);

    return 0;
}



int wrconfig(void)
{
    int		rc;

    rc = do_wrconfig();
    syslog(LOG_NOTICE, "Rewritten configuration, rc=%d", rc);
    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 rdconfig(void) 
{
    int		rc = 0;
    char	*mypath;
    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 *)"/.brewco/etc/");
    mkdirs(mypath, 0755);
    mypath = xstrcat(mypath, (char *)"brewco.xml");
    if ((doc = xmlParseFile(mypath)) == NULL) {
	/*
	 * No config file, create a fresh one
	 */
	syslog(LOG_NOTICE, "rdconfig: %s not found, creating", mypath);
	wrconfig();

	if ((doc = xmlParseFile(mypath)) == NULL) {
	    syslog(LOG_NOTICE, "rdconfig: could not create %s", mypath);
	    free(mypath);
	    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*)"BREWCO")) {
	syslog(LOG_NOTICE, "XML file %s is not a valid configuration file.", mypath);
	xmlFreeDoc(doc);
	return 1;
    }

    /*
     * Parse configuration
     */
    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);
		syslog(LOG_NOTICE, "XML file %s is not a valid version", mypath);
		return 1;
	    }
	    xmlFree(key);
	}
	if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) {
	    Config.name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
	}
	if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMPFORMAT"))) {
	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
	    Config.tempFormat = key[0];
	    xmlFree(key);
	}
	if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_SENSOR_ADDRESS"))) {
	    Config.hlt_sensor_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
	}
	if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_SENSOR_ADDRESS"))) {
	    Config.mlt_sensor_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
	}
#ifdef HAVE_WIRINGPI_H
	if ((!xmlStrcmp(cur->name, (const xmlChar *)"LCDS"))) {
	    parseLCDs(doc, cur);
	}
#endif
	cur = cur->next;
    }
    xmlFreeDoc(doc);

    free(mypath);
    mypath = NULL;

    return rc;
}


mercurial