|
8 | 8 | #include <NimBLEDevice.h> |
9 | 9 |
|
10 | 10 | #include <WiFi.h> // WiFi library that also provides WiFiClient |
| 11 | +#include <WiFiClientSecure.h> |
11 | 12 | #include <ArduinoJson.h> |
12 | 13 | #include <PubSubClient.h> // For MQTT |
13 | 14 |
|
@@ -356,6 +357,57 @@ static jsval_t js_delay(struct js *js, jsval_t *args, int nargs) { |
356 | 357 | return js_mknull(); |
357 | 358 | } |
358 | 359 |
|
| 360 | +// LVGL Timer Bridging Functions |
| 361 | + |
| 362 | +// This C++ function will be the callback for LVGL. It will execute a JS function. |
| 363 | +static void elk_timer_cb(lv_timer_t *timer) { |
| 364 | + char *func_name = (char *)timer->user_data; |
| 365 | + |
| 366 | + if (func_name != NULL && js != NULL) { |
| 367 | + // Construct a snippet of JavaScript to call the function, e.g., "my_func();" |
| 368 | + char snippet[64]; |
| 369 | + snprintf(snippet, sizeof(snippet), "%s();", func_name); |
| 370 | + |
| 371 | + // Use js_eval to execute the function call. |
| 372 | + jsval_t res = js_eval(js, snippet, strlen(snippet)); |
| 373 | + if (js_type(res) == JS_ERR) { |
| 374 | + LOGF("[TIMER CB] Error executing JS function '%s': %s\n", func_name, js_str(js, res)); |
| 375 | + } |
| 376 | + } |
| 377 | +} |
| 378 | + |
| 379 | +// This is the function we will expose to JavaScript. |
| 380 | +// It creates an LVGL timer that will call our C++ callback. |
| 381 | +static jsval_t js_create_timer(struct js *js, jsval_t *args, int nargs) { |
| 382 | + // Expects: function name (string), period in ms (number) |
| 383 | + if (nargs < 2) { |
| 384 | + LOG("create_timer expects: function_name, period_ms"); |
| 385 | + return js_mknull(); |
| 386 | + } |
| 387 | + |
| 388 | + size_t func_name_len; |
| 389 | + char *func_name_str = js_getstr(js, args[0], &func_name_len); |
| 390 | + double period = js_getnum(args[1]); |
| 391 | + |
| 392 | + if (!func_name_str || func_name_len == 0) { |
| 393 | + return js_mknull(); |
| 394 | + } |
| 395 | + |
| 396 | + char *name_for_timer = (char *)malloc(func_name_len + 1); |
| 397 | + if (!name_for_timer) { |
| 398 | + LOG("Failed to allocate memory for timer callback name"); |
| 399 | + return js_mknull(); |
| 400 | + } |
| 401 | + memcpy(name_for_timer, func_name_str, func_name_len); |
| 402 | + name_for_timer[func_name_len] = '\0'; |
| 403 | + |
| 404 | + // Create the LVGL timer |
| 405 | + lv_timer_create(elk_timer_cb, (uint32_t)period, name_for_timer); |
| 406 | + |
| 407 | + LOGF("Created LVGL timer to call JS function '%s' every %dms\n", name_for_timer, (int)period); |
| 408 | + return js_mknull(); |
| 409 | +} |
| 410 | + |
359 | 411 | // sd_read_file(path) |
360 | 412 | static jsval_t js_sd_read_file(struct js *js, jsval_t *args, int nargs) { |
361 | 413 | if (nargs != 1) return js_mknull(); |
@@ -430,6 +482,50 @@ static jsval_t js_sd_list_dir(struct js *js, jsval_t *args, int nargs) { |
430 | 482 | return js_mkstr(js, fileList, fileListLen); |
431 | 483 | } |
432 | 484 |
|
| 485 | +// Helper function to convert a JS string to a JS number |
| 486 | +static jsval_t js_to_number(struct js *js, jsval_t *args, int nargs) { |
| 487 | + if (nargs != 1) { |
| 488 | + return js_mknum(0); // Return 0 if no argument |
| 489 | + } |
| 490 | + |
| 491 | + // If it's already a number, just return it. |
| 492 | + if (js_type(args[0]) == JS_NUM) { |
| 493 | + return args[0]; |
| 494 | + } |
| 495 | + |
| 496 | + // Get the string value from the JS argument |
| 497 | + size_t len; |
| 498 | + const char *str = js_getstr(js, args[0], &len); |
| 499 | + if (!str) { |
| 500 | + return js_mknum(0); // Return 0 if not a valid string |
| 501 | + } |
| 502 | + |
| 503 | + // Convert the C-string to a double and return as a JS number |
| 504 | + return js_mknum(atof(str)); |
| 505 | +} |
| 506 | + |
| 507 | +// Helper function to convert a JS number to a JS string |
| 508 | +static jsval_t js_number_to_string(struct js *js, jsval_t *args, int nargs) { |
| 509 | + if (nargs != 1) { |
| 510 | + return js_mkstr(js, "", 0); |
| 511 | + } |
| 512 | + |
| 513 | + uint8_t type = js_type(args[0]); |
| 514 | + |
| 515 | + if (type == JS_NUM) { |
| 516 | + char buf[32]; |
| 517 | + double num = js_getnum(args[0]); |
| 518 | + // Using "%.17g" is how the Elk engine itself formats numbers |
| 519 | + snprintf(buf, sizeof(buf), "%.17g", num); |
| 520 | + return js_mkstr(js, buf, strlen(buf)); |
| 521 | + } else if (type == JS_STR) { |
| 522 | + // If it's already a string (like from parse_json_value), just return it |
| 523 | + return args[0]; |
| 524 | + } |
| 525 | + |
| 526 | + return js_mkstr(js, "", 0); |
| 527 | +} |
| 528 | + |
433 | 529 | /****************************************************************************** |
434 | 530 | * F) Load GIF from SD => g_gifBuffer => "M:mygif" |
435 | 531 | ******************************************************************************/ |
@@ -3011,6 +3107,9 @@ void register_js_functions() { |
3011 | 3107 | js_set(js, global, "wifi_status", js_mkfun(js_wifi_status)); |
3012 | 3108 | js_set(js, global, "wifi_get_ip", js_mkfun(js_wifi_get_ip)); |
3013 | 3109 | js_set(js, global, "delay", js_mkfun(js_delay)); |
| 3110 | + js_set(js, global, "create_timer", js_mkfun(js_create_timer)); |
| 3111 | + js_set(js, global, "toNumber", js_mkfun(js_to_number)); |
| 3112 | + js_set(js, global, "numberToString", js_mkfun(js_number_to_string)); |
3014 | 3113 |
|
3015 | 3114 | // bridging for indexOf / substring |
3016 | 3115 | js_set(js, global, "str_index_of", js_mkfun(js_str_index_of)); |
@@ -3180,12 +3279,10 @@ static void elk_task(void *pvParam) { |
3180 | 3279 | // 4) Now keep running lv_timer_handler() or your lvgl_loop |
3181 | 3280 | // so that the UI remains active |
3182 | 3281 | for(;;) { |
3183 | | - // Check Wi-Fi and MQTT, handle reconnections |
3184 | | - wifiMqttMaintainLoop(); |
| 3282 | + if (g_mqtt_enabled) { |
| 3283 | + wifiMqttMaintainLoop(); |
| 3284 | + } |
3185 | 3285 | lv_timer_handler(); |
3186 | 3286 | vTaskDelay(pdMS_TO_TICKS(5)); |
3187 | 3287 | } |
3188 | | - |
3189 | | - // If you ever want to exit the task, do: |
3190 | | - // vTaskDelete(NULL); |
3191 | 3288 | } |
0 commit comments