--- a/thermferm/server.c Sat Aug 02 22:33:15 2014 +0200 +++ b/thermferm/server.c Sun Aug 03 22:49:33 2014 +0200 @@ -41,6 +41,7 @@ extern const char DEVTYPE[7][6]; extern const char DEVPRESENT[4][6]; extern const char DEVDIR[7][11]; +extern const char PROFSTATE[4][6]; int s; /* connected socket */ @@ -98,11 +99,9 @@ /* * ADD PROFILE name - * ADD UNIT name */ int unit_add(char *buf) { - units_list *unit, *tmpu; profiles_list *profile, *tmpp; uuid_t uu; char *opt, *param; @@ -148,45 +147,6 @@ syslog(LOG_NOTICE, "Profile \"%s\" with uuid %s added", param, profile->uuid); srv_send((char *)"211 Profile \"%s\" with uuid %s added", param, profile->uuid); return 0; - - } else if (strcmp(opt, (char *)"UNIT") == 0) { - unit = (units_list *)malloc(sizeof(units_list)); - unit->next = NULL; - unit->version = 1; - unit->uuid = malloc(37); - uuid_generate(uu); - uuid_unparse(uu, unit->uuid); - if (current_unit) - free(current_unit); - current_unit = xstrcpy(unit->uuid); - unit->name = xstrcpy(param); - unit->air_address = unit->beer_address = unit->io1_address = unit->io2_address = unit->profile = NULL; - unit->volume = 0.0; - unit->air_state = unit->beer_state = 1; - unit->heater_available = unit->cooler_available = unit->fan_available = FALSE; - unit->air_temperature = unit->beer_temperature = 20000; - unit->beer_set = unit->fridge_set = 20.0; - unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = unit->prof_state = 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; - - if (Config.units == NULL) { - Config.units = unit; - } else { - for (tmpu = Config.units; tmpu; tmpu = tmpu->next) { - if (tmpu->next == NULL) { - tmpu->next = unit; - break; - } - } - } - - syslog(LOG_NOTICE, "Unit with uuid %s added", unit->uuid); - srv_send((char *)"211 Unit with uuid %s added", unit->uuid); - return 0; } srv_send((char *)"502 Unknown command option"); @@ -202,7 +162,6 @@ profiles_list *previous = NULL; prof_step *step, *olds; - while (current) { if (strcmp(current->uuid, uuid) == 0) { if (previous == NULL) { @@ -351,7 +310,7 @@ if (strcmp(opt, (char *)"LIST") == 0) { srv_send((char *)"212 bus devices:"); for (device = Config.devices; device; device = device->next) { - srv_send((char *)"%s,%s,%d,%d,%s", device->uuid, device->address, device->subdevice, device->inuse, device->comment); + srv_send((char *)"%s,%s,%d,%d,%s,%s", device->uuid, device->address, device->subdevice, device->inuse, device->comment, DEVDIR[device->direction]); } srv_send((char *)"."); return 0; @@ -547,7 +506,6 @@ * LIST * LIST LOG * LIST PROFILES - * LIST UNIT */ int cmd_list(char *buf) { @@ -627,63 +585,6 @@ } srv_send((char *)"."); return 0; - - } else if (strcmp(opt, (char *)"UNIT") == 0) { - /* - * List configured and selected fermenter unit - */ - if (current_unit == NULL) { - srv_send((char *)"401 No fermenter unit selected"); - return 1; - } - - srv_send((char *)"213 Unit %s listing follows:", current_unit); - for (unit = Config.units; unit; unit = unit->next) { - if (strcmp(current_unit, unit->uuid) == 0) { - srv_send((char *)"NAME,%s", unit->name); - srv_send((char *)"UUID,%s", unit->uuid); - if (unit->air_address) { - srv_send((char *)"AIR_ADDRESS,%s", unit->air_address); - srv_send((char *)"AIR_STATE,%s", TEMPSTATE[unit->air_state]); - srv_send((char *)"AIR_TEMPERATURE,%.3f", unit->air_temperature / 1000.0); - } - if (unit->beer_address) { - srv_send((char *)"BEER_ADDRESS,%s", unit->beer_address); - srv_send((char *)"BEER_STATE,%s", TEMPSTATE[unit->beer_state]); - srv_send((char *)"BEER_TEMPERATURE,%.3f", unit->beer_temperature / 1000.0); - } - if (unit->io1_address) { - srv_send((char *)"IO1_ADDRESS,%s", unit->io1_address); - } - if (unit->io2_address) { - srv_send((char *)"IO2_ADDRESS,%s", unit->io2_address); - } - if (unit->heater_available) { - srv_send((char *)"HEATER_AVAILABLE,%s", unit->heater_available); - srv_send((char *)"HEATER_STATE,%d", unit->heater_state); - } - if (unit->cooler_available) { - srv_send((char *)"COOLER_AVAILABLE,%s", unit->cooler_available); - srv_send((char *)"COOLER_STATE,%d", unit->cooler_state); - } - if (unit->fan_available) { - srv_send((char *)"FAN_AVAILABLE,%s", unit->fan_available); - srv_send((char *)"FAN_STATE,%d", unit->fan_state); - } - srv_send((char *)"MODE,%s", UNITMODE[unit->mode]); - srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set); - srv_send((char *)"BEER_SET,%.1f", unit->beer_set); - if (unit->profile) { - srv_send((char *)"PROFILE,%s", unit->profile); - } - srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min); - srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max); - srv_send((char *)"IDLE_RANGE_L,%.1f", unit->idle_rangeL); - srv_send((char *)"IDLE_RANGE_H,%.1f", unit->idle_rangeH); - } - } - srv_send((char *)"."); - return 0; } srv_send((char *)"502 Unknown command option"); @@ -935,14 +836,6 @@ /* - * SET BEER float - * SET FRIDGE float - * SET VOLUME float - * SET IDLE_LOW float - * SET IDLE_HIGH float - * SET TEMP_MIN float - * SET TEMP_MAX float - * SET NAME string * SET PROFILE string */ int cmd_set(char *buf) @@ -984,90 +877,7 @@ break; } - /* - * If a valid parameter float value - */ - if (rc == 1) { - if (strcmp(opt, (char *)"BEER") == 0) { - if ((fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) { - unit->beer_set = fval; - srv_send((char *)"214 Unit %s BEER set to %.1f", current_unit, fval); - return 0; - } else { - srv_send((char *)"510 New temperature not between %.1f and %.1f", unit->temp_set_min, unit->temp_set_max); - return 1; - } - } else if (strcmp(opt, (char *)"FRIDGE") == 0) { - if ((fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) { - unit->fridge_set = fval; - srv_send((char *)"214 Unit %s BEER set to %.1f", current_unit, fval); - return 0; - } else { - srv_send((char *)"510 New temperature not between %.1f and %.1f", unit->temp_set_min, unit->temp_set_max); - return 1; - } - } else if (strcmp(opt, (char *)"VOLUME") == 0) { - /* - * Must fit in a 2 TEU container - */ - if ((fval >= 0.0) && (fval <= 77020.0)) { - unit->volume = fval; - srv_send((char *)"214 Unit %s VOLUME set to %.1f", current_unit, fval); - return 0; - } else { - srv_send((char *)"510 New volume not between 0 and 77020"); - return 1; - } - } else if (strcmp(opt, (char *)"IDLE_LOW") == 0) { - if ((fval >= -5.0) && (fval <= -0.1)) { - unit->idle_rangeL = fval; - srv_send((char *)"214 Unit %s IDLE_LOW set to %.1f", current_unit, fval); - return 0; - } else { - srv_send((char *)"510 New value not between -5.0 and -0.1"); - return 1; - } - } else if (strcmp(opt, (char *)"IDLE_HIGH") == 0) { - if ((fval >= 0.1) && (fval <= 5.0)) { - unit->idle_rangeH = fval; - srv_send((char *)"214 Unit %s IDLE_HIGH set to %.1f", current_unit, fval); - return 0; - } else { - srv_send((char *)"510 New value not between -5.0 and -0.1"); - return 1; - } - } else if (strcmp(opt, (char *)"TEMP_MIN") == 0) { - if ((fval >= -2.0) && (fval <= 35.0) && (fval < unit->temp_set_max)) { - unit->temp_set_min = fval; - srv_send((char *)"214 Unit %s TEMP_MIN set to %.1f", current_unit, fval); - return 0; - } else { - srv_send((char *)"510 New value not between -2.0 and 35.0 and lower then TEMP_MAX"); - return 1; - } - } else if (strcmp(opt, (char *)"TEMP_MAX") == 0) { - if ((fval >= -2.0) && (fval <= 35.0) && (fval > unit->temp_set_min)) { - unit->temp_set_max = fval; - srv_send((char *)"214 Unit %s TEMP_MAX set to %.1f", current_unit, fval); - return 0; - } else { - srv_send((char *)"510 New value not between -2.0 and 35.0 and higher then TEMP_MIN"); - return 1; - } - } - } - - /* - * Set new unit or beer name - */ - if (strcmp(opt, (char *)"NAME") == 0) { - if (unit->name) - free(unit->name); - unit->name = xstrcpy(param); - srv_send((char *)"214 Unit %s NAME set to '%s'", current_unit, param); - // TODO: change logfile name - return 0; - } else if (strcmp(opt, (char *)"PROFILE") == 0) { + if (strcmp(opt, (char *)"PROFILE") == 0) { /* * Check for active profile, already selected etc. */ @@ -1098,13 +908,98 @@ +int delete_Unit(char *uuid) +{ + units_list *current = Config.units; + units_list *previous = NULL; + + while (current) { + if (strcmp(current->uuid, uuid) == 0) { + if (previous == NULL) { + Config.units = current->next; + free(current->uuid); + current->uuid = NULL; + free(current->name); + current->name = NULL; + if (current->air_address) + free(current->air_address); + current->air_address = NULL; + if (current->beer_address) + free(current->beer_address); + current->beer_address = NULL; + if (current->heater_address) + free(current->heater_address); + current->heater_address = NULL; + if (current->cooler_address) + free(current->cooler_address); + current->cooler_address = NULL; + if (current->fan_address) + free(current->fan_address); + current->fan_address = NULL; + if (current->door_address) + free(current->door_address); + current->door_address = NULL; + if (current->profile) + free(current->profile); + current->profile = NULL; + free(current); + return 1; + } else { + free(current->uuid); + current->uuid = NULL; + free(current->name); + current->name = NULL; + if (current->air_address) + free(current->air_address); + current->air_address = NULL; + if (current->beer_address) + free(current->beer_address); + current->beer_address = NULL; + if (current->heater_address) + free(current->heater_address); + current->heater_address = NULL; + if (current->cooler_address) + free(current->cooler_address); + current->cooler_address = NULL; + if (current->fan_address) + free(current->fan_address); + current->fan_address = NULL; + if (current->door_address) + free(current->door_address); + current->door_address = NULL; + if (current->profile) + free(current->profile); + current->profile = NULL; + free(current); + current = previous->next; + return 1; + } + } else { + previous = current; + current = current->next; + } + } + return 0; +} + + + /* * UNIT uuid + * UNIT ADD name + * UNIT DEL uuid + * UNIT LIST + * UNIT GET uuid + * UNIT PUT uuid */ int cmd_unit(char *buf) { - char *opt; - units_list *tmp; + char *opt, *param = NULL, *kwd, *val, ibuf[SS_BUFSIZE]; + units_list *unit, *tmpu; + uuid_t uu; + socklen_t fromlen; + int i, rlen; + float fval; opt = strtok(buf, " \0"); opt = strtok(NULL, " \0"); @@ -1113,24 +1008,271 @@ srv_send((char *)"501 Parameter missing"); return 1; } + param = strtok(NULL, "\0"); - if (strlen(opt) == 36) { + /* + * UNIT uuid + */ + if ((strlen(opt) == 36) && (param == NULL)) { /* * Search using uuid */ - for (tmp = Config.units; tmp; tmp = tmp->next) { - if (strcmp(opt, tmp->uuid) == 0) { - srv_send((char *)"210 Unit %s selected", tmp->uuid); + for (unit = Config.units; unit; unit = unit->next) { + if (strcmp(opt, unit->uuid) == 0) { + srv_send((char *)"210 Unit %s selected", unit->uuid); if (current_unit) free(current_unit); - current_unit = xstrcpy(tmp->uuid);; - return 0; + current_unit = xstrcpy(unit->uuid);; + return 1; + } + } + srv_send((char *)"410 No such unit"); + return 1; + } + + if ((strcmp(opt, (char *)"LIST") == 0) && (param == NULL)) { + srv_send((char *)"212 Fermenter Units list follows:"); + for (unit = Config.units; unit; unit = unit->next) { + srv_send((char *)"%s,%s,%s", unit->uuid, unit->name, UNITMODE[unit->mode]); + } + srv_send((char *)"."); + return 1; + } + + if (param == NULL) { + srv_send((char *)"501 Parameter missing"); + return 1; + } + + if (strcmp(opt, (char *)"ADD") == 0) { + unit = (units_list *)malloc(sizeof(units_list)); + unit->next = NULL; + unit->version = 1; + unit->uuid = malloc(37); + uuid_generate(uu); + uuid_unparse(uu, unit->uuid); + if (current_unit) + free(current_unit); + current_unit = xstrcpy(unit->uuid); + unit->name = xstrcpy(param); + unit->air_address = unit->beer_address = unit->heater_address = unit->cooler_address = \ + unit->fan_address = unit->door_address = unit->profile = NULL; + unit->volume = 0.0; + unit->air_state = unit->beer_state = 1; + unit->air_temperature = unit->beer_temperature = 20000; + unit->beer_set = unit->fridge_set = 20.0; + unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = unit->prof_state = 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; + + if (Config.units == NULL) { + Config.units = unit; + } else { + for (tmpu = Config.units; tmpu; tmpu = tmpu->next) { + if (tmpu->next == NULL) { + tmpu->next = unit; + break; + } + } + } + + syslog(LOG_NOTICE, "Unit with uuid %s added", unit->uuid); + srv_send((char *)"211 Unit with uuid %s added", unit->uuid); + return 0; + } + + if (strcmp(opt, (char *)"DEL") == 0) { + if (delete_Unit(param)) { + syslog(LOG_NOTICE, "Deleted Unit with %s", param); + srv_send((char *)"211 Unit %s deleted", param); + return 0; + } else { + srv_send((char *)"440 Delete Unit: No such unit %s", param); + return 1; + } + } + + if (strcmp(opt, (char *)"GET") == 0) { + for (unit = Config.units; unit; unit = unit->next) { + if (strcmp(param, unit->uuid) == 0) { + srv_send((char *)"213 Unit %s listing follows:", unit->uuid); + srv_send((char *)"NAME,%s", unit->name); + srv_send((char *)"UUID,%s", unit->uuid); + srv_send((char *)"VOLUME,%2f", unit->volume); + srv_send((char *)"AIR_ADDRESS,%s", unit->air_address); + srv_send((char *)"AIR_STATE,%s", TEMPSTATE[unit->air_state]); + srv_send((char *)"AIR_TEMPERATURE,%.3f", unit->air_temperature / 1000.0); + srv_send((char *)"BEER_ADDRESS,%s", MBSE_SS(unit->beer_address)); + srv_send((char *)"BEER_STATE,%s", TEMPSTATE[unit->beer_state]); + srv_send((char *)"BEER_TEMPERATURE,%.3f", unit->beer_temperature / 1000.0); + srv_send((char *)"HEATER_ADDRESS,%s", unit->heater_address); + srv_send((char *)"HEATER_STATE,%d", unit->heater_state); + srv_send((char *)"COOLER_ADDRESS,%s", unit->cooler_address); + srv_send((char *)"COOLER_STATE,%d", unit->cooler_state); + srv_send((char *)"FAN_ADDRESS,%s", unit->fan_address); + srv_send((char *)"FAN_STATE,%d", unit->fan_state); + srv_send((char *)"DOOR_ADDRESS,%s", unit->door_address); + srv_send((char *)"DOOR_STATE,%d", unit->door_state); + srv_send((char *)"MODE,%s", UNITMODE[unit->mode]); + srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set); + srv_send((char *)"BEER_SET,%.1f", unit->beer_set); + srv_send((char *)"PROFILE,%s", unit->profile); + if (unit->profile) { + srv_send((char *)"PROF_STARTED,%d", (int)unit->prof_started); + srv_send((char *)"PROF_STATE,%s", PROFSTATE[unit->prof_state]); + srv_send((char *)"PROF_TARGET,%.3f", unit->prof_target); + } + srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min); + srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max); + srv_send((char *)"IDLE_RANGE_L,%.1f", unit->idle_rangeL); + srv_send((char *)"IDLE_RANGE_H,%.1f", unit->idle_rangeH); + srv_send((char *)"."); + return 1; } } srv_send((char *)"410 No such unit"); return 1; } + if (strcmp(opt, (char *)"PUT") == 0) { + for (unit = Config.units ; unit; unit = unit->next) { + if (strcmp(unit->uuid, param) == 0) { + while (1) { + memset((char *)&ibuf, 0, SS_BUFSIZE); + fromlen = sizeof(peeraddr_in); + rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen); + if (rlen == -1) { + syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno)); + srv_send((char *)"518 recfrom(): %s", strerror(errno)); + return 1; + } + for (i = 0; i < strlen(ibuf); i++) { + if (ibuf[i] == '\n') + ibuf[i] = '\0'; + if (ibuf[i] == '\r') + ibuf[i] = '\0'; + } + for (i = strlen(ibuf) -1; i > 0; i--) { + if (ibuf[i] == ' ') + ibuf[i] = '\0'; + else + break; + } + if (strlen(ibuf)) { + if (debug) { + syslog(LOG_NOTICE, "recv: \"%s\"", ibuf); + fprintf(stdout, "recv: \"%s\"\n", ibuf); + } + if (strcmp(ibuf, (char *)".") == 0) { + srv_send((char *)"219 Accepted Unit record"); + return 0; + } + kwd = strtok(ibuf, ",\0"); + val = strtok(NULL, "\0"); + if (kwd && val) { + /* + * Accept writable data. The client can sent just one line, + * but may also sent everything. Simply ignore things we + * don't understand. + */ + if (strcmp(kwd, (char *)"NAME") == 0) { + if (unit->name) + free(unit->name); + unit->name = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"VOLUME") == 0) { + if (sscanf(val, "%f", &fval) == 1) + unit->volume = fval; + + } else if (strcmp(kwd, (char *)"AIR_ADDRESS") == 0) { + if (unit->air_address) + free(unit->air_address); + unit->air_address = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"BEER_ADDRESS") == 0) { + if (unit->beer_address) + free(unit->beer_address); + unit->beer_address = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"HEATER_ADDRESS") == 0) { + if (unit->heater_address) + free(unit->heater_address); + unit->heater_address = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"COOLER_ADDRESS") == 0) { + if (unit->cooler_address) + free(unit->cooler_address); + unit->cooler_address = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"FAN_ADDRESS") == 0) { + if (unit->fan_address) + free(unit->fan_address); + unit->fan_address = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"DOOR_ADDRESS") == 0) { + if (unit->door_address) + free(unit->door_address); + unit->door_address = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"MODE") == 0) { + for (i = 0; i < 5; i++) { + if (strcmp(val, UNITMODE[i]) == 0) { + unit->mode = i; + break; + } + } + + } else if (strcmp(kwd, (char *)"FRIDGE_SET") == 0) { + if (sscanf(val, "%f", &fval) == 1) + unit->fridge_set = fval; + + } else if (strcmp(kwd, (char *)"BEER_SET") == 0) { + if (sscanf(val, "%f", &fval) == 1) + unit->beer_set = fval; + + } else if (strcmp(kwd, (char *)"PROFILE") == 0) { + if (unit->profile) + free(unit->profile); + unit->profile = xstrcpy(val); + + } else if (strcmp(kwd, (char *)"PROF_STATE") == 0) { + for (i = 0; i < 4; i++) { + if (strcmp(val, PROFSTATE[i]) == 0) { + unit->prof_state = i; + break; + } + } + + } else if (strcmp(kwd, (char *)"TEMP_SET_MIN") == 0) { + if (sscanf(val, "%f", &fval) == 1) + unit->temp_set_min = fval; + + } else if (strcmp(kwd, (char *)"TEMP_SET_MAX") == 0) { + if (sscanf(val, "%f", &fval) == 1) + unit->temp_set_max = fval; + + } else if (strcmp(kwd, (char *)"IDLE_RANGE_L") == 0) { + if (sscanf(val, "%f", &fval) == 1) + unit->idle_rangeL = fval; + + } else if (strcmp(kwd, (char *)"IDLE_RANGE_H") == 0) { + if (sscanf(val, "%f", &fval) == 1) + unit->idle_rangeH = fval; + + } + } + } + } + } + } + srv_send((char *)"440 No such device"); + return 1; + } + + srv_send((char *)"502 Unknown command option"); return 1; } @@ -1189,11 +1331,9 @@ srv_send((char *)""); // 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 *)"DEVICE ADD type Add new Device type"); -// srv_send((char *)"DEVICE DEL uuid Delete Device by uuid"); + srv_send((char *)"DEVICE DEL uuid Delete Device by uuid"); srv_send((char *)"DEVICE LIST List Devices"); srv_send((char *)"DEVICE GET uuid Get Device record by uuid"); srv_send((char *)"DEVICE PUT uuid Put Device record by uuid"); @@ -1201,23 +1341,20 @@ srv_send((char *)"LIST List all fermenter units"); 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 of current unit"); srv_send((char *)"PROFILE uuid,name Profile rename"); srv_send((char *)"PROFILE GETS uuid Profile get steps list"); srv_send((char *)"PROFILE PUTS uuid Profile put steps list"); - 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 *)"UNIT ADD name Add a new unit with name"); + srv_send((char *)"UNIT DEL uuid Delete Unit by uuid"); + srv_send((char *)"UNIT LIST List Units"); + srv_send((char *)"UNIT GET uuid Get Unit record by uuid"); + srv_send((char *)"UNIT PUT uuid Put Unit record by uuid"); srv_send((char *)"."); } else if (strncmp(buf, "LCD", 3) == 0) { #ifdef HAVE_WIRINGPI_H @@ -1245,7 +1382,8 @@ if (cmd_set(buf) == 0) wrconfig(); } else if (strncmp(buf, "UNIT", 4) == 0) { - cmd_unit(buf); + if (cmd_unit(buf) == 0) + wrconfig(); } else { if (debug) fprintf(stdout, "unknown command \"%s\"\n", buf);