# HG changeset patch # User Michiel Broek # Date 1404421904 -7200 # Node ID 901ca9858a7a83cc8f708e320284161c3ed4c65b # Parent 28ee293654fdccdf44934ab3129c14d883d8d41d Added fermenting profiles to the configuration diff -r 28ee293654fd -r 901ca9858a7a thermferm/rdconfig.c --- a/thermferm/rdconfig.c Wed Jul 02 22:41:31 2014 +0200 +++ b/thermferm/rdconfig.c Thu Jul 03 23:11:44 2014 +0200 @@ -37,15 +37,16 @@ void killconfig(void) { - w1_therm *tmp1, *old1; - units_list *tmp2; + w1_therm *tmp1; + units_list *tmp2; + profiles_list *tmp3; + prof_step *tmp4; if (Config.name) free(Config.name); Config.name = NULL; - for (tmp1 = Config.w1therms; tmp1; tmp1 = old1) { - old1 = tmp1->next; + for (tmp1 = Config.w1therms; tmp1; tmp1 = tmp1->next) { if (tmp1->master) free(tmp1->master); if (tmp1->name) @@ -77,6 +78,20 @@ } Config.units = NULL; + for (tmp3 = Config.profiles; tmp3; tmp3 = tmp3->next) { + if (tmp3->uuid) + free(tmp3->uuid); + if (tmp3->name) + free(tmp3->name); + if (tmp3->steps) { + for (tmp4 = tmp3->steps; tmp4; tmp4 = tmp4->next) { + free(tmp4); + } + } + free(tmp3); + } + Config.profiles = NULL; + #ifdef HAVE_WIRINGPI_H Config.lcd_cols = 16; Config.lcd_rows = 2; @@ -96,6 +111,8 @@ xmlBufferPtr buf; w1_therm *tmp1; units_list *tmp3; + profiles_list *tmp4; + prof_step *tmp5; /* * Create a new XML buffer, to which the XML document will be written @@ -363,6 +380,74 @@ } /* + * Fermenting profiles + */ + if (Config.profiles) { + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "PROFILES")) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); + return 1; + } + for (tmp4 = Config.profiles; tmp4; tmp4 = tmp4->next) { + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "PROFILE")) < 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", tmp4->uuid)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", tmp4->name)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if (tmp4->steps) { + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "STEPS")) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterStartElement"); + return 1; + } + for (tmp5 = tmp4->steps; tmp5; tmp5 = tmp5->next) { + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "STEP")) < 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 "DURATION", "%d", tmp5->duration)) < 0) { + syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "TARGET", "%.1f", tmp5->target)) < 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; + } + } + 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) { @@ -686,8 +771,140 @@ { cur = cur->xmlChildrenNode; while (cur != NULL) { - if ((!xmlStrcmp(cur->name, (const xmlChar *)"UNIT"))) { - parseUnit(doc, cur); + if ((!xmlStrcmp(cur->name, (const xmlChar *)"UNIT"))) { + parseUnit(doc, cur); + } + cur = cur->next; + } + return 0; +} + + + +int parseStep(xmlDocPtr doc, xmlNodePtr cur, prof_step **profstep) +{ + xmlChar *key; + int ival; + float val; + prof_step *step, *tmp; + + step = (prof_step *)malloc(sizeof(prof_step)); + step->next = NULL; + step->version = 1; + step->duration = 0; + step->target = 20.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; + } + step->version = 1; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"DURATION"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + step->duration = ival; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"TARGET"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &val) == 1) + step->target = val; + xmlFree(key); + } + cur = cur->next; + } + + if (*profstep == NULL) { + *profstep = step; + } else { + for (tmp = *profstep; tmp; tmp = tmp->next) { + if (tmp->next == NULL) { + tmp->next = step; + break; + } + } + } + return 0; +} + + + +int parseSteps(xmlDocPtr doc, xmlNodePtr cur, prof_step **step) +{ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"STEP"))) { + parseStep(doc, cur, step); + } + cur = cur->next; + } + return 0; +} + + + +int parseProfile(xmlDocPtr doc, xmlNodePtr cur) +{ + xmlChar *key; + profiles_list *profile, *tmp; + + profile = (profiles_list *)malloc(sizeof(profiles_list)); + profile->next = NULL; + profile->version = 1; + profile->uuid = profile->name = NULL; + profile->steps = NULL; + + 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; + } + profile->version = 1; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"UUID"))) { + profile->uuid = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) { + profile->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"STEPS"))) { + parseSteps(doc, cur, &(profile)->steps); + } + cur = cur->next; + } + + if (Config.profiles == NULL) { + Config.profiles = profile; + } else { + for (tmp = Config.profiles; tmp; tmp = tmp->next) { + if (tmp->next == NULL) { + tmp->next = profile; + break; + } + } + } + + return 0; +} + + + +int parseProfiles(xmlDocPtr doc, xmlNodePtr cur) +{ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROFILE"))) { + parseProfile(doc, cur); } cur = cur->next; } @@ -784,6 +1001,9 @@ if ((!xmlStrcmp(cur->name, (const xmlChar *)"FERMENTERS"))) { parseFermenters(doc, cur); } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"PROFILES"))) { + parseProfiles(doc, cur); + } cur = cur->next; } xmlFreeDoc(doc); diff -r 28ee293654fd -r 901ca9858a7a thermferm/thermferm.h --- a/thermferm/thermferm.h Wed Jul 02 22:41:31 2014 +0200 +++ b/thermferm/thermferm.h Thu Jul 03 23:11:44 2014 +0200 @@ -51,12 +51,6 @@ #define MBSE_SS(x) (x)?(x):"(null)" -/* rdconfig.c */ -//typedef struct _key_list { -// char *key; -// int (*prc)(char **); -// char **dest; -//} key_list; /* * Fermenter units. These units are connected via the 1-wire bus. @@ -108,6 +102,29 @@ #define UNITIO2_FAN 0x01 /* Fan bit */ #define UNITIO2_DOOR 0x02 /* Door status */ + + +/* + * Fermenting steps + */ +typedef struct _prof_step { + struct _prof_step *next; + int version; /* Version 1 */ + int duration; /* Duration in hours */ + float target; /* Target temperature */ +} prof_step; + +/* + * Fermenting profiles + */ +typedef struct _prof_list { + struct _prof_list *next; + int version; /* Version 1 */ + char *uuid; /* Profile uuid */ + char *name; /* Profile name */ + prof_step *steps; /* Profile steps */ +} profiles_list; + #define PROFILE_OFF 0 /* Profile not active */ #define PROFILE_PAUSE 1 /* Profile pause */ #define PROFILE_RUN 2 /* Profile is running */ @@ -136,6 +153,7 @@ int lcd_address; /* LCD display i2c address */ #endif units_list *units; /* Fermenter units */ + profiles_list *profiles; /* Ferment profiles */ /* ControlSettings: */ unsigned char cs_mode; /* mode */ float cs_beerSet; /* beer temperature */