# HG changeset patch # User Michiel Broek # Date 1406236288 -7200 # Node ID 8bd209d1c020b953fdc862cd5a03004649c83da6 # Parent 528dc0bb81ab8562faf3bdc33f0ca9048a50366b Added some profile commands to the server. Profile names can be changed from the web interface. Removed obsolete commands. diff -r 528dc0bb81ab -r 8bd209d1c020 thermferm/server.c --- a/thermferm/server.c Thu Jul 24 20:45:15 2014 +0200 +++ b/thermferm/server.c Thu Jul 24 23:11:28 2014 +0200 @@ -410,6 +410,73 @@ /* + * PROFILE List profile status of current unit + * PROFILE uuid,name Rename profile name + */ +int cmd_profile(char *buf) +{ + char *opt, *uuid, *param; + profiles_list *profile; + units_list *unit; + + opt = strtok(buf, " \0"); + opt = strtok(NULL, "\0"); + + if (opt == NULL) { + /* + * Profile status of current unit + */ + if (current_unit == NULL) { + srv_send((char *)"401 No fermenter unit selected"); + return 1; + } + for (unit = Config.units; unit; unit = unit->next) { + if (strcmp(current_unit, unit->uuid) == 0) + break; + } + + if (unit->profile == NULL) { + srv_send((char *)"441 Unit has no profile"); + return 1; + } + if (unit->mode != UNITMODE_PROFILE) { + srv_send((char *)"442 Unit is not using a profile"); + return 1; + } + srv_send((char *)"241 Profile status follows:"); + + + srv_send((char *)"."); + return 1; + + } else { + /* + * uuid,name rename profile + */ + uuid = strtok(opt, ","); + param = strtok(NULL, "\0"); + fprintf(stdout, "uuid: '%s' param: '%s'\n", uuid, param); + for (profile = Config.profiles; profile; profile = profile->next) { + if (strcmp(profile->uuid, uuid) == 0) { + syslog(LOG_NOTICE, "Profile %s rename from '%s' to '%s'", uuid, profile->name, param); + if (profile->name) + free(profile->name); + profile->name = xstrcpy(param); + srv_send((char *)"240 Profile updated"); + return 0; + } + } + srv_send((char *)"440 No such profile"); + return 1; + } + + srv_send((char *)"502 Unknown command option"); + return 1; +} + + + +/* * SET BEER float * SET FRIDGE float * SET VOLUME float @@ -424,6 +491,7 @@ { char *opt, *param; units_list *unit; + profiles_list *profile; int rc; float fval; @@ -542,7 +610,28 @@ // TODO: change logfile name return 0; } else if (strcmp(opt, (char *)"PROFILE") == 0) { - // check profile file, excists, type, at least one profile item + /* + * Check for active profile, already selected etc. + */ + if (unit->profile && (unit->mode == UNITMODE_PROFILE)) { + srv_send((char *)"541 Cannot change profile while a profile is active"); + return 1; + } + if (unit->profile && (strcmp(unit->profile, param) == 0)) { + srv_send((char *)"542 Profile already set"); + return 1; + } + for (profile = Config.profiles; profile; profile = profile->next) { + if (strcmp(profile->uuid, param) == 0) { + if (unit->profile) + free(unit->profile); + unit->profile = xstrcpy(param); + srv_send((char *)"242 Unit profile changed to %s", param); + return 0; + } + } + srv_send((char *)"543 Invalid profile"); + return 1; } srv_send((char *)"502 Unknown command option"); @@ -592,10 +681,9 @@ void cmd_server(void) { - char *inp, *p, *q, buf[SS_BUFSIZE], obuf[SS_BUFSIZE]; - int i, rc, rlen; + char buf[SS_BUFSIZE]; + int i, rlen; socklen_t fromlen; - float newtemp; #ifdef HAVE_WIRINGPI_H int j; #endif @@ -634,27 +722,31 @@ srv_send((char *)"100 Help text follows"); srv_send((char *)"Recognized commands:"); srv_send((char *)""); - srv_send((char *)"ADD PROFILE name Add a new profile with \"name\""); - srv_send((char *)"ADD UNIT name Add a new unit with \"name\""); - srv_send((char *)"LCD Get LCD screen (allways 4 rows of 20 characters)"); - srv_send((char *)"LIST List all fermenter units"); - srv_send((char *)"LIST BUS List 1-wire bus"); - srv_send((char *)"LIST LOG List logfile data in 1 hour lines"); - srv_send((char *)"LIST PROFILES List available profiles"); - srv_send((char *)"LIST UNIT List fermenter unit"); +// 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + srv_send((char *)"ADD PROFILE name Add a new profile with \"name\""); + srv_send((char *)"ADD UNIT name Add a new unit with \"name\""); +// srv_send((char *)"DEL PROFILE uuid Delete profile with uuid"); +// srv_send((char *)"DEL UNIT uuid Delete unit with uuid"); + srv_send((char *)"LCD Get LCD screen (allways 4 rows of 20 characters)"); + srv_send((char *)"LIST List all fermenter units"); + srv_send((char *)"LIST BUS List 1-wire bus"); + srv_send((char *)"LIST LOG List logfile data in 1 hour lines"); + srv_send((char *)"LIST PROFILES List available profiles"); + srv_send((char *)"LIST UNIT List fermenter unit"); srv_send((char *)"MODE OFF|NONE|BEER|FRIDGE|PROFILE"); -// srv_send((char *)"PROFILE Profile status"); -// srv_send((char *)"PROFILE start|stop|pause Profile start, stop or pause"); - srv_send((char *)"SET BEER val Set beer temperature"); - srv_send((char *)"SET FRIDGE val Set fridge temperature"); - srv_send((char *)"SET IDLE_LOW val Set idle temperature low (-5.0 .. -0.1)"); - srv_send((char *)"SET IDLE_HIGH val Set idle temperature high (0.1 .. 5.0)"); - srv_send((char *)"SET NAME name Set name or beername for the unit"); -// srv_send((char *)"SET PROFILE uuid,name Set named profile"); - srv_send((char *)"SET TEMP_MIN val Set unit minimum temperature"); - srv_send((char *)"SET TEMP_MAX val Set unit maximum temperature"); - srv_send((char *)"SET VOLUME val Set unit volume"); - srv_send((char *)"UNIT uuid Select unit by uuid"); +// srv_send((char *)"PROFILE Profile status of current unit"); + srv_send((char *)"PROFILE uuid,name Profile rename"); + srv_send((char *)"SET BEER val Set beer temperature"); + srv_send((char *)"SET FRIDGE val Set fridge temperature"); + srv_send((char *)"SET IDLE_LOW val Set idle temperature low (-5.0 .. -0.1)"); + srv_send((char *)"SET IDLE_HIGH val Set idle temperature high (0.1 .. 5.0)"); + srv_send((char *)"SET NAME name Set name or beername for the unit"); + srv_send((char *)"SET PROFILE uuid Set unit profile"); +// srv_send((char *)"SET PROFILE start|stop|pause Profile start, stop or pause"); + srv_send((char *)"SET TEMP_MIN val Set unit minimum temperature"); + srv_send((char *)"SET TEMP_MAX val Set unit maximum temperature"); + srv_send((char *)"SET VOLUME val Set unit volume"); + srv_send((char *)"UNIT uuid Select unit by uuid"); srv_send((char *)"."); } else if (strncmp(buf, "LCD", 3) == 0) { #ifdef HAVE_WIRINGPI_H @@ -674,143 +766,18 @@ cmd_list(buf); } else if (strncmp(buf, "MODE", 4) == 0) { cmd_mode(buf); + } else if (strncmp(buf, "PROFILE", 7) == 0) { + if (cmd_profile(buf) == 0) + wrconfig(); } else if (strncmp(buf, "SET", 3) == 0) { if (cmd_set(buf) == 0) wrconfig(); } else if (strncmp(buf, "UNIT", 4) == 0) { cmd_unit(buf); - - /* - * Now the old style (brewPi) commands. These will go away. - */ - } else if (strncmp(buf, "ack", 3) == 0) { - srv_send((char *)"ack"); - } else if (strncmp(buf, "lcd", 3) == 0) { - sprintf(obuf, "[\" \", \" \", \" \", \" \"]"); -#ifdef HAVE_WIRINGPI_H - for (i = 0; i < 20; i++) { - obuf[i+2] = lcdbuf[lcdHandle][i][0]; - obuf[i+26] = lcdbuf[lcdHandle][i][1]; - obuf[i+50] = lcdbuf[lcdHandle][i][2]; - obuf[i+74] = lcdbuf[lcdHandle][i][3]; - } -#endif - srv_send(obuf); - } else if (strncmp(buf, "getMode", 7) == 0) { - srv_send("%c", UNITmode[Config.units->mode]); - } else if (strncmp(buf, "getFridge", 9) == 0) { - srv_send("%.1f", Config.units->fridge_set); - } else if (strncmp(buf, "getBeer", 7) == 0) { - srv_send("%.1f", Config.units->beer_set); - } else if (strncmp(buf, "getControlConstants", 19) == 0) { - srv_send("{ \"tempFormat\":\"%c\", \"tempSetMin\":%.1f, \"tempSetMax\":%.1f, \"idleRangeH\":%.3f, \"idleRangeL\":%.3f }", - Config.tempFormat, Config.units->temp_set_min, Config.units->temp_set_max, Config.units->idle_rangeH, Config.units->idle_rangeL); - } else if (strncmp(buf, "getControlSettings", 18) == 0) { - srv_send("{ \"mode\":\"%c\", \"beerSet\":%.1f, \"fridgeSet\":%.1f, \"heatEstimator\":%.1f, \"coolEstimator\":%.1f }", - UNITmode[Config.units->mode], Config.units->beer_set, Config.units->fridge_set, cs_heatEstimator, cs_coolEstimator); - } else if (strncmp(buf, "getControlVariables", 19) == 0) { - srv_send("{ \"beerDiff\":%.2f }", cv_beerDiff); - } else if (strncmp(buf, "loadDefaultControlSettings", 26) == 0) { - // Does nothing anymore - srv_send("ack"); - } else if (strncmp(buf, "loadDefaultControlConstants", 27) == 0) { - // Does nothing anymore - srv_send("ack"); - } else if (strncmp(buf, "setBeer=", 8) == 0) { - inp = xstrcpy(buf+8); - rc = sscanf(inp, "%f", &newtemp); - if (debug) - fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc); - if (rc == 1) { - if ((Config.units->temp_set_min <= newtemp) && (newtemp <= Config.units->temp_set_max)) { - syslog(LOG_NOTICE, "Beer temperature set to %.1f degrees in web interface", newtemp); - srv_send("ack"); - Config.units->mode = UNITMODE_BEER; - Config.units->beer_set = newtemp; - } else { - syslog(LOG_NOTICE, "Beer temperature setting %.1f is outside of allowed range %.1f - %.1f", newtemp, Config.units->temp_set_min, Config.units->temp_set_max); - srv_send("err"); - } - } else { - syslog(LOG_NOTICE, "Cannot convert temperature '%s' to float", inp); - srv_send("err"); - } - free(inp); - } else if (strncmp(buf, "setFridge=", 10) == 0) { - inp = xstrcpy(buf+10); - rc = sscanf(inp, "%f", &newtemp); - if (debug) - fprintf(stdout, "new temp from %s, %.1f, rc=%d\n", inp, newtemp, rc); - if (rc == 1) { - if ((Config.units->temp_set_min <= newtemp) && (newtemp <= Config.units->temp_set_max)) { - syslog(LOG_NOTICE, "Fridge temperature set to %.1f degrees in web interface", newtemp); - srv_send("ack"); - Config.units->mode = UNITMODE_FRIDGE; - Config.units->fridge_set = newtemp; - } else { - syslog(LOG_NOTICE, "Fridge temperature setting %.1f is outside of allowed range %.1f - %.1f", newtemp, Config.units->temp_set_min, Config.units->temp_set_max); - srv_send("err"); - } - } else { - syslog(LOG_NOTICE, "Cannot convert temperature '%s' to float", inp); - srv_send("err"); - } - free(inp); - } else if (strncmp(buf, "setOff", 6) == 0) { - if (debug) - fprintf(stdout, "temperature control disabled\n"); - syslog(LOG_NOTICE, "Notification: Temperature control disabled"); - Config.units->mode = UNITMODE_OFF; - srv_send("ack"); - } else if (strncmp(buf, "setParameters=", 14) == 0) { - inp = xstrcpy(buf+14); /* {"tempSetMax":30.5} */ - if (debug) - fprintf(stdout, "setParameters: %s\n", inp); - strtok(inp, (char *)"\""); - p = strtok(NULL, (char *)"\""); - q = strtok(NULL, (char *)":,}"); - if (strcmp(p, (char *)"tempSetMin") == 0) { - rc = sscanf(q, "%f", &newtemp); - if (rc == 1) { - syslog(LOG_NOTICE, "cc_tempSetMin = %1.f", newtemp); - Config.units->temp_set_min = newtemp; - srv_send("ack"); - } else { - srv_send("ERR"); - } - } else if (strcmp(p, (char *)"tempSetMax") == 0) { - rc = sscanf(q, "%f", &newtemp); - if (rc == 1) { - syslog(LOG_NOTICE, "cc_tempSetMax = %1.f", newtemp); - Config.units->temp_set_max = newtemp; - srv_send("ack"); - } else { - srv_send("ERR"); - } - } else { - fprintf(stdout, "p='%s' q='%s' inp='%s'\n", p, q, inp); - srv_send("ERR"); - } - free(inp); - // stopScript - // quit - // eraseLogs - // interval - // startNewBrew - // pauseLogging - // stopLogging - // resumeLogging - // dateTimeFormatDisplay - } else if (strncmp(buf, "setActiveProfile", 16) == 0) { - syslog(LOG_NOTICE, "Setting profile '%s' as active profile", "undefined"); - // programArduino - // refreshDeviceList - // getDeviceList - // applyDevice } else { if (debug) fprintf(stdout, "unknown command \"%s\"\n", buf); - srv_send((char *)"ERR"); + srv_send((char *)"500 Unknown command"); } } } @@ -819,6 +786,7 @@ } + #ifdef HAVE_WIRINGPI_H PI_THREAD (my_server_loop) #else diff -r 528dc0bb81ab -r 8bd209d1c020 thermferm/thermferm.h --- a/thermferm/thermferm.h Thu Jul 24 20:45:15 2014 +0200 +++ b/thermferm/thermferm.h Thu Jul 24 23:11:28 2014 +0200 @@ -88,7 +88,7 @@ float temp_set_max; /* Maximum temperature */ float idle_rangeL; /* Idle temperature low */ float idle_rangeH; /* Idle range high */ - char *profile; /* Active profile */ + char *profile; /* Active profile uuid */ time_t prof_started; /* Profile start time */ int prof_state; /* Profile OFF|PAUSE|RUN|DONE */ } units_list; diff -r 528dc0bb81ab -r 8bd209d1c020 www-thermferm/getprofiles.php --- a/www-thermferm/getprofiles.php Thu Jul 24 20:45:15 2014 +0200 +++ b/www-thermferm/getprofiles.php Thu Jul 24 23:11:28 2014 +0200 @@ -24,6 +24,33 @@ require_once('utilities.php'); + +if (isset($_GET['update'])) { + /* + * Build the update command + */ + $update_cmd = "PROFILE ".$_GET['UUID'].",".$_GET['Name']; + + $sock = open_socket(); + if ($sock != false) { + /* + * Send command and absorb the result. + */ + socket_write($sock, $update_cmd, 4096); + while (1) { + $line = socket_read($sock, 4096); + if ($line === '') + break; + } + socket_close($sock); + } +} + + + +/* + * Get current profiles + */ $sock = open_socket(); if ($sock == false) { echo ""; @@ -40,9 +67,8 @@ } socket_close($sock); $arr = explode("\r\n", $answer); - +$row = '['; -$row = '['; /* We don't use json_encode because it doesn't work for our purpose */ if (startsWith($arr[0], "212")) { diff -r 528dc0bb81ab -r 8bd209d1c020 www-thermferm/js/maintenance_panel.js --- a/www-thermferm/js/maintenance_panel.js Thu Jul 24 20:45:15 2014 +0200 +++ b/www-thermferm/js/maintenance_panel.js Thu Jul 24 23:11:28 2014 +0200 @@ -21,6 +21,10 @@ *****************************************************************************/ $(document).ready(function () { + + var data = {}; + var theme = 'ui-redmond'; + /* * 1-Wire bus */ @@ -38,7 +42,7 @@ $("#jqxgrid_bus").jqxGrid( { width: 770, height: 280, source: dataAdapter_bus, - theme: 'ui-redmond', + theme: theme, columnsresize: true, columns: [ { text: 'Address', datafield: 'Address', width: 150 }, @@ -58,19 +62,37 @@ { name: 'Name', type: 'string' }, { name: 'Steps', type: 'int' } ], - url: 'getprofiles.php' + url: 'getprofiles.php', + updaterow: function (rowid, rowdata, commit) { + // synchronize with the server - send update command + var data = "update=true&UUID=" + rowdata.UUID + "&Name=" + rowdata.Name; + $.ajax({ + dataType: 'json', + url: 'getprofiles.php', + data: data, + success: function (data, status, xhr) { + // update command is executed. + commit(true); + }, + error: function () { + // cancel changes. + commit(false); + } + }); + } }; var dataAdapter_profiles = new $.jqx.dataAdapter(source_profiles); $("#jqxgrid_profiles").jqxGrid( { width: 770, height: 280, + selectionmode: 'singlecell', source: dataAdapter_profiles, - theme: 'ui-redmond', + theme: theme, columnsresize: true, editable: true, columns: [ { text: 'UUID', editable: false, datafield: 'UUID', width: 280 }, { text: 'Name', datafield: 'Name', minwidth: 120 }, - { text: 'Steps', datafield: 'Steps', width: 50 } + { text: 'Steps', editable: false, datafield: 'Steps', width: 50 } ] }); @@ -90,7 +112,7 @@ $("#jqxgrid_units").jqxGrid( { width: 770, height: 280, source: dataAdapter_units, - theme: 'ui-redmond', + theme: theme, columnsresize: true, editable: true, columns: [