1 /***************************************************************************** |
|
2 * Copyright (C) 2015 |
|
3 * |
|
4 * Michiel Broek <mbroek at mbse dot eu> |
|
5 * |
|
6 * This file is part of the mbsePi-apps |
|
7 * |
|
8 * This is free software; you can redistribute it and/or modify it |
|
9 * under the terms of the GNU General Public License as published by the |
|
10 * Free Software Foundation; either version 2, or (at your option) any |
|
11 * later version. |
|
12 * |
|
13 * mbsePi-apps is distributed in the hope that it will be useful, but |
|
14 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
16 * General Public License for more details. |
|
17 * |
|
18 * You should have received a copy of the GNU General Public License |
|
19 * along with ThermFerm; see the file COPYING. If not, write to the Free |
|
20 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
21 *****************************************************************************/ |
|
22 |
|
23 #include "brewco.h" |
|
24 #include "slcd.h" |
|
25 #include "setup.h" |
|
26 #include "prompt.h" |
|
27 #include "xutil.h" |
|
28 #include "keyboard.h" |
|
29 #include "rdconfig.h" |
|
30 #include "rdrecipes.h" |
|
31 |
|
32 |
|
33 extern int my_shutdown; |
|
34 extern int debug; |
|
35 extern sys_config Config; |
|
36 extern int lcdHandle; |
|
37 extern int slcdHandle; |
|
38 extern a_recipe *recipes; |
|
39 |
|
40 |
|
41 |
|
42 void editFloat(float *value, float low, float high, char *text) |
|
43 { |
|
44 int key; |
|
45 float new = *value; |
|
46 char pmpt[81]; |
|
47 |
|
48 prompt(0, NULL); |
|
49 prompt(133, NULL); |
|
50 |
|
51 for (;;) { |
|
52 snprintf(pmpt, Config.lcd_cols + 1, "%s: %5.1f\001", text, new); |
|
53 prompt(200, pmpt); |
|
54 if (new == low) |
|
55 prompt(404, NULL); |
|
56 else if (new == high) |
|
57 prompt(402, NULL); |
|
58 else |
|
59 prompt(403, NULL); |
|
60 |
|
61 key = keywait(); |
|
62 if ((key == KEY_RETURN) || my_shutdown) |
|
63 return; |
|
64 if (key == KEY_UP) { |
|
65 new = new + 0.5; |
|
66 if (new > high) |
|
67 new = high; |
|
68 } |
|
69 if (key == KEY_DOWN) { |
|
70 new = new - 0.5; |
|
71 if (new < low) |
|
72 new = low; |
|
73 } |
|
74 if (key == KEY_ENTER) { |
|
75 *value = new; |
|
76 return; |
|
77 } |
|
78 } |
|
79 } |
|
80 |
|
81 |
|
82 |
|
83 void editDouble(double *value, double low, double high, char *text) |
|
84 { |
|
85 int key; |
|
86 double new = *value; |
|
87 char pmpt[81]; |
|
88 |
|
89 prompt(0, NULL); |
|
90 prompt(138, NULL); |
|
91 |
|
92 for (;;) { |
|
93 snprintf(pmpt, Config.lcd_cols + 1, "%s: %5.2lf", text, new); |
|
94 prompt(200, pmpt); |
|
95 if (new == low) |
|
96 prompt(404, NULL); |
|
97 else if (new == high) |
|
98 prompt(402, NULL); |
|
99 else |
|
100 prompt(403, NULL); |
|
101 |
|
102 key = keywait(); |
|
103 if ((key == KEY_RETURN) || my_shutdown) |
|
104 return; |
|
105 if (key == KEY_UP) { |
|
106 new = new + 0.5; |
|
107 if (new > high) |
|
108 new = high; |
|
109 } |
|
110 if (key == KEY_DOWN) { |
|
111 new = new - 0.5; |
|
112 if (new < low) |
|
113 new = low; |
|
114 } |
|
115 if (key == KEY_ENTER) { |
|
116 *value = new; |
|
117 return; |
|
118 } |
|
119 } |
|
120 } |
|
121 |
|
122 |
|
123 |
|
124 void editInteger(int *value, int low, int high, int step, char *text, char *text2) |
|
125 { |
|
126 int key, new = *value; |
|
127 char pmpt[81]; |
|
128 |
|
129 prompt(0, NULL); |
|
130 prompt(134, NULL); |
|
131 |
|
132 for (;;) { |
|
133 snprintf(pmpt, Config.lcd_cols + 1, "%s: %3d %s", text, new, text2); |
|
134 prompt(200, pmpt); |
|
135 if (new == low) |
|
136 prompt(404, NULL); |
|
137 else if (new == high) |
|
138 prompt(402, NULL); |
|
139 else |
|
140 prompt(403, NULL); |
|
141 |
|
142 key = keywait(); |
|
143 if ((key == KEY_RETURN) || my_shutdown) |
|
144 return; |
|
145 if (key == KEY_UP) { |
|
146 new += step; |
|
147 if (new > high) |
|
148 new = high; |
|
149 } |
|
150 if (key == KEY_DOWN) { |
|
151 new -= step; |
|
152 if (new < low) |
|
153 new = low; |
|
154 } |
|
155 if (key == KEY_ENTER) { |
|
156 *value = new; |
|
157 return; |
|
158 } |
|
159 } |
|
160 } |
|
161 |
|
162 |
|
163 |
|
164 void togglePmpts(int *value, char *text, int pno, char *pmpt1, char *pmpt2) |
|
165 { |
|
166 int key, new = *value; |
|
167 char pmpt[81]; |
|
168 |
|
169 prompt(0, NULL); |
|
170 prompt(pno, NULL); |
|
171 |
|
172 for (;;) { |
|
173 |
|
174 snprintf(pmpt, Config.lcd_cols + 1, "%s: %s", text, new ? pmpt1:pmpt2); |
|
175 prompt(200, pmpt); |
|
176 if (new) { |
|
177 prompt(404, NULL); |
|
178 } else { |
|
179 prompt(402, NULL); |
|
180 } |
|
181 |
|
182 key = keywait(); |
|
183 if ((key == KEY_RETURN) || my_shutdown) |
|
184 return; |
|
185 if ((key == KEY_UP) && new) |
|
186 new = 0; |
|
187 else if ((key == KEY_DOWN) && (new == 0)) |
|
188 new = 1; |
|
189 if (key == KEY_ENTER) { |
|
190 *value = new; |
|
191 return; |
|
192 } |
|
193 } |
|
194 } |
|
195 |
|
196 |
|
197 |
|
198 void toggleYesNo(int *value, char *text) |
|
199 { |
|
200 togglePmpts(value, text, 132, (char *)"Yes", (char *)"No "); |
|
201 } |
|
202 |
|
203 |
|
204 |
|
205 void toggleDirection(int *value, char *text) |
|
206 { |
|
207 togglePmpts(value, text, 137, (char *)"Reverse", (char *)"Direct "); |
|
208 } |
|
209 |
|
210 |
|
211 |
|
212 void editName(char *name, char *text) |
|
213 { |
|
214 char pmpt[81]; |
|
215 int i, x = 0, key, val; |
|
216 |
|
217 if (debug) |
|
218 fprintf(stdout, "editName(%s)\n", name); |
|
219 |
|
220 prompt(0, NULL); |
|
221 prompt(131, NULL); /* " Change Name " */ |
|
222 prompt(417, NULL); /* " up dwn next ok " */ |
|
223 |
|
224 for (;;) { |
|
225 snprintf(pmpt, Config.lcd_cols + 1, " "); |
|
226 prompt(200, pmpt); |
|
227 #ifdef HAVE_WIRINGPI_H |
|
228 lcdPosition(lcdHandle, x, 1); |
|
229 lcdPutchar(lcdHandle, '*'); |
|
230 #endif |
|
231 slcdPosition(slcdHandle, x, 1); |
|
232 slcdPutchar(slcdHandle, '*'); |
|
233 snprintf(pmpt, Config.lcd_cols + 1, "%s", name); |
|
234 prompt(300, pmpt); |
|
235 |
|
236 key = keywait(); |
|
237 |
|
238 if ((key == KEY_ENTER) || my_shutdown) { |
|
239 if (debug) |
|
240 fprintf(stdout, "End editName(%s)\n", name); |
|
241 for (i = strlen(name) -1; i > 1; i--) { |
|
242 if (name[i] != ' ') |
|
243 break; |
|
244 name[i] = '\0'; |
|
245 } |
|
246 if (debug) |
|
247 fprintf(stdout, "End editName(%s)\n", name); |
|
248 return; |
|
249 } |
|
250 if (key == KEY_RETURN) { |
|
251 if (x < 19) |
|
252 x++; |
|
253 else |
|
254 x = 0; |
|
255 if (debug) |
|
256 fprintf(stdout, "editName: strlen=%d x=%d\n", (int)strlen(name) - 1, x); |
|
257 if (x > ((int)strlen(name) - 1)) { |
|
258 name[x + 1] = '\0'; |
|
259 name[x] = ' '; |
|
260 } |
|
261 } |
|
262 if (key == KEY_UP || key == KEY_DOWN) { |
|
263 val = name[x]; |
|
264 if ((key == KEY_UP) && (val < 126)) |
|
265 val++; |
|
266 if ((key == KEY_DOWN) && (val > 32)) |
|
267 val--; |
|
268 name[x] = val; |
|
269 } |
|
270 } |
|
271 } |
|
272 |
|
273 |
|
274 |
|
275 void editPID(pid_var *pid) |
|
276 { |
|
277 int idx = 1, key, val; |
|
278 char pmpt[81]; |
|
279 double Kp, Ki, Kd; |
|
280 |
|
281 if (debug) |
|
282 fprintf(stdout, "editPID()\n"); |
|
283 |
|
284 for (;;) { |
|
285 prompt(0, NULL); |
|
286 prompt(192, NULL); |
|
287 |
|
288 if (idx == 1) |
|
289 prompt(402, NULL); |
|
290 else if (idx == 5) |
|
291 prompt(404, NULL); |
|
292 else |
|
293 prompt(403, NULL); |
|
294 |
|
295 switch (idx) { |
|
296 case 1: snprintf(pmpt, Config.lcd_cols + 1, "PID Kp: %5.2f", PID_getKp(pid)); |
|
297 break; |
|
298 case 2: snprintf(pmpt, Config.lcd_cols + 1, "PID Ki: %5.2f", PID_getKi(pid)); |
|
299 break; |
|
300 case 3: snprintf(pmpt, Config.lcd_cols + 1, "PID Kd: %5.2f", PID_getKd(pid)); |
|
301 break; |
|
302 case 4: snprintf(pmpt, Config.lcd_cols + 1, "SampleTime: %3d mSec", PID_getSampleTime(pid)); |
|
303 break; |
|
304 case 5: snprintf(pmpt, Config.lcd_cols + 1, "Direction: %s", PID_getDirection(pid) ? (char *)"Reverse" : (char *)"Direct"); |
|
305 break; |
|
306 } |
|
307 prompt(200, pmpt); |
|
308 |
|
309 key = keywait(); |
|
310 if ((key == KEY_RETURN) || my_shutdown) { |
|
311 if (debug) |
|
312 fprintf(stdout, "End editPID\n"); |
|
313 return; |
|
314 } |
|
315 |
|
316 if ((key == KEY_UP) && (idx > 1)) |
|
317 idx--; |
|
318 if ((key == KEY_DOWN) && (idx < 5)) |
|
319 idx++; |
|
320 |
|
321 if (key == KEY_ENTER) { |
|
322 |
|
323 Kp = PID_getKp(pid); |
|
324 Ki = PID_getKi(pid); |
|
325 Kd = PID_getKd(pid); |
|
326 |
|
327 switch(idx) { |
|
328 case 1: editDouble(&Kp, 0.5, 50, (char *)"PID Kp"); |
|
329 PID_setTunings(pid, Kp, Ki, Kd); |
|
330 break; |
|
331 case 2: editDouble(&Ki, 0.5, 50, (char *)"PID Ki"); |
|
332 PID_setTunings(pid, Kp, Ki, Kd); |
|
333 break; |
|
334 case 3: editDouble(&Kd, 0.5, 50, (char *)"PID Kd"); |
|
335 PID_setTunings(pid, Kp, Ki, Kd); |
|
336 break; |
|
337 case 4: val = PID_getSampleTime(pid); |
|
338 editInteger(&val, 50, 500, 10, (char *)"SampleTime", (char *)"mSec"); |
|
339 PID_setSampleTime(pid, val); |
|
340 break; |
|
341 case 5: val = PID_getDirection(pid); |
|
342 toggleDirection(&val, (char *)"Direction"); |
|
343 PID_setDirection(pid, val); |
|
344 break; |
|
345 } |
|
346 } |
|
347 } |
|
348 } |
|
349 |
|
350 |
|
351 |
|
352 void editMash(mash_step *mash) |
|
353 { |
|
354 int key, idx = 1, lo, hi; |
|
355 char pmpt[81]; |
|
356 |
|
357 for (;;) { |
|
358 prompt(0, NULL); |
|
359 prompt(194, NULL); |
|
360 |
|
361 if (mash->canskip) { |
|
362 lo = 1; |
|
363 if (mash->skip) |
|
364 hi = 1; |
|
365 else |
|
366 hi = 3; |
|
367 } else { |
|
368 lo = 2; |
|
369 hi = 3; |
|
370 } |
|
371 if (idx < lo) |
|
372 idx = lo; |
|
373 if (idx > hi) |
|
374 idx = hi; |
|
375 if (debug) |
|
376 fprintf(stdout, "editMash canskip=%d skip=%d lo=%d hi=%d idx=%d\n", mash->canskip, mash->skip, lo, hi, idx); |
|
377 |
|
378 switch (idx) { |
|
379 case 1: snprintf(pmpt, Config.lcd_cols + 1, " Mashstep skip: %s", mash->skip ? (char *)"Yes":(char *)"No"); |
|
380 break; |
|
381 case 2: snprintf(pmpt, Config.lcd_cols + 1, " Setpoint: %5.1f\001", mash->setpoint); |
|
382 break; |
|
383 case 3: snprintf(pmpt, Config.lcd_cols + 1, " Duration: %3d mins", mash->duration); |
|
384 break; |
|
385 } |
|
386 prompt(200, pmpt); |
|
387 |
|
388 if (lo == hi) |
|
389 prompt(405, NULL); /* "--- --- quit ok " */ |
|
390 else if (idx == lo) |
|
391 prompt(402, NULL); /* "--- dwn quit ok " */ |
|
392 else if (idx == hi) |
|
393 prompt(404, NULL); /* " up --- quit ok " */ |
|
394 else |
|
395 prompt(403, NULL); /* " up dwn quit ok " */ |
|
396 |
|
397 key = keywait(); |
|
398 if ((key == KEY_RETURN) || my_shutdown) |
|
399 return; |
|
400 if ((key == KEY_UP) && (idx > lo)) |
|
401 idx--; |
|
402 if ((key == KEY_DOWN) && (idx < hi)) |
|
403 idx++; |
|
404 if (key == KEY_ENTER) { |
|
405 switch(idx) { |
|
406 case 1: toggleYesNo(&mash->skip, (char *)" Mashstep skip"); |
|
407 break; |
|
408 case 2: editFloat(&mash->setpoint, mash->min, mash->max, (char *)" Setpoint"); |
|
409 break; |
|
410 case 3: editInteger(&mash->duration, 1, 120, 1, (char *)" Duration", (char *)"mins"); |
|
411 break; |
|
412 } |
|
413 } |
|
414 } |
|
415 } |
|
416 |
|
417 |
|
418 |
|
419 void editHopaddition(hop_addition *hops, int boiltime) |
|
420 { |
|
421 int key, idx = 1, hi; |
|
422 char pmpt[81]; |
|
423 |
|
424 for (;;) { |
|
425 prompt(0, NULL); |
|
426 prompt(195, NULL); |
|
427 |
|
428 if (hops->skip) |
|
429 hi = 1; |
|
430 else |
|
431 hi = 2; |
|
432 if (idx > hi) |
|
433 idx = hi; |
|
434 if (debug) |
|
435 fprintf(stdout, "editHopaddition skip=%d hi=%d idx=%d\n", hops->skip, hi, idx); |
|
436 |
|
437 switch (idx) { |
|
438 case 1: snprintf(pmpt, Config.lcd_cols + 1, "Addition skip: %s", hops->skip ? (char *)"Yes":(char *)"No"); |
|
439 break; |
|
440 case 2: snprintf(pmpt, Config.lcd_cols + 1, " Boil for: %3d mins", hops->boiltime); |
|
441 break; |
|
442 } |
|
443 prompt(200, pmpt); |
|
444 |
|
445 if (hi == 1) |
|
446 prompt(405, NULL); /* "--- --- quit ok " */ |
|
447 else if (idx == 1) |
|
448 prompt(402, NULL); /* "--- dwn quit ok " */ |
|
449 else if (idx == hi) |
|
450 prompt(404, NULL); /* " up --- quit ok " */ |
|
451 else |
|
452 prompt(403, NULL); /* " up dwn quit ok " */ |
|
453 |
|
454 key = keywait(); |
|
455 if ((key == KEY_RETURN) || my_shutdown) |
|
456 return; |
|
457 if ((key == KEY_UP) && (idx > 1)) |
|
458 idx--; |
|
459 if ((key == KEY_DOWN) && (idx < hi)) |
|
460 idx++; |
|
461 if (key == KEY_ENTER) { |
|
462 switch (idx) { |
|
463 case 1: toggleYesNo(&hops->skip, (char *)"Addition skip"); |
|
464 break; |
|
465 case 2: editInteger(&hops->boiltime, -1, boiltime, 1, (char *)" Boil for", (char *)"mins"); |
|
466 break; |
|
467 } |
|
468 } |
|
469 } |
|
470 } |
|
471 |
|
472 |
|
473 |
|
474 void editHopstand(hop_stand *hops) |
|
475 { |
|
476 int key, idx = 1, hi; |
|
477 char pmpt[81]; |
|
478 |
|
479 for (;;) { |
|
480 prompt(0, NULL); |
|
481 prompt(196, NULL); |
|
482 |
|
483 if (hops->skip) |
|
484 hi = 1; |
|
485 else |
|
486 hi = 4; |
|
487 if (idx < 1) |
|
488 idx = 1; |
|
489 if (idx > hi) |
|
490 idx = hi; |
|
491 if (debug) |
|
492 fprintf(stdout, "editHopstand skip=%d hi=%d idx=%d\n", hops->skip, hi, idx); |
|
493 |
|
494 switch (idx) { |
|
495 case 1: snprintf(pmpt, Config.lcd_cols + 1, "Hopstand skip: %s", hops->skip ? (char *)"Yes":(char *)"No"); |
|
496 break; |
|
497 case 2: snprintf(pmpt, Config.lcd_cols + 1, "Hold temperature: %s", hops->hold ? (char *)"Yes":(char *)"No"); |
|
498 break; |
|
499 case 3: snprintf(pmpt, Config.lcd_cols + 1, " Setpoint: %5.1f\001", hops->setpoint); |
|
500 break; |
|
501 case 4: snprintf(pmpt, Config.lcd_cols + 1, " Duration: %3d mins", hops->duration); |
|
502 break; |
|
503 } |
|
504 prompt(200, pmpt); |
|
505 |
|
506 if (hi == 1) |
|
507 prompt(405, NULL); /* "--- --- quit ok " */ |
|
508 else if (idx == 1) |
|
509 prompt(402, NULL); /* "--- dwn quit ok " */ |
|
510 else if (idx == hi) |
|
511 prompt(404, NULL); /* " up --- quit ok " */ |
|
512 else |
|
513 prompt(403, NULL); /* " up dwn quit ok " */ |
|
514 |
|
515 key = keywait(); |
|
516 if ((key == KEY_RETURN) || my_shutdown) |
|
517 return; |
|
518 if ((key == KEY_UP) && (idx > 1)) |
|
519 idx--; |
|
520 if ((key == KEY_DOWN) && (idx < hi)) |
|
521 idx++; |
|
522 if (key == KEY_ENTER) { |
|
523 switch(idx) { |
|
524 case 1: toggleYesNo(&hops->skip, (char *)"Hopstand skip"); |
|
525 break; |
|
526 case 2: toggleYesNo(&hops->hold, (char *)"Hold temperature"); |
|
527 break; |
|
528 case 3: editFloat(&hops->setpoint, hops->min, hops->max, (char *)" Setpoint"); |
|
529 break; |
|
530 case 4: editInteger(&hops->duration, 10, 240, 10, (char *)" Duration", (char *)"mins"); |
|
531 break; |
|
532 } |
|
533 } |
|
534 } |
|
535 } |
|
536 |
|
537 |
|
538 |
|
539 void editSensor(char *uuid, char *text) |
|
540 { |
|
541 char pmpt[81]; |
|
542 int i, old, choices, idx = 1, key; |
|
543 devices_list *device; |
|
544 |
|
545 if (debug) |
|
546 fprintf(stdout, "editSensor(%s, %s)\n", uuid, text); |
|
547 |
|
548 old = 1; // 1d0e5bb8-7408-48b9-abb4-e9041d7b99fe |
|
549 if ((i = strcmp((char *)"00000000-0000-0000-0000-000000000000", uuid))) { |
|
550 for (device = Config.devices; device; device = device->next) { |
|
551 if (device->direction == DEVDIR_IN_ANALOG) { |
|
552 old++; |
|
553 if (strcmp(device->uuid, uuid) == 0) |
|
554 break; |
|
555 } |
|
556 } |
|
557 } |
|
558 |
|
559 if (debug) |
|
560 fprintf(stdout, "editSensor(%s) old sensor index=%d\n", text, old); |
|
561 |
|
562 for (;;) { |
|
563 prompt(0, NULL); |
|
564 snprintf(pmpt, Config.lcd_cols + 1, "Edit %s", text); |
|
565 prompt(100, pmpt); |
|
566 |
|
567 /* |
|
568 * Count valid sensors |
|
569 */ |
|
570 choices = 1; |
|
571 if (old == 1) { |
|
572 snprintf(pmpt, Config.lcd_cols + 1, "N/A"); |
|
573 } |
|
574 for (device = Config.devices; device; device = device->next) { |
|
575 if (device->direction == DEVDIR_IN_ANALOG) { |
|
576 choices++; |
|
577 if (choices == old) { |
|
578 snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description); |
|
579 } |
|
580 } |
|
581 } |
|
582 prompt(200, pmpt); /* Display current sensor */ |
|
583 i = 1; |
|
584 if (idx == 1) { |
|
585 snprintf(pmpt, Config.lcd_cols + 1, "N/A"); |
|
586 } else { |
|
587 for (device = Config.devices; device; device = device->next) { |
|
588 if (device->direction == DEVDIR_IN_ANALOG) { |
|
589 i++; |
|
590 if (i == idx) { |
|
591 snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description); |
|
592 } |
|
593 } |
|
594 } |
|
595 } |
|
596 prompt(300, pmpt); /* Display possible new sensor */ |
|
597 |
|
598 |
|
599 if (choices == 1) |
|
600 prompt(405, NULL); |
|
601 else if (idx == 1) |
|
602 prompt(402, NULL); |
|
603 else if (idx == choices) |
|
604 prompt(404, NULL); |
|
605 else |
|
606 prompt(403, NULL); |
|
607 |
|
608 key = keywait(); |
|
609 if ((key == KEY_RETURN) || my_shutdown) { |
|
610 if (debug) |
|
611 fprintf(stdout, "End editSensor\n"); |
|
612 return; |
|
613 } |
|
614 |
|
615 if ((key == KEY_UP) && (idx > 1)) |
|
616 idx--; |
|
617 if ((key == KEY_DOWN) && (idx < choices)) |
|
618 idx++; |
|
619 |
|
620 if ((key == KEY_ENTER) && (idx != old)) { |
|
621 /* |
|
622 * Select new sensor. |
|
623 */ |
|
624 if (idx == 1) { |
|
625 /* |
|
626 * Disable the sensor |
|
627 */ |
|
628 strncpy(uuid, (char *)"00000000-0000-0000-0000-000000000000", 36); |
|
629 old = idx; |
|
630 } else { |
|
631 i = 1; |
|
632 for (device = Config.devices; device; device = device->next) { |
|
633 if (device->direction == DEVDIR_IN_ANALOG) { |
|
634 i++; |
|
635 if (i == idx) { |
|
636 strncpy(uuid, device->uuid, 36); |
|
637 break; |
|
638 } |
|
639 } |
|
640 } |
|
641 old = idx; |
|
642 } |
|
643 } |
|
644 } |
|
645 } |
|
646 |
|
647 |
|
648 |
|
649 void editRelay(char *uuid, char *text) |
|
650 { |
|
651 char pmpt[81]; |
|
652 int i, old, choices, idx = 1, key; |
|
653 devices_list *device; |
|
654 |
|
655 if (debug) |
|
656 fprintf(stdout, "editRelay(%s, %s)\n", uuid, text); |
|
657 |
|
658 old = 1; // 1d0e5bb8-7408-48b9-abb4-e9041d7b99fe |
|
659 if ((i = strcmp((char *)"00000000-0000-0000-0000-000000000000", uuid))) { |
|
660 for (device = Config.devices; device; device = device->next) { |
|
661 if (device->direction == DEVDIR_OUT_ANALOG) { |
|
662 old++; |
|
663 if (strcmp(device->uuid, uuid) == 0) |
|
664 break; |
|
665 } |
|
666 } |
|
667 } |
|
668 |
|
669 if (debug) |
|
670 fprintf(stdout, "editRelay(%s) old sensor index=%d\n", text, old); |
|
671 |
|
672 for (;;) { |
|
673 prompt(0, NULL); |
|
674 snprintf(pmpt, Config.lcd_cols + 1, "Edit %s", text); |
|
675 prompt(100, pmpt); |
|
676 |
|
677 /* |
|
678 * Count valid sensors |
|
679 */ |
|
680 choices = 1; |
|
681 if (old == 1) { |
|
682 snprintf(pmpt, Config.lcd_cols + 1, "N/A"); |
|
683 } |
|
684 for (device = Config.devices; device; device = device->next) { |
|
685 if (device->direction == DEVDIR_OUT_ANALOG) { |
|
686 choices++; |
|
687 if (choices == old) { |
|
688 snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description); |
|
689 } |
|
690 } |
|
691 } |
|
692 prompt(200, pmpt); /* Display current relay */ |
|
693 i = 1; |
|
694 if (idx == 1) { |
|
695 snprintf(pmpt, Config.lcd_cols + 1, "N/A"); |
|
696 } else { |
|
697 for (device = Config.devices; device; device = device->next) { |
|
698 if (device->direction == DEVDIR_OUT_ANALOG) { |
|
699 i++; |
|
700 if (i == idx) { |
|
701 snprintf(pmpt, Config.lcd_cols + 1, "%s", device->description); |
|
702 } |
|
703 } |
|
704 } |
|
705 } |
|
706 prompt(300, pmpt); /* Display possible new relay */ |
|
707 |
|
708 if (choices == 1) |
|
709 prompt(405, NULL); |
|
710 else if (idx == 1) |
|
711 prompt(402, NULL); |
|
712 else if (idx == choices) |
|
713 prompt(404, NULL); |
|
714 else |
|
715 prompt(403, NULL); |
|
716 |
|
717 key = keywait(); |
|
718 if ((key == KEY_RETURN) || my_shutdown) { |
|
719 if (debug) |
|
720 fprintf(stdout, "End editRelay\n"); |
|
721 return; |
|
722 } |
|
723 |
|
724 if ((key == KEY_UP) && (idx > 1)) |
|
725 idx--; |
|
726 if ((key == KEY_DOWN) && (idx < choices)) |
|
727 idx++; |
|
728 |
|
729 if ((key == KEY_ENTER) && (idx != old)) { |
|
730 /* |
|
731 * Select new output. |
|
732 */ |
|
733 if (idx == 1) { |
|
734 /* |
|
735 * Disable the output |
|
736 */ |
|
737 strncpy(uuid, (char *)"00000000-0000-0000-0000-000000000000", 36); |
|
738 old = idx; |
|
739 } else { |
|
740 i = 1; |
|
741 for (device = Config.devices; device; device = device->next) { |
|
742 if (device->direction == DEVDIR_OUT_ANALOG) { |
|
743 i++; |
|
744 if (i == idx) { |
|
745 strncpy(uuid, device->uuid, 36); |
|
746 break; |
|
747 } |
|
748 } |
|
749 } |
|
750 old = idx; |
|
751 } |
|
752 } |
|
753 } |
|
754 } |
|
755 |
|
756 |
|
757 |
|
758 /* |
|
759 * Edit a single unit |
|
760 */ |
|
761 void editUnit(units_list *unit) |
|
762 { |
|
763 int idx = 1, key; |
|
764 char pmpt[81], *uuid, *name; |
|
765 uLong ocrc, ncrc; |
|
766 |
|
767 if (debug) |
|
768 fprintf(stdout, "Start edit brewsystem %d %s\n", unit->number, unit->uuid); |
|
769 |
|
770 prompt(0, NULL); |
|
771 ncrc = ocrc = crc32(0L, Z_NULL, 0); |
|
772 ocrc = crc32(ocrc, (const Bytef *) unit, sizeof(units_list)); |
|
773 |
|
774 for (;;) { |
|
775 |
|
776 prompt(0, NULL); |
|
777 prompt(193, NULL); |
|
778 |
|
779 if (idx == 1) |
|
780 prompt(402, NULL); |
|
781 else if (idx == 21) |
|
782 prompt(404, NULL); |
|
783 else |
|
784 prompt(403, NULL); |
|
785 |
|
786 switch (idx) { // 12345678901234567890 |
|
787 case 1: snprintf(pmpt, Config.lcd_cols + 1, "Unit name:"); |
|
788 prompt(200, pmpt); |
|
789 snprintf(pmpt, Config.lcd_cols + 1, "%s", unit->name); |
|
790 prompt(300, pmpt); |
|
791 break; |
|
792 case 2: snprintf(pmpt, Config.lcd_cols + 1, " HLT sensor setup"); |
|
793 prompt(200, pmpt); |
|
794 break; |
|
795 case 3: snprintf(pmpt, Config.lcd_cols + 1, " HLT heater setup"); |
|
796 prompt(200, pmpt); |
|
797 break; |
|
798 case 4: snprintf(pmpt, Config.lcd_cols + 1, " MLT sensor setup"); |
|
799 prompt(200, pmpt); |
|
800 break; |
|
801 case 5: snprintf(pmpt, Config.lcd_cols + 1, " MLT heater setup"); |
|
802 prompt(200, pmpt); |
|
803 break; |
|
804 case 6: snprintf(pmpt, Config.lcd_cols + 1, " MLT pump setup"); |
|
805 prompt(200, pmpt); |
|
806 break; |
|
807 case 7: snprintf(pmpt, Config.lcd_cols + 1, "MLT heat b4 HLT: %s", unit->hlt_heater_mltfirst ? (char *)"Yes":(char *)"No"); |
|
808 prompt(200, pmpt); |
|
809 break; |
|
810 case 8: snprintf(pmpt, Config.lcd_cols + 1, "Pump cycle: %3d mins", unit->pump_cycle); |
|
811 prompt(200, pmpt); |
|
812 break; |
|
813 case 9: snprintf(pmpt, Config.lcd_cols + 1, "Pump rest : %3d mins", unit->pump_rest); |
|
814 prompt(200, pmpt); |
|
815 break; |
|
816 case 10: snprintf(pmpt, Config.lcd_cols + 1, " Pump pre-mash: %s", unit->pump_premash ? (char *)"Yes":(char *)"No"); |
|
817 prompt(200, pmpt); |
|
818 break; |
|
819 case 11: snprintf(pmpt, Config.lcd_cols + 1, " Pump on-mash: %s", unit->pump_onmash ? (char *)"Yes":(char *)"No"); |
|
820 prompt(200, pmpt); |
|
821 break; |
|
822 case 12: snprintf(pmpt, Config.lcd_cols + 1, " Pump mashout: %s", unit->pump_mashout ? (char *)"Yes":(char *)"No"); |
|
823 prompt(200, pmpt); |
|
824 break; |
|
825 case 13: snprintf(pmpt, Config.lcd_cols + 1, " Pump on-boil: %s", unit->pump_onboil ? (char *)"Yes":(char *)"No"); |
|
826 prompt(200, pmpt); |
|
827 break; |
|
828 case 14: snprintf(pmpt, Config.lcd_cols + 1, " Pump stop: %5.1f\001", unit->pump_stop); |
|
829 prompt(200, pmpt); |
|
830 break; |
|
831 case 15: snprintf(pmpt, Config.lcd_cols + 1, " Skip Add: %s", unit->skip_add ? (char *)"Yes":(char *)"No"); |
|
832 prompt(200, pmpt); |
|
833 break; |
|
834 case 16: snprintf(pmpt, Config.lcd_cols + 1, " Skip Remove: %s", unit->skip_remove ? (char *)"Yes":(char *)"No"); |
|
835 prompt(200, pmpt); |
|
836 break; |
|
837 case 17: snprintf(pmpt, Config.lcd_cols + 1, " Skip Iodine: %s", unit->skip_iodine ? (char *)"Yes":(char *)"No"); |
|
838 prompt(200, pmpt); |
|
839 break; |
|
840 case 18: snprintf(pmpt, Config.lcd_cols + 1, "Iodine time: %3d min", unit->iodine_time); |
|
841 prompt(200, pmpt); |
|
842 break; |
|
843 case 19: snprintf(pmpt, Config.lcd_cols + 1, " Whirlpool: %s", unit->whirlpool ? (char *)"Yes":(char *)"No"); |
|
844 prompt(200, pmpt); |
|
845 break; |
|
846 case 20: snprintf(pmpt, Config.lcd_cols + 1, " HLT PID setup"); |
|
847 prompt(200, pmpt); |
|
848 break; |
|
849 case 21: snprintf(pmpt, Config.lcd_cols + 1, " MLT PID setup"); |
|
850 prompt(200, pmpt); |
|
851 break; |
|
852 } |
|
853 |
|
854 key = keywait(); |
|
855 if ((key == KEY_RETURN) || my_shutdown) { |
|
856 ncrc = crc32(ncrc, (const Bytef *)unit, sizeof(units_list)); |
|
857 if (ocrc != ncrc) |
|
858 wrconfig(); |
|
859 if (debug) |
|
860 fprintf(stdout, "End edit brewsystem %d %s\n", unit->number, unit->uuid); |
|
861 return; |
|
862 } |
|
863 |
|
864 if ((key == KEY_UP) && (idx > 1)) |
|
865 idx--; |
|
866 if ((key == KEY_DOWN) && (idx < 21)) |
|
867 idx++; |
|
868 |
|
869 if (key == KEY_ENTER) { |
|
870 switch(idx) { |
|
871 case 1: name = calloc(sizeof(char), 21); |
|
872 snprintf(name, 21, unit->name); |
|
873 editName(name, (char *)"Unit name"); |
|
874 if (unit->name) |
|
875 free(unit->name); |
|
876 unit->name = xstrcpy(name); |
|
877 free(name); |
|
878 break; |
|
879 case 2: uuid = xstrcpy(unit->hlt_sensor.uuid); |
|
880 editSensor(uuid, (char *)"HLT sensor"); |
|
881 strncpy(unit->hlt_sensor.uuid, uuid, 36); |
|
882 free(uuid); |
|
883 break; |
|
884 case 3: uuid = xstrcpy(unit->hlt_heater.uuid); |
|
885 editRelay(uuid, (char *)"HLT heater"); |
|
886 strncpy(unit->hlt_heater.uuid, uuid, 36); |
|
887 free(uuid); |
|
888 break; |
|
889 case 4: uuid = xstrcpy(unit->mlt_sensor.uuid); |
|
890 editSensor(uuid, (char *)"MLT sensor"); |
|
891 strncpy(unit->mlt_sensor.uuid, uuid, 36); |
|
892 free(uuid); |
|
893 break; |
|
894 case 5: uuid = xstrcpy(unit->mlt_heater.uuid); |
|
895 editRelay(uuid, (char *)"MLT heater"); |
|
896 strncpy(unit->mlt_heater.uuid, uuid, 36); |
|
897 free(uuid); |
|
898 break; |
|
899 case 6: uuid = xstrcpy(unit->mlt_pump.uuid); |
|
900 editRelay(uuid, (char *)"MLT pump"); |
|
901 strncpy(unit->mlt_pump.uuid, uuid, 36); |
|
902 free(uuid); |
|
903 break; |
|
904 case 7: toggleYesNo(&unit->hlt_heater_mltfirst, (char *)"MLT heat b4 HLT"); |
|
905 break; |
|
906 case 8: editInteger(&unit->pump_cycle, 5, 15, 1, (char *)"Pump cycle", (char *)"mins"); |
|
907 break; |
|
908 case 9: editInteger(&unit->pump_rest, 1, 5, 1, (char *)"Pump rest ", (char *)"mins"); |
|
909 break; |
|
910 case 10: toggleYesNo(&unit->pump_premash, (char *)" Pump pre-mash"); |
|
911 break; |
|
912 case 11: toggleYesNo(&unit->pump_onmash, (char *)" Pump on-mash"); |
|
913 break; |
|
914 case 12: toggleYesNo(&unit->pump_mashout, (char *)" Pump mashout"); |
|
915 break; |
|
916 case 13: toggleYesNo(&unit->pump_onboil, (char *)" Pump on-boil"); |
|
917 break; |
|
918 case 14: editFloat(&unit->pump_stop, 80.0, 110.0, (char *)" Pump stop"); |
|
919 break; |
|
920 case 15: toggleYesNo(&unit->skip_add, (char *)"Skip add water"); |
|
921 break; |
|
922 case 16: toggleYesNo(&unit->skip_remove, (char *)"Skip remove Mash"); |
|
923 break; |
|
924 case 17: toggleYesNo(&unit->skip_iodine, (char *)"Skip iodine test"); |
|
925 break; |
|
926 case 18: editInteger(&unit->iodine_time, 10, 240, 10, (char *)"Iodine time", (char *)"min"); |
|
927 break; |
|
928 case 19: toggleYesNo(&unit->whirlpool, (char *)"Do a whirlpool"); |
|
929 break; |
|
930 case 20: editPID(unit->PID_hlt); |
|
931 break; |
|
932 case 21: editPID(unit->PID_mlt); |
|
933 break; |
|
934 } |
|
935 } |
|
936 } |
|
937 } |
|
938 |
|
939 |
|
940 |
|
941 void addUnit(int number) |
|
942 { |
|
943 units_list *tmpu, *unit = (units_list *)malloc(sizeof(units_list)); |
|
944 char name[81]; |
|
945 uuid_t uu; |
|
946 double Input, Output, Setpoint; |
|
947 |
|
948 if (debug) |
|
949 fprintf(stdout, "Adding new brewsystem %d\n", number); |
|
950 unit->next = NULL; |
|
951 unit->version = 1; |
|
952 unit->uuid = malloc(37); |
|
953 uuid_generate(uu); |
|
954 uuid_unparse(uu, unit->uuid); |
|
955 snprintf(name, 20, "System %d", number); |
|
956 unit->name = xstrcpy(name); |
|
957 unit->number = number; |
|
958 if (number == 1) |
|
959 unit->active = 1; |
|
960 else |
|
961 unit->active = 0; |
|
962 unit->hlt_sensor.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000"); |
|
963 unit->hlt_sensor.state = DEVPRESENT_UNDEF; |
|
964 unit->hlt_sensor.value = 0; |
|
965 unit->mlt_sensor.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000"); |
|
966 unit->mlt_sensor.state = DEVPRESENT_UNDEF; |
|
967 unit->mlt_sensor.value = 0; |
|
968 unit->hlt_heater.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000"); |
|
969 unit->hlt_heater.value = 0; |
|
970 unit->hlt_heater.delay = 0; |
|
971 unit->mlt_heater.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000"); |
|
972 unit->mlt_heater.value = 0; |
|
973 unit->mlt_heater.delay = 0; |
|
974 unit->mlt_pump.uuid = xstrcpy((char *)"00000000-0000-0000-0000-000000000000"); |
|
975 unit->mlt_pump.value = 0; |
|
976 unit->mlt_pump.delay = 0; |
|
977 unit->hlt_heater_mltfirst = 1; |
|
978 unit->pump_cycle = 7; |
|
979 unit->pump_rest = 2; |
|
980 unit->pump_premash = 1; |
|
981 unit->pump_onmash = 1; |
|
982 unit->pump_mashout = 0; |
|
983 unit->pump_onboil = 0; |
|
984 unit->pump_stop = 90; |
|
985 unit->skip_add = 0; |
|
986 unit->skip_remove = 0; |
|
987 unit->skip_iodine = 0; |
|
988 unit->iodine_time = 90; |
|
989 unit->whirlpool = 1; |
|
990 unit->PID_hlt = (pid_var *)malloc(sizeof(pid_var)); |
|
991 unit->PID_mlt = (pid_var *)malloc(sizeof(pid_var)); |
|
992 Input = Setpoint = 20.0; |
|
993 Output = 0; |
|
994 PID_init(unit->PID_hlt, &Input, &Output, &Setpoint, 2, 5, 1, P_DIRECT); |
|
995 PID_init(unit->PID_mlt, &Input, &Output, &Setpoint, 2, 5, 1, P_DIRECT); |
|
996 |
|
997 editUnit(unit); |
|
998 |
|
999 if (Config.units == NULL) { |
|
1000 Config.units = unit; |
|
1001 } else { |
|
1002 for (tmpu = Config.units; tmpu; tmpu = tmpu->next) { |
|
1003 if (tmpu->next == NULL) { |
|
1004 tmpu->next = unit; |
|
1005 break; |
|
1006 } |
|
1007 } |
|
1008 } |
|
1009 syslog(LOG_NOTICE, "Brewsystem %d added to the configuration", number); |
|
1010 if (debug) |
|
1011 fprintf(stdout, "Brewsystem %d added to the configuration\n", number); |
|
1012 } |
|
1013 |
|
1014 |
|
1015 |
|
1016 /* |
|
1017 * Edit a single recipe |
|
1018 */ |
|
1019 void editRecipe(a_recipe *recipe) |
|
1020 { |
|
1021 int idx = 1, i, key; |
|
1022 char pmpt[81], *name; |
|
1023 uLong ocrc, ncrc; |
|
1024 |
|
1025 if (debug) |
|
1026 fprintf(stdout, "Start edit recipe `%s' %s\n", recipe->name, recipe->uuid); |
|
1027 |
|
1028 prompt(0, NULL); |
|
1029 ncrc = ocrc = crc32(0L, Z_NULL, 0); |
|
1030 ocrc = crc32(ocrc, (const Bytef *) recipe, sizeof(a_recipe)); |
|
1031 |
|
1032 for (;;) { |
|
1033 |
|
1034 prompt(0, NULL); |
|
1035 prompt(191, NULL); /* " Edit recipe " */ |
|
1036 |
|
1037 if (idx == 1) |
|
1038 prompt(402, NULL); /* "--- dwn quit ok " */ |
|
1039 else if (idx == 24) |
|
1040 prompt(404, NULL); /* " up --- quit ok " */ |
|
1041 else |
|
1042 prompt(403, NULL); /* " up dwn quit ok " */ |
|
1043 |
|
1044 switch (idx) { // 12345678901234567890 |
|
1045 case 1: snprintf(pmpt, Config.lcd_cols + 1, "Recipe name:"); |
|
1046 prompt(200, pmpt); |
|
1047 snprintf(pmpt, Config.lcd_cols + 1, "%s", recipe->name); |
|
1048 prompt(300, pmpt); |
|
1049 break; |
|
1050 case 2: snprintf(pmpt, Config.lcd_cols + 1, "Recipe code:"); |
|
1051 prompt(200, pmpt); |
|
1052 snprintf(pmpt, Config.lcd_cols + 1, "%s", recipe->code); |
|
1053 prompt(300, pmpt); |
|
1054 break; |
|
1055 case 3: snprintf(pmpt, Config.lcd_cols + 1, "Boil time: %3d mins", recipe->boiltime); |
|
1056 prompt(200, pmpt); |
|
1057 break; |
|
1058 case 4: snprintf(pmpt, Config.lcd_cols + 1, " Cool to: %5.1f\001", recipe->coolto); |
|
1059 prompt(200, pmpt); |
|
1060 break; |
|
1061 case 5: |
|
1062 case 6: |
|
1063 case 7: |
|
1064 case 8: |
|
1065 case 9: |
|
1066 case 10: |
|
1067 case 11: |
|
1068 case 12: snprintf(pmpt, Config.lcd_cols + 1, "Mash: %s", recipe->mash[idx - 5].name); |
|
1069 prompt(200, pmpt); |
|
1070 if (recipe->mash[idx - 5].skip) |
|
1071 snprintf(pmpt, Config.lcd_cols + 1, " Skipped"); |
|
1072 else |
|
1073 snprintf(pmpt, Config.lcd_cols + 1, " Sv %4.1f\001 %3d mins", recipe->mash[idx - 5].setpoint, recipe->mash[idx - 5].duration); |
|
1074 prompt(300, pmpt); |
|
1075 break; |
|
1076 case 13: |
|
1077 case 14: |
|
1078 case 15: |
|
1079 case 16: |
|
1080 case 17: |
|
1081 case 18: |
|
1082 case 19: |
|
1083 case 20: |
|
1084 case 21: |
|
1085 case 22: snprintf(pmpt, Config.lcd_cols + 1, "Add: %s", recipe->hops[idx - 13].name); |
|
1086 prompt(200, pmpt); |
|
1087 if (recipe->hops[idx - 13].skip) |
|
1088 snprintf(pmpt, Config.lcd_cols + 1, " Skipped"); |
|
1089 else { |
|
1090 if (recipe->hops[idx - 13].boiltime == -1) |
|
1091 snprintf(pmpt, Config.lcd_cols + 1, " First Wort Hop"); |
|
1092 else |
|
1093 snprintf(pmpt, Config.lcd_cols + 1, " Boil for %3d mins", recipe->hops[idx - 13].boiltime); |
|
1094 } |
|
1095 prompt(300, pmpt); |
|
1096 break; |
|
1097 case 23: |
|
1098 case 24: |
|
1099 case 25: snprintf(pmpt, Config.lcd_cols + 1, "Hopstand: %s", recipe->hopstand[idx - 23].name); |
|
1100 prompt(200, pmpt); |
|
1101 if (recipe->hopstand[idx - 23].skip) |
|
1102 snprintf(pmpt, Config.lcd_cols + 1, " Skipped"); |
|
1103 else if (recipe->hopstand[idx - 23].hold) |
|
1104 snprintf(pmpt, Config.lcd_cols + 1, "Hold at %4.1f %3d mins", recipe->hopstand[idx - 23].setpoint, recipe->hopstand[idx - 23].duration); |
|
1105 else |
|
1106 snprintf(pmpt, Config.lcd_cols + 1, "Hold for %3d mins", recipe->hopstand[idx - 23].duration); |
|
1107 prompt(300, pmpt); |
|
1108 break; |
|
1109 } |
|
1110 |
|
1111 key = keywait(); |
|
1112 if ((key == KEY_RETURN) || my_shutdown) { |
|
1113 ncrc = crc32(ncrc, (const Bytef *)recipe, sizeof(a_recipe)); |
|
1114 if (ocrc != ncrc) { |
|
1115 /* |
|
1116 * Fix some user errors |
|
1117 */ |
|
1118 for (i = 0; i < 8; i++) |
|
1119 if (recipe->hops[i].boiltime > recipe->boiltime) |
|
1120 recipe->hops[i].boiltime = recipe->boiltime; |
|
1121 wrrecipes(); |
|
1122 } |
|
1123 if (debug) |
|
1124 fprintf(stdout, "End edit recipe `%s' %s\n", recipe->name, recipe->uuid); |
|
1125 return; |
|
1126 } |
|
1127 |
|
1128 if ((key == KEY_UP) && (idx > 1)) |
|
1129 idx--; |
|
1130 if ((key == KEY_DOWN) && (idx < 24)) |
|
1131 idx++; |
|
1132 |
|
1133 if (key == KEY_ENTER) { |
|
1134 switch(idx) { |
|
1135 case 1: name = calloc(sizeof(char), 21); |
|
1136 snprintf(name, 21, recipe->name); |
|
1137 editName(name, (char *)"Recipe name"); |
|
1138 if (recipe->name) |
|
1139 free(recipe->name); |
|
1140 recipe->name = xstrcpy(name); |
|
1141 free(name); |
|
1142 break; |
|
1143 case 2: name = calloc(sizeof(char), 21); |
|
1144 snprintf(name, 21, recipe->code); |
|
1145 editName(name, (char *)"Recipe code"); |
|
1146 if (recipe->code) |
|
1147 free(recipe->code); |
|
1148 recipe->code = xstrcpy(name); |
|
1149 free(name); |
|
1150 break; |
|
1151 case 3: editInteger(&recipe->boiltime, 60, 240, 5, (char *)"Boil time:", (char *)"mins"); |
|
1152 break; |
|
1153 case 4: editFloat(&recipe->coolto, 10.0, 30.0, (char *)" Cool to"); |
|
1154 |
|
1155 case 5: |
|
1156 case 6: |
|
1157 case 7: |
|
1158 case 8: |
|
1159 case 9: |
|
1160 case 10: |
|
1161 case 11: |
|
1162 case 12: editMash(&recipe->mash[idx-5]); |
|
1163 break; |
|
1164 case 13: |
|
1165 case 14: |
|
1166 case 15: |
|
1167 case 16: |
|
1168 case 17: |
|
1169 case 18: |
|
1170 case 19: |
|
1171 case 20: |
|
1172 case 21: |
|
1173 case 22: editHopaddition(&recipe->hops[idx-13], recipe->boiltime); |
|
1174 break; |
|
1175 case 23: |
|
1176 case 24: |
|
1177 case 25: editHopstand(&recipe->hopstand[idx-23]); |
|
1178 break; |
|
1179 } |
|
1180 } |
|
1181 } |
|
1182 } |
|
1183 |
|
1184 |
|
1185 |
|
1186 void addRecipe(int number) |
|
1187 { |
|
1188 a_recipe *tmpu, *recipe = (a_recipe *)malloc(sizeof(a_recipe)); |
|
1189 char name[81]; |
|
1190 uuid_t uu; |
|
1191 |
|
1192 if (debug) |
|
1193 fprintf(stdout, "Adding new recipe %d\n", number); |
|
1194 recipe->next = NULL; |
|
1195 recipe->uuid = malloc(37); |
|
1196 uuid_generate(uu); |
|
1197 uuid_unparse(uu, recipe->uuid); |
|
1198 snprintf(name, 21, "New recipe %d", number); |
|
1199 recipe->name = xstrcpy(name); |
|
1200 snprintf(name, 21, "%04d", number); |
|
1201 recipe->code = xstrcpy(name); |
|
1202 recipe->boiltime = 90; |
|
1203 recipe->coolto = 20.0; |
|
1204 recipe->starttime = recipe->endtime = (time_t)0; |
|
1205 /* |
|
1206 * Initial mash schedule, set a single-step 67 degr. mash |
|
1207 */ |
|
1208 recipe->mash[0].name = xstrcpy((char *)"Mash-in"); |
|
1209 recipe->mash[0].min = 20; |
|
1210 recipe->mash[0].max = 80; |
|
1211 recipe->mash[0].canskip = 0; |
|
1212 recipe->mash[0].setpoint = 68.0; |
|
1213 recipe->mash[0].skip = 0; |
|
1214 recipe->mash[0].duration = 1; |
|
1215 recipe->mash[1].name = xstrcpy((char *)"Phytase"); |
|
1216 recipe->mash[1].min = 25; |
|
1217 recipe->mash[1].max = 55; |
|
1218 recipe->mash[1].canskip = 1; |
|
1219 recipe->mash[1].setpoint = 40.0; |
|
1220 recipe->mash[1].skip = 1; |
|
1221 recipe->mash[1].duration = 10; |
|
1222 recipe->mash[2].name = xstrcpy((char *)"Glucanase"); |
|
1223 recipe->mash[2].min = 35; |
|
1224 recipe->mash[2].max = 50; |
|
1225 recipe->mash[2].canskip = 1; |
|
1226 recipe->mash[2].setpoint = 45.0; |
|
1227 recipe->mash[2].skip = 1; |
|
1228 recipe->mash[2].duration = 10; |
|
1229 recipe->mash[3].name = xstrcpy((char *)"Protease"); |
|
1230 recipe->mash[3].min = 45; |
|
1231 recipe->mash[3].max = 60; |
|
1232 recipe->mash[3].canskip = 1; |
|
1233 recipe->mash[3].setpoint = 55.0; |
|
1234 recipe->mash[3].skip = 1; |
|
1235 recipe->mash[3].duration = 10; |
|
1236 recipe->mash[4].name = xstrcpy((char *)"B-Amylase"); |
|
1237 recipe->mash[4].min = 50; |
|
1238 recipe->mash[4].max = 70; |
|
1239 recipe->mash[4].canskip = 1; |
|
1240 recipe->mash[4].setpoint = 62.0; |
|
1241 recipe->mash[4].skip = 1; |
|
1242 recipe->mash[4].duration = 30; |
|
1243 recipe->mash[5].name = xstrcpy((char *)"A-Amylase 1"); |
|
1244 recipe->mash[5].min = 60; |
|
1245 recipe->mash[5].max = 76; |
|
1246 recipe->mash[5].canskip = 1; |
|
1247 recipe->mash[5].setpoint = 67.0; |
|
1248 recipe->mash[5].skip = 1; |
|
1249 recipe->mash[5].duration = 30; |
|
1250 recipe->mash[6].name = xstrcpy((char *)"A-Amylase 2"); |
|
1251 recipe->mash[6].min = 60; |
|
1252 recipe->mash[6].max = 76; |
|
1253 recipe->mash[6].canskip = 0; |
|
1254 recipe->mash[6].setpoint = 67.0; |
|
1255 recipe->mash[6].skip = 0; |
|
1256 recipe->mash[6].duration = 60; |
|
1257 recipe->mash[7].name = xstrcpy((char *)"Mash-out"); |
|
1258 recipe->mash[7].min = 75; |
|
1259 recipe->mash[7].max = 80; |
|
1260 recipe->mash[7].canskip = 0; |
|
1261 recipe->mash[7].setpoint = 78.0; |
|
1262 recipe->mash[7].skip = 0; |
|
1263 recipe->mash[7].duration = 10; |
|
1264 |
|
1265 /* |
|
1266 * Add 2 hop additions, maximum 10 |
|
1267 */ |
|
1268 recipe->hops[0].name = xstrcpy((char *)"Hops 1"); |
|
1269 recipe->hops[0].skip = 0; |
|
1270 recipe->hops[0].boiltime = 90; |
|
1271 recipe->hops[1].name = xstrcpy((char *)"Hops 2"); |
|
1272 recipe->hops[1].skip = 0; |
|
1273 recipe->hops[1].boiltime = 5; |
|
1274 recipe->hops[2].name = xstrcpy((char *)"Hops 3"); |
|
1275 recipe->hops[2].skip = 1; |
|
1276 recipe->hops[2].boiltime = 0; |
|
1277 recipe->hops[3].name = xstrcpy((char *)"Hops 4"); |
|
1278 recipe->hops[3].skip = 1; |
|
1279 recipe->hops[3].boiltime = 0; |
|
1280 recipe->hops[4].name = xstrcpy((char *)"Hops 5"); |
|
1281 recipe->hops[4].skip = 1; |
|
1282 recipe->hops[4].boiltime = 0; |
|
1283 recipe->hops[5].name = xstrcpy((char *)"Hops 6"); |
|
1284 recipe->hops[5].skip = 1; |
|
1285 recipe->hops[5].boiltime = 0; |
|
1286 recipe->hops[6].name = xstrcpy((char *)"Hops 7"); |
|
1287 recipe->hops[6].skip = 1; |
|
1288 recipe->hops[6].boiltime = 0; |
|
1289 recipe->hops[7].name = xstrcpy((char *)"Hops 8"); |
|
1290 recipe->hops[7].skip = 1; |
|
1291 recipe->hops[7].boiltime = 0; |
|
1292 recipe->hops[8].name = xstrcpy((char *)"Hops 9"); |
|
1293 recipe->hops[8].skip = 1; |
|
1294 recipe->hops[8].boiltime = 0; |
|
1295 recipe->hops[9].name = xstrcpy((char *)"Hops 10"); |
|
1296 recipe->hops[9].skip = 1; |
|
1297 recipe->hops[9].boiltime = 0; |
|
1298 |
|
1299 /* |
|
1300 * Add 3 hopstands, disabled by default. |
|
1301 */ |
|
1302 recipe->hopstand[0].name = xstrcpy((char *)"Hopstand hot"); |
|
1303 recipe->hopstand[0].min = 88; |
|
1304 recipe->hopstand[0].max = 100; |
|
1305 recipe->hopstand[0].hold = 0; |
|
1306 recipe->hopstand[0].setpoint = 93.0; |
|
1307 recipe->hopstand[0].skip = 1; |
|
1308 recipe->hopstand[0].duration = 30; |
|
1309 recipe->hopstand[1].name = xstrcpy((char *)"Hopstand default"); |
|
1310 recipe->hopstand[1].min = 72; |
|
1311 recipe->hopstand[1].max = 77; |
|
1312 recipe->hopstand[1].hold = 0; |
|
1313 recipe->hopstand[1].setpoint = 75.0; |
|
1314 recipe->hopstand[1].skip = 1; |
|
1315 recipe->hopstand[1].duration = 60; |
|
1316 recipe->hopstand[2].name = xstrcpy((char *)"Hopstand cool"); |
|
1317 recipe->hopstand[2].min = 60; |
|
1318 recipe->hopstand[2].max = 66; |
|
1319 recipe->hopstand[2].hold = 0; |
|
1320 recipe->hopstand[2].setpoint = 63.0; |
|
1321 recipe->hopstand[2].skip = 1; |
|
1322 recipe->hopstand[2].duration = 60; |
|
1323 |
|
1324 editRecipe(recipe); |
|
1325 |
|
1326 if (recipes == NULL) { |
|
1327 recipes = recipe; |
|
1328 } else { |
|
1329 for (tmpu = recipes; tmpu; tmpu = tmpu->next) { |
|
1330 if (tmpu->next == NULL) { |
|
1331 tmpu->next = recipe; |
|
1332 break; |
|
1333 } |
|
1334 } |
|
1335 } |
|
1336 syslog(LOG_NOTICE, "Recipe %d added", number); |
|
1337 if (debug) |
|
1338 fprintf(stdout, "Recipe %d added\n", number); |
|
1339 } |
|
1340 |
|
1341 |
|
1342 |
|
1343 void editRecipes(void) |
|
1344 { |
|
1345 int total, i, key, choice = 1;; |
|
1346 a_recipe *recipe; |
|
1347 char pmpt[81]; |
|
1348 |
|
1349 prompt(0, NULL); |
|
1350 for (;;) { |
|
1351 total = 0; |
|
1352 for (recipe = recipes; recipe; recipe = recipe->next) { |
|
1353 total++; |
|
1354 } |
|
1355 |
|
1356 if (debug) |
|
1357 fprintf(stdout, "editRecipes total=%d choice=%d\n", total, choice); |
|
1358 |
|
1359 i = 0; |
|
1360 if (total) { |
|
1361 for (recipe = recipes; recipe; recipe = recipe->next) { |
|
1362 i++; |
|
1363 if (i == choice) |
|
1364 break; |
|
1365 } |
|
1366 } |
|
1367 |
|
1368 prompt(102, NULL); /* " SETUP MENU " */ |
|
1369 prompt(221, NULL); /* " Select Recipe " */ |
|
1370 if (total) { |
|
1371 snprintf(pmpt, Config.lcd_cols + 1, "%s %s ", recipe->code, recipe->name); |
|
1372 prompt(300, pmpt); |
|
1373 } |
|
1374 if (total == 0) |
|
1375 prompt(416, NULL); /* "add --- quit --- " */ |
|
1376 else if (total == 1) |
|
1377 prompt(415, NULL); /* "add --- quit ok " */ |
|
1378 else if (total && (choice == 1)) |
|
1379 prompt(414, NULL); /* "add dwn quit ok " */ |
|
1380 else if (total && (choice == total)) |
|
1381 prompt(404, NULL); /* " up --- quit ok " */ |
|
1382 else |
|
1383 prompt(403, NULL); /* " up dwn quit ok " */ |
|
1384 |
|
1385 key = keywait(); |
|
1386 if ((key == KEY_RETURN) || my_shutdown) |
|
1387 return; |
|
1388 if (total && (key == KEY_ENTER)) { |
|
1389 editRecipe(recipe); |
|
1390 prompt(0, NULL); |
|
1391 } |
|
1392 if (key == KEY_UP) { |
|
1393 if ((total == 1) || (choice == 1)) |
|
1394 addRecipe(total + 1); |
|
1395 else if (choice > 1) |
|
1396 choice--; |
|
1397 } |
|
1398 if ((key == KEY_DOWN) && (total > 1) && (choice < total)) |
|
1399 choice++; |
|
1400 } |
|
1401 } |
|
1402 |
|
1403 |
|
1404 |
|
1405 void editUnits(void) |
|
1406 { |
|
1407 int total, i, key, choice = 1;; |
|
1408 units_list *unit; |
|
1409 char pmpt[81]; |
|
1410 |
|
1411 prompt(0, NULL); |
|
1412 for (;;) { |
|
1413 total = 0; |
|
1414 for (unit = Config.units; unit; unit = unit->next) { |
|
1415 total++; |
|
1416 } |
|
1417 |
|
1418 if (debug) |
|
1419 fprintf(stdout, "editUnits total=%d choice=%d\n", total, choice); |
|
1420 |
|
1421 if (total == 0) { |
|
1422 /* |
|
1423 * Impossible unless first setup was skipped |
|
1424 */ |
|
1425 addUnit(1); |
|
1426 total = 1; |
|
1427 } else { |
|
1428 i = 0; |
|
1429 for (unit = Config.units; unit; unit = unit->next) { |
|
1430 i++; |
|
1431 if (i == choice) |
|
1432 break; |
|
1433 } |
|
1434 prompt(102, NULL); /* " SETUP MENU " */ |
|
1435 prompt(222, NULL); /* " Select Brewsystem " */ |
|
1436 snprintf(pmpt, Config.lcd_cols + 1, "%s ", unit->name); |
|
1437 prompt(300, pmpt); |
|
1438 if (total == 1) |
|
1439 prompt(415, NULL); /* "add --- quit ok " */ |
|
1440 else if (choice == 1) |
|
1441 prompt(414, NULL); /* "add dwn quit ok " */ |
|
1442 else if (choice == total) |
|
1443 prompt(404, NULL); /* " up --- quit ok " */ |
|
1444 else |
|
1445 prompt(403, NULL); /* " up dwn quit ok " */ |
|
1446 |
|
1447 key = keywait(); |
|
1448 if ((key == KEY_RETURN) || my_shutdown) |
|
1449 return; |
|
1450 if (key == KEY_ENTER) { |
|
1451 editUnit(unit); |
|
1452 prompt(0, NULL); |
|
1453 } |
|
1454 if (key == KEY_UP) { |
|
1455 if ((total == 1) || (choice == 1)) |
|
1456 addUnit(total + 1); |
|
1457 else if (choice > 1) |
|
1458 choice--; |
|
1459 } |
|
1460 if ((key == KEY_DOWN) && (total > 1) && (choice < total)) |
|
1461 choice++; |
|
1462 } |
|
1463 } |
|
1464 } |
|
1465 |
|
1466 |
|
1467 |
|
1468 void setup(void) |
|
1469 { |
|
1470 int key, option = 202; |
|
1471 |
|
1472 for (;;) { |
|
1473 if (debug) |
|
1474 fprintf(stdout, "setup() option=%d\n", option); |
|
1475 prompt(0, NULL); |
|
1476 prompt(102, NULL); /* " SETUP MENU " */ |
|
1477 prompt(option, NULL); |
|
1478 if (option == 202) |
|
1479 prompt(402, NULL); /* "--- dwn quit ok " */ |
|
1480 #ifdef USE_SIMULATOR |
|
1481 else if (option == 205) |
|
1482 #else |
|
1483 else if (option == 204) |
|
1484 #endif |
|
1485 prompt(404, NULL); /* " up --- quit ok " */ |
|
1486 else |
|
1487 prompt(403, NULL); /* " up dwn quit ok " */ |
|
1488 |
|
1489 key = keywait(); |
|
1490 |
|
1491 if ((key == KEY_RETURN) || my_shutdown) |
|
1492 return; |
|
1493 if ((key == KEY_UP) && (option > 202)) { |
|
1494 option--; |
|
1495 } |
|
1496 #ifdef USE_SIMULATOR |
|
1497 if ((key == KEY_DOWN) && (option < 205)) { |
|
1498 #else |
|
1499 if ((key == KEY_DOWN) && (option < 204)) { |
|
1500 #endif |
|
1501 option++; |
|
1502 } |
|
1503 |
|
1504 if (key == KEY_ENTER) { |
|
1505 switch(option) { |
|
1506 case 202: editRecipes(); |
|
1507 break; |
|
1508 case 203: editUnits(); |
|
1509 break; |
|
1510 case 204: // devices |
|
1511 break; |
|
1512 #ifdef USE_SIMULATOR |
|
1513 case 205: // simulator |
|
1514 break; |
|
1515 #endif |
|
1516 } |
|
1517 if (my_shutdown) |
|
1518 return; |
|
1519 } |
|
1520 } |
|
1521 } |
|
1522 |
|
1523 |
|