1198 return 0; |
1146 return 0; |
1199 } |
1147 } |
1200 |
1148 |
1201 |
1149 |
1202 |
1150 |
1203 /* |
|
1204 * PROFILE ADD name Add a new profile |
|
1205 * PROFILE DEL uuid Delete profile with uuid |
|
1206 * PROFILE LIST List available profiles |
|
1207 * PROFILE GET uuid Get profile record |
|
1208 * PROFILE PUT uuid Put profile record |
|
1209 * PROFILE GETS uuid Get profile steps list |
|
1210 * PROFILE PUTS uuid Put profile steps list |
|
1211 */ |
|
1212 int cmd_profile(char *buf) |
|
1213 { |
|
1214 char ibuf[SS_BUFSIZE], *sstep, *rest, *tlarg, *tharg, *frarg, *param, *kwd, *val; |
|
1215 int j, ival, rlen, istep, irest, ifrarg; |
|
1216 float ftlarg, ftharg, fval; |
|
1217 char *opt; |
|
1218 profiles_list *profile, *tmpp; |
|
1219 prof_step *step, *olds; |
|
1220 uuid_t uu; |
|
1221 |
|
1222 opt = strtok(buf, " \0"); |
|
1223 opt = strtok(NULL, " \0"); |
|
1224 |
|
1225 if (opt == NULL) { |
|
1226 srv_send((char *)"501 Subcommand missing"); |
|
1227 return 0; |
|
1228 } |
|
1229 |
|
1230 if (strcmp(opt, (char *)"HELP") == 0) { |
|
1231 srv_send((char *)"100 Help text follows:"); |
|
1232 srv_send((char *)"Recognized commands:"); |
|
1233 srv_send((char *)"PROFILE uuid,name Profile rename"); |
|
1234 srv_send((char *)"PROFILE ADD name Add new Profile with name"); |
|
1235 srv_send((char *)"PROFILE DEL uuid Delete Profile by uuid"); |
|
1236 srv_send((char *)"PROFILE LIST List available profiles"); |
|
1237 srv_send((char *)"PROFILE GET uuid Get Profile record by uuid"); |
|
1238 srv_send((char *)"PROFILE PUT uuid Put Profile record by uuid"); |
|
1239 srv_send((char *)"PROFILE GETS uuid Profile get steps list"); |
|
1240 srv_send((char *)"PROFILE PUTS uuid Profile put steps list"); |
|
1241 srv_send((char *)"."); |
|
1242 return 0; |
|
1243 } |
|
1244 |
|
1245 if (strcmp(opt, (char *)"LIST") == 0) { |
|
1246 /* |
|
1247 * Fermenting profiles |
|
1248 */ |
|
1249 srv_send((char *)"212 Profiles list follows:"); |
|
1250 for (profile = Config.profiles; profile; profile = profile->next) { |
|
1251 j = 0; |
|
1252 for (step = profile->steps; step; step = step->next) |
|
1253 j++; |
|
1254 srv_send((char *)"%s,%s,%d,%d", profile->uuid, profile->name, j, profile->busy); |
|
1255 } |
|
1256 srv_send((char *)"."); |
|
1257 return 0; |
|
1258 } |
|
1259 |
|
1260 param = strtok(NULL, "\0"); |
|
1261 if (param == NULL) { |
|
1262 srv_send((char *)"502 Parameter missing"); |
|
1263 return 0; |
|
1264 } |
|
1265 |
|
1266 if (strcmp(opt, (char *)"ADD") == 0) { |
|
1267 profile = (profiles_list *)malloc(sizeof(profiles_list)); |
|
1268 profile->next = NULL; |
|
1269 profile->version = 1; |
|
1270 profile->uuid = malloc(37); |
|
1271 uuid_generate(uu); |
|
1272 uuid_unparse(uu, profile->uuid); |
|
1273 profile->name = xstrcpy(param); |
|
1274 profile->busy = profile->fridge_mode = 0; |
|
1275 profile->inittemp_lo = 19.8; |
|
1276 profile->inittemp_hi = 20.2; |
|
1277 profile->steps = NULL; |
|
1278 if (Config.profiles == NULL) { |
|
1279 Config.profiles = profile; |
|
1280 } else { |
|
1281 for (tmpp = Config.profiles; tmpp; tmpp = tmpp->next) { |
|
1282 if (tmpp->next == NULL) { |
|
1283 tmpp->next = profile; |
|
1284 break; |
|
1285 } |
|
1286 } |
|
1287 } |
|
1288 |
|
1289 syslog(LOG_NOTICE, "Profile %s added", profile->uuid); |
|
1290 srv_send((char *)"211 Profile %s added", profile->uuid); |
|
1291 return 1; |
|
1292 |
|
1293 |
|
1294 } else if (strcmp(opt, (char *)"DEL") == 0) { |
|
1295 if (delete_Profile(param)) { |
|
1296 syslog(LOG_NOTICE, "Profile %s deleted", param); |
|
1297 srv_send((char *)"211 Profile %s deleted", param); |
|
1298 return 1; |
|
1299 } else { |
|
1300 srv_send((char *)"440 No such profile"); |
|
1301 return 0; |
|
1302 } |
|
1303 |
|
1304 } else if (strcmp(opt, (char *)"GET") == 0) { |
|
1305 for (profile = Config.profiles; profile; profile = profile->next) { |
|
1306 if (strcmp(profile->uuid, param) == 0) { |
|
1307 srv_send((char *)"213 Profile record follows:"); |
|
1308 srv_send((char *)"UUID,%s", profile->uuid); |
|
1309 srv_send((char *)"NAME,%s", profile->name); |
|
1310 srv_send((char *)"INITTEMP_LO,%.1f", profile->inittemp_lo); |
|
1311 srv_send((char *)"INITTEMP_HI,%.1f", profile->inittemp_hi); |
|
1312 srv_send((char *)"FRIDGE_MODE,%d", profile->fridge_mode); |
|
1313 srv_send((char *)"."); |
|
1314 return 0; |
|
1315 } |
|
1316 } |
|
1317 srv_send((char *)"440 No such profile"); |
|
1318 return 0; |
|
1319 |
|
1320 } else if (strcmp(opt, (char *)"PUT") == 0) { |
|
1321 for (profile = Config.profiles; profile; profile = profile->next) { |
|
1322 if (strcmp(profile->uuid, param) == 0) { |
|
1323 while (1) { |
|
1324 rlen = srv_recv(ibuf); |
|
1325 if (rlen == -1) { |
|
1326 return 0; |
|
1327 } |
|
1328 if (strlen(ibuf)) { |
|
1329 if (strcmp(ibuf, (char *)".") == 0) { |
|
1330 srv_send((char *)"219 Accepted Profile record"); |
|
1331 return 1; |
|
1332 } |
|
1333 kwd = strtok(ibuf, ",\0"); |
|
1334 val = strtok(NULL, "\0"); |
|
1335 if (kwd && val) { |
|
1336 if (strcmp(kwd, (char *)"NAME") == 0) { |
|
1337 if (profile->name) { |
|
1338 if (strcmp(profile->name, val)) |
|
1339 syslog(LOG_NOTICE, "Profile %s name `%s' to `%s'", profile->uuid, profile->name, val); |
|
1340 free(profile->name); |
|
1341 } |
|
1342 profile->name = xstrcpy(val); |
|
1343 } else if (strcmp(kwd, (char *)"INITTEMP_LO") == 0) { |
|
1344 if (sscanf(val, "%f", &fval) == 1) { |
|
1345 if (profile->inittemp_lo != fval) |
|
1346 syslog(LOG_NOTICE, "Profile %s initial temperature low %.1f to %.1f", profile->uuid, profile->inittemp_lo, fval); |
|
1347 profile->inittemp_lo = fval; |
|
1348 } |
|
1349 } else if (strcmp(kwd, (char *)"INITTEMP_HI") == 0) { |
|
1350 if (sscanf(val, "%f", &fval) == 1) { |
|
1351 if (profile->inittemp_hi != fval) |
|
1352 syslog(LOG_NOTICE, "Profile %s initial temperature high %.1f to %.1f", profile->uuid, profile->inittemp_hi, fval); |
|
1353 profile->inittemp_hi = fval; |
|
1354 } |
|
1355 } else if (strcmp(kwd, (char *)"FRIDGE_MODE") == 0) { |
|
1356 if (sscanf(val, "%d", &ival) == 1) { |
|
1357 if (profile->fridge_mode != ival) |
|
1358 syslog(LOG_NOTICE, "Profile %s fridge mode %d to %d", profile->uuid, profile->fridge_mode, ival); |
|
1359 profile->fridge_mode = ival; |
|
1360 } |
|
1361 } |
|
1362 } |
|
1363 } |
|
1364 } |
|
1365 } |
|
1366 } |
|
1367 srv_send((char *)"440 No such profile"); |
|
1368 return 0; |
|
1369 |
|
1370 } else if (strcmp(opt, (char *)"GETS") == 0) { |
|
1371 |
|
1372 for (profile = Config.profiles; profile; profile = profile->next) { |
|
1373 if (strcmp(profile->uuid, param) == 0) { |
|
1374 srv_send((char *)"215 Profile steps follow:"); |
|
1375 for (step = profile->steps; step; step = step->next) { |
|
1376 srv_send((char *)"%d,%d,%.1f,%.1f,%d", step->steptime, step->resttime, step->target_lo, step->target_hi, step->fridge_mode); |
|
1377 } |
|
1378 srv_send((char *)"."); |
|
1379 return 0; |
|
1380 } |
|
1381 } |
|
1382 |
|
1383 srv_send((char *)"440 No such profile"); |
|
1384 return 0; |
|
1385 |
|
1386 } else if (strcmp(opt, (char *)"PUTS") == 0) { |
|
1387 |
|
1388 for (profile = Config.profiles; profile; profile = profile->next) { |
|
1389 if (strcmp(profile->uuid, param) == 0) { |
|
1390 |
|
1391 if (profile->steps) { |
|
1392 syslog(LOG_NOTICE, "PROFILE PUTS %s erased all old steps", profile->uuid); |
|
1393 for (step = profile->steps; step; step = olds) { |
|
1394 olds = step->next; |
|
1395 free(step); |
|
1396 } |
|
1397 profile->steps = NULL; |
|
1398 } |
|
1399 |
|
1400 j = 0; |
|
1401 while (1) { |
|
1402 rlen = srv_recv(ibuf); |
|
1403 if (rlen == -1) { |
|
1404 return 0; |
|
1405 } else { |
|
1406 if (strlen(ibuf)) { |
|
1407 if (strcmp(ibuf, (char *)".") == 0) { |
|
1408 |
|
1409 srv_send((char *)"219 Accepted Profile steps"); |
|
1410 return 1; |
|
1411 } |
|
1412 sstep = strtok(ibuf, ",\0"); |
|
1413 rest = strtok(NULL, ",\0"); |
|
1414 tlarg = strtok(NULL, ",\0"); |
|
1415 tharg = strtok(NULL, ",\0"); |
|
1416 frarg = strtok(NULL, "\0"); |
|
1417 |
|
1418 if ((sscanf(sstep, "%d", &istep) == 1) && |
|
1419 (sscanf(rest, "%d", &irest) == 1) && |
|
1420 (sscanf(tlarg, "%f", &ftlarg) == 1) && |
|
1421 (sscanf(tharg, "%f", &ftharg) == 1) && |
|
1422 (sscanf(frarg, "%d", &ifrarg) == 1)) { |
|
1423 |
|
1424 j++; |
|
1425 syslog(LOG_NOTICE, "PROFILE PUTS %s add step %d: steptime=%d resttime=%d target=%.1f..%.1f fridge_mode=%d", |
|
1426 profile->uuid, j, istep, irest, ftlarg, ftharg, ifrarg); |
|
1427 step = (prof_step *)malloc(sizeof(prof_step)); |
|
1428 step->next = NULL; |
|
1429 step->version = 1; |
|
1430 step->steptime = istep; |
|
1431 step->resttime = irest; |
|
1432 step->target_lo = ftlarg; |
|
1433 step->target_hi = ftharg; |
|
1434 step->fridge_mode = ifrarg; |
|
1435 |
|
1436 if (profile->steps == NULL) { |
|
1437 profile->steps = step; |
|
1438 } else { |
|
1439 for (olds = profile->steps; olds; olds = olds->next) { |
|
1440 if (olds->next == NULL) { |
|
1441 olds->next = step; |
|
1442 break; |
|
1443 } |
|
1444 } |
|
1445 } |
|
1446 } |
|
1447 } |
|
1448 } |
|
1449 } |
|
1450 } |
|
1451 } |
|
1452 |
|
1453 srv_send((char *)"440 No such profile"); |
|
1454 return 0; |
|
1455 } |
|
1456 |
|
1457 srv_send((char *)"504 Subcommand error"); |
|
1458 return 0; |
|
1459 } |
|
1460 |
|
1461 |
|
1462 |
|
1463 #ifdef USE_SIMULATOR |
1151 #ifdef USE_SIMULATOR |
1464 int delete_Simulator(char *uuid) |
1152 int delete_Simulator(char *uuid) |
1465 { |
1153 { |
1466 simulator_list *current = Config.simulators; |
1154 simulator_list *current = Config.simulators; |
1467 simulator_list *previous = NULL; |
1155 simulator_list *previous = NULL; |
1970 |
1678 |
1971 sprintf(an, "unit%d", Config.next_unit); |
1679 sprintf(an, "unit%d", Config.next_unit); |
1972 Config.next_unit++; |
1680 Config.next_unit++; |
1973 unit = (units_list *)malloc(sizeof(units_list)); |
1681 unit = (units_list *)malloc(sizeof(units_list)); |
1974 unit->next = NULL; |
1682 unit->next = NULL; |
1975 unit->version = 1; |
|
1976 unit->uuid = malloc(37); |
1683 unit->uuid = malloc(37); |
1977 uuid_generate(uu); |
1684 uuid_generate(uu); |
1978 uuid_unparse(uu, unit->uuid); |
1685 uuid_unparse(uu, unit->uuid); |
1979 unit->product_uuid = NULL; |
1686 unit->product_uuid = NULL; |
1980 unit->product_code = xstrcpy((char *)"FAKE0000"); |
1687 unit->product_code = xstrcpy((char *)"FAKE0000"); |
1981 unit->product_name = xstrcpy(param); |
1688 unit->product_name = xstrcpy(param); |
1982 unit->alias = xstrcpy(an); |
1689 unit->alias = xstrcpy(an); |
1983 unit->air_address = unit->beer_address = unit->chiller_address = unit->heater_address = unit->cooler_address = \ |
1690 unit->air_address = unit->beer_address = unit->chiller_address = unit->heater_address = unit->cooler_address = \ |
1984 unit->fan_address = unit->door_address = unit->light_address = \ |
1691 unit->fan_address = unit->door_address = unit->light_address = \ |
1985 unit->psu_address = unit->profile = NULL; |
1692 unit->psu_address = unit->profile_uuid = unit->profile_name = NULL; |
1986 unit->air_idx = unit->beer_idx = unit->chiller_idx = unit->heater_idx = unit->cooler_idx = unit->fan_idx = \ |
1693 unit->air_idx = unit->beer_idx = unit->chiller_idx = unit->heater_idx = unit->cooler_idx = unit->fan_idx = \ |
1987 unit->door_idx = unit->light_idx = unit->psu_idx = 0; |
1694 unit->door_idx = unit->light_idx = unit->psu_idx = unit->profile_fridge_mode = \ |
|
1695 unit->profile_duration = unit->profile_totalsteps = 0; |
|
1696 unit->profile_steps = NULL; |
1988 unit->volume = unit->prof_peak_abs = unit->prof_peak_rel = 0.0; |
1697 unit->volume = unit->prof_peak_abs = unit->prof_peak_rel = 0.0; |
1989 unit->air_state = unit->beer_state = unit->chiller_state = 1; |
1698 unit->air_state = unit->beer_state = unit->chiller_state = 1; |
1990 unit->air_temperature = unit->beer_temperature = unit->chiller_temperature = 20000; |
1699 unit->air_temperature = unit->beer_temperature = unit->chiller_temperature = 20000; |
1991 unit->beer_set = unit->fridge_set = 20.0; |
1700 unit->beer_set = unit->fridge_set = unit->profile_inittemp_lo = unit->profile_inittemp_hi =20.0; |
1992 unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = \ |
1701 unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = \ |
1993 unit->light_state = unit->psu_state = unit->prof_state = unit->stage = 0; |
1702 unit->light_state = unit->psu_state = unit->prof_state = unit->stage = 0; |
1994 unit->heater_delay = unit->cooler_delay = unit->fan_delay = 20; /* 5 minutes delay */ |
1703 unit->heater_delay = unit->cooler_delay = unit->fan_delay = 20; /* 5 minutes delay */ |
1995 unit->light_delay = 1; /* 15 seconds delay */ |
1704 unit->light_delay = 1; /* 15 seconds delay */ |
1996 unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; |
1705 unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; |
2122 srv_send((char *)"PSU_ADDRESS,%s", unit->psu_address); |
1831 srv_send((char *)"PSU_ADDRESS,%s", unit->psu_address); |
2123 srv_send((char *)"PSU_STATE,%d", unit->psu_state); |
1832 srv_send((char *)"PSU_STATE,%d", unit->psu_state); |
2124 srv_send((char *)"PSU_IDX,%d", unit->psu_idx); |
1833 srv_send((char *)"PSU_IDX,%d", unit->psu_idx); |
2125 srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set); |
1834 srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set); |
2126 srv_send((char *)"BEER_SET,%.1f", unit->beer_set); |
1835 srv_send((char *)"BEER_SET,%.1f", unit->beer_set); |
2127 srv_send((char *)"PROFILE,%s", unit->profile); |
1836 if (unit->profile_uuid) { |
2128 srv_send((char *)"PROF_STARTED,%d", (int)unit->prof_started); |
1837 srv_send((char *)"PROFILE_UUID,%s", unit->profile_uuid); |
2129 if (unit->prof_state == PROFILE_RUN) { |
1838 srv_send((char *)"PROFILE_NAME,%s", unit->profile_name); |
2130 srv_send((char *)"PROF_STATE,%s %d%%", PROFSTATE[unit->prof_state], unit->prof_percent); |
1839 srv_send((char *)"PROFILE_INITTEMP_LO,%.1f", unit->profile_inittemp_lo); |
2131 } else { |
1840 srv_send((char *)"PROFILE_INITTEMP_HI,%.1f", unit->profile_inittemp_hi); |
2132 srv_send((char *)"PROF_STATE,%s", PROFSTATE[unit->prof_state]); |
1841 srv_send((char *)"PROFILE_FRIDGE_MODE,%d", unit->profile_fridge_mode); |
|
1842 srv_send((char *)"PROFILE_DURATION,%d", unit->profile_duration); |
|
1843 srv_send((char *)"PROFILE_TOTALSTEPS,%d", unit->profile_totalsteps); |
|
1844 srv_send((char *)"PROF_STARTED,%d", (int)unit->prof_started); |
|
1845 if (unit->prof_state == PROFILE_RUN) { |
|
1846 srv_send((char *)"PROF_STATE,%s %d%%", PROFSTATE[unit->prof_state], unit->prof_percent); |
|
1847 } else { |
|
1848 srv_send((char *)"PROF_STATE,%s", PROFSTATE[unit->prof_state]); |
|
1849 } |
|
1850 srv_send((char *)"PROF_TARGET_LO,%.3f", unit->prof_target_lo); |
|
1851 srv_send((char *)"PROF_TARGET_HI,%.3f", unit->prof_target_hi); |
|
1852 srv_send((char *)"PROF_FRIDGE_MODE,%d", unit->prof_fridge_mode); |
|
1853 srv_send((char *)"PROF_PEAK_ABS,%.3f", unit->prof_peak_abs); |
|
1854 srv_send((char *)"PROF_PEAK_REL,%.3f", unit->prof_peak_rel); |
|
1855 srv_send((char *)"PROF_PRIMARY_DONE,%d", (int)unit->prof_primary_done); |
2133 } |
1856 } |
2134 srv_send((char *)"PROF_TARGET_LO,%.3f", unit->prof_target_lo); |
|
2135 srv_send((char *)"PROF_TARGET_HI,%.3f", unit->prof_target_hi); |
|
2136 srv_send((char *)"PROF_FRIDGE_MODE,%d", unit->prof_fridge_mode); |
|
2137 srv_send((char *)"PROF_PEAK_ABS,%.3f", unit->prof_peak_abs); |
|
2138 srv_send((char *)"PROF_PEAK_REL,%.3f", unit->prof_peak_rel); |
|
2139 srv_send((char *)"PROF_PRIMARY_DONE,%d", (int)unit->prof_primary_done); |
|
2140 srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min); |
1857 srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min); |
2141 srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max); |
1858 srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max); |
2142 srv_send((char *)"ALARM,%d", unit->alarm_flag); |
1859 srv_send((char *)"ALARM,%d", unit->alarm_flag); |
2143 srv_send((char *)"."); |
1860 srv_send((char *)"."); |
2144 return 0; |
1861 return 0; |
2591 if (unit->PID_heat->idleRange != fval) |
2308 if (unit->PID_heat->idleRange != fval) |
2592 syslog(LOG_NOTICE, "Fermenter unit %s PID_heat idleRange %.2f to %.2f", unit->uuid, unit->PID_heat->idleRange, fval); |
2309 syslog(LOG_NOTICE, "Fermenter unit %s PID_heat idleRange %.2f to %.2f", unit->uuid, unit->PID_heat->idleRange, fval); |
2593 unit->PID_heat->idleRange = fval; |
2310 unit->PID_heat->idleRange = fval; |
2594 } |
2311 } |
2595 |
2312 |
2596 } else if (strcmp(kwd, (char *)"PROFILE") == 0) { |
2313 } else if (val && (strcmp(kwd, (char *)"PROF_STATE") == 0) && unit->profile_uuid) { |
2597 if (unit->prof_state == PROFILE_OFF) { |
|
2598 /* |
|
2599 * Only change profile if it is not active, else drop this one. |
|
2600 */ |
|
2601 if (unit->profile && val && strcmp(unit->profile, val)) |
|
2602 syslog(LOG_NOTICE, "Fermenter unit %s profile name `%s' to `%s'", unit->uuid, unit->profile, val); |
|
2603 if (unit->profile) |
|
2604 free(unit->profile); |
|
2605 |
|
2606 if (val) |
|
2607 unit->profile = xstrcpy(val); |
|
2608 else |
|
2609 unit->profile = NULL; |
|
2610 /* |
|
2611 * Reset all output devices |
|
2612 */ |
|
2613 unit->PID_cool->OutP = unit->PID_heat->OutP = 0.0; |
|
2614 unit->PID_cool->Mode = unit->PID_heat->Mode = PID_MODE_NONE; |
|
2615 unit->heater_state = unit->cooler_state = unit->fan_state = unit->light_state = 0; |
|
2616 unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0; |
|
2617 device_out(unit->heater_address, unit->heater_state); |
|
2618 device_out(unit->cooler_address, unit->cooler_state); |
|
2619 device_out(unit->fan_address, unit->fan_state); |
|
2620 device_out(unit->light_address, unit->light_state); |
|
2621 unit->mqtt_flag |= MQTT_FLAG_DATA; |
|
2622 } |
|
2623 |
|
2624 } else if (val && (strcmp(kwd, (char *)"PROF_STATE") == 0)) { |
|
2625 for (i = 0; i < 5; i++) { |
2314 for (i = 0; i < 5; i++) { |
2626 if (strcmp(val, PROFSTATE[i]) == 0) { |
2315 if (strcmp(val, PROFSTATE[i]) == 0) { |
2627 switch (i) { |
2316 switch (i) { |
2628 case PROFILE_OFF: if (unit->prof_state == PROFILE_DONE) { |
2317 case PROFILE_OFF: if (unit->prof_state == PROFILE_DONE) { |
2629 unit->prof_state = PROFILE_OFF; |
2318 unit->prof_state = PROFILE_OFF; |