Sat, 04 May 2019 11:41:16 +0200
Work on web interface using websockets.
0 | 1 | /** |
2 | * @file task_tft.c | |
4 | 3 | * @brief BrewBoard TFT and Touch screen driver for a 320x240 ILI9341 based display. |
4 | * But because the application is controlled using the touch screen, all the | |
5 | * processing of menus is also found here. | |
6 | * It's the first started task, but it does nothing until the Main_Screen | |
7 | * variable is set. | |
0 | 8 | */ |
9 | ||
10 | #include "config.h" | |
11 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
12 | spi_lobo_device_handle_t spi; ///< TFT screen SPI handler |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
13 | spi_lobo_device_handle_t tsspi = NULL; ///< Touchscreen SPI handler |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
14 | extern sButton Buttons[MAXBUTTONS]; ///< 40 buttons on a screen. |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
15 | time_t now; ///< Current time |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
16 | struct tm timeinfo; ///< Current time structure |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
17 | char s_timer[10]; ///< Timer sctring buffer |
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
18 | char s_top_msg[64]; ///< Top message string buffer |
0 | 19 | |
20 | extern float stageTemp; | |
21 | extern uint16_t stageTime; | |
22 | extern uint16_t TimeWhirlPool; | |
23 | extern uint32_t TimeLeft; | |
24 | extern uint32_t TimeSpent; | |
25 | extern uint32_t SecsCount; | |
26 | extern uint32_t pumpTime; | |
27 | extern uint32_t TimeBrewing; | |
28 | extern uint16_t Steady; | |
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
29 | esp_timer_handle_t timerHandle; ///< Timer handler |
0 | 30 | extern bool _NewMinute; |
31 | extern bool _UseHLT; | |
32 | extern bool System_TimeOk; | |
40
71e06f6d80fd
Work on web interface using websockets.
Michiel Broek <mbroek@mbse.eu>
parents:
39
diff
changeset
|
33 | extern const esp_app_desc_t *app_desc; |
0 | 34 | |
35 | static const char *TAG = "task_tft"; | |
36 | ||
1
ad2c8b13eb88
Updated lots of doxygen comments
Michiel Broek <mbroek@mbse.eu>
parents:
0
diff
changeset
|
37 | #define SPI_BUS TFT_HSPI_HOST ///< SPI bus for the TFT, TFT_VSPI_HOST or TFT_HSPI_HOST |
0 | 38 | |
39 | extern int Main_Screen; | |
40 | extern int Old_Screen; | |
41 | extern int MLT_pin; | |
42 | extern int HLT_pin; | |
43 | extern int Pump_pin; | |
44 | extern DS18B20_State *ds18b20_state; | |
45 | extern DRIVER_State *driver_state; | |
46 | extern JSON_log *json_log; | |
47 | extern SemaphoreHandle_t xSemaphoreDS18B20; | |
48 | extern SemaphoreHandle_t xSemaphoreDriver; | |
49 | extern SemaphoreHandle_t xSemaphoreWiFi; | |
50 | extern WIFI_State *wifi_state; | |
51 | extern double Output; | |
52 | extern sButton Buttons[MAXBUTTONS]; | |
53 | ||
54 | extern int BoilPower, LastMashStep; | |
55 | extern char temp_buf[], logline[], strftime_buf[64]; | |
56 | extern bool loop, CoolBeep, Resume, pumpRest, updateRuntime; | |
57 | extern bool NewMinute, TempReached; | |
58 | extern uint8_t MashState; | |
59 | extern float temp_MLT, MinMash, MaxMash; | |
60 | extern uint32_t power_MLT, power_HLT, counts; | |
61 | ||
62 | ||
63 | #ifdef CONFIG_TEMP_SENSORS_SIMULATOR | |
64 | extern float Fake_MLT; | |
65 | extern float Fake_HLT; | |
66 | #endif | |
67 | ||
68 | ||
69 | ||
70 | /** | |
71 | * @brief Seconds timer callback. | |
72 | */ | |
73 | void TimerCallback(void *arg); | |
74 | ||
75 | ||
76 | /***************************************************************************/ | |
77 | ||
78 | ||
79 | ||
80 | int init_tft_display(void) | |
81 | { | |
82 | esp_err_t ret; | |
83 | esp_timer_create_args_t timerSecond = { | |
84 | .callback = &TimerCallback, | |
85 | .name = "SecondsTimer" | |
86 | }; | |
87 | ||
88 | ESP_LOGI(TAG, "Initialize TFT"); | |
89 | ||
90 | max_rdclock = 8000000; | |
91 | TFT_PinsInit(); | |
92 | ||
93 | spi_lobo_bus_config_t buscfg = { | |
94 | .miso_io_num=PIN_NUM_MISO, // set SPI MISO pin | |
95 | .mosi_io_num=PIN_NUM_MOSI, // set SPI MOSI pin | |
96 | .sclk_io_num=PIN_NUM_CLK, // set SPI CLK pin | |
97 | .quadwp_io_num=-1, | |
98 | .quadhd_io_num=-1, | |
99 | .max_transfer_sz = 6*1024, | |
100 | }; | |
101 | spi_lobo_device_interface_config_t devcfg={ | |
102 | .clock_speed_hz=8000000, // Initial clock out at 8 MHz | |
103 | .mode=0, // SPI mode 0 | |
104 | .spics_io_num=-1, // we will use external CS pin | |
105 | .spics_ext_io_num=PIN_NUM_CS, // external CS pin | |
106 | .flags=LB_SPI_DEVICE_HALFDUPLEX, // ALWAYS SET to HALF DUPLEX MODE!! for display spi | |
107 | }; | |
108 | spi_lobo_device_interface_config_t tsdevcfg={ | |
109 | .clock_speed_hz=2500000, //Clock out at 2.5 MHz | |
110 | .mode=0, //SPI mode 0 | |
111 | .spics_io_num=PIN_NUM_TCS, //Touch CS pin | |
112 | .spics_ext_io_num=-1, //Not using the external CS | |
113 | }; | |
114 | ||
115 | ESP_LOGI(TAG, "TFT pins: miso=%d, mosi=%d, sck=%d, cs=%d", PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK, PIN_NUM_CS); | |
116 | ||
117 | ret = spi_lobo_bus_add_device(SPI_BUS, &buscfg, &devcfg, &spi); | |
118 | assert(ret == ESP_OK); | |
119 | disp_spi = spi; | |
120 | ||
121 | // ==== Test select/deselect ==== | |
122 | ret = spi_lobo_device_select(spi, 1); | |
123 | assert(ret == ESP_OK); | |
124 | ret = spi_lobo_device_deselect(spi); | |
125 | assert(ret == ESP_OK); | |
126 | ||
127 | ESP_LOGI(TAG, "SPI: attached display, spi bus: %d, speed: %u, bus uses native pins: %s", | |
128 | SPI_BUS, spi_lobo_get_speed(spi), spi_lobo_uses_native_pins(spi) ? "true" : "false"); | |
129 | ||
130 | ESP_LOGI(TAG, "TS pins : miso=%d, mosi=%d, sck=%d, cs=%d", PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK, PIN_NUM_TCS); | |
131 | ||
132 | ret=spi_lobo_bus_add_device(SPI_BUS, &buscfg, &tsdevcfg, &tsspi); | |
133 | assert(ret == ESP_OK); | |
134 | ts_spi = tsspi; | |
135 | ||
136 | // ==== Test select/deselect ==== | |
137 | ret = spi_lobo_device_select(tsspi, 1); | |
138 | assert(ret == ESP_OK); | |
139 | ret = spi_lobo_device_deselect(tsspi); | |
140 | assert(ret == ESP_OK); | |
141 | ||
142 | ESP_LOGI(TAG, "SPI: attached TS device, spi bus: %d, speed: %u", SPI_BUS, spi_lobo_get_speed(tsspi)); | |
143 | ||
144 | // ==== Initialize the Display ==== | |
145 | TFT_display_init(); | |
146 | ||
147 | // ---- Detect maximum read speed ---- | |
148 | max_rdclock = find_rd_speed(); | |
149 | ||
150 | // ==== Set SPI clock used for display operations ==== | |
151 | spi_lobo_set_speed(spi, DEFAULT_SPI_CLOCK); | |
152 | ESP_LOGI(TAG, "SPI: Max rd speed: %u, changed speed to %u", max_rdclock, spi_lobo_get_speed(spi)); | |
153 | ||
154 | font_rotate = 0; | |
155 | text_wrap = 0; | |
156 | font_transparent = 0; | |
157 | font_forceFixed = 0; | |
158 | gray_scale = 0; | |
159 | TFT_setGammaCurve(DEFAULT_GAMMA_CURVE); | |
160 | TFT_setRotation(LANDSCAPE); | |
161 | TFT_setFont(DEFAULT_FONT, NULL); | |
162 | TFT_resetclipwin(); | |
163 | ||
164 | /* | |
165 | * Create a one second periodic timer. | |
166 | */ | |
167 | ret = esp_timer_create(&timerSecond, &timerHandle); | |
168 | assert(ret == ESP_OK); | |
169 | ret = esp_timer_start_periodic(timerHandle, 1000000); | |
170 | assert(ret == ESP_OK); | |
171 | ||
172 | return ret; | |
173 | } | |
174 | ||
175 | ||
176 | ||
177 | void TimerCallback(void *arg) | |
178 | { | |
179 | TimeSpent++; | |
180 | SecsCount++; | |
181 | Steady++; | |
182 | TimeBrewing++; | |
183 | runtime.TimeBrewing++; | |
184 | if ((SecsCount % 60) == 0) | |
185 | _NewMinute = true; | |
186 | ||
187 | if (TimeLeft) { | |
188 | TimeLeft--; | |
189 | if (TimeLeft == 5) { | |
190 | SoundPlay(SOUND_TimeOut); | |
191 | } | |
192 | if ((TimeLeft % 60) == 0) { | |
193 | pumpTime++; | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
198 | ||
199 | ||
200 | void TimerSet(uint32_t seconds) | |
201 | { | |
202 | Steady = TimeSpent = SecsCount = 0; | |
203 | TimeLeft = seconds; | |
204 | } | |
205 | ||
206 | ||
207 | ||
208 | void TimerShow(uint32_t Time, int X, int Y) | |
209 | { | |
210 | uint8_t Hours = (uint8_t)(Time / 3600); | |
211 | uint8_t Minutes = (uint8_t)((Time % 3600) / 60); | |
212 | uint8_t Seconds = (uint8_t)(Time % 60); | |
213 | char msg[32]; | |
214 | static uint32_t _oldTime = 0; | |
215 | ||
216 | if (Time != _oldTime) { | |
217 | _fg = TFT_GREEN; | |
218 | TFT_setFont(FONT_7SEG, NULL); | |
219 | set_7seg_font_atrib(12, 2, 1, TFT_DARKGREY); | |
220 | snprintf(s_timer, 9, "%02d:%02d:%02d", Hours, Minutes, Seconds); | |
221 | TFT_print(s_timer, X, Y); | |
222 | _oldTime = Time; | |
223 | snprintf(msg, 31, "{\"timer\":\"%s\"}", s_timer); | |
224 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
225 | } | |
226 | } | |
227 | ||
228 | ||
229 | ||
230 | void TopMessage(char *text) | |
231 | { | |
232 | char msg[64]; | |
233 | ||
234 | snprintf(s_top_msg, 63, "%s", text); | |
235 | _fg = TFT_YELLOW; | |
236 | font_transparent = 1; | |
237 | TFT_setFont(DEJAVU24_FONT, NULL); | |
238 | TFT_fillRect(0, 0, 319, 25, TFT_NAVY); | |
239 | TFT_print(s_top_msg, CENTER, 2); | |
240 | font_transparent = 0; | |
241 | snprintf(msg, 63, "{\"top_msg\":\"%s\"}", s_top_msg); | |
242 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
243 | } | |
244 | ||
245 | ||
246 | ||
247 | void MLT_info(int x, int y, bool update) | |
248 | { | |
249 | char ctemp[16], csp[16], cpower[16], msg[32]; | |
250 | static char ltemp[16], lsp[16], lpower[16]; | |
251 | bool con, cpwr, cpump = false; | |
252 | static bool lon, lpwr, lpump; | |
253 | ||
254 | _bg = (color_t){ 48, 48, 48 }; | |
255 | _fg = TFT_WHITE; | |
256 | color_t _led = { 31,255, 31}; | |
257 | color_t _pump = {127,175,255}; | |
258 | color_t _pwr = {255, 47, 47}; | |
259 | ||
260 | if (! update) { | |
261 | TFT_fillRect(x, y, 178, 90, _bg); | |
262 | TFT_drawRect(x, y, 178, 90, _fg); | |
263 | TFT_drawFastHLine(x, y + 21, 178, _fg); | |
264 | TFT_setFont(DEJAVU18_FONT, NULL); | |
265 | TFT_print("MLT", x + 67, y + 3); | |
266 | } | |
267 | ||
268 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
269 | sprintf(ctemp, "%7.3f", driver_state->mlt_pv); | |
270 | if (driver_state->mlt_mode) { | |
271 | sprintf(csp, "%6.2f sp", driver_state->mlt_sp); | |
272 | } else { | |
273 | csp[0] = '\0'; | |
274 | } | |
275 | if ((driver_state->mlt_mode == MLT_MODE_BANG) || (driver_state->mlt_mode == MLT_MODE_PID) || (driver_state->mlt_mode == MLT_MODE_EXT)) { | |
276 | sprintf(cpower, "%3d%%", driver_state->mlt_power); | |
277 | } else { | |
278 | cpower[0] = '\0'; | |
279 | } | |
280 | xSemaphoreGive(xSemaphoreDriver); | |
281 | } | |
282 | ||
283 | con = (MLT_pin) ? true : false; | |
284 | if ((con != lon) || (! update)) { | |
285 | if (con) { | |
286 | TFT_fillCircle(x + 166, y + 11, 8, _led); | |
287 | } else { | |
288 | TFT_fillCircle(x + 166, y + 11, 8, _bg); | |
289 | } | |
290 | lon = con; | |
291 | snprintf(msg, 31, "{\"mlt_led\":\"%s\"}", con ? "1":"0"); | |
292 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
293 | } | |
294 | ||
295 | cpump = (Pump_pin) ? true : false; | |
296 | if ((cpump != lpump) || (! update)) { | |
297 | if (cpump) { | |
298 | TFT_fillCircle(x + 146, y + 11, 8, _pump); | |
299 | } else { | |
300 | TFT_fillCircle(x + 146, y + 11, 8, _bg); | |
301 | } | |
302 | lpump = cpump; | |
303 | snprintf(msg, 31, "{\"pump_led\":\"%s\"}", cpump ? "1":"0"); | |
304 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
305 | } | |
306 | ||
307 | if (equipment.SSR2 == SSR2_ON_IDLE) { | |
308 | cpwr = (HLT_pin) ? true : false; | |
309 | if ((cpwr != lpwr) || (! update)) { | |
310 | if (cpwr) { | |
311 | TFT_fillCircle(x + 126, y + 11, 8, _pwr); | |
312 | } else { | |
313 | TFT_fillCircle(x + 126, y + 11, 8, _bg); | |
314 | } | |
315 | lpwr = cpwr; | |
316 | snprintf(msg, 31, "{\"hlt_led\":\"%s\"}", cpwr ? "1":"0"); | |
317 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
318 | } | |
319 | } | |
320 | ||
321 | if (strcmp(ctemp, ltemp) || (! update)) { | |
322 | TFT_setFont(USER_FONT, "/spiffs/fonts/Grotesk24x48.fon"); | |
323 | TFT_print(ctemp, x + 5, y + 23); | |
324 | strncpy(ltemp, ctemp, 16); | |
325 | snprintf(msg, 31, "{\"mlt_pv\":\"%s\"}", ctemp); | |
326 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
327 | } | |
328 | ||
329 | TFT_setFont(DEJAVU18_FONT, NULL); | |
330 | if (strcmp(csp, lsp) || (! update)) { | |
331 | TFT_clearStringRect(x + 5, y + 70, "123.45 sp"); | |
332 | TFT_print(csp, x + 5, y + 70); | |
333 | strncpy(lsp, csp, 16); | |
334 | snprintf(msg, 31, "{\"mlt_sp\":\"%s\"}", csp); | |
335 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
336 | } | |
337 | if (strcmp(cpower, lpower) || (! update)) { | |
338 | TFT_clearStringRect(x + 120, y + 70, "100%"); | |
339 | TFT_print(cpower, x + 120, y + 70); | |
340 | strncpy(lpower, cpower, 16); | |
341 | snprintf(msg, 31, "{\"mlt_power\":\"%s\"}", cpower); | |
342 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
343 | } | |
344 | } | |
345 | ||
346 | ||
347 | ||
348 | void HLT_info(int x, int y, bool update, bool small) | |
349 | { | |
350 | char ctemp[16], csp[16], cpower[16], msg[32]; | |
351 | static char ltemp[16], lsp[16], lpower[16]; | |
352 | bool con = false; | |
353 | static bool lon; | |
354 | uint8_t H; | |
355 | ||
356 | _bg = (color_t){ 63, 63, 64 }; | |
357 | _fg = TFT_YELLOW; | |
358 | color_t _led = {255, 47, 47}; | |
359 | H = (small) ? 70 : 90; | |
360 | ||
361 | if (! update) { | |
362 | TFT_fillRect(x, y, 178, H, _bg); | |
363 | TFT_drawRect(x, y, 178, H, _fg); | |
364 | TFT_drawFastHLine(x, y + 21, 178, _fg); | |
365 | TFT_setFont(DEJAVU18_FONT, NULL); | |
366 | TFT_print("HLT", x + 67, y + 3); | |
367 | } | |
368 | ||
369 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
370 | sprintf(ctemp, "%7.3f", driver_state->hlt_pv); | |
371 | if (driver_state->hlt_mode == HLT_MODE_BANG) { | |
372 | sprintf(cpower, "%3d%%", driver_state->hlt_power); | |
373 | } else { | |
374 | cpower[0] = '\0'; | |
375 | } | |
376 | if (driver_state->hlt_mode == HLT_MODE_BANG || driver_state->hlt_mode == HLT_MODE_OFF) { | |
377 | sprintf(csp, "%6.2f sp", driver_state->hlt_sp); | |
378 | } else { | |
379 | csp[0] = '\0'; | |
380 | } | |
381 | xSemaphoreGive(xSemaphoreDriver); | |
382 | } | |
383 | ||
384 | con = (HLT_pin) ? true : false; | |
385 | if ((con != lon) || (! update)) { | |
386 | if (con) { | |
387 | TFT_fillCircle(x + 166, y + 11, 8, _led); | |
388 | } else { | |
389 | TFT_fillCircle(x + 166, y + 11, 8, _bg); | |
390 | } | |
391 | lon = con; | |
392 | snprintf(msg, 31, "{\"hlt_led\":\"%s\"}", con ? "1":"0"); | |
393 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
394 | } | |
395 | ||
396 | if (strcmp(ltemp, ctemp) || (! update)) { | |
397 | if (small) { | |
398 | TFT_setFont(USER_FONT, "/spiffs/fonts/DejaVuSans24.fon"); | |
399 | TFT_print(ctemp, x + 40, y + 25); | |
400 | } else { | |
401 | TFT_setFont(USER_FONT, "/spiffs/fonts/Grotesk24x48.fon"); | |
402 | TFT_print(ctemp, x + 5, y + 23); | |
403 | } | |
404 | strncpy(ltemp, ctemp, 16); | |
405 | snprintf(msg, 31, "{\"hlt_pv\":\"%s\"}", ctemp); | |
406 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
407 | } | |
408 | ||
409 | H = (small) ? 50 : 70; | |
410 | TFT_setFont(DEJAVU18_FONT, NULL); | |
411 | if (strcmp(csp, lsp) || (! update)) { | |
412 | TFT_clearStringRect(x + 5, y + H, "123.45 sp"); | |
413 | TFT_print(csp, x + 5, y + H); | |
414 | strncpy(lsp, csp, 16); | |
415 | snprintf(msg, 31, "{\"hlt_sp\":\"%s\"}", csp); | |
416 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
417 | } | |
418 | if (strcmp(cpower, lpower) || (! update)) { | |
419 | TFT_clearStringRect(x + 120, y + H, "100%"); | |
420 | TFT_print(cpower, x + 120, y + H); | |
421 | strncpy(lpower, cpower, 16); | |
422 | snprintf(msg, 31, "{\"hlt_power\":\"%s\"}", cpower); | |
423 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
424 | } | |
425 | } | |
426 | ||
427 | ||
428 | ||
429 | void update_json(void) | |
430 | { | |
431 | int Hour = (TimeBrewing / 3600); | |
432 | int Minute = ((TimeBrewing % 3600) / 60); | |
433 | ||
434 | if (counts == 0) | |
435 | counts = 1; // Prevent division by zero. | |
436 | ||
437 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
438 | snprintf(json_log->time, 8, "%02d:%02d", Hour, Minute); | |
439 | json_log->mlt_sp = driver_state->mlt_sp; | |
440 | json_log->mlt_pv = driver_state->mlt_pv; | |
441 | json_log->mlt_power = power_MLT / counts; | |
442 | json_log->mlt_tempreached = TempReached ? 1:0; | |
443 | json_log->pump_run = driver_state->pump_run; | |
444 | json_log->hlt_sp = driver_state->hlt_sp; | |
445 | json_log->hlt_pv = driver_state->hlt_pv; | |
446 | json_log->hlt_power = power_HLT / counts; | |
447 | json_log->event[0] = '\0'; | |
448 | xSemaphoreGive(xSemaphoreDriver); | |
449 | } | |
450 | } | |
451 | ||
452 | ||
453 | ||
454 | void TFTstartWS(int client) | |
455 | { | |
456 | char msg[1024]; | |
457 | char mlt_sp[16], mlt_power[16], hlt_sp[16], hlt_power[16]; | |
458 | ||
459 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
460 | if (driver_state->mlt_sp) { | |
461 | snprintf(mlt_sp, 15, "%6.2f sp", driver_state->mlt_sp); | |
462 | snprintf(mlt_power, 15, "%3d%%", driver_state->mlt_power); | |
463 | } else { | |
464 | mlt_sp[0] = '\0'; | |
465 | mlt_power[0] = '\0'; | |
466 | } | |
467 | if (driver_state->hlt_sp) { | |
468 | snprintf(hlt_sp, 15, "%6.2f sp", driver_state->hlt_sp); | |
469 | snprintf(hlt_power, 15, "%3d%%", driver_state->hlt_power); | |
470 | } else { | |
471 | hlt_sp[0] = '\0'; | |
472 | hlt_power[0] = '\0'; | |
473 | } | |
474 | snprintf(msg, 1023, "{\"main\":\"%d\",\"mlt_led\":\"%d\",\"mlt_pv\":\"%7.3f\",\"mlt_sp\":\"%s\",\"mlt_power\":\"%s\"" \ | |
475 | ",\"pump_led\":\"%d\",\"hlt_led\":\"%d\",\"hlt_pv\":\"%7.3f\",\"hlt_sp\":\"%s\",\"hlt_power\":\"%s\"" \ | |
476 | ",\"timer\":\"%s\",\"top_msg\":\"%s\"}", | |
477 | Main_Screen, (MLT_pin) ? 1:0, driver_state->mlt_pv, mlt_sp, mlt_power, | |
478 | (Pump_pin) ? 1:0, (HLT_pin) ? 1:0, driver_state->hlt_pv, hlt_sp, hlt_power, | |
479 | s_timer, s_top_msg); | |
480 | ||
481 | xSemaphoreGive(xSemaphoreDriver); | |
482 | ws_server_send_text_client(client, msg, strlen(msg)); | |
483 | } | |
484 | ||
485 | } | |
486 | ||
487 | ||
488 | ||
489 | void task_tft(void *pvParameter) | |
490 | { | |
491 | char msg[32]; | |
492 | ||
493 | ESP_LOGI(TAG, "Initialize TFT/Touch task"); | |
494 | ||
495 | /* | |
496 | * Task loop. Read touchscreen events. | |
497 | */ | |
498 | while (1) { | |
499 | /* | |
500 | * Build new screen. | |
501 | */ | |
502 | startover: | |
503 | ||
504 | updateRuntime = false; | |
505 | if (_NewMinute) { | |
506 | _NewMinute = false; | |
507 | NewMinute = true; | |
508 | } | |
509 | ||
510 | /* | |
511 | * Timekeeping. In the WiFi task sntp is started if there | |
512 | * is a valid internet connection. | |
513 | */ | |
514 | time(&now); | |
515 | localtime_r(&now, &timeinfo); | |
516 | // Is time set? If not, tm_year will be (1970 - 1900). | |
517 | if ((timeinfo.tm_year > (2016 - 1900)) && (! System_TimeOk)) { | |
518 | System_TimeOk = true; | |
519 | strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); | |
520 | ESP_LOGI(TAG, "System time is set: %s", strftime_buf); | |
521 | } | |
522 | ||
523 | if (Old_Screen != Main_Screen) { | |
524 | ||
525 | if ((Main_Screen == MAIN_MODE_FREE) && ((config.ts_xleft == 0) || (config.ts_ybottom == 0))) { | |
526 | Main_Screen = MAIN_MODE_CALIBRATION; | |
527 | } | |
528 | ||
529 | /* | |
530 | * With each screenchange, remove the timer too. | |
531 | */ | |
532 | snprintf(msg, 31, "{\"main\":\"%d\",\"timer\":\"\"}", Main_Screen); | |
533 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
534 | ||
535 | ESP_LOGI(TAG, "Change screen %d to %d", Old_Screen, Main_Screen); | |
536 | _bg = TFT_BLACK; | |
537 | TFT_fillScreen(_bg); | |
538 | TFT_resetclipwin(); | |
539 | Buttons_Clear(); | |
540 | Old_Screen = Main_Screen; | |
541 | ||
542 | switch (Main_Screen) { | |
543 | case MAIN_MODE_FREE: | |
544 | TopMessage("Hoofdmenu"); | |
545 | MLT_info(71, 26, false); | |
546 | if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_HLT_IND)) { | |
547 | HLT_info(71,150, false, false); | |
548 | } | |
549 | Buttons_Add( 5, 26, 60, 40, "Hand", 0); | |
550 | Buttons_Add(255, 26, 60, 40, "Auto", 1); | |
551 | Buttons_Add( 5, 200, 60, 40, "Info", 2); | |
552 | Buttons_Add(255, 200, 60, 40, "Tools", 3); | |
553 | Buttons_Show(); | |
554 | break; | |
555 | ||
556 | case MAIN_MODE_CALIBRATION: | |
557 | Calibration_Init(); | |
558 | break; | |
559 | ||
560 | case MAIN_INFO: | |
39
e5900c9b9a7b
Use PROJECT_VER for version number. Updated README and info screen.
Michiel Broek <mbroek@mbse.eu>
parents:
25
diff
changeset
|
561 | sprintf(temp_buf, "BrewBoard %s", app_desc->version); |
0 | 562 | TopMessage(temp_buf); |
563 | _fg = TFT_YELLOW; | |
564 | TFT_setFont(UBUNTU16_FONT, NULL); | |
565 | TFT_print("Written by Michiel Broek (C) 2018\r\n\n", 0, 50); | |
566 | // ------------------------------------- | |
567 | _fg = TFT_ORANGE; | |
568 | TFT_print("Parts are written by Chris Morgan,\r\n", 0, LASTY); | |
39
e5900c9b9a7b
Use PROJECT_VER for version number. Updated README and info screen.
Michiel Broek <mbroek@mbse.eu>
parents:
25
diff
changeset
|
569 | TFT_print("Brett Beauregard, Blake Felt, LoBo,\r\n", 0, LASTY); |
0 | 570 | TFT_print("and David Antliff.\r\n", 0, LASTY); |
571 | ShowInteger(1,140, "Free memory", " bytes", esp_get_free_heap_size()); | |
572 | ShowText(1,158, "IDF version", (char *)esp_get_idf_version()); | |
573 | Buttons_Add(130, 200, 60, 40, "Ok", 0); | |
574 | Buttons[0].dark = true; | |
575 | Buttons_Show(); | |
576 | break; | |
577 | ||
578 | case MAIN_TOOLS: | |
579 | TopMessage("Tools menu"); | |
580 | Buttons_Add( 20, 40,120, 40, "Setup", 0); | |
581 | Buttons_Add( 20,120,120, 40, "Bestanden", 1); | |
582 | Buttons_Add(180, 40,120, 40, "Recepten", 2); | |
583 | Buttons_Add(180,120,120, 40, "Updates", 3); | |
584 | Buttons_Add(130, 200, 60, 40, "Ok", 4); | |
585 | Buttons[4].dark = true; | |
586 | Buttons_Show(); | |
587 | break; | |
588 | ||
589 | case MAIN_TOOLS_SETUP: | |
590 | case MAIN_TOOLS_SETUP_CONFIG: | |
591 | case MAIN_TOOLS_SETUP_CO_EDIT: | |
592 | case MAIN_TOOLS_SETUP_EQUIPMENT: | |
593 | case MAIN_TOOLS_SETUP_EQ_EDIT: | |
594 | case MAIN_TOOLS_SETUP_CALIBRATION: | |
595 | Setup_Init(); | |
596 | break; | |
597 | ||
598 | case MAIN_TOOLS_SETUP_WIFI: | |
599 | case MAIN_TOOLS_SETUP_WIFI_CUR: | |
600 | case MAIN_TOOLS_SETUP_WIFI_CON: | |
601 | case MAIN_TOOLS_SETUP_WIFI_NEW: | |
602 | if (WiFi_Init()) | |
603 | goto startover; | |
604 | break; | |
605 | ||
606 | case MAIN_TOOLS_RECIPE: | |
607 | case MAIN_TOOLS_RECIPE_EDIT: | |
608 | Recipes_Init(); | |
609 | break; | |
610 | ||
611 | case MAIN_TOOLS_FILES: | |
2
7a03d81c0e0d
Added database backup and restore.
Michiel Broek <mbroek@mbse.eu>
parents:
1
diff
changeset
|
612 | case MAIN_TOOLS_FILES_DIR: |
7a03d81c0e0d
Added database backup and restore.
Michiel Broek <mbroek@mbse.eu>
parents:
1
diff
changeset
|
613 | case MAIN_TOOLS_FILES_RESTORE: |
7a03d81c0e0d
Added database backup and restore.
Michiel Broek <mbroek@mbse.eu>
parents:
1
diff
changeset
|
614 | case MAIN_TOOLS_FILES_BACKUP: |
0 | 615 | Files_Init(); |
616 | break; | |
617 | ||
618 | case MAIN_TOOLS_UPDATES: | |
619 | Updates_Init(); | |
620 | break; | |
621 | ||
622 | case MAIN_AUTO_INIT: | |
623 | case MAIN_AUTO_DELAYSTART: | |
624 | case MAIN_AUTO_HEATUP: | |
625 | case MAIN_AUTO_MASH_IN: | |
626 | case MAIN_AUTO_MASH_1: | |
627 | case MAIN_AUTO_MASH_2: | |
628 | case MAIN_AUTO_MASH_3: | |
629 | case MAIN_AUTO_MASH_4: | |
630 | case MAIN_AUTO_MASH_5: | |
631 | case MAIN_AUTO_MASH_6: | |
632 | case MAIN_AUTO_MASH_OUT: | |
633 | case MAIN_AUTO_TOBOIL: | |
634 | case MAIN_AUTO_BOILING: | |
635 | case MAIN_AUTO_COOLING_H: | |
636 | case MAIN_AUTO_COOLING_M: | |
637 | case MAIN_AUTO_COOLING_C: | |
638 | case MAIN_AUTO_WHIRLPOOL9: | |
639 | case MAIN_AUTO_WHIRLPOOL7: | |
640 | case MAIN_AUTO_WHIRLPOOL6: | |
641 | case MAIN_AUTO_WHIRLPOOL2: | |
642 | case MAIN_AUTO_DONE: | |
643 | case MAIN_AUTO_ABORT: | |
644 | if (Automation_Init()) | |
645 | goto startover; | |
646 | break; | |
647 | ||
648 | case MAIN_MANUAL_INIT: | |
649 | case MAIN_MANUAL_MAIN: | |
650 | if (Manual_Init()) | |
651 | goto startover; | |
652 | break; | |
653 | ||
654 | default: | |
655 | break; | |
656 | } | |
657 | } | |
658 | ||
659 | /* | |
660 | * Update screen | |
661 | */ | |
662 | switch (Main_Screen) { | |
663 | case MAIN_MODE_FREE: | |
664 | MLT_info(71, 26, true); | |
665 | if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_HLT_IND)) { | |
666 | HLT_info(71, 150, true, false); | |
667 | } | |
668 | switch (Buttons_Scan()) { | |
669 | case 0: Main_Screen = MAIN_MANUAL_INIT; break; | |
670 | case 1: Main_Screen = MAIN_AUTO_INIT; break; | |
671 | case 2: Main_Screen = MAIN_INFO; break; | |
672 | case 3: Main_Screen = MAIN_TOOLS; break; | |
673 | default: break; | |
674 | } | |
25
79ee940410de
Show clock on the main screen, but only if the ntp time has been set.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
675 | if (System_TimeOk) { |
79ee940410de
Show clock on the main screen, but only if the ntp time has been set.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
676 | strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); |
79ee940410de
Show clock on the main screen, but only if the ntp time has been set.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
677 | TFT_setFont(DEJAVU18_FONT, NULL); |
79ee940410de
Show clock on the main screen, but only if the ntp time has been set.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
678 | _bg = TFT_BLACK; |
79ee940410de
Show clock on the main screen, but only if the ntp time has been set.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
679 | _fg = TFT_ORANGE; |
79ee940410de
Show clock on the main screen, but only if the ntp time has been set.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
680 | TFT_print(strftime_buf, CENTER, 125); |
79ee940410de
Show clock on the main screen, but only if the ntp time has been set.
Michiel Broek <mbroek@mbse.eu>
parents:
4
diff
changeset
|
681 | } |
0 | 682 | break; |
683 | ||
684 | case MAIN_MODE_CALIBRATION: | |
685 | Calibration_Loop(); | |
686 | Main_Screen = MAIN_MODE_FREE; | |
687 | break; | |
688 | ||
689 | case MAIN_TOOLS: | |
690 | switch (Buttons_Scan()) { | |
691 | case 0: Main_Screen = MAIN_TOOLS_SETUP; break; | |
692 | case 1: Main_Screen = MAIN_TOOLS_FILES; break; | |
693 | case 2: Main_Screen = MAIN_TOOLS_RECIPE; break; | |
694 | case 3: Main_Screen = MAIN_TOOLS_UPDATES; break; | |
695 | case 4: Main_Screen = MAIN_MODE_FREE; break; | |
696 | default: break; | |
697 | } | |
698 | break; | |
699 | ||
700 | case MAIN_TOOLS_SETUP: | |
701 | case MAIN_TOOLS_SETUP_CONFIG: | |
702 | case MAIN_TOOLS_SETUP_CO_EDIT: | |
703 | case MAIN_TOOLS_SETUP_EQUIPMENT: | |
704 | case MAIN_TOOLS_SETUP_EQ_EDIT: | |
705 | case MAIN_TOOLS_SETUP_CALIBRATION: | |
706 | Setup_Loop(); | |
707 | break; | |
708 | ||
709 | case MAIN_TOOLS_SETUP_WIFI: | |
710 | case MAIN_TOOLS_SETUP_WIFI_CUR: | |
711 | case MAIN_TOOLS_SETUP_WIFI_CON: | |
712 | case MAIN_TOOLS_SETUP_WIFI_NEW: | |
713 | if (WiFi_Loop()) | |
714 | goto startover; | |
715 | break; | |
716 | ||
717 | case MAIN_TOOLS_RECIPE: | |
718 | case MAIN_TOOLS_RECIPE_EDIT: | |
719 | Recipes_Loop(); | |
720 | break; | |
721 | ||
722 | case MAIN_TOOLS_FILES: | |
2
7a03d81c0e0d
Added database backup and restore.
Michiel Broek <mbroek@mbse.eu>
parents:
1
diff
changeset
|
723 | case MAIN_TOOLS_FILES_DIR: |
7a03d81c0e0d
Added database backup and restore.
Michiel Broek <mbroek@mbse.eu>
parents:
1
diff
changeset
|
724 | case MAIN_TOOLS_FILES_RESTORE: |
7a03d81c0e0d
Added database backup and restore.
Michiel Broek <mbroek@mbse.eu>
parents:
1
diff
changeset
|
725 | case MAIN_TOOLS_FILES_BACKUP: |
0 | 726 | Files_Loop(); |
727 | break; | |
728 | ||
729 | case MAIN_TOOLS_UPDATES: | |
730 | Updates_Loop(); | |
731 | break; | |
732 | ||
733 | case MAIN_INFO: | |
734 | if (Buttons_Scan() == 0) { | |
735 | Main_Screen = MAIN_MODE_FREE; | |
736 | } | |
737 | break; | |
738 | ||
739 | case MAIN_AUTO_INIT: | |
740 | case MAIN_AUTO_DELAYSTART: | |
741 | case MAIN_AUTO_HEATUP: | |
742 | case MAIN_AUTO_MASH_IN: | |
743 | case MAIN_AUTO_MASH_1: | |
744 | case MAIN_AUTO_MASH_2: | |
745 | case MAIN_AUTO_MASH_3: | |
746 | case MAIN_AUTO_MASH_4: | |
747 | case MAIN_AUTO_MASH_5: | |
748 | case MAIN_AUTO_MASH_6: | |
749 | case MAIN_AUTO_MASH_OUT: | |
750 | case MAIN_AUTO_TOBOIL: | |
751 | case MAIN_AUTO_BOILING: | |
752 | case MAIN_AUTO_COOLING_H: | |
753 | case MAIN_AUTO_COOLING_M: | |
754 | case MAIN_AUTO_COOLING_C: | |
755 | case MAIN_AUTO_WHIRLPOOL9: | |
756 | case MAIN_AUTO_WHIRLPOOL7: | |
757 | case MAIN_AUTO_WHIRLPOOL6: | |
758 | case MAIN_AUTO_WHIRLPOOL2: | |
759 | case MAIN_AUTO_DONE: | |
760 | case MAIN_AUTO_ABORT: | |
761 | if (Automation_Loop()) | |
762 | goto startover; | |
763 | break; | |
764 | ||
765 | case MAIN_MANUAL_INIT: | |
766 | case MAIN_MANUAL_MAIN: | |
767 | if (Manual_Loop()) | |
768 | goto startover; | |
769 | break; | |
770 | ||
771 | default: | |
772 | break; | |
773 | } | |
774 | ||
775 | if (updateRuntime) { | |
776 | write_runtime(); | |
777 | } | |
778 | ||
779 | /* | |
780 | * Count power average during brewing. | |
781 | */ | |
782 | if ((Main_Screen >= MAIN_AUTO_MASH_IN) && (Main_Screen < MAIN_AUTO_DONE)) { | |
783 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
784 | power_MLT += driver_state->mlt_power; | |
785 | power_HLT += driver_state->hlt_power; | |
786 | counts++; | |
787 | xSemaphoreGive(xSemaphoreDriver); | |
788 | } | |
789 | } | |
790 | ||
791 | if (NewMinute) { | |
792 | /* | |
793 | * Brew logging. | |
794 | */ | |
795 | if ((Main_Screen >= MAIN_AUTO_MASH_IN) && (Main_Screen < MAIN_AUTO_DONE)) { | |
796 | update_json(); | |
797 | log_json(); | |
798 | power_MLT = power_HLT = counts = 0; | |
799 | } | |
800 | } | |
801 | ||
802 | NewMinute = false; | |
803 | vTaskDelay(50 / portTICK_PERIOD_MS); | |
804 | } | |
805 | } | |
806 | ||
807 |